Support blank cosmetic

This commit is contained in:
fullwall 2024-10-28 01:19:30 +08:00
parent 72dabc2c2d
commit 0b978f6322
3 changed files with 39 additions and 9 deletions

View File

@ -17,14 +17,15 @@ import net.citizensnpcs.api.gui.MenuSlot;
import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.trait.trait.Equipment; import net.citizensnpcs.api.trait.trait.Equipment;
import net.citizensnpcs.api.trait.trait.Equipment.EquipmentSlot; import net.citizensnpcs.api.trait.trait.Equipment.EquipmentSlot;
import net.citizensnpcs.util.Util;
@Menu(title = "NPC Equipment", type = InventoryType.CHEST, dimensions = { 3, 9 }) @Menu(title = "NPC Equipment", type = InventoryType.CHEST, dimensions = { 3, 9 })
@MenuSlot(slot = { 0, 0 }, material = Material.DIAMOND_SWORD, lore = "Place in hand item below", amount = 1)
@MenuSlot( @MenuSlot(
slot = { 0, 1 }, slot = { 0, 1 },
compatMaterial = { "SHIELD", "BARRIER", "FIRE" }, compatMaterial = { "SHIELD", "BARRIER", "FIRE" },
lore = "Place offhand item below", lore = "Place offhand item below",
amount = 1) amount = 1)
@MenuSlot(slot = { 0, 0 }, material = Material.DIAMOND_SWORD, lore = "Place in hand item below", amount = 1)
@MenuSlot(slot = { 0, 2 }, material = Material.DIAMOND_HELMET, lore = "Place helmet below", amount = 1) @MenuSlot(slot = { 0, 2 }, material = Material.DIAMOND_HELMET, lore = "Place helmet below", amount = 1)
@MenuSlot(slot = { 0, 3 }, material = Material.DIAMOND_CHESTPLATE, lore = "Place chestplate below", amount = 1) @MenuSlot(slot = { 0, 3 }, material = Material.DIAMOND_CHESTPLATE, lore = "Place chestplate below", amount = 1)
@MenuSlot(slot = { 0, 4 }, material = Material.DIAMOND_LEGGINGS, lore = "Place leggings below", amount = 1) @MenuSlot(slot = { 0, 4 }, material = Material.DIAMOND_LEGGINGS, lore = "Place leggings below", amount = 1)
@ -48,27 +49,31 @@ public class GenericEquipperGUI extends InventoryMenuPage {
ctx.getSlot(1 * 9 + i).setItemStack(trait.get(slot)); ctx.getSlot(1 * 9 + i).setItemStack(trait.get(slot));
if (trait.getCosmetic(slot) != null) { if (trait.getCosmetic(slot) != null) {
ctx.getSlot(2 * 9 + i).setItemStack(trait.getCosmetic(slot)); ctx.getSlot(2 * 9 + i).setItemStack(trait.getCosmetic(slot));
} else {
ctx.getSlot(2 * 9 + i).setItemStack(Util.createItem(Util.getFallbackMaterial("BARRIER", "FIRE"),
"No cosmetic", "Click to enable cosmetic for this equipment"));
} }
Function<Material, Boolean> filter = type -> true; Function<ItemStack, Boolean> filter = type -> true;
switch (slot) { switch (slot) {
case BOOTS: case BOOTS:
case LEGGINGS: case LEGGINGS:
filter = type -> type.name().endsWith(slot.name()); filter = stack -> Util.isEquippable(stack, slot) || stack.getType().name().endsWith(slot.name());
break; break;
case CHESTPLATE: case CHESTPLATE:
filter = type -> type == Material.ELYTRA || type.name().endsWith(slot.name()); filter = stack -> Util.isEquippable(stack, slot) || stack.getType() == Material.ELYTRA
|| stack.getType().name().endsWith(slot.name());
default: default:
break; break;
} }
Function<Material, Boolean> ffilter = filter; Function<ItemStack, Boolean> ffilter = filter;
ctx.getSlot(1 * 9 + i).addClickHandler(event -> set(slot, event, ffilter)); ctx.getSlot(1 * 9 + i).addClickHandler(event -> set(slot, event, ffilter));
ctx.getSlot(2 * 9 + i).addClickHandler(event -> setCosmetic(slot, event, ffilter)); ctx.getSlot(2 * 9 + i).addClickHandler(event -> setCosmetic(slot, event, ffilter));
} }
} }
private void set(EquipmentSlot slot, CitizensInventoryClickEvent event, Function<Material, Boolean> filter) { private void set(EquipmentSlot slot, CitizensInventoryClickEvent event, Function<ItemStack, Boolean> filter) {
ItemStack result = event.getResultItemNonNull(); ItemStack result = event.getResultItemNonNull();
if (event.isCancelled() || (result.getType() != Material.AIR && !filter.apply(result.getType()))) { if (event.isCancelled() || (result.getType() != Material.AIR && !filter.apply(result))) {
event.setResult(Result.DENY); event.setResult(Result.DENY);
return; return;
} }
@ -76,9 +81,21 @@ public class GenericEquipperGUI extends InventoryMenuPage {
} }
private void setCosmetic(EquipmentSlot slot, CitizensInventoryClickEvent event, private void setCosmetic(EquipmentSlot slot, CitizensInventoryClickEvent event,
Function<Material, Boolean> filter) { Function<ItemStack, Boolean> filter) {
if (event.getCursorNonNull().getType() == Material.AIR) {
if (event.getCurrentItemNonNull().getType() == Util.getFallbackMaterial("BARRIER", "FIRE")) {
event.setCurrentItem(null);
npc.getOrAddTrait(Equipment.class).setCosmetic(slot, new ItemStack(Material.AIR, 1));
} else if (event.getCurrentItem() == null) {
event.setCurrentItem(Util.createItem(Util.getFallbackMaterial("BARRIER", "FIRE"), "No cosmetic",
"Click to enable cosmetic for this equipment"));
npc.getOrAddTrait(Equipment.class).setCosmetic(slot, null);
}
event.setResult(Result.DENY);
return;
}
ItemStack result = event.getResultItemNonNull(); ItemStack result = event.getResultItemNonNull();
if (event.isCancelled() || (result.getType() != Material.AIR && !filter.apply(result.getType()))) { if (event.isCancelled() || (result.getType() != Material.AIR && !filter.apply(result))) {
event.setResult(Result.DENY); event.setResult(Result.DENY);
return; return;
} }

View File

@ -93,6 +93,7 @@ public class Messages {
public static final String CONTROLLABLE_SET = "citizens.commands.npc.controllable.set"; public static final String CONTROLLABLE_SET = "citizens.commands.npc.controllable.set";
public static final String COPIER_EDITOR_BEGIN = "citizens.editors.copier.begin"; public static final String COPIER_EDITOR_BEGIN = "citizens.editors.copier.begin";
public static final String COPIER_EDITOR_END = "citizens.editors.copier.end"; public static final String COPIER_EDITOR_END = "citizens.editors.copier.end";
public static final String COSMETIC_EQUIPMENT_SET = "citizens.commands.npc.setequipment.cosmetic-set";
public static final String CURRENT_WAYPOINT_PROVIDER = "citizens.waypoints.current-provider"; public static final String CURRENT_WAYPOINT_PROVIDER = "citizens.waypoints.current-provider";
public static final String DEFAULT_POSE_SET = "citizens.commands.npc.pose.default-pose-set"; public static final String DEFAULT_POSE_SET = "citizens.commands.npc.pose.default-pose-set";
public static final String DELAY_TRIGGER_PROMPT = "citizens.editors.waypoints.triggers.delay.prompt"; public static final String DELAY_TRIGGER_PROMPT = "citizens.editors.waypoints.triggers.delay.prompt";

View File

@ -51,6 +51,7 @@ import net.citizensnpcs.api.event.NPCCollisionEvent;
import net.citizensnpcs.api.event.NPCPistonPushEvent; import net.citizensnpcs.api.event.NPCPistonPushEvent;
import net.citizensnpcs.api.event.NPCPushEvent; import net.citizensnpcs.api.event.NPCPushEvent;
import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.trait.trait.Equipment.EquipmentSlot;
import net.citizensnpcs.api.util.BoundingBox; import net.citizensnpcs.api.util.BoundingBox;
import net.citizensnpcs.api.util.Messaging; import net.citizensnpcs.api.util.Messaging;
import net.citizensnpcs.api.util.Placeholders; import net.citizensnpcs.api.util.Placeholders;
@ -300,6 +301,11 @@ public class Util {
return BEDROCK_NAME_PREFIX != null ? name.startsWith(BEDROCK_NAME_PREFIX) : false; return BEDROCK_NAME_PREFIX != null ? name.startsWith(BEDROCK_NAME_PREFIX) : false;
} }
public static boolean isEquippable(ItemStack stack, EquipmentSlot slot) {
return SUPPORTS_HAS_EQUIPPABLE && stack.hasItemMeta() && stack.getItemMeta().hasEquippable()
&& stack.getItemMeta().getEquippable().getSlot() == slot.toBukkit();
}
public static boolean isHorse(EntityType type) { public static boolean isHorse(EntityType type) {
String name = type.name(); String name = type.name();
return type == EntityType.HORSE || name.contains("_HORSE") || name.equals("DONKEY") || name.equals("MULE") return type == EntityType.HORSE || name.contains("_HORSE") || name.equals("DONKEY") || name.equals("MULE")
@ -622,6 +628,7 @@ public class Util {
private static String BEDROCK_NAME_PREFIX = "."; private static String BEDROCK_NAME_PREFIX = ".";
private static Scoreboard DUMMY_SCOREBOARD; private static Scoreboard DUMMY_SCOREBOARD;
private static boolean SUPPORTS_BUKKIT_GETENTITY = true; private static boolean SUPPORTS_BUKKIT_GETENTITY = true;
private static boolean SUPPORTS_HAS_EQUIPPABLE = false;
private static final DecimalFormat TWO_DIGIT_DECIMAL = new DecimalFormat(); private static final DecimalFormat TWO_DIGIT_DECIMAL = new DecimalFormat();
static { static {
@ -630,6 +637,11 @@ public class Util {
} catch (NullPointerException e) { } catch (NullPointerException e) {
} }
TWO_DIGIT_DECIMAL.setMaximumFractionDigits(2); TWO_DIGIT_DECIMAL.setMaximumFractionDigits(2);
try {
ItemMeta.class.getMethod("hasEquippable");
} catch (NoSuchMethodException e) {
SUPPORTS_HAS_EQUIPPABLE = false;
}
try { try {
Bukkit.class.getMethod("getEntity", UUID.class); Bukkit.class.getMethod("getEntity", UUID.class);
} catch (Exception e) { } catch (Exception e) {