diff --git a/main/src/main/java/net/citizensnpcs/Citizens.java b/main/src/main/java/net/citizensnpcs/Citizens.java index aa23f6286..57d809045 100644 --- a/main/src/main/java/net/citizensnpcs/Citizens.java +++ b/main/src/main/java/net/citizensnpcs/Citizens.java @@ -28,7 +28,6 @@ import com.comphenix.protocol.ProtocolLibrary; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; import com.google.common.collect.Maps; -import com.google.common.io.Files; import com.mojang.authlib.GameProfile; import ch.ethz.globis.phtree.PhTreeHelper; @@ -82,8 +81,6 @@ import net.citizensnpcs.npc.profile.ProfileFetcher; import net.citizensnpcs.npc.skin.Skin; import net.citizensnpcs.trait.ClickRedirectTrait; import net.citizensnpcs.trait.CommandTrait; -import net.citizensnpcs.trait.HologramTrait; -import net.citizensnpcs.trait.ScriptTrait; import net.citizensnpcs.trait.ShopTrait; import net.citizensnpcs.util.Messages; import net.citizensnpcs.util.NMS; @@ -98,6 +95,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin { private final CommandManager commands = new CommandManager(); private Settings config; private boolean enabled; + private Locale locale; private LocationLookup locationLookup; private final NMSHelper nmsHelper = new NMSHelper() { private boolean SUPPORT_OWNER_PROFILE = true; @@ -185,11 +183,14 @@ public class Citizens extends JavaPlugin implements CitizensPlugin { if (type.equalsIgnoreCase("nbt")) { saves = new NBTStorage(new File(folder, Setting.STORAGE_FILE.asString()), "Citizens NPC Storage"); } + if (saves == null) { saves = new YamlStorage(new File(folder, Setting.STORAGE_FILE.asString()), "Citizens NPC Storage"); } + if (!saves.load()) return null; + return SimpleNPCDataStore.create(saves); } @@ -282,11 +283,6 @@ public class Citizens extends JavaPlugin implements CitizensPlugin { return getClassLoader(); } - @Override - public File getScriptFolder() { - return new File(getDataFolder(), "scripts"); - } - public StoredShops getShops() { return shops; } @@ -552,6 +548,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin { } } Translator.setInstance(new File(getDataFolder(), "lang"), locale); + this.locale = locale; } private void startMetrics() { @@ -562,16 +559,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin { return 0; return Iterables.size(npcRegistry); })); - metrics.addCustomChart(new Metrics.AdvancedPie("hologram_direction", () -> { - Map res = Maps.newHashMap(); - for (NPC npc : npcRegistry) { - HologramTrait hg = npc.getTraitNullable(HologramTrait.class); - if (hg != null) { - res.put(hg.getDirection().name(), res.getOrDefault(hg.getDirection().name(), 0) + 1); - } - } - return res; - })); + metrics.addCustomChart(new Metrics.SimplePie("locale", () -> locale.toString())); metrics.addCustomChart(new Metrics.AdvancedPie("traits", () -> { Map res = Maps.newHashMap(); for (NPC npc : npcRegistry) { @@ -583,19 +571,6 @@ public class Citizens extends JavaPlugin implements CitizensPlugin { } return res; })); - metrics.addCustomChart(new Metrics.AdvancedPie("script_extensions", () -> { - Map res = Maps.newHashMap(); - for (NPC npc : npcRegistry) { - ScriptTrait trait = npc.getTraitNullable(ScriptTrait.class); - if (trait != null) { - for (String file : trait.getScripts()) { - String ext = Files.getFileExtension(file); - res.put(ext, res.getOrDefault(ext, 0) + 1); - } - } - } - return res; - })); } catch (Exception e) { Messaging.logTr(Messages.METRICS_ERROR_NOTIFICATION, e.getMessage()); } @@ -630,7 +605,8 @@ public class Citizens extends JavaPlugin implements CitizensPlugin { @Override public void run() { Plugin plib = Bukkit.getPluginManager().getPlugin("ProtocolLib"); - if (plib != null && plib.isEnabled() && ProtocolLibrary.getProtocolManager() != null) { + if (Setting.HOOK_PROTOCOLLIB.asBoolean() && plib != null && plib.isEnabled() + && ProtocolLibrary.getProtocolManager() != null) { try { protocolListener = new ProtocolLibListener(Citizens.this); } catch (Throwable t) { diff --git a/main/src/main/java/net/citizensnpcs/EventListen.java b/main/src/main/java/net/citizensnpcs/EventListen.java index 5638296c6..77b6aa28c 100644 --- a/main/src/main/java/net/citizensnpcs/EventListen.java +++ b/main/src/main/java/net/citizensnpcs/EventListen.java @@ -232,6 +232,7 @@ public class EventListen implements Listener { public void onChunkUnload(final ChunkUnloadEvent event) { if (chunkEventListener != null) return; + unloadNPCs(event, Arrays.asList(event.getChunk().getEntities())); } @@ -401,6 +402,7 @@ public class EventListen implements Listener { ChunkCoord coord = new ChunkCoord(event.getSpawnLocation()); if (toRespawn.containsEntry(coord, event.getNPC())) return; + Messaging.debug("Stored", event.getNPC(), "for respawn from NPCNeedsRespawnEvent"); toRespawn.put(coord, event.getNPC()); } diff --git a/main/src/main/java/net/citizensnpcs/ProtocolLibListener.java b/main/src/main/java/net/citizensnpcs/ProtocolLibListener.java index 39ca5d48c..42dfe2cbc 100644 --- a/main/src/main/java/net/citizensnpcs/ProtocolLibListener.java +++ b/main/src/main/java/net/citizensnpcs/ProtocolLibListener.java @@ -74,6 +74,7 @@ public class ProtocolLibListener implements Listener { NPC npc = getNPCFromPacket(event); if (npc == null || !npc.data().has(NPC.Metadata.HOLOGRAM_LINE_SUPPLIER)) return; + Function hvs = npc.data().get(NPC.Metadata.HOLOGRAM_LINE_SUPPLIER); int version = manager.getProtocolVersion(event.getPlayer()); PacketContainer packet = event.getPacket(); @@ -81,6 +82,7 @@ public class ProtocolLibListener implements Listener { List wwo = packet.getWatchableCollectionModifier().readSafely(0); if (wwo == null) return; + boolean delta = false; String text = hvs.apply(event.getPlayer()); for (WrappedWatchableObject wo : wwo) { @@ -94,6 +96,7 @@ public class ProtocolLibListener implements Listener { delta = true; break; } + if (delta) { packet.getWatchableCollectionModifier().write(0, wwo); } @@ -101,6 +104,7 @@ public class ProtocolLibListener implements Listener { List wdvs = packet.getDataValueCollectionModifier().readSafely(0); if (wdvs == null) return; + boolean delta = false; String text = hvs.apply(event.getPlayer()); for (WrappedDataValue wdv : wdvs) { @@ -109,6 +113,7 @@ public class ProtocolLibListener implements Listener { wdv.setValue(Optional.of(Messaging.minecraftComponentFromRawMessage(text))); break; } + if (delta) { packet.getDataValueCollectionModifier().write(0, wdvs); } @@ -138,6 +143,7 @@ public class ProtocolLibListener implements Listener { PlayerInfoData npcInfo = list.get(i); if (npcInfo == null) continue; + MirrorTrait trait = mirrorTraits.get(npcInfo.getProfile().getUUID()); if (trait == null || !trait.isMirroring(event.getPlayer())) continue; @@ -239,6 +245,7 @@ public class ProtocolLibListener implements Listener { Integer id = packet.getIntegers().readSafely(0); if (id == null) return null; + entity = manager.getEntityFromID(event.getPlayer().getWorld(), id); } catch (FieldAccessException | IllegalArgumentException ex) { if (!LOGGED_ERROR) { @@ -271,6 +278,7 @@ public class ProtocolLibListener implements Listener { rotationTraits.put(event.getNPC().getEntity().getEntityId(), event.getNPC().getTraitNullable(RotationTrait.class)); } + if (event.getNPC().hasTrait(MirrorTrait.class) && event.getNPC().getOrAddTrait(MobType.class).getType() == EntityType.PLAYER) { mirrorTraits.put(event.getNPC().getEntity().getUniqueId(), diff --git a/main/src/main/java/net/citizensnpcs/Settings.java b/main/src/main/java/net/citizensnpcs/Settings.java index 2382258f0..cd47fd3d3 100644 --- a/main/src/main/java/net/citizensnpcs/Settings.java +++ b/main/src/main/java/net/citizensnpcs/Settings.java @@ -180,6 +180,7 @@ public class Settings { "npc.hologram.always-update-position", false), HOLOGRAM_UPDATE_RATE("How often to update hologram names (including placeholders)", "npc.hologram.update-rate-ticks", "npc.hologram.update-rate", "1s"), + HOOK_PROTOCOLLIB("Whether to hook into ProtocolLib", "general.interop.protocollib", true), INITIAL_PLAYER_JOIN_SKIN_PACKET_DELAY("How long to wait before sending skins to joined players", "npc.skins.player-join-update-delay-ticks", "npc.skins.player-join-update-delay", "1s"), KEEP_CHUNKS_LOADED("Whether to keep NPC chunks loaded", "npc.chunks.always-keep-loaded", false), diff --git a/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java b/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java index 594524426..c0e311304 100644 --- a/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java +++ b/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java @@ -123,7 +123,6 @@ import net.citizensnpcs.trait.FollowTrait; import net.citizensnpcs.trait.GameModeTrait; import net.citizensnpcs.trait.Gravity; import net.citizensnpcs.trait.HologramTrait; -import net.citizensnpcs.trait.HologramTrait.HologramDirection; import net.citizensnpcs.trait.HomeTrait; import net.citizensnpcs.trait.HorseModifiers; import net.citizensnpcs.trait.LookClose; @@ -138,7 +137,6 @@ import net.citizensnpcs.trait.Powered; import net.citizensnpcs.trait.RabbitType; import net.citizensnpcs.trait.RotationTrait; import net.citizensnpcs.trait.ScoreboardTrait; -import net.citizensnpcs.trait.ScriptTrait; import net.citizensnpcs.trait.SheepTrait; import net.citizensnpcs.trait.ShopTrait; import net.citizensnpcs.trait.ShopTrait.NPCShop; @@ -995,15 +993,15 @@ public class NPCCommands { @Command( aliases = { "npc" }, - usage = "follow (player name|NPC id) (-p[rotect]) (--margin [margin])", + usage = "follow (player name|NPC id) (-p[rotect]) (--margin [margin]) (--enable [boolean])", desc = "Toggles NPC following you", flags = "p", modifiers = { "follow" }, min = 1, max = 2, permission = "citizens.npc.follow") - public void follow(CommandContext args, CommandSender sender, NPC npc, @Flag("margin") Double margin) - throws CommandException { + public void follow(CommandContext args, CommandSender sender, NPC npc, @Flag("margin") Double margin, + @Flag("enable") Boolean explicit) throws CommandException { boolean protect = args.hasFlag('p'); FollowTrait trait = npc.getOrAddTrait(FollowTrait.class); if (margin != null) { @@ -1035,7 +1033,8 @@ public class NPCCommands { args.getString(1)); return; } - boolean following = !trait.isEnabled(); + + boolean following = explicit == null ? !trait.isEnabled() : explicit; trait.follow(following ? player.getPlayer() : null); Messaging.sendTr(sender, following ? Messages.FOLLOW_SET : Messages.FOLLOW_UNSET, npc.getName(), player.getName()); @@ -1129,17 +1128,15 @@ public class NPCCommands { @Command( aliases = { "npc" }, - usage = "hologram add [text] | set [line #] [text] | remove [line #] | clear | lineheight [height] | direction [up|down] | margintop [line #] [margin] | marginbottom [line #] [margin]", + usage = "hologram add [text] | set [line #] [text] | remove [line #] | clear | lineheight [height] | margintop [line #] [margin] | marginbottom [line #] [margin]", desc = "Controls NPC hologram text", modifiers = { "hologram" }, min = 1, max = -1, permission = "citizens.npc.hologram") - public void hologram(CommandContext args, CommandSender sender, NPC npc, - @Arg( - value = 1, - completions = { "add", "set", "remove", "clear", "lineheight", "direction", "margintop", - "marginbottom" }) String action) + public void hologram(CommandContext args, CommandSender sender, NPC npc, @Arg( + value = 1, + completions = { "add", "set", "remove", "clear", "lineheight", "margintop", "marginbottom" }) String action) throws CommandException { HologramTrait trait = npc.getOrAddTrait(HologramTrait.class); if (args.argsLength() == 1) { @@ -1194,11 +1191,6 @@ public class NPCCommands { } else if (action.equalsIgnoreCase("lineheight")) { trait.setLineHeight(args.getDouble(2)); Messaging.sendTr(sender, Messages.HOLOGRAM_LINE_HEIGHT_SET, args.getDouble(2)); - } else if (action.equalsIgnoreCase("direction")) { - HologramDirection direction = args.getString(2).equalsIgnoreCase("up") ? HologramDirection.BOTTOM_UP - : HologramDirection.TOP_DOWN; - trait.setDirection(direction); - Messaging.sendTr(sender, Messages.HOLOGRAM_DIRECTION_SET, Util.prettyEnum(direction)); } else if (action.equalsIgnoreCase("margintop")) { if (args.argsLength() == 2) { throw new CommandException(Messages.HOLOGRAM_INVALID_LINE); @@ -1385,20 +1377,24 @@ public class NPCCommands { throws CommandException { EntityType type = npc.getOrAddTrait(MobType.class).getType(); if (!type.name().contains("ITEM_FRAME") && !type.name().contains("ITEM_DISPLAY") - && type != EntityType.DROPPED_ITEM && type != EntityType.FALLING_BLOCK) + && !type.name().contains("BLOCK_DISPLAY") && type != EntityType.DROPPED_ITEM + && type != EntityType.FALLING_BLOCK) throw new CommandException(CommandMessages.REQUIREMENTS_INVALID_MOB_TYPE, Util.prettyEnum(type)); ItemStack stack = args.hasFlag('h') ? ((Player) sender).getItemInHand() : new ItemStack(mat, 1); if (modify != null) { stack = Util.parseItemStack(stack, modify); } + if (mat == null && !args.hasFlag('h')) throw new CommandException(Messages.UNKNOWN_MATERIAL); ItemStack fstack = stack.clone(); npc.setItemProvider(() -> fstack); + if (npc.isSpawned()) { npc.despawn(DespawnReason.PENDING_RESPAWN); npc.spawn(npc.getStoredLocation(), SpawnReason.RESPAWN); } + Messaging.sendTr(sender, Messages.ITEM_SET, Util.prettyEnum(stack.getType())); } @@ -2596,34 +2592,6 @@ public class NPCCommands { } } - @Command( - aliases = { "npc" }, - usage = "script --add [files] --remove [files]", - desc = "Controls an NPC's scripts", - modifiers = { "script" }, - min = 1, - max = 1, - permission = "citizens.npc.script") - public void script(CommandContext args, CommandSender sender, NPC npc, @Flag("add") String add, - @Flag("remove") String remove) { - ScriptTrait trait = npc.getOrAddTrait(ScriptTrait.class); - if (add != null) { - List files = new ArrayList(); - for (String file : add.split(",")) { - if (!trait.validateFile(file)) { - Messaging.sendErrorTr(sender, Messages.INVALID_SCRIPT_FILE, file); - return; - } - files.add(file); - } - trait.addScripts(files); - } - if (remove != null) { - trait.removeScripts(Arrays.asList(remove.split(","))); - } - Messaging.sendTr(sender, Messages.CURRENT_SCRIPTS, npc.getName(), Joiner.on("]],[[ ").join(trait.getScripts())); - } - @Command( aliases = { "npc" }, usage = "select|sel [id|name] (--range range) (--registry [name])", diff --git a/main/src/main/java/net/citizensnpcs/npc/CitizensNPC.java b/main/src/main/java/net/citizensnpcs/npc/CitizensNPC.java index 790e99911..e1e141b69 100644 --- a/main/src/main/java/net/citizensnpcs/npc/CitizensNPC.java +++ b/main/src/main/java/net/citizensnpcs/npc/CitizensNPC.java @@ -343,6 +343,7 @@ public class CitizensNPC extends AbstractNPC { Messaging.debug("Retrying spawn of", this, "later, SpawnReason." + reason + ". Was loaded", loaded, "is loaded", Util.isLoaded(at)); } + // we need to wait before trying to spawn entityController.remove(); Bukkit.getPluginManager().callEvent(new NPCNeedsRespawnEvent(this, at)); diff --git a/main/src/main/java/net/citizensnpcs/npc/CitizensNPCRegistry.java b/main/src/main/java/net/citizensnpcs/npc/CitizensNPCRegistry.java index 4323e3f86..f0950d1c1 100644 --- a/main/src/main/java/net/citizensnpcs/npc/CitizensNPCRegistry.java +++ b/main/src/main/java/net/citizensnpcs/npc/CitizensNPCRegistry.java @@ -87,7 +87,8 @@ public class CitizensNPCRegistry implements NPCRegistry { public NPC createNPCUsingItem(EntityType type, String name, ItemStack item) { NPC npc = createNPC(type, name); if (type == EntityType.DROPPED_ITEM || type == EntityType.FALLING_BLOCK || type == EntityType.ITEM_FRAME - || type.name().equals("GLOW_ITEM_FRAME") || type.name().equals("ITEM_DISPLAY")) { + || type.name().equals("GLOW_ITEM_FRAME") || type.name().equals("ITEM_DISPLAY") + || type.name().equals("BLOCK_DISPLAY")) { npc.data().set(NPC.Metadata.ITEM_AMOUNT, item.getAmount()); npc.data().set(NPC.Metadata.ITEM_ID, item.getType().name()); npc.data().set(NPC.Metadata.ITEM_DATA, item.getData().getData()); diff --git a/main/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java b/main/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java index b02552ee1..12461f341 100644 --- a/main/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java +++ b/main/src/main/java/net/citizensnpcs/npc/CitizensTraitFactory.java @@ -49,7 +49,6 @@ import net.citizensnpcs.trait.RabbitType; import net.citizensnpcs.trait.RotationTrait; import net.citizensnpcs.trait.Saddle; import net.citizensnpcs.trait.ScoreboardTrait; -import net.citizensnpcs.trait.ScriptTrait; import net.citizensnpcs.trait.SheepTrait; import net.citizensnpcs.trait.SitTrait; import net.citizensnpcs.trait.SkinLayers; @@ -117,7 +116,6 @@ public class CitizensTraitFactory implements TraitFactory { registerTrait(TraitInfo.create(RotationTrait.class)); registerTrait(TraitInfo.create(Saddle.class)); registerTrait(TraitInfo.create(ScoreboardTrait.class)); - registerTrait(TraitInfo.create(ScriptTrait.class).optInToStats()); registerTrait(TraitInfo.create(SitTrait.class).optInToStats()); registerTrait(TraitInfo.create(SleepTrait.class)); registerTrait(TraitInfo.create(SheepTrait.class)); diff --git a/main/src/main/java/net/citizensnpcs/trait/DropsTrait.java b/main/src/main/java/net/citizensnpcs/trait/DropsTrait.java index deaefb888..031c93db3 100644 --- a/main/src/main/java/net/citizensnpcs/trait/DropsTrait.java +++ b/main/src/main/java/net/citizensnpcs/trait/DropsTrait.java @@ -45,6 +45,7 @@ public class DropsTrait extends Trait { public void onNPCDeath(NPCDeathEvent event) { if (!event.getNPC().equals(npc)) return; + Random random = Util.getFastRandom(); for (ItemDrop drop : drops) { if (random.nextDouble() < drop.chance) { diff --git a/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java b/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java index e65bd2dac..a5b5f40e1 100644 --- a/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java +++ b/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java @@ -43,8 +43,6 @@ import net.citizensnpcs.util.Util; public class HologramTrait extends Trait { private Location currentLoc; private BiFunction customHologramSupplier; - @Persist - private HologramDirection direction = HologramDirection.BOTTOM_UP; private double lastEntityHeight = 0; private boolean lastNameplateVisible; @Persist @@ -110,10 +108,7 @@ public class HologramTrait extends Trait { hologramNPC.addTrait(PacketNPC.class); } - hologramNPC.spawn(currentLoc.clone().add(0, - getEntityHeight() - + (direction == HologramDirection.BOTTOM_UP ? heightOffset : getMaxHeight() - heightOffset), - 0)); + hologramNPC.spawn(currentLoc.clone().add(0, getEntityHeight() + heightOffset, 0)); if (useDisplayEntities) { ((Interaction) hologramNPC.getEntity()).setInteractionWidth(0); @@ -150,13 +145,6 @@ public class HologramTrait extends Trait { return hologramNPC; } - /** - * @return The direction that hologram lines are displayed in - */ - public HologramDirection getDirection() { - return direction; - } - private double getEntityHeight() { return NMS.getHeight(npc.getEntity()); } @@ -195,10 +183,6 @@ public class HologramTrait extends Trait { return Lists.transform(lines, l -> l.text); } - private double getMaxHeight() { - return (lastNameplateVisible ? getLineHeight() : 0) + getHeight(lines.size() - 1); - } - /** * Note: this is implementation-specific and may be removed at a later date. */ @@ -349,8 +333,7 @@ public class HologramTrait extends Trait { } if (updatePosition && !useDisplayEntities) { - Location tp = npcLoc.clone().add(0, lastEntityHeight - + (direction == HologramDirection.BOTTOM_UP ? getHeight(i) : getMaxHeight() - getHeight(i)), 0); + Location tp = npcLoc.clone().add(0, lastEntityHeight + getHeight(i), 0); hologramNPC.teleport(tp, TeleportCause.PLUGIN); } @@ -385,17 +368,6 @@ public class HologramTrait extends Trait { } } - /** - * @see #getDirection() - * @param direction - * The new direction - */ - public void setDirection(HologramDirection direction) { - this.direction = direction; - - reloadLineHolograms(); - } - /** * Sets the hologram line at a specific index * @@ -461,11 +433,6 @@ public class HologramTrait extends Trait { reloadLineHolograms(); } - public enum HologramDirection { - BOTTOM_UP, - TOP_DOWN; - } - private class HologramLine implements Function { NPC hologram; double mb, mt; diff --git a/main/src/main/java/net/citizensnpcs/trait/RotationTrait.java b/main/src/main/java/net/citizensnpcs/trait/RotationTrait.java index a599c09c7..2d72164db 100644 --- a/main/src/main/java/net/citizensnpcs/trait/RotationTrait.java +++ b/main/src/main/java/net/citizensnpcs/trait/RotationTrait.java @@ -109,6 +109,7 @@ public class RotationTrait extends Trait { PacketRotationSession session = itr.next(); if (ran.contains(session)) continue; + ran.add(session); session.run(npc.getEntity()); if (!session.isActive()) { @@ -192,6 +193,7 @@ public class RotationTrait extends Trait { if (triple == null) { triple = new PacketRotationTriple(entity); } + session.run(triple); if (!session.isActive()) { triple = null; diff --git a/main/src/main/java/net/citizensnpcs/trait/ScriptTrait.java b/main/src/main/java/net/citizensnpcs/trait/ScriptTrait.java deleted file mode 100644 index 0d9c5bcb9..000000000 --- a/main/src/main/java/net/citizensnpcs/trait/ScriptTrait.java +++ /dev/null @@ -1,143 +0,0 @@ -package net.citizensnpcs.trait; - -import java.io.File; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; - -import org.bukkit.Bukkit; -import org.bukkit.plugin.java.JavaPlugin; - -import net.citizensnpcs.Citizens; -import net.citizensnpcs.api.CitizensAPI; -import net.citizensnpcs.api.persistence.Persist; -import net.citizensnpcs.api.scripting.CompileCallback; -import net.citizensnpcs.api.scripting.Script; -import net.citizensnpcs.api.scripting.ScriptCompiler; -import net.citizensnpcs.api.scripting.ScriptFactory; -import net.citizensnpcs.api.trait.Trait; -import net.citizensnpcs.api.trait.TraitName; -import net.citizensnpcs.api.util.DataKey; - -/** - * Stores a list of scripts, which are pieces of arbitrary code that can be run every tick. - * - * @see ScriptCompiler - */ -@TraitName("scripttrait") -public class ScriptTrait extends Trait { - @Persist - private final List files = new ArrayList(); - private final List runnableScripts = new ArrayList(); - - public ScriptTrait() { - super("scripttrait"); - } - - /** - * Add and load all given script file names - * - * @see #loadScript(String) - */ - public void addScripts(List scripts) { - for (String f : scripts) { - if (!files.contains(f) && validateFile(f)) { - loadScript(f); - files.add(f); - } - } - } - - public List getScripts() { - return files; - } - - @Override - public void load(DataKey key) { - for (String file : files) { - if (validateFile(file)) { - loadScript(file); - } - } - } - - /** - * Compile and load a script given by the file name. - * - * @param file - * the script file name relative to the script folder - * @see Citizens#getScriptFolder() - */ - public void loadScript(final String file) { - File f = new File(JavaPlugin.getPlugin(Citizens.class).getScriptFolder(), file); - CitizensAPI.getScriptCompiler().compile(f).cache(true).withCallback(new CompileCallback() { - @Override - public void onScriptCompiled(String sourceDescriptor, ScriptFactory compiled) { - final Script newInstance = compiled.newInstance(); - Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() { - @Override - public void run() { - try { - newInstance.invoke("onLoad", npc); - } catch (RuntimeException e) { - if (!(e.getCause() instanceof NoSuchMethodException)) { - throw e; - } - } - runnableScripts.add(new RunnableScript(newInstance, file)); - } - }); - } - }).beginWithFuture(); - } - - /** - * Removes the given script file names. - */ - public void removeScripts(List scripts) { - files.removeAll(scripts); - Iterator itr = runnableScripts.iterator(); - while (itr.hasNext()) { - if (scripts.remove(itr.next().file)) { - itr.remove(); - } - } - } - - @Override - public void run() { - Iterator itr = runnableScripts.iterator(); - while (itr.hasNext()) { - try { - itr.next().script.invoke("run", npc); - } catch (RuntimeException e) { - if (e.getCause() instanceof NoSuchMethodException) { - itr.remove(); - } else { - throw e; - } - } - } - } - - /** - * Whether the file exists and can be compiled by the system {@link ScriptCompiler}. - */ - public boolean validateFile(String file) { - File f = new File(JavaPlugin.getPlugin(Citizens.class).getScriptFolder(), file); - if (!f.exists() || !f.getParentFile().equals(JavaPlugin.getPlugin(Citizens.class).getScriptFolder())) { - return false; - } - return CitizensAPI.getScriptCompiler().canCompile(f); - } - - private static class RunnableScript { - String file; - Script script; - - public RunnableScript(Script script, String file) { - this.script = script; - this.file = file; - } - } -} diff --git a/main/src/main/java/net/citizensnpcs/trait/versioned/WardenTrait.java b/main/src/main/java/net/citizensnpcs/trait/versioned/WardenTrait.java index f6ab0405f..0136a583f 100644 --- a/main/src/main/java/net/citizensnpcs/trait/versioned/WardenTrait.java +++ b/main/src/main/java/net/citizensnpcs/trait/versioned/WardenTrait.java @@ -7,6 +7,7 @@ import org.bukkit.Bukkit; import org.bukkit.command.CommandSender; import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; +import org.bukkit.entity.Pose; import org.bukkit.entity.Warden; import com.google.common.collect.Maps; @@ -21,6 +22,8 @@ import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.trait.Trait; import net.citizensnpcs.api.trait.TraitName; import net.citizensnpcs.api.util.Messaging; +import net.citizensnpcs.util.Messages; +import net.citizensnpcs.util.NMS; @TraitName("wardentrait") public class WardenTrait extends Trait { @@ -46,16 +49,16 @@ public class WardenTrait extends Trait { @Command( aliases = { "npc" }, - usage = "warden anger [entity uuid/player name] [anger]", + usage = "warden dig|emerge|roar|anger [entity uuid/player name] [anger]", desc = "Sets warden modifiers", modifiers = { "warden" }, min = 1, max = 4, permission = "citizens.npc.warden") @Requirements(selected = true, ownership = true, types = EntityType.WARDEN) - public static void Warden(CommandContext args, CommandSender sender, NPC npc, - @Arg(value = 1, completions = { "anger" }) String command, @Arg(2) String player, @Arg(3) Integer anger) - throws CommandException { + public static void warden(CommandContext args, CommandSender sender, NPC npc, + @Arg(value = 1, completions = { "anger", "dig", "emerge", "roar" }) String command, @Arg(2) String player, + @Arg(3) Integer anger) throws CommandException { WardenTrait trait = npc.getOrAddTrait(WardenTrait.class); String output = ""; if (command.equalsIgnoreCase("anger")) { @@ -68,9 +71,20 @@ public class WardenTrait extends Trait { } catch (IllegalArgumentException iae) { entity = Bukkit.getOfflinePlayer(player).getPlayer(); } + if (entity != null) { trait.addAnger(entity, anger); + output = Messaging.tr(Messages.WARDEN_ANGER_ADDED, entity, anger); } + } else if (command.equalsIgnoreCase("dig")) { + NMS.setWardenPose(npc.getEntity(), Pose.DIGGING); + output = Messaging.tr(Messages.WARDEN_POSE_SET, npc.getName(), "dig"); + } else if (command.equalsIgnoreCase("emerge")) { + NMS.setWardenPose(npc.getEntity(), Pose.EMERGING); + output = Messaging.tr(Messages.WARDEN_POSE_SET, npc.getName(), "emerge"); + } else if (command.equalsIgnoreCase("roar")) { + NMS.setWardenPose(npc.getEntity(), Pose.ROARING); + output = Messaging.tr(Messages.WARDEN_POSE_SET, npc.getName(), "roar"); } if (!output.isEmpty()) { diff --git a/main/src/main/java/net/citizensnpcs/util/Messages.java b/main/src/main/java/net/citizensnpcs/util/Messages.java index a6bace3b8..5db4682ac 100644 --- a/main/src/main/java/net/citizensnpcs/util/Messages.java +++ b/main/src/main/java/net/citizensnpcs/util/Messages.java @@ -461,6 +461,8 @@ public class Messages { public static final String WANDER_WAYPOINTS_REMOVED_REGION = "citizens.editors.waypoints.wander.removed-region"; public static final String WANDER_WAYPOINTS_WORLDGUARD_REGION_NOT_FOUND = "citizens.editors.waypoints.wander.worldguard-region-not-found"; public static final String WANDER_WAYPOINTS_WORLDGUARD_REGION_SET = "citizens.editors.waypoints.wander.worldguard-region-set"; + public static final String WARDEN_ANGER_ADDED = "citizens.commands.npc.warden.anger-added"; + public static final String WARDEN_POSE_SET = "citizens.commands.npc.warden.pose-set"; public static final String WAYPOINT_ADDED = "citizens.commands.waypoints.add.waypoint-added"; public static final String WAYPOINT_PROVIDER_SET = "citizens.waypoints.set-provider"; public static final String WAYPOINT_REMOVED = "citizens.commands.waypoints.waypoint-removed"; diff --git a/main/src/main/java/net/citizensnpcs/util/NMS.java b/main/src/main/java/net/citizensnpcs/util/NMS.java index 27ab6e0d7..c4bb24afd 100644 --- a/main/src/main/java/net/citizensnpcs/util/NMS.java +++ b/main/src/main/java/net/citizensnpcs/util/NMS.java @@ -852,10 +852,14 @@ public class NMS { BRIDGE.setTeamNameTagVisible(team, visible); } - public static void setVerticalMovement(org.bukkit.entity.Entity bukkitEntity, double d) { + public static void setVerticalMovement(Entity bukkitEntity, double d) { BRIDGE.setVerticalMovement(bukkitEntity, d); } + public static void setWardenPose(Entity entity, Object pose) { + BRIDGE.setWardenPose(entity, pose); + } + public static void setWitherInvulnerable(Wither wither, boolean charged) { BRIDGE.setWitherCharged(wither, charged); } diff --git a/main/src/main/java/net/citizensnpcs/util/NMSBridge.java b/main/src/main/java/net/citizensnpcs/util/NMSBridge.java index a83d7d6c0..d75708669 100644 --- a/main/src/main/java/net/citizensnpcs/util/NMSBridge.java +++ b/main/src/main/java/net/citizensnpcs/util/NMSBridge.java @@ -48,7 +48,7 @@ import net.citizensnpcs.util.EntityPacketTracker.PacketAggregator; public interface NMSBridge { default void activate(Entity entity) { - }; + } public boolean addEntityToWorld(Entity entity, SpawnReason custom); @@ -60,9 +60,9 @@ public interface NMSBridge { public default Iterable createBundlePacket(List packets) { return packets; - } + }; - public EntityPacketTracker createPacketTracker(Entity entity, PacketAggregator agg);; + public EntityPacketTracker createPacketTracker(Entity entity, PacketAggregator agg); public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) throws Throwable; @@ -82,9 +82,9 @@ public interface NMSBridge { public float getHeadYaw(Entity entity); - public double getHeight(Entity entity); + public double getHeight(Entity entity);; - public float getHorizontalMovement(Entity entity);; + public float getHorizontalMovement(Entity entity); public CompoundTag getNBT(ItemStack item); @@ -147,9 +147,9 @@ public interface NMSBridge { public Runnable playerTicker(Player entity); - public void registerEntityClass(Class clazz); + public void registerEntityClass(Class clazz);; - public void remove(Entity entity);; + public void remove(Entity entity); public void removeFromServerPlayerList(Player player); @@ -165,7 +165,7 @@ public interface NMSBridge { public void sendTabListRemove(Player recipient, Collection skinnableNPCs); - public void sendTabListRemove(Player recipient, Player listPlayer); + public void sendTabListRemove(Player recipient, Player listPlayer);; public void sendTeamPacket(Player recipient, Team team, int mode);; @@ -174,11 +174,11 @@ public interface NMSBridge { public default void setAllayDancing(Entity entity, boolean dancing) { throw new UnsupportedOperationException(); - }; + } - public void setBodyYaw(Entity entity, float yaw); + public void setBodyYaw(Entity entity, float yaw);; - public void setBoundingBox(Entity entity, BoundingBox box);; + public void setBoundingBox(Entity entity, BoundingBox box); public default void setCamelPose(Entity entity, CamelPose pose) { throw new UnsupportedOperationException(); @@ -245,6 +245,9 @@ public interface NMSBridge { public void setVerticalMovement(Entity bukkitEntity, double d); + public default void setWardenPose(Entity entity, Object pose) { + } + public void setWitherCharged(Wither wither, boolean charged); public boolean shouldJump(Entity entity); @@ -264,5 +267,5 @@ public interface NMSBridge { public void updateNavigationWorld(Entity entity, World world); - public void updatePathfindingRange(NPC npc, float pathfindingRange);; + public void updatePathfindingRange(NPC npc, float pathfindingRange); } diff --git a/main/src/main/resources/messages_en.properties b/main/src/main/resources/messages_en.properties index 371cb01e5..fcfc811e8 100644 --- a/main/src/main/resources/messages_en.properties +++ b/main/src/main/resources/messages_en.properties @@ -333,6 +333,8 @@ citizens.commands.npc.useitem.held-item-toggled=Using held item set to [[{0}]]. citizens.commands.npc.useitem.offhand-item-toggled=Using offhand item set to [[{0}]]. citizens.commands.npc.vulnerable.set=[[{0}]] is now vulnerable. citizens.commands.npc.vulnerable.stopped=[[{0}]] is no longer vulnerable. +citizens.commands.npc.warden.anger-added=[[{1}]] anger added towards [[{0}]]. +citizens.commands.npc.warden.pose-set=[[{0}]]''s pose set to [[{1}]]. citizens.commands.npc.wolf.unknown-collar-color=[[{0}]] is not an RGB-formatted collar color or the name of a DyeColor. citizens.commands.npc.wolf.collar-color-unsupported=[[{0}]] is not a RGB color code that can be used on a wolf''s collar. citizens.commands.npc.villager.level-set=Level set to [[{0}]]. diff --git a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerControllerMove.java b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerControllerMove.java index ab0347d0a..79c654adb 100644 --- a/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerControllerMove.java +++ b/v1_10_R1/src/main/java/net/citizensnpcs/nms/v1_10_R1/util/PlayerControllerMove.java @@ -116,5 +116,6 @@ public class PlayerControllerMove extends ControllerMove { @Override public double f() { - return thi + return this.e; + } } \ No newline at end of file diff --git a/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/entity/EntityHumanNPC.java b/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/entity/EntityHumanNPC.java index 4e277caee..149dff3d3 100644 --- a/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/entity/EntityHumanNPC.java +++ b/v1_15_R1/src/main/java/net/citizensnpcs/nms/v1_15_R1/entity/EntityHumanNPC.java @@ -159,9 +159,9 @@ public class EntityHumanNPC extends EntityPlayer implements NPCHolder, Skinnable public void die(DamageSource damagesource) { // players that die are not normally removed from the world. when the // NPC dies, we are done with the instance and it should be removed. - if (dead) { + if (dead) return; - } + super.die(damagesource); Bukkit.getScheduler().runTaskLater(CitizensAPI.getPlugin(), new Runnable() { @Override @@ -389,11 +389,13 @@ public class EntityHumanNPC extends EntityPlayer implements NPCHolder, Skinnable super.tick(); if (npc == null) return; + noclip = isSpectator(); Bukkit.getServer().getPluginManager().unsubscribeFromPermission("bukkit.broadcast.user", getBukkitEntity()); boolean navigating = npc.getNavigator().isNavigating(); updatePackets(navigating); npc.update(); + if (npc.data().get(NPC.Metadata.PICKUP_ITEMS, false)) { AxisAlignedBB axisalignedbb; if (this.isPassenger() && !this.getVehicle().dead) { @@ -401,6 +403,7 @@ public class EntityHumanNPC extends EntityPlayer implements NPCHolder, Skinnable } else { axisalignedbb = this.getBoundingBox().grow(1.0, 0.5, 1.0); } + for (Entity entity : this.world.getEntities(this, axisalignedbb)) { if (!entity.dead) { entity.pickup(this); diff --git a/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/entity/EntityHumanNPC.java b/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/entity/EntityHumanNPC.java index 33604d354..ff4c7bc87 100644 --- a/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/entity/EntityHumanNPC.java +++ b/v1_16_R3/src/main/java/net/citizensnpcs/nms/v1_16_R3/entity/EntityHumanNPC.java @@ -147,9 +147,9 @@ public class EntityHumanNPC extends EntityPlayer implements NPCHolder, Skinnable public void die(DamageSource damagesource) { // players that die are not normally removed from the world. when the // NPC dies, we are done with the instance and it should be removed. - if (dead) { + if (dead) return; - } + super.die(damagesource); Bukkit.getScheduler().runTaskLater(CitizensAPI.getPlugin(), new Runnable() { @Override diff --git a/v1_17_R1/pom.xml b/v1_17_R1/pom.xml index c226712a3..419fa00f2 100644 --- a/v1_17_R1/pom.xml +++ b/v1_17_R1/pom.xml @@ -6,7 +6,7 @@ net.citizensnpcs citizens-parent - 2.0.32-SNAPSHOT + 2.0.33-SNAPSHOT citizens-v1_17_R1 diff --git a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/entity/nonliving/BlockDisplayController.java b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/entity/nonliving/BlockDisplayController.java index 61c561f6b..209c0c2de 100644 --- a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/entity/nonliving/BlockDisplayController.java +++ b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/entity/nonliving/BlockDisplayController.java @@ -1,7 +1,9 @@ package net.citizensnpcs.nms.v1_19_R3.entity.nonliving; import org.bukkit.Bukkit; +import org.bukkit.Location; import org.bukkit.craftbukkit.v1_19_R3.CraftServer; +import org.bukkit.craftbukkit.v1_19_R3.CraftWorld; import org.bukkit.craftbukkit.v1_19_R3.entity.CraftBlockDisplay; import org.bukkit.craftbukkit.v1_19_R3.entity.CraftEntity; import org.bukkit.util.Vector; @@ -32,6 +34,17 @@ public class BlockDisplayController extends MobEntityController { super(EntityBlockDisplayNPC.class); } + @Override + protected org.bukkit.entity.Entity createEntity(Location at, NPC npc) { + final EntityBlockDisplayNPC handle = new EntityBlockDisplayNPC(EntityType.BLOCK_DISPLAY, + ((CraftWorld) at.getWorld()).getHandle(), npc); + if (npc != null) { + ((org.bukkit.entity.BlockDisplay) handle.getBukkitEntity()) + .setBlock(npc.getItemProvider().get().getType().createBlockData()); + } + return handle.getBukkitEntity(); + } + @Override public org.bukkit.entity.BlockDisplay getBukkitEntity() { return (org.bukkit.entity.BlockDisplay) super.getBukkitEntity(); diff --git a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/NMSImpl.java b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/NMSImpl.java index 4bb307f2c..a7166ae32 100644 --- a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/NMSImpl.java +++ b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/NMSImpl.java @@ -297,6 +297,7 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerPlayerConnection; import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundEvents; import net.minecraft.tags.FluidTags; import net.minecraft.util.Mth; import net.minecraft.world.Container; @@ -342,6 +343,7 @@ import net.minecraft.world.entity.item.FallingBlockEntity; import net.minecraft.world.entity.monster.EnderMan; import net.minecraft.world.entity.monster.Shulker; import net.minecraft.world.entity.monster.piglin.Piglin; +import net.minecraft.world.entity.monster.warden.Warden; import net.minecraft.world.entity.projectile.FishingHook; import net.minecraft.world.entity.vehicle.AbstractMinecart; import net.minecraft.world.inventory.AnvilMenu; @@ -1665,6 +1667,44 @@ public class NMSImpl implements NMSBridge { handle.xxa = (float) d; } + @Override + public void setWardenPose(org.bukkit.entity.Entity entity, Object pose) { + Warden warden = (Warden) getHandle(entity); + if (pose == org.bukkit.entity.Pose.DIGGING) { + if (warden.hasPose(Pose.DIGGING)) + return; + + warden.setPose(Pose.DIGGING); + warden.playSound(SoundEvents.WARDEN_DIG, 5.0F, 1.0F); + } else if (pose == org.bukkit.entity.Pose.EMERGING) { + if (warden.hasPose(Pose.EMERGING)) + return; + + warden.setPose(Pose.EMERGING); + warden.playSound(SoundEvents.WARDEN_EMERGE, 5.0F, 1.0F); + + Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), () -> { + if (warden.hasPose(Pose.EMERGING)) { + warden.setPose(Pose.STANDING); + } + }, 134); + } else if (pose == org.bukkit.entity.Pose.ROARING) { + if (warden.hasPose(Pose.ROARING)) + return; + + warden.setPose(Pose.ROARING); + warden.playSound(SoundEvents.WARDEN_ROAR, 3.0F, 1.0F); + + Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), () -> { + if (warden.hasPose(Pose.ROARING)) { + warden.setPose(Pose.STANDING); + } + }, 84); + } else { + warden.setPose(Pose.STANDING); + } + } + @Override public void setWitherCharged(Wither wither, boolean charged) { WitherBoss handle = ((CraftWither) wither).getHandle(); diff --git a/v1_20_R2/src/main/java/net/citizensnpcs/nms/v1_20_R2/entity/WardenController.java b/v1_20_R2/src/main/java/net/citizensnpcs/nms/v1_20_R2/entity/WardenController.java index dd2ed643f..9b58fd797 100644 --- a/v1_20_R2/src/main/java/net/citizensnpcs/nms/v1_20_R2/entity/WardenController.java +++ b/v1_20_R2/src/main/java/net/citizensnpcs/nms/v1_20_R2/entity/WardenController.java @@ -15,7 +15,6 @@ import net.citizensnpcs.npc.ai.NPCHolder; import net.citizensnpcs.util.NMS; import net.citizensnpcs.util.Util; import net.minecraft.core.BlockPos; - import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.sounds.SoundEvent; @@ -94,6 +93,7 @@ public class WardenController extends MobEntityController { super.customServerAiStep(); return; } + NMSImpl.updateMinecraftAIState(npc, this); npc.update(); if (npc.useMinecraftAI()) { diff --git a/v1_20_R2/src/main/java/net/citizensnpcs/nms/v1_20_R2/entity/nonliving/BlockDisplayController.java b/v1_20_R2/src/main/java/net/citizensnpcs/nms/v1_20_R2/entity/nonliving/BlockDisplayController.java index 92f404064..68431274f 100644 --- a/v1_20_R2/src/main/java/net/citizensnpcs/nms/v1_20_R2/entity/nonliving/BlockDisplayController.java +++ b/v1_20_R2/src/main/java/net/citizensnpcs/nms/v1_20_R2/entity/nonliving/BlockDisplayController.java @@ -1,7 +1,9 @@ package net.citizensnpcs.nms.v1_20_R2.entity.nonliving; import org.bukkit.Bukkit; +import org.bukkit.Location; import org.bukkit.craftbukkit.v1_20_R2.CraftServer; +import org.bukkit.craftbukkit.v1_20_R2.CraftWorld; import org.bukkit.craftbukkit.v1_20_R2.entity.CraftBlockDisplay; import org.bukkit.craftbukkit.v1_20_R2.entity.CraftEntity; import org.bukkit.util.Vector; @@ -14,7 +16,6 @@ import net.citizensnpcs.nms.v1_20_R2.util.NMSImpl; import net.citizensnpcs.npc.CitizensNPC; import net.citizensnpcs.npc.ai.NPCHolder; import net.citizensnpcs.util.Util; - import net.minecraft.nbt.CompoundTag; import net.minecraft.server.level.ServerLevel; import net.minecraft.tags.TagKey; @@ -32,6 +33,17 @@ public class BlockDisplayController extends MobEntityController { super(EntityBlockDisplayNPC.class); } + @Override + protected org.bukkit.entity.Entity createEntity(Location at, NPC npc) { + final EntityBlockDisplayNPC handle = new EntityBlockDisplayNPC(EntityType.BLOCK_DISPLAY, + ((CraftWorld) at.getWorld()).getHandle(), npc); + if (npc != null) { + ((org.bukkit.entity.BlockDisplay) handle.getBukkitEntity()) + .setBlock(npc.getItemProvider().get().getType().createBlockData()); + } + return handle.getBukkitEntity(); + } + @Override public org.bukkit.entity.BlockDisplay getBukkitEntity() { return (org.bukkit.entity.BlockDisplay) super.getBukkitEntity(); @@ -111,6 +123,7 @@ public class BlockDisplayController extends MobEntityController { public Entity teleportTo(ServerLevel worldserver, Vec3 location) { if (npc == null) return super.teleportTo(worldserver, location); + return NMSImpl.teleportAcrossWorld(this, worldserver, location); } diff --git a/v1_20_R2/src/main/java/net/citizensnpcs/nms/v1_20_R2/util/NMSImpl.java b/v1_20_R2/src/main/java/net/citizensnpcs/nms/v1_20_R2/util/NMSImpl.java index 07a62b847..ef654a696 100644 --- a/v1_20_R2/src/main/java/net/citizensnpcs/nms/v1_20_R2/util/NMSImpl.java +++ b/v1_20_R2/src/main/java/net/citizensnpcs/nms/v1_20_R2/util/NMSImpl.java @@ -287,6 +287,7 @@ import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.network.ServerPlayerConnection; import net.minecraft.sounds.SoundEvent; +import net.minecraft.sounds.SoundEvents; import net.minecraft.tags.FluidTags; import net.minecraft.util.Mth; import net.minecraft.world.Container; @@ -332,6 +333,7 @@ import net.minecraft.world.entity.item.FallingBlockEntity; import net.minecraft.world.entity.monster.EnderMan; import net.minecraft.world.entity.monster.Shulker; import net.minecraft.world.entity.monster.piglin.Piglin; +import net.minecraft.world.entity.monster.warden.Warden; import net.minecraft.world.entity.projectile.FishingHook; import net.minecraft.world.entity.vehicle.AbstractMinecart; import net.minecraft.world.inventory.AnvilMenu; @@ -457,7 +459,7 @@ public class NMSImpl implements NMSBridge { } EnchantmentHelper.doPostHurtEffects(source, target); EnchantmentHelper.doPostDamageEffects(target, source); - }; + } @Override public void cancelMoveDestination(org.bukkit.entity.Entity entity) { @@ -473,7 +475,7 @@ public class NMSImpl implements NMSBridge { t.printStackTrace(); } } - } + }; @Override @SuppressWarnings("rawtypes") @@ -1641,6 +1643,44 @@ public class NMSImpl implements NMSBridge { handle.xxa = (float) d; } + @Override + public void setWardenPose(org.bukkit.entity.Entity entity, Object pose) { + Warden warden = (Warden) getHandle(entity); + if (pose == org.bukkit.entity.Pose.DIGGING) { + if (warden.hasPose(Pose.DIGGING)) + return; + + warden.setPose(Pose.DIGGING); + warden.playSound(SoundEvents.WARDEN_DIG, 5.0F, 1.0F); + } else if (pose == org.bukkit.entity.Pose.EMERGING) { + if (warden.hasPose(Pose.EMERGING)) + return; + + warden.setPose(Pose.EMERGING); + warden.playSound(SoundEvents.WARDEN_EMERGE, 5.0F, 1.0F); + + Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), () -> { + if (warden.hasPose(Pose.EMERGING)) { + warden.setPose(Pose.STANDING); + } + }, 134); + } else if (pose == org.bukkit.entity.Pose.ROARING) { + if (warden.hasPose(Pose.ROARING)) + return; + + warden.setPose(Pose.ROARING); + warden.playSound(SoundEvents.WARDEN_ROAR, 3.0F, 1.0F); + + Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), () -> { + if (warden.hasPose(Pose.ROARING)) { + warden.setPose(Pose.STANDING); + } + }, 84); + } else { + warden.setPose(Pose.STANDING); + } + } + @Override public void setWitherCharged(Wither wither, boolean charged) { WitherBoss handle = ((CraftWither) wither).getHandle(); @@ -1672,7 +1712,7 @@ public class NMSImpl implements NMSBridge { @Override public void sleep(org.bukkit.entity.Player player, boolean sleeping) { getHandle(player).setPose(sleeping ? Pose.SLEEPING : Pose.STANDING); - } + }; @Override public void trySwim(org.bukkit.entity.Entity entity) { @@ -2197,17 +2237,30 @@ public class NMSImpl implements NMSBridge { if (pitch == null) { pitch = handle.getXRot(); } + List> toSend = Lists.newArrayList(); if (position) { TrackedEntity entry = ((ServerLevel) handle.level()).getChunkSource().chunkMap.entityMap .get(handle.getId()); + if (entry == null) { + Messaging.debug("Null tracker entity for ", from); + return Collections.emptyList(); + } + VecDeltaCodec vdc = null; try { - vdc = (VecDeltaCodec) POSITION_CODEC_GETTER.invoke((ServerEntity) SERVER_ENTITY_GETTER.invoke(entry)); + ServerEntity serverEntity = (ServerEntity) SERVER_ENTITY_GETTER.invoke(entry); + if (serverEntity == null) { + Messaging.debug("Null server entity for ", from); + return Collections.emptyList(); + } + + vdc = (VecDeltaCodec) POSITION_CODEC_GETTER.invoke(serverEntity); } catch (Throwable e) { e.printStackTrace(); return Collections.emptyList(); } + Vec3 pos = handle.trackingPosition(); toSend.add(new ClientboundMoveEntityPacket.PosRot(handle.getId(), (short) vdc.encodeX(pos), (short) vdc.encodeY(pos), (short) vdc.encodeZ(pos), (byte) (bodyYaw * 256.0F / 360.0F),