Implement inventory GUI into /npc equip

This commit is contained in:
fullwall 2021-01-31 00:29:27 +08:00
parent 0ded25ad5e
commit 47707fe628
4 changed files with 115 additions and 32 deletions

View File

@ -1,22 +1,15 @@
package net.citizensnpcs.commands;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
import org.bukkit.entity.Player;
import com.google.common.collect.Maps;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.command.Command;
import net.citizensnpcs.api.command.CommandContext;
import net.citizensnpcs.api.command.Requirements;
import net.citizensnpcs.api.gui.InventoryMenu;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.util.Messaging;
import net.citizensnpcs.editor.CopierEditor;
import net.citizensnpcs.editor.Editor;
import net.citizensnpcs.editor.EquipmentEditor;
import net.citizensnpcs.editor.EquipmentGUI;
import net.citizensnpcs.trait.text.Text;
import net.citizensnpcs.trait.waypoint.Waypoints;
@ -43,12 +36,6 @@ public class EditorCommands {
max = 1,
permission = "citizens.npc.edit.equip")
public void equip(CommandContext args, Player player, NPC npc) {
if (Messaging.isDebugging() && false) {
InventoryMenu create = InventoryMenu.createWithContext(EquipmentGUI.class, Maps.newHashMap());
Bukkit.getPluginManager().registerEvents(create, CitizensAPI.getPlugin());
create.present(player);
return;
}
Editor.enterOrLeave(player, new EquipmentEditor(player, npc));
}

View File

@ -9,6 +9,8 @@ import org.bukkit.entity.Player;
import org.bukkit.event.Event.Result;
import org.bukkit.event.EventHandler;
import org.bukkit.event.block.Action;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryCloseEvent;
import org.bukkit.event.player.AsyncPlayerChatEvent;
import org.bukkit.event.player.PlayerInteractEntityEvent;
import org.bukkit.event.player.PlayerInteractEvent;
@ -17,6 +19,7 @@ import org.bukkit.inventory.ItemStack;
import com.google.common.collect.Maps;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.gui.InventoryMenu;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.trait.trait.Equipment;
import net.citizensnpcs.api.trait.trait.Equipment.EquipmentSlot;
@ -25,6 +28,7 @@ import net.citizensnpcs.util.Messages;
import net.citizensnpcs.util.Util;
public class EquipmentEditor extends Editor {
private InventoryMenu menu;
private final NPC npc;
private final Player player;
@ -35,14 +39,41 @@ public class EquipmentEditor extends Editor {
@Override
public void begin() {
if (!EQUIPPERS.containsKey(npc.getEntity().getType())) {
Map<String, Object> ctx = Maps.newHashMap();
ctx.put("npc", npc);
menu = InventoryMenu.createWithContext(EquipmentGUI.class, ctx);
menu.present(player);
return;
}
Messaging.sendTr(player, Messages.EQUIPMENT_EDITOR_BEGIN);
}
@Override
public void end() {
if (menu != null) {
menu.close();
menu = null;
return;
}
Messaging.sendTr(player, Messages.EQUIPMENT_EDITOR_END);
}
@EventHandler
public void onInventoryClick(InventoryClickEvent event) {
if (menu != null && event.getWhoClicked().equals(player)) {
menu.onInventoryClick(event);
}
}
@EventHandler
public void onInventoryClose(InventoryCloseEvent event) {
if (menu != null && event.getPlayer().equals(player)) {
menu.onInventoryClose(event);
Editor.leave((Player) event.getPlayer());
}
}
@EventHandler(ignoreCancelled = true)
public void onPlayerChat(final AsyncPlayerChatEvent event) {
if (!event.getPlayer().equals(player))

View File

@ -1,64 +1,130 @@
package net.citizensnpcs.editor;
import java.util.function.Function;
import org.bukkit.Material;
import org.bukkit.entity.HumanEntity;
import org.bukkit.event.inventory.ClickType;
import org.bukkit.event.Event.Result;
import org.bukkit.event.inventory.InventoryAction;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.inventory.ItemStack;
import net.citizensnpcs.api.gui.ClickHandler;
import net.citizensnpcs.api.gui.InjectContext;
import net.citizensnpcs.api.gui.InventoryMenuPage;
import net.citizensnpcs.api.gui.InventoryMenuSlot;
import net.citizensnpcs.api.gui.Menu;
import net.citizensnpcs.api.gui.MenuContext;
import net.citizensnpcs.api.gui.MenuPattern;
import net.citizensnpcs.api.gui.MenuSlot;
import net.citizensnpcs.api.util.Messaging;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.trait.trait.Equipment;
import net.citizensnpcs.api.trait.trait.Equipment.EquipmentSlot;
@Menu(title = "NPC Equipment", type = InventoryType.CHEST, dimensions = { 2, 5 })
@MenuSlot(value = { 0, 0 }, material = Material.DIAMOND_SWORD, amount = 1, filter = ClickType.UNKNOWN)
@MenuSlot(value = { 0, 1 }, material = Material.ELYTRA, amount = 1, filter = ClickType.UNKNOWN)
@MenuSlot(value = { 0, 2 }, material = Material.DIAMOND_HELMET, amount = 1, filter = ClickType.UNKNOWN)
@MenuSlot(value = { 0, 3 }, material = Material.DIAMOND_CHESTPLATE, amount = 1, filter = ClickType.UNKNOWN)
@MenuSlot(value = { 0, 4 }, material = Material.DIAMOND_LEGGINGS, amount = 1, filter = ClickType.UNKNOWN)
@MenuSlot(value = { 0, 5 }, material = Material.DIAMOND_BOOTS, amount = 1, filter = ClickType.UNKNOWN)
@MenuPattern(offset = { 0, 6 }, slots = { @MenuSlot(filter = ClickType.UNKNOWN, pat = 'x') }, value = "xxx\nxxx")
@MenuSlot(slot = { 0, 2 }, material = Material.DIAMOND_HELMET, amount = 1, filter = InventoryAction.UNKNOWN)
@MenuSlot(slot = { 0, 4 }, material = Material.DIAMOND_LEGGINGS, amount = 1, filter = InventoryAction.UNKNOWN)
@MenuSlot(slot = { 0, 1 }, material = Material.ELYTRA, amount = 1, filter = InventoryAction.UNKNOWN)
@MenuSlot(slot = { 0, 0 }, material = Material.DIAMOND_SWORD, amount = 1, filter = InventoryAction.UNKNOWN)
@MenuSlot(slot = { 0, 3 }, material = Material.DIAMOND_CHESTPLATE, amount = 1, filter = InventoryAction.UNKNOWN)
@MenuSlot(slot = { 0, 5 }, material = Material.DIAMOND_BOOTS, amount = 1, filter = InventoryAction.UNKNOWN)
@MenuPattern(offset = { 0, 6 }, slots = { @MenuSlot(filter = InventoryAction.UNKNOWN, pat = 'x') }, value = "xxx\nxxx")
public class EquipmentGUI extends InventoryMenuPage {
@MenuSlot(slot = { 1, 5 })
private InventoryMenuSlot boots;
@MenuSlot(slot = { 1, 3 })
private InventoryMenuSlot chest;
@MenuSlot(slot = { 1, 0 })
private InventoryMenuSlot hand;
@MenuSlot(slot = { 1, 2 })
private InventoryMenuSlot helmet;
@MenuSlot(slot = { 1, 4 })
private InventoryMenuSlot leggings;
@InjectContext
private NPC npc;
@MenuSlot(slot = { 1, 1 })
private InventoryMenuSlot offhand;
// TODO: move into API?
private ItemStack getResult(InventoryClickEvent event) {
ItemStack stack = event.getCurrentItem() == null ? new ItemStack(event.getCursor().getType(), 0)
: event.getCurrentItem().clone();
switch (event.getAction()) {
case PICKUP_ONE:
stack.setAmount(stack.getAmount() - 1);
break;
case PICKUP_HALF:
stack.setAmount((int) Math.floor(stack.getAmount() / 2.0));
break;
case PICKUP_ALL:
stack = null;
break;
case PLACE_ALL:
stack.setAmount(
Math.min(stack.getAmount() + event.getCursor().getAmount(), stack.getType().getMaxStackSize()));
break;
case PLACE_SOME:
stack.setAmount(Math.min(stack.getAmount(), stack.getType().getMaxStackSize()));
break;
case PLACE_ONE:
stack.setAmount(stack.getAmount() + 1);
break;
default:
event.setCancelled(true);
event.setResult(Result.DENY);
return null;
}
return stack;
}
@Override
public void initialise(MenuContext ctx) {
Equipment trait = npc.getOrAddTrait(Equipment.class);
hand.setItemStack(trait.get(EquipmentSlot.HAND));
helmet.setItemStack(trait.get(EquipmentSlot.HELMET));
chest.setItemStack(trait.get(EquipmentSlot.CHESTPLATE));
leggings.setItemStack(trait.get(EquipmentSlot.LEGGINGS));
boots.setItemStack(trait.get(EquipmentSlot.BOOTS));
offhand.setItemStack(trait.get(EquipmentSlot.OFF_HAND));
}
@Override
public void onClick(InventoryMenuSlot slot, InventoryClickEvent event) {
Messaging.log(event);
}
@Override
public void onClose(HumanEntity player) {
Messaging.log("CLOSED", player);
private void set(EquipmentSlot slot, InventoryClickEvent event, Function<Material, Boolean> filter) {
ItemStack result = getResult(event);
if (event.isCancelled() || (result != null && !filter.apply(result.getType()))) {
event.setResult(Result.DENY);
return;
}
npc.getOrAddTrait(Equipment.class).set(slot, result);
}
@ClickHandler(slot = { 1, 5 })
public void setBoots(InventoryMenuSlot slot, InventoryClickEvent event) {
set(EquipmentSlot.BOOTS, event, (type) -> type.name().endsWith("BOOTS"));
}
@ClickHandler(slot = { 1, 3 })
public void setChest(InventoryMenuSlot slot, InventoryClickEvent event) {
set(EquipmentSlot.CHESTPLATE, event,
(type) -> type.name().endsWith("CHESTPLATE") || type.name().equals("ELYTRA"));
}
@ClickHandler(slot = { 1, 0 })
public void setHand(InventoryMenuSlot slot, InventoryClickEvent event) {
set(EquipmentSlot.HAND, event, (type) -> true);
}
@ClickHandler(slot = { 1, 2 })
public void setHelmet(InventoryMenuSlot slot, InventoryClickEvent event) {
set(EquipmentSlot.HELMET, event, (type) -> true);
}
@ClickHandler(slot = { 1, 4 })
public void setLeggings(InventoryMenuSlot slot, InventoryClickEvent event) {
set(EquipmentSlot.LEGGINGS, event, (type) -> type.name().endsWith("LEGGINGS"));
}
@ClickHandler(slot = { 1, 1 })
public void setOffhand(InventoryMenuSlot slot, InventoryClickEvent event) {
set(EquipmentSlot.OFF_HAND, event, (type) -> true);
}
}

View File

@ -17,7 +17,6 @@ import net.citizensnpcs.util.Messages;
public class GenericEquipper implements Equipper {
@Override
public void equip(Player equipper, NPC toEquip) {
// TODO: migrate to an inventory-GUI system
ItemStack hand = equipper.getInventory().getItemInHand();
Equipment trait = toEquip.getOrAddTrait(Equipment.class);
EquipmentSlot slot = EquipmentSlot.HAND;