diff --git a/main/src/main/java/net/citizensnpcs/Citizens.java b/main/src/main/java/net/citizensnpcs/Citizens.java index 28c69da0c..225bbb1f7 100644 --- a/main/src/main/java/net/citizensnpcs/Citizens.java +++ b/main/src/main/java/net/citizensnpcs/Citizens.java @@ -459,7 +459,6 @@ public class Citizens extends JavaPlugin implements CitizensPlugin { getServer().getPluginManager().callEvent(new CitizensPreReloadEvent()); templateRegistry = new TemplateRegistry(new File(this.getDataFolder(), "templates").toPath()); - saves.reloadFromSource(); saves.loadInto(npcRegistry); diff --git a/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java b/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java index f4afd203b..a288f3f3b 100644 --- a/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java +++ b/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java @@ -24,6 +24,7 @@ import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.Material; import org.bukkit.OfflinePlayer; +import org.bukkit.Rotation; import org.bukkit.Sound; import org.bukkit.World; import org.bukkit.block.Block; @@ -128,6 +129,7 @@ import net.citizensnpcs.trait.Gravity; import net.citizensnpcs.trait.HologramTrait; import net.citizensnpcs.trait.HomeTrait; import net.citizensnpcs.trait.HorseModifiers; +import net.citizensnpcs.trait.ItemFrameTrait; import net.citizensnpcs.trait.LookClose; import net.citizensnpcs.trait.MirrorTrait; import net.citizensnpcs.trait.MountTrait; @@ -959,7 +961,7 @@ public class NPCCommands { flags = "b", permission = "citizens.npc.endercrystal") @Requirements(ownership = true, selected = true, types = EntityType.ENDER_CRYSTAL) - public void endercrystal(CommandContext args, Player sender, NPC npc) throws CommandException { + public void endercrystal(CommandContext args, CommandSender sender, NPC npc) throws CommandException { if (args.hasFlag('b')) { EnderCrystalTrait trait = npc.getOrAddTrait(EnderCrystalTrait.class); boolean showing = !trait.isShowBase(); @@ -972,6 +974,42 @@ public class NPCCommands { throw new CommandException(); } + @Command( + aliases = { "npc" }, + usage = "itemframe --visible [true|false] --fixed [true|false] --rotation [rotation] --item [item]", + desc = "", + modifiers = { "itemframe" }, + min = 1, + max = 1, + flags = "", + permission = "citizens.npc.itemframe") + @Requirements(ownership = true, selected = true, types = EntityType.ITEM_FRAME) + public void endercrystal(CommandContext args, CommandSender sender, NPC npc, @Flag("visible") Boolean visible, + @Flag("fixed") Boolean fixed, @Flag("rotation") Rotation rotation, @Flag("item") ItemStack item) + throws CommandException { + ItemFrameTrait ift = npc.getOrAddTrait(ItemFrameTrait.class); + String msg = ""; + if (visible != null) { + ift.setVisible(visible); + msg += " " + Messaging.tr(Messages.ITEMFRAME_VISIBLE_SET, visible); + } + if (fixed != null) { + ift.setFixed(fixed); + msg += " " + Messaging.tr(Messages.ITEMFRAME_FIXED_SET, fixed); + } + if (item != null) { + ift.setItem(item); + msg += " " + Messaging.tr(Messages.ITEMFRAME_ITEM_SET, item); + } + if (rotation != null) { + ift.setRotation(rotation); + msg += " " + Messaging.tr(Messages.ITEMFRAME_ROTATION_SET, rotation); + } + if (msg.isEmpty()) + throw new CommandUsageException(); + Messaging.send(sender, msg.trim()); + } + @Command( aliases = { "npc" }, usage = "enderman -a(ngry)", @@ -981,7 +1019,7 @@ public class NPCCommands { min = 1, max = 2, permission = "citizens.npc.enderman") - public void enderman(CommandContext args, Player sender, NPC npc) throws CommandException { + public void enderman(CommandContext args, CommandSender sender, NPC npc) throws CommandException { if (args.hasFlag('a')) { boolean angry = npc.getOrAddTrait(EndermanTrait.class).toggleAngry(); Messaging.sendTr(sender, angry ? Messages.ENDERMAN_ANGRY_SET : Messages.ENDERMAN_ANGRY_UNSET, @@ -3149,17 +3187,20 @@ public class NPCCommands { min = 1, max = 2, permission = "citizens.npc.target") - public void target(CommandContext args, Player sender, NPC npc) { + public void target(CommandContext args, CommandSender sender, NPC npc) throws CommandUsageException { if (args.hasFlag('c')) { npc.getNavigator().cancelNavigation(); return; } - Entity toTarget = args.argsLength() < 2 ? sender : Bukkit.getPlayer(args.getString(1)); - if (toTarget == null) { + Entity toTarget = args.argsLength() < 2 && sender instanceof Player ? (Player) sender + : Bukkit.getPlayer(args.getString(1)); + if (toTarget == null && args.argsLength() == 2) { toTarget = Bukkit.getEntity(UUID.fromString(args.getString(1))); } if (toTarget != null) { npc.getNavigator().setTarget(toTarget, args.hasFlag('a')); + } else { + throw new CommandUsageException(); } } diff --git a/main/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java b/main/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java index d445e1520..bb60aea69 100644 --- a/main/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java +++ b/main/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java @@ -36,6 +36,7 @@ import net.citizensnpcs.trait.Gravity; import net.citizensnpcs.trait.HologramTrait; import net.citizensnpcs.trait.HomeTrait; import net.citizensnpcs.trait.HorseModifiers; +import net.citizensnpcs.trait.ItemFrameTrait; import net.citizensnpcs.trait.LookClose; import net.citizensnpcs.trait.MirrorTrait; import net.citizensnpcs.trait.MountTrait; @@ -89,6 +90,7 @@ public class CitizensTraitFactory implements TraitFactory { registerTrait(TraitInfo.create(HorseModifiers.class)); registerTrait(TraitInfo.create(HologramTrait.class)); registerTrait(TraitInfo.create(Inventory.class)); + registerTrait(TraitInfo.create(ItemFrameTrait.class)); registerTrait(TraitInfo.create(LookClose.class)); registerTrait(TraitInfo.create(PaintingTrait.class)); registerTrait(TraitInfo.create(MirrorTrait.class).optInToStats()); diff --git a/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java b/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java index 4ed1f73b8..247b12d4e 100644 --- a/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java +++ b/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java @@ -395,7 +395,7 @@ public class HologramTrait extends Trait { @Override public void render0(NPC base, Vector3d offset) { if (hologram.getEntity().getVehicle() == null) { - base.getEntity().addPassenger(hologram.getEntity()); + NMS.mount(base.getEntity(), hologram.getEntity()); } } } @@ -482,7 +482,7 @@ public class HologramTrait extends Trait { public void render0(NPC npc, Vector3d offset) { lastOffset = new Vector3d(offset); if (hologram.getEntity().getVehicle() == null) { - npc.getEntity().addPassenger(hologram.getEntity()); + NMS.mount(npc.getEntity(), hologram.getEntity()); } } } @@ -516,7 +516,7 @@ public class HologramTrait extends Trait { tf.getTranslation().y = (float) offset.y + 0.1f; disp.setTransformation(tf); if (hologram.getEntity().getVehicle() == null) { - base.getEntity().addPassenger(hologram.getEntity()); + NMS.mount(base.getEntity(), hologram.getEntity()); } } @@ -658,15 +658,17 @@ public class HologramTrait extends Trait { @Override protected NPC createNPC(Entity base, String name, Vector3d offset) { - NPC npc = registry.createNPC(EntityType.TEXT_DISPLAY, ""); - npc.data().set(NPC.Metadata.NAMEPLATE_VISIBLE, false); - npc.data().set(NPC.Metadata.TEXT_DISPLAY_COMPONENT, Messaging.minecraftComponentFromRawMessage(name)); - return npc; + NPC hologram = registry.createNPC(EntityType.TEXT_DISPLAY, ""); + hologram.data().set(NPC.Metadata.NAMEPLATE_VISIBLE, false); + hologram.data().set(NPC.Metadata.TEXT_DISPLAY_COMPONENT, Messaging.minecraftComponentFromRawMessage(name)); + return hologram; } @Override public void render0(NPC base, Vector3d offset) { TextDisplay disp = (TextDisplay) hologram.getEntity(); + disp.setInterpolationDelay(0); + disp.setInterpolationDuration(0); disp.setBillboard(Billboard.CENTER); Transformation tf = disp.getTransformation(); tf.getTranslation().y = (float) offset.y + 0.2f; @@ -675,7 +677,7 @@ public class HologramTrait extends Trait { disp.setBackgroundColor(color); } if (hologram.getEntity().getVehicle() == null) { - base.getEntity().addPassenger(hologram.getEntity()); + NMS.mount(base.getEntity(), hologram.getEntity()); } } @@ -688,7 +690,7 @@ public class HologramTrait extends Trait { this.text = Placeholders.replace(raw, null, npc); if (hologram == null) return; - npc.data().set(NPC.Metadata.TEXT_DISPLAY_COMPONENT, Messaging.minecraftComponentFromRawMessage(text)); + hologram.data().set(NPC.Metadata.TEXT_DISPLAY_COMPONENT, Messaging.minecraftComponentFromRawMessage(text)); } } diff --git a/main/src/main/java/net/citizensnpcs/trait/ItemFrameTrait.java b/main/src/main/java/net/citizensnpcs/trait/ItemFrameTrait.java new file mode 100644 index 000000000..f9e064dfe --- /dev/null +++ b/main/src/main/java/net/citizensnpcs/trait/ItemFrameTrait.java @@ -0,0 +1,83 @@ +package net.citizensnpcs.trait; + +import org.bukkit.Rotation; +import org.bukkit.entity.ItemFrame; +import org.bukkit.inventory.ItemStack; + +import net.citizensnpcs.api.persistence.Persist; +import net.citizensnpcs.api.trait.Trait; +import net.citizensnpcs.api.trait.TraitName; + +/** + * Persists {@link ItemFrame} metadata. + */ +@TraitName("itemframe") +public class ItemFrameTrait extends Trait { + @Persist + private Boolean fixed; + @Persist + private ItemStack item; + @Persist + private Rotation rotation = Rotation.NONE; + @Persist + private boolean visible = true; + + public ItemFrameTrait() { + super("itemframe"); + } + + public Boolean getFixed() { + return fixed; + } + + public ItemStack getItem() { + return item; + } + + public Rotation getRotation() { + return rotation; + } + + public boolean isVisible() { + return visible; + } + + @Override + public void onSpawn() { + if (npc.getEntity() instanceof ItemFrame) { + ItemFrame frame = (ItemFrame) npc.getEntity(); + if (rotation != null) { + frame.setRotation(rotation); + } + if (item != null) { + frame.setItem(item); + } + if (fixed != null) { + frame.setFixed(fixed); + } else { + frame.setFixed(npc.isProtected()); + } + frame.setVisible(visible); + } + } + + public void setFixed(boolean fixed) { + this.fixed = fixed; + onSpawn(); + } + + public void setItem(ItemStack item) { + this.item = item; + onSpawn(); + } + + public void setRotation(Rotation rot) { + rotation = rot; + onSpawn(); + } + + public void setVisible(boolean visible) { + this.visible = visible; + onSpawn(); + } +} diff --git a/main/src/main/java/net/citizensnpcs/util/Messages.java b/main/src/main/java/net/citizensnpcs/util/Messages.java index 5f1943c27..b4c36c84a 100644 --- a/main/src/main/java/net/citizensnpcs/util/Messages.java +++ b/main/src/main/java/net/citizensnpcs/util/Messages.java @@ -204,6 +204,10 @@ public class Messages { public static final String INVALID_TROPICALFISH_PATTERN = "citizens.commands.npc.tropicalfish.invalid-pattern"; public static final String INVALID_VILLAGER_TYPE = "citizens.commands.npc.villager.invalid-type"; public static final String ITEM_SET = "citizens.commands.npc.item.item-set"; + public static final String ITEMFRAME_FIXED_SET = "citizens.commands.npc.itemframe.fixed-set"; + public static final String ITEMFRAME_ITEM_SET = "citizens.commands.npc.itemframe.item-set"; + public static final String ITEMFRAME_ROTATION_SET = "citizens.commands.npc.itemframe.rotation-set"; + public static final String ITEMFRAME_VISIBLE_SET = "citizens.commands.npc.itemframe.visible-set"; public static final String KNOCKBACK_SET = "citizens.commands.npc.knockback.set"; public static final String KNOCKBACK_UNSET = "citizens.commands.npc.knockback.unset"; public static final String LEASHABLE_SET = "citizens.commands.npc.leashable.set"; diff --git a/main/src/main/resources/en.json b/main/src/main/resources/en.json index 402d25168..2245f67db 100644 --- a/main/src/main/resources/en.json +++ b/main/src/main/resources/en.json @@ -83,6 +83,11 @@ "citizens.commands.npc.chunkload.unset" : "[[{0}]] will no longer force chunks to be loaded.", "citizens.commands.npc.collidable.description" : "Toggles an NPC''s collidability", "citizens.commands.npc.collidable.help" : "", + "citizens.commands.npc.itemframe.description" : "Sets itemframe modifiers", + "citizens.commands.npc.itemframe.rotation-set" : "Rotation set to [[{0}]]", + "citizens.commands.npc.itemframe.item-set" : "Item set to [[{0}]]", + "citizens.commands.npc.itemframe.fixed-set" : "Fixed (whether the item can be rotated) set to [[{0}]]", + "citizens.commands.npc.itemframe.visible-set" : "Visible set to [[{0}]]", "citizens.commands.npc.collidable.set" : "[[{0}]] will now collide with entities.", "citizens.commands.npc.collidable.unset" : "[[{0}]] will no longer collide with entities.", "citizens.commands.npc.command.all-players-forgotten" : "[[{0}]] forgot all player command history.", diff --git a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/entity/nonliving/TextDisplayController.java b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/entity/nonliving/TextDisplayController.java index 96a2162d2..058c9c801 100644 --- a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/entity/nonliving/TextDisplayController.java +++ b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/entity/nonliving/TextDisplayController.java @@ -16,7 +16,6 @@ import net.citizensnpcs.npc.ai.NPCHolder; import net.citizensnpcs.util.Util; import net.minecraft.core.PositionImpl; import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.tags.TagKey; import net.minecraft.world.entity.Display.TextDisplay; @@ -114,9 +113,8 @@ public class TextDisplayController extends MobEntityController { super.tick(); if (npc != null) { npc.update(); - Component component = npc.data().get(NPC.Metadata.TEXT_DISPLAY_COMPONENT); - if (component != null) { - setText(component); + if (npc.data().has(NPC.Metadata.TEXT_DISPLAY_COMPONENT)) { + setText(npc.data().get(NPC.Metadata.TEXT_DISPLAY_COMPONENT)); npc.data().remove(NPC.Metadata.TEXT_DISPLAY_COMPONENT); } } diff --git a/v1_20_R3/src/main/java/net/citizensnpcs/nms/v1_20_R3/entity/nonliving/TextDisplayController.java b/v1_20_R3/src/main/java/net/citizensnpcs/nms/v1_20_R3/entity/nonliving/TextDisplayController.java index b8979b926..164e26eee 100644 --- a/v1_20_R3/src/main/java/net/citizensnpcs/nms/v1_20_R3/entity/nonliving/TextDisplayController.java +++ b/v1_20_R3/src/main/java/net/citizensnpcs/nms/v1_20_R3/entity/nonliving/TextDisplayController.java @@ -14,7 +14,6 @@ import net.citizensnpcs.npc.CitizensNPC; import net.citizensnpcs.npc.ai.NPCHolder; import net.citizensnpcs.util.Util; import net.minecraft.nbt.CompoundTag; -import net.minecraft.network.chat.Component; import net.minecraft.server.level.ServerLevel; import net.minecraft.tags.TagKey; import net.minecraft.world.entity.Display.TextDisplay; @@ -104,9 +103,8 @@ public class TextDisplayController extends MobEntityController { super.tick(); if (npc != null) { npc.update(); - Component component = npc.data().get(NPC.Metadata.TEXT_DISPLAY_COMPONENT); - if (component != null) { - setText(component); + if (npc.data().has(NPC.Metadata.TEXT_DISPLAY_COMPONENT)) { + setText(npc.data().get(NPC.Metadata.TEXT_DISPLAY_COMPONENT)); npc.data().remove(NPC.Metadata.TEXT_DISPLAY_COMPONENT); } }