diff --git a/main/src/main/java/net/citizensnpcs/EventListen.java b/main/src/main/java/net/citizensnpcs/EventListen.java index 52a23ea76..677206719 100644 --- a/main/src/main/java/net/citizensnpcs/EventListen.java +++ b/main/src/main/java/net/citizensnpcs/EventListen.java @@ -215,12 +215,7 @@ public class EventListen implements Listener { void loadNPCs(ChunkEvent event) { ChunkCoord coord = new ChunkCoord(event.getChunk()); - Runnable runnable = new Runnable() { - @Override - public void run() { - respawnAllFromCoord(coord, event); - } - }; + Runnable runnable = () -> respawnAllFromCoord(coord, event); if (Messaging.isDebugging() && Setting.DEBUG_CHUNK_LOADS.asBoolean() && toRespawn.containsKey(coord)) { new Exception("CITIZENS CHUNK LOAD DEBUG " + coord).printStackTrace(); } diff --git a/main/src/main/java/net/citizensnpcs/Settings.java b/main/src/main/java/net/citizensnpcs/Settings.java index c2266acd0..22cae89cb 100644 --- a/main/src/main/java/net/citizensnpcs/Settings.java +++ b/main/src/main/java/net/citizensnpcs/Settings.java @@ -218,6 +218,9 @@ public class Settings { NPC_COMMAND_ON_GLOBAL_COOLDOWN_MESSAGE("npc.commands.error-messages.on-global-cooldown", "Please wait for {minutes} minutes and {seconds_over} seconds."), NPC_COST("The default cost to create an NPC", "economy.npc.cost", 100D), + NPC_SKIN_FETCH_DEFAULT( + "Whether to try and look for the player skin for all new NPCs. If this is set to false and you create an NPC named Dinnerbone, the NPC will have the default (steve/alex/...) skin rather than trying to fetch the Dinnerbone skin.", + "npc.skins.try-fetch-default-skin", true), NPC_SKIN_RETRY_DELAY("How long before retrying skin requests (typically due to Mojang rate limiting)", "npc.skins.retry-delay", "5s"), NPC_SKIN_ROTATION_UPDATE_DEGREES("npc.skins.rotation-update-degrees", 90f), diff --git a/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java b/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java index e3c5d6ead..4ed3ed438 100644 --- a/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java +++ b/main/src/main/java/net/citizensnpcs/commands/NPCCommands.java @@ -537,9 +537,9 @@ public class NPCCommands { } if (args.argsLength() == 4) { commands.setCost(args.getDouble(2), args.getInteger(3)); - Messaging.sendTr(sender, Messages.COMMAND_INDIVIDUAL_COST_SET, args.getDouble(2) == -1 ? "-1 (default)" : args.getDouble(2), args.getInteger(3)); - } - else { + Messaging.sendTr(sender, Messages.COMMAND_INDIVIDUAL_COST_SET, + args.getDouble(2) == -1 ? "-1 (default)" : args.getDouble(2), args.getInteger(3)); + } else { commands.setCost(args.getDouble(2)); Messaging.sendTr(sender, Messages.COMMAND_COST_SET, args.getDouble(2)); } @@ -549,9 +549,9 @@ public class NPCCommands { } if (args.argsLength() == 4) { commands.setExperienceCost(args.getInteger(2), args.getInteger(3)); - Messaging.sendTr(sender, Messages.COMMAND_INDIVIDUAL_EXPERIENCE_COST_SET, args.getInteger(2) == -1 ? "-1 (default)" : args.getInteger(2), args.getInteger(3)); - } - else { + Messaging.sendTr(sender, Messages.COMMAND_INDIVIDUAL_EXPERIENCE_COST_SET, + args.getInteger(2) == -1 ? "-1 (default)" : args.getInteger(2), args.getInteger(3)); + } else { commands.setExperienceCost(args.getInteger(2)); Messaging.sendTr(sender, Messages.COMMAND_EXPERIENCE_COST_SET, args.getInteger(2)); } @@ -569,9 +569,9 @@ public class NPCCommands { throw new CommandException(CommandMessages.MUST_BE_INGAME); if (args.argsLength() == 2) { InventoryMenu.createSelfRegistered(new ItemRequirementGUI(commands)).present(((Player) sender)); - } - else { - InventoryMenu.createSelfRegistered(new ItemRequirementGUI(commands, args.getInteger(2))).present(((Player) sender)); + } else { + InventoryMenu.createSelfRegistered(new ItemRequirementGUI(commands, args.getInteger(2))) + .present(((Player) sender)); } } else if (action.equalsIgnoreCase("errormsg")) { CommandTraitError which = Util.matchEnum(CommandTraitError.values(), args.getString(2)); @@ -2784,6 +2784,8 @@ public class NPCCommands { final SkinTrait trait = npc.getOrAddTrait(SkinTrait.class); if (args.hasFlag('c')) { trait.clearTexture(); + Messaging.sendTr(sender, Messages.SKIN_CLEARED); + return; } else if (url != null || file != null) { Messaging.sendTr(sender, Messages.FETCHING_SKIN, file); Bukkit.getScheduler().runTaskAsynchronously(CitizensAPI.getPlugin(), () -> { diff --git a/main/src/main/java/net/citizensnpcs/npc/CitizensNPC.java b/main/src/main/java/net/citizensnpcs/npc/CitizensNPC.java index 78950a980..ec7350bdd 100644 --- a/main/src/main/java/net/citizensnpcs/npc/CitizensNPC.java +++ b/main/src/main/java/net/citizensnpcs/npc/CitizensNPC.java @@ -236,7 +236,7 @@ public class CitizensNPC extends AbstractNPC { boolean wasSpawned = entityController == null ? false : isSpawned(); Location prev = null; if (wasSpawned) { - prev = getEntity().getLocation(CACHE_LOCATION); + prev = getEntity().getLocation(); despawn(DespawnReason.PENDING_RESPAWN); } PacketNPC packet = getTraitNullable(PacketNPC.class); @@ -446,7 +446,7 @@ public class CitizensNPC extends AbstractNPC { if (hasTrait(SitTrait.class) && getOrAddTrait(SitTrait.class).isSitting()) { getOrAddTrait(SitTrait.class).setSitting(location); } - Location npcLoc = getEntity().getLocation(CACHE_LOCATION); + Location npcLoc = getEntity().getLocation(); if (isSpawned() && npcLoc.getWorld() == location.getWorld()) { if (npcLoc.distance(location) < 1) { NMS.setHeadYaw(getEntity(), location.getYaw()); @@ -625,7 +625,6 @@ public class CitizensNPC extends AbstractNPC { } } - private static final Location CACHE_LOCATION = new Location(null, 0, 0, 0); private static final SetMultimap CHUNK_LOADERS = HashMultimap.create(); private static boolean SUPPORT_GLOWING = true; private static boolean SUPPORT_NODAMAGE_TICKS = true; diff --git a/main/src/main/java/net/citizensnpcs/npc/CitizensNPCRegistry.java b/main/src/main/java/net/citizensnpcs/npc/CitizensNPCRegistry.java index 74eecd274..8bf9635c7 100644 --- a/main/src/main/java/net/citizensnpcs/npc/CitizensNPCRegistry.java +++ b/main/src/main/java/net/citizensnpcs/npc/CitizensNPCRegistry.java @@ -27,6 +27,7 @@ import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.npc.NPCDataStore; import net.citizensnpcs.api.npc.NPCRegistry; import net.citizensnpcs.api.trait.Trait; +import net.citizensnpcs.api.util.RemoveReason; import net.citizensnpcs.npc.ai.NPCHolder; import net.citizensnpcs.trait.ArmorStandTrait; import net.citizensnpcs.trait.LookClose; @@ -118,7 +119,7 @@ public class CitizensNPCRegistry implements NPCRegistry { npc.despawn(DespawnReason.REMOVAL); for (Trait t : npc.getTraits()) { HandlerList.unregisterAll(t); - t.onRemove(); + t.onRemove(RemoveReason.REMOVAL); } itr.remove(); if (saves != null) { diff --git a/main/src/main/java/net/citizensnpcs/npc/ai/AStarNavigationStrategy.java b/main/src/main/java/net/citizensnpcs/npc/ai/AStarNavigationStrategy.java index 262e46142..c6c1cc46c 100644 --- a/main/src/main/java/net/citizensnpcs/npc/ai/AStarNavigationStrategy.java +++ b/main/src/main/java/net/citizensnpcs/npc/ai/AStarNavigationStrategy.java @@ -79,7 +79,7 @@ public class AStarNavigationStrategy extends AbstractPathStrategy { public boolean update() { if (plan == null) { if (planner == null) { - planner = new AStarPlanner(params, npc.getEntity().getLocation(NPC_LOCATION), destination); + planner = new AStarPlanner(params, npc.getEntity().getLocation(), destination); } CancelReason reason = planner.tick(Setting.ASTAR_ITERATIONS_PER_TICK.asInt(), Setting.MAXIMUM_ASTAR_ITERATIONS.asInt()); @@ -97,9 +97,9 @@ public class AStarNavigationStrategy extends AbstractPathStrategy { if (vector == null) { vector = plan.getCurrentVector(); } - Location loc = npc.getEntity().getLocation(NPC_LOCATION); + Location loc = npc.getEntity().getLocation(); /* Proper door movement - gets stuck on corners at times - + Block block = currLoc.getWorld().getBlockAt(vector.getBlockX(), vector.getBlockY(), vector.getBlockZ()); if (MinecraftBlockExaminer.isDoor(block.getType())) { Door door = (Door) block.getState().getData(); @@ -131,7 +131,7 @@ public class AStarNavigationStrategy extends AbstractPathStrategy { NMS.setDestination(npc.getEntity(), dest.getX(), dest.getY(), dest.getZ(), params.speed()); } else { Vector dir = dest.toVector().subtract(npc.getEntity().getLocation().toVector()).normalize().multiply(0.2); - boolean liquidOrInLiquid = MinecraftBlockExaminer.isLiquidOrInLiquid(NPC_LOCATION.getBlock()); + boolean liquidOrInLiquid = MinecraftBlockExaminer.isLiquidOrInLiquid(loc.getBlock()); if ((dY >= 1 && Math.sqrt(xzDistance) <= 0.4) || (dY >= 0.2 && liquidOrInLiquid)) { dir.add(new Vector(0, 0.75, 0)); } @@ -201,5 +201,4 @@ public class AStarNavigationStrategy extends AbstractPathStrategy { } private static final AStarMachine ASTAR = AStarMachine.createWithDefaultStorage(); - private static final Location NPC_LOCATION = new Location(null, 0, 0, 0); } diff --git a/main/src/main/java/net/citizensnpcs/npc/ai/CitizensNavigator.java b/main/src/main/java/net/citizensnpcs/npc/ai/CitizensNavigator.java index 51ef16edd..2215f9224 100644 --- a/main/src/main/java/net/citizensnpcs/npc/ai/CitizensNavigator.java +++ b/main/src/main/java/net/citizensnpcs/npc/ai/CitizensNavigator.java @@ -486,7 +486,7 @@ public class CitizensNavigator implements Navigator, Runnable { private boolean updateStationaryStatus() { if (localParams.stationaryTicks() < 0) return false; - Location current = npc.getEntity().getLocation(STATIONARY_LOCATION); + Location current = npc.getEntity().getLocation(); if (!SpigotUtil.checkYSafe(current.getY(), current.getWorld())) { stopNavigating(CancelReason.STUCK); return true; @@ -534,7 +534,6 @@ public class CitizensNavigator implements Navigator, Runnable { } } - private static final Location STATIONARY_LOCATION = new Location(null, 0, 0, 0); private static boolean SUPPORT_CHUNK_TICKETS = true; private static int UNINITIALISED_SPEED = Integer.MIN_VALUE; } diff --git a/main/src/main/java/net/citizensnpcs/npc/ai/FlyingAStarNavigationStrategy.java b/main/src/main/java/net/citizensnpcs/npc/ai/FlyingAStarNavigationStrategy.java index 9b3bfc4be..4deecab50 100644 --- a/main/src/main/java/net/citizensnpcs/npc/ai/FlyingAStarNavigationStrategy.java +++ b/main/src/main/java/net/citizensnpcs/npc/ai/FlyingAStarNavigationStrategy.java @@ -136,7 +136,7 @@ public class FlyingAStarNavigationStrategy extends AbstractPathStrategy { if (getCancelReason() != null || plan == null || plan.isComplete()) { return true; } - Location current = npc.getEntity().getLocation(NPC_LOCATION); + Location current = npc.getEntity().getLocation(); if (current.toVector().distance(vector) <= parameters.distanceMargin()) { plan.update(npc); if (plan.isComplete()) { @@ -184,5 +184,4 @@ public class FlyingAStarNavigationStrategy extends AbstractPathStrategy { } private static final AStarMachine ASTAR = AStarMachine.createWithDefaultStorage(); - private static final Location NPC_LOCATION = new Location(null, 0, 0, 0); } diff --git a/main/src/main/java/net/citizensnpcs/npc/ai/MCNavigationStrategy.java b/main/src/main/java/net/citizensnpcs/npc/ai/MCNavigationStrategy.java index e3fd91ad9..d1f32cb25 100644 --- a/main/src/main/java/net/citizensnpcs/npc/ai/MCNavigationStrategy.java +++ b/main/src/main/java/net/citizensnpcs/npc/ai/MCNavigationStrategy.java @@ -82,7 +82,7 @@ public class MCNavigationStrategy extends AbstractPathStrategy { if (getCancelReason() != null) return true; boolean wasFinished = navigator.update(); - Location loc = entity.getLocation(HANDLE_LOCATION); + Location loc = entity.getLocation(); double dX = target.getX() - loc.getX(); double dZ = target.getZ() - loc.getZ(); double dY = target.getY() - loc.getY(); @@ -107,6 +107,4 @@ public class MCNavigationStrategy extends AbstractPathStrategy { boolean update(); } - - private static final Location HANDLE_LOCATION = new Location(null, 0, 0, 0); } diff --git a/main/src/main/java/net/citizensnpcs/npc/ai/MCTargetStrategy.java b/main/src/main/java/net/citizensnpcs/npc/ai/MCTargetStrategy.java index 818b63b0f..bf47b58af 100644 --- a/main/src/main/java/net/citizensnpcs/npc/ai/MCTargetStrategy.java +++ b/main/src/main/java/net/citizensnpcs/npc/ai/MCTargetStrategy.java @@ -55,7 +55,7 @@ public class MCTargetStrategy implements PathStrategy, EntityTarget { } private double distance() { - return handle.getLocation(HANDLE_LOCATION).distance(target.getLocation(TARGET_LOCATION)); + return handle.getLocation().distance(target.getLocation()); } @Override @@ -292,6 +292,4 @@ public class MCTargetStrategy implements PathStrategy, EntityTarget { return false; } }; - private static final Location HANDLE_LOCATION = new Location(null, 0, 0, 0); - private static final Location TARGET_LOCATION = new Location(null, 0, 0, 0); } diff --git a/main/src/main/java/net/citizensnpcs/npc/ai/StraightLineNavigationStrategy.java b/main/src/main/java/net/citizensnpcs/npc/ai/StraightLineNavigationStrategy.java index 36b1f6124..4de2eac90 100644 --- a/main/src/main/java/net/citizensnpcs/npc/ai/StraightLineNavigationStrategy.java +++ b/main/src/main/java/net/citizensnpcs/npc/ai/StraightLineNavigationStrategy.java @@ -61,7 +61,7 @@ public class StraightLineNavigationStrategy extends AbstractPathStrategy { if (getCancelReason() != null || npc.getStoredLocation().getWorld() != destination.getWorld()) { return true; } - Location currLoc = npc.getEntity().getLocation(NPC_LOCATION); + Location currLoc = npc.getEntity().getLocation(); if (currLoc.distance(destination) <= params.distanceMargin()) { return true; } @@ -127,6 +127,4 @@ public class StraightLineNavigationStrategy extends AbstractPathStrategy { } return false; } - - private static final Location NPC_LOCATION = new Location(null, 0, 0, 0); } diff --git a/main/src/main/java/net/citizensnpcs/npc/skin/SkinPacketTracker.java b/main/src/main/java/net/citizensnpcs/npc/skin/SkinPacketTracker.java index c96ad93ee..f851370f8 100644 --- a/main/src/main/java/net/citizensnpcs/npc/skin/SkinPacketTracker.java +++ b/main/src/main/java/net/citizensnpcs/npc/skin/SkinPacketTracker.java @@ -6,7 +6,6 @@ import java.util.Map; import java.util.UUID; import org.bukkit.Bukkit; -import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -165,7 +164,7 @@ public class SkinPacketTracker { public void updateNearbyViewers(double radius) { Player from = entity.getBukkitEntity(); - CitizensAPI.getLocationLookup().getNearbyPlayers(from.getLocation(CACHE_LOCATION), radius).forEach(player -> { + CitizensAPI.getLocationLookup().getNearbyPlayers(from.getLocation(), radius).forEach(player -> { if (!player.canSee(from) || player.hasMetadata("NPC")) return; updateViewer(player); @@ -228,7 +227,6 @@ public class SkinPacketTracker { } } - private static final Location CACHE_LOCATION = new Location(null, 0, 0, 0); private static PlayerListener LISTENER; private static final int PACKET_DELAY_REMOVE = 2; private static final TabListRemover TAB_LIST_REMOVER = new TabListRemover(); diff --git a/main/src/main/java/net/citizensnpcs/npc/skin/SkinUpdateTracker.java b/main/src/main/java/net/citizensnpcs/npc/skin/SkinUpdateTracker.java index 5ee035eb5..60ba9ccbf 100644 --- a/main/src/main/java/net/citizensnpcs/npc/skin/SkinUpdateTracker.java +++ b/main/src/main/java/net/citizensnpcs/npc/skin/SkinUpdateTracker.java @@ -72,8 +72,8 @@ public class SkinUpdateTracker { if (!player.getWorld().equals(entity.getWorld())) return false; - Location playerLoc = player.getLocation(CACHE_LOCATION); - Location skinLoc = entity.getLocation(NPC_LOCATION); + Location playerLoc = player.getLocation(); + Location skinLoc = entity.getLocation(); if (playerLoc.distance(skinLoc) > Setting.NPC_SKIN_VIEW_DISTANCE.asDouble()) return false; @@ -281,12 +281,12 @@ public class SkinUpdateTracker { return; double viewDistance = Setting.NPC_SKIN_VIEW_DISTANCE.asDouble(); - Location location = entity.getLocation(NPC_LOCATION); + Location location = entity.getLocation(); List players = entity.getWorld().getPlayers(); for (Player player : players) { if (player.hasMetadata("NPC")) continue; - Location ploc = player.getLocation(CACHE_LOCATION); + Location ploc = player.getLocation(); if (ploc.getWorld() != location.getWorld()) continue; if (ploc.distance(location) > viewDistance) @@ -410,7 +410,7 @@ public class SkinUpdateTracker { } boolean shouldUpdate(Player player) { - Location currentLoc = player.getLocation(CACHE_LOCATION); + Location currentLoc = player.getLocation(); // make sure player is in same world if (!currentLoc.getWorld().equals(this.location.getWorld())) { @@ -461,8 +461,6 @@ public class SkinUpdateTracker { } } - private static final Location CACHE_LOCATION = new Location(null, 0, 0, 0); private static final float FIELD_OF_VIEW = 70F; private static final int MOVEMENT_SKIN_UPDATE_DISTANCE = 25; - private static final Location NPC_LOCATION = new Location(null, 0, 0, 0); } diff --git a/main/src/main/java/net/citizensnpcs/trait/ClickRedirectTrait.java b/main/src/main/java/net/citizensnpcs/trait/ClickRedirectTrait.java index ae7905f9f..d9dabfab1 100644 --- a/main/src/main/java/net/citizensnpcs/trait/ClickRedirectTrait.java +++ b/main/src/main/java/net/citizensnpcs/trait/ClickRedirectTrait.java @@ -2,10 +2,14 @@ package net.citizensnpcs.trait; import java.util.UUID; +import org.bukkit.event.EventHandler; + import net.citizensnpcs.api.CitizensAPI; +import net.citizensnpcs.api.event.NPCAddTraitEvent; import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.trait.Trait; import net.citizensnpcs.api.trait.TraitName; +import net.citizensnpcs.api.trait.trait.PlayerFilter; import net.citizensnpcs.api.util.DataKey; /** @@ -33,6 +37,13 @@ public class ClickRedirectTrait extends Trait { redirectNPC = CitizensAPI.getNPCRegistry().getByUniqueIdGlobal(UUID.fromString(key.getString("uuid"))); } + @EventHandler + public void onTraitAdd(NPCAddTraitEvent event) { + if (event.getNPC() == redirectNPC && event.getTrait() instanceof PlayerFilter) { + ((PlayerFilter) event.getTrait()).addChildNPC(npc); + } + } + @Override public void save(DataKey key) { key.removeKey("uuid"); diff --git a/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java b/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java index 073955bf7..9c787e4d3 100644 --- a/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java +++ b/main/src/main/java/net/citizensnpcs/trait/HologramTrait.java @@ -202,7 +202,8 @@ public class HologramTrait extends Trait { public void load(DataKey root) { clear(); for (DataKey key : root.getRelative("lines").getIntegerSubKeys()) { - HologramLine line = new HologramLine(key.keyExists("text") ? key.getString("text") : key.getString(""), true); + HologramLine line = new HologramLine(key.keyExists("text") ? key.getString("text") : key.getString(""), + true); line.mt = key.keyExists("margin.top") ? key.getDouble("margin.top") : 0.0; line.mb = key.keyExists("margin.bottom") ? key.getDouble("margin.bottom") : 0.0; lines.add(line); @@ -420,8 +421,7 @@ public class HologramTrait extends Trait { public void setMargin(int idx, String type, double margin) { if (type.equalsIgnoreCase("top")) { lines.get(idx).mt = margin; - } - else if (type.equalsIgnoreCase("bottom")) { + } else if (type.equalsIgnoreCase("bottom")) { lines.get(idx).mb = margin; } reloadLineHolograms(); diff --git a/main/src/main/java/net/citizensnpcs/trait/LookClose.java b/main/src/main/java/net/citizensnpcs/trait/LookClose.java index c35d37df7..1ba8f7d96 100644 --- a/main/src/main/java/net/citizensnpcs/trait/LookClose.java +++ b/main/src/main/java/net/citizensnpcs/trait/LookClose.java @@ -147,8 +147,9 @@ public class LookClose extends Trait implements Toggleable { } } else { double min = range; + Location npcLoc = npc.getStoredLocation(); for (Player player : getNearbyPlayers()) { - double dist = player.getLocation(CACHE_LOCATION).distance(NPC_LOCATION); + double dist = player.getLocation().distance(npcLoc); if (dist > min) continue; min = dist; @@ -168,15 +169,16 @@ public class LookClose extends Trait implements Toggleable { private List getNearbyPlayers() { List options = Lists.newArrayList(); + Location npcLoc = npc.getStoredLocation(); Iterable nearby = targetNPCs ? npc.getEntity().getNearbyEntities(range, range, range).stream() - .filter(e -> e.getType() == EntityType.PLAYER && e.getWorld() == NPC_LOCATION.getWorld()) + .filter(e -> e.getType() == EntityType.PLAYER && e.getWorld() == npcLoc.getWorld()) .map(e -> (Player) e).collect(Collectors.toList()) - : CitizensAPI.getLocationLookup().getNearbyPlayers(NPC_LOCATION, range); + : CitizensAPI.getLocationLookup().getNearbyPlayers(npcLoc, range); for (Player player : nearby) { if (player == lookingAt || (!targetNPCs && CitizensAPI.getNPCRegistry().getNPC(player) != null)) continue; - if (player.getLocation().getWorld() != NPC_LOCATION.getWorld() || isInvisible(player)) + if (player.getLocation().getWorld() != npcLoc.getWorld() || isInvisible(player)) continue; options.add(player); @@ -232,8 +234,7 @@ public class LookClose extends Trait implements Toggleable { private boolean isValid(Player entity) { return entity.isOnline() && entity.isValid() && entity.getWorld() == npc.getEntity().getWorld() - && entity.getLocation(PLAYER_LOCATION).distanceSquared(NPC_LOCATION) < range * range - && !isInvisible(entity); + && entity.getLocation().distance(npc.getStoredLocation()) <= range && !isInvisible(entity); } @Override @@ -292,7 +293,6 @@ public class LookClose extends Trait implements Toggleable { return; } - npc.getEntity().getLocation(NPC_LOCATION); findNewTarget(); if (npc.getNavigator().isNavigating() || npc.getNavigator().isPaused()) { @@ -310,8 +310,8 @@ public class LookClose extends Trait implements Toggleable { if (npc.getEntity().getType().name().equals("SHULKER")) { boolean wasSilent = npc.getEntity().isSilent(); npc.getEntity().setSilent(true); - NMS.setPeekShulker(npc.getEntity(), 100 - 4 * (int) Math - .floor(npc.getStoredLocation().distanceSquared(lookingAt.getLocation(PLAYER_LOCATION)))); + NMS.setPeekShulker(npc.getEntity(), + 100 - 4 * (int) Math.floor(npc.getStoredLocation().distanceSquared(lookingAt.getLocation()))); npc.getEntity().setSilent(wasSilent); } } @@ -403,8 +403,4 @@ public class LookClose extends Trait implements Toggleable { private static boolean isEqual(float[] array) { return Math.abs(array[0] - array[1]) < 0.001; } - - private static final Location CACHE_LOCATION = new Location(null, 0, 0, 0); - private static final Location NPC_LOCATION = new Location(null, 0, 0, 0); - private static final Location PLAYER_LOCATION = new Location(null, 0, 0, 0); } \ No newline at end of file diff --git a/main/src/main/java/net/citizensnpcs/trait/PacketNPC.java b/main/src/main/java/net/citizensnpcs/trait/PacketNPC.java index 6cf2d99ed..23add5fa6 100644 --- a/main/src/main/java/net/citizensnpcs/trait/PacketNPC.java +++ b/main/src/main/java/net/citizensnpcs/trait/PacketNPC.java @@ -12,6 +12,7 @@ import net.citizensnpcs.api.event.SpawnReason; import net.citizensnpcs.api.npc.NPC; import net.citizensnpcs.api.trait.Trait; import net.citizensnpcs.api.trait.TraitName; +import net.citizensnpcs.api.util.RemoveReason; import net.citizensnpcs.npc.EntityController; import net.citizensnpcs.util.EntityPacketTracker; import net.citizensnpcs.util.NMS; @@ -31,10 +32,15 @@ public class PacketNPC extends Trait { } @Override - public void onRemove() { - npc.despawn(DespawnReason.PENDING_RESPAWN); - Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), - () -> npc.spawn(npc.getStoredLocation(), SpawnReason.RESPAWN)); + public void onRemove(RemoveReason reason) { + if (reason == RemoveReason.REMOVAL) { + npc.despawn(DespawnReason.PENDING_RESPAWN); + Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), () -> { + if (npc.getStoredLocation() != null) { + npc.spawn(npc.getStoredLocation(), SpawnReason.RESPAWN); + } + }); + } } @Override diff --git a/main/src/main/java/net/citizensnpcs/trait/SkinTrait.java b/main/src/main/java/net/citizensnpcs/trait/SkinTrait.java index 0631394cb..c56b721da 100644 --- a/main/src/main/java/net/citizensnpcs/trait/SkinTrait.java +++ b/main/src/main/java/net/citizensnpcs/trait/SkinTrait.java @@ -1,5 +1,7 @@ package net.citizensnpcs.trait; +import org.bukkit.ChatColor; + import com.google.common.base.Charsets; import com.google.common.base.Preconditions; import com.google.common.io.BaseEncoding; @@ -12,12 +14,11 @@ import net.citizensnpcs.api.util.DataKey; import net.citizensnpcs.api.util.Placeholders; import net.citizensnpcs.npc.skin.Skin; import net.citizensnpcs.npc.skin.SkinnableEntity; -import org.bukkit.ChatColor; @TraitName("skintrait") public class SkinTrait extends Trait { @Persist - private boolean fetchDefaultSkin = true; + private boolean fetchDefaultSkin = Setting.NPC_SKIN_FETCH_DEFAULT.asBoolean(); private String filledPlaceholder; @Persist private String signature; diff --git a/main/src/main/java/net/citizensnpcs/util/Util.java b/main/src/main/java/net/citizensnpcs/util/Util.java index 45b0bfbc6..9b98d4843 100644 --- a/main/src/main/java/net/citizensnpcs/util/Util.java +++ b/main/src/main/java/net/citizensnpcs/util/Util.java @@ -9,7 +9,7 @@ import java.util.List; import java.util.Random; import java.util.Set; import java.util.UUID; -import java.util.concurrent.ExecutionException; +import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import java.util.function.Function; @@ -23,7 +23,6 @@ import org.bukkit.entity.Entity; import org.bukkit.entity.EntityType; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; -import org.bukkit.event.Event; import org.bukkit.event.player.PlayerInteractEntityEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.inventory.ItemFlag; @@ -60,26 +59,22 @@ public class Util { } } - public static boolean callEventPossiblySync(Event event, boolean sync) { + public static T callPossiblySync(Callable callable, boolean sync) { if (!sync) { try { - Bukkit.getPluginManager().callEvent(event); - return false; - } catch (IllegalStateException ex) { - // sync method called + return callable.call(); + } catch (Exception e) { + e.printStackTrace(); } } + try { - Bukkit.getScheduler().callSyncMethod(CitizensAPI.getPlugin(), () -> { - Bukkit.getPluginManager().callEvent(event); - return null; - }).get(); - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (ExecutionException e) { + return Bukkit.getScheduler().callSyncMethod(CitizensAPI.getPlugin(), callable).get(); + } catch (Exception e) { e.printStackTrace(); } - return true; + + return null; } public static Vector callPushEvent(NPC npc, double x, double y, double z) { @@ -152,7 +147,7 @@ public class Util { double pitchCos = Math.cos(Math.toRadians(pitch)); Vector vector = new Vector(Math.sin(Math.toRadians(yaw)) * -pitchCos, -Math.sin(Math.toRadians(pitch)), Math.cos(Math.toRadians(yaw)) * pitchCos).normalize(); - faceLocation(entity, entity.getLocation(AT_LOCATION).clone().add(vector)); + faceLocation(entity, entity.getLocation().clone().add(vector)); } public static void faceEntity(Entity entity, Entity to) { @@ -161,7 +156,7 @@ public class Util { if (to instanceof LivingEntity) { NMS.look(entity, to); } else { - faceLocation(entity, to.getLocation(AT_LOCATION)); + faceLocation(entity, to.getLocation()); } } @@ -180,7 +175,7 @@ public class Util { } public static Location getCenterLocation(Block block) { - Location bloc = block.getLocation(AT_LOCATION); + Location bloc = block.getLocation(); Location center = new Location(bloc.getWorld(), bloc.getBlockX() + 0.5, bloc.getBlockY(), bloc.getBlockZ() + 0.5); BoundingBox bb = NMS.getCollisionBox(block); @@ -194,7 +189,7 @@ public class Util { * Returns the yaw to face along the given velocity (corrected for dragon yaw i.e. facing backwards) */ public static float getDragonYaw(Entity entity, double motX, double motZ) { - Location location = entity.getLocation(AT_LOCATION); + Location location = entity.getLocation(); double x = location.getX(); double z = location.getZ(); double tX = x + motX; @@ -240,7 +235,7 @@ public class Util { public static boolean inBlock(Entity entity) { // TODO: bounding box aware? - Location loc = entity.getLocation(AT_LOCATION); + Location loc = entity.getLocation(); if (!Util.isLoaded(loc)) { return false; } @@ -557,7 +552,6 @@ public class Util { + TimeUnit.MILLISECONDS.convert(delay.getNano(), TimeUnit.NANOSECONDS)) / 50; } - private static final Location AT_LOCATION = new Location(null, 0, 0, 0); private static final Scoreboard DUMMY_SCOREBOARD = Bukkit.getScoreboardManager().getNewScoreboard(); private static String MINECRAFT_REVISION; private static final DecimalFormat TWO_DIGIT_DECIMAL = new DecimalFormat(); diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/BatController.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/BatController.java index 9e3f1c753..0cb2e4a3f 100644 --- a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/BatController.java +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/entity/BatController.java @@ -55,7 +55,7 @@ public class BatController extends MobEntityController { super(types, level); this.npc = (CitizensNPC) npc; if (npc != null) { - setFlying(false); + setResting(false); } } @@ -165,10 +165,6 @@ public class BatController extends MobEntityController { return npc == null ? super.save(save) : false; } - public void setFlying(boolean flying) { - setResting(flying); - } - @Override public boolean updateFluidHeightAndDoFluidPushing(Tag Tag, double d0) { if (npc == null) { diff --git a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerlistTracker.java b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerlistTracker.java index e731e6446..700f6a809 100644 --- a/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerlistTracker.java +++ b/v1_17_R1/src/main/java/net/citizensnpcs/nms/v1_17_R1/util/PlayerlistTracker.java @@ -54,20 +54,34 @@ public class PlayerlistTracker extends ChunkMap.TrackedEntity { public void updatePlayer(final ServerPlayer entityplayer) { if (!tracker.isRemoved() && !seenBy.contains(entityplayer.connection) && tracker instanceof NPCHolder) { NPC npc = ((NPCHolder) tracker).getNPC(); - NPCSeenByPlayerEvent event = new NPCSeenByPlayerEvent(npc, entityplayer.getBukkitEntity()); - REQUIRES_SYNC = Util.callEventPossiblySync(event, REQUIRES_SYNC); - if (event.isCancelled()) - return; - Integer trackingRange = npc.data(). get(NPC.Metadata.TRACKING_RANGE); - if (TRACKING_RANGE_SETTER != null && trackingRange != null - && npc.data().get("last-tracking-range", -1) != trackingRange.intValue()) { - try { - TRACKING_RANGE_SETTER.invoke(this, trackingRange); - npc.data().set("last-tracking-range", trackingRange); - } catch (Throwable e) { - e.printStackTrace(); - } + if (REQUIRES_SYNC == null) { + REQUIRES_SYNC = !Bukkit.isPrimaryThread(); } + boolean cancelled = Util.callPossiblySync(() -> { + NPCSeenByPlayerEvent event = new NPCSeenByPlayerEvent(npc, entityplayer.getBukkitEntity()); + try { + Bukkit.getPluginManager().callEvent(event); + } catch (IllegalStateException e) { + REQUIRES_SYNC = true; + throw e; + } + if (event.isCancelled()) + return true; + Integer trackingRange = npc.data(). get(NPC.Metadata.TRACKING_RANGE); + if (TRACKING_RANGE_SETTER != null && trackingRange != null + && npc.data().get("last-tracking-range", -1) != trackingRange.intValue()) { + try { + TRACKING_RANGE_SETTER.invoke(PlayerlistTracker.this, trackingRange); + npc.data().set("last-tracking-range", trackingRange); + } catch (Throwable e) { + e.printStackTrace(); + } + } + return false; + }, REQUIRES_SYNC); + + if (cancelled) + return; } if (entityplayer instanceof EntityHumanNPC) @@ -115,7 +129,7 @@ public class PlayerlistTracker extends ChunkMap.TrackedEntity { private static final MethodHandle E = NMS.getGetter(ServerEntity.class, "e"); private static final MethodHandle F = NMS.getGetter(ServerEntity.class, "f"); - private static volatile boolean REQUIRES_SYNC; + private static volatile Boolean REQUIRES_SYNC; private static final MethodHandle TRACKER = NMS.getFirstGetter(TrackedEntity.class, Entity.class); private static final MethodHandle TRACKER_ENTRY = NMS.getFirstGetter(TrackedEntity.class, ServerEntity.class); private static final MethodHandle TRACKING_RANGE = NMS.getFirstGetter(TrackedEntity.class, int.class); diff --git a/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/entity/BatController.java b/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/entity/BatController.java index 086529448..7d06303ca 100644 --- a/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/entity/BatController.java +++ b/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/entity/BatController.java @@ -57,7 +57,7 @@ public class BatController extends MobEntityController { super(types, level); this.npc = (CitizensNPC) npc; if (npc != null) { - setFlying(false); + setResting(false); } } @@ -167,10 +167,6 @@ public class BatController extends MobEntityController { return npc == null ? super.save(save) : false; } - public void setFlying(boolean flying) { - setResting(flying); - } - @Override public Entity teleportTo(ServerLevel worldserver, BlockPos location) { if (npc == null) diff --git a/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/util/PlayerlistTracker.java b/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/util/PlayerlistTracker.java index 0872f9332..309890be9 100644 --- a/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/util/PlayerlistTracker.java +++ b/v1_18_R2/src/main/java/net/citizensnpcs/nms/v1_18_R2/util/PlayerlistTracker.java @@ -54,20 +54,34 @@ public class PlayerlistTracker extends ChunkMap.TrackedEntity { public void updatePlayer(final ServerPlayer entityplayer) { if (!tracker.isRemoved() && !seenBy.contains(entityplayer.connection) && tracker instanceof NPCHolder) { NPC npc = ((NPCHolder) tracker).getNPC(); - NPCSeenByPlayerEvent event = new NPCSeenByPlayerEvent(npc, entityplayer.getBukkitEntity()); - REQUIRES_SYNC = Util.callEventPossiblySync(event, REQUIRES_SYNC); - if (event.isCancelled()) - return; - Integer trackingRange = npc.data(). get(NPC.Metadata.TRACKING_RANGE); - if (TRACKING_RANGE_SETTER != null && trackingRange != null - && npc.data().get("last-tracking-range", -1) != trackingRange.intValue()) { - try { - TRACKING_RANGE_SETTER.invoke(this, trackingRange); - npc.data().set("last-tracking-range", trackingRange); - } catch (Throwable e) { - e.printStackTrace(); - } + if (REQUIRES_SYNC == null) { + REQUIRES_SYNC = !Bukkit.isPrimaryThread(); } + boolean cancelled = Util.callPossiblySync(() -> { + NPCSeenByPlayerEvent event = new NPCSeenByPlayerEvent(npc, entityplayer.getBukkitEntity()); + try { + Bukkit.getPluginManager().callEvent(event); + } catch (IllegalStateException e) { + REQUIRES_SYNC = true; + throw e; + } + if (event.isCancelled()) + return true; + Integer trackingRange = npc.data(). get(NPC.Metadata.TRACKING_RANGE); + if (TRACKING_RANGE_SETTER != null && trackingRange != null + && npc.data().get("last-tracking-range", -1) != trackingRange.intValue()) { + try { + TRACKING_RANGE_SETTER.invoke(PlayerlistTracker.this, trackingRange); + npc.data().set("last-tracking-range", trackingRange); + } catch (Throwable e) { + e.printStackTrace(); + } + } + return false; + }, REQUIRES_SYNC); + + if (cancelled) + return; } if (entityplayer instanceof EntityHumanNPC) @@ -115,7 +129,7 @@ public class PlayerlistTracker extends ChunkMap.TrackedEntity { private static final MethodHandle E = NMS.getGetter(ServerEntity.class, "e"); private static final MethodHandle F = NMS.getGetter(ServerEntity.class, "f"); - private static volatile boolean REQUIRES_SYNC; + private static volatile Boolean REQUIRES_SYNC; private static final MethodHandle TRACKER = NMS.getFirstGetter(TrackedEntity.class, Entity.class); private static final MethodHandle TRACKER_ENTRY = NMS.getFirstGetter(TrackedEntity.class, ServerEntity.class); private static final MethodHandle TRACKING_RANGE = NMS.getFirstGetter(TrackedEntity.class, int.class); diff --git a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/entity/BatController.java b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/entity/BatController.java index e75debb0c..6540bfc79 100644 --- a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/entity/BatController.java +++ b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/entity/BatController.java @@ -57,7 +57,7 @@ public class BatController extends MobEntityController { super(types, level); this.npc = (CitizensNPC) npc; if (npc != null) { - setFlying(false); + setResting(false); } } @@ -167,10 +167,6 @@ public class BatController extends MobEntityController { return npc == null ? super.save(save) : false; } - public void setFlying(boolean flying) { - setResting(flying); - } - @Override public Entity teleportTo(ServerLevel worldserver, PositionImpl location) { if (npc == null) diff --git a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/CitizensEntityTracker.java b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/CitizensEntityTracker.java index a64c10619..68accd741 100644 --- a/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/CitizensEntityTracker.java +++ b/v1_19_R3/src/main/java/net/citizensnpcs/nms/v1_19_R3/util/CitizensEntityTracker.java @@ -81,20 +81,34 @@ public class CitizensEntityTracker extends ChunkMap.TrackedEntity { if (!tracker.isRemoved() && !seenBy.contains(entityplayer.connection) && tracker instanceof NPCHolder) { NPC npc = ((NPCHolder) tracker).getNPC(); - NPCSeenByPlayerEvent event = new NPCSeenByPlayerEvent(npc, entityplayer.getBukkitEntity()); - REQUIRES_SYNC = Util.callEventPossiblySync(event, REQUIRES_SYNC); - if (event.isCancelled()) - return; - Integer trackingRange = npc.data(). get(NPC.Metadata.TRACKING_RANGE); - if (TRACKING_RANGE_SETTER != null && trackingRange != null - && npc.data().get("last-tracking-range", -1) != trackingRange.intValue()) { - try { - TRACKING_RANGE_SETTER.invoke(this, trackingRange); - npc.data().set("last-tracking-range", trackingRange); - } catch (Throwable e) { - e.printStackTrace(); - } + if (REQUIRES_SYNC == null) { + REQUIRES_SYNC = !Bukkit.isPrimaryThread(); } + boolean cancelled = Util.callPossiblySync(() -> { + NPCSeenByPlayerEvent event = new NPCSeenByPlayerEvent(npc, entityplayer.getBukkitEntity()); + try { + Bukkit.getPluginManager().callEvent(event); + } catch (IllegalStateException e) { + REQUIRES_SYNC = true; + throw e; + } + if (event.isCancelled()) + return true; + Integer trackingRange = npc.data(). get(NPC.Metadata.TRACKING_RANGE); + if (TRACKING_RANGE_SETTER != null && trackingRange != null + && npc.data().get("last-tracking-range", -1) != trackingRange.intValue()) { + try { + TRACKING_RANGE_SETTER.invoke(CitizensEntityTracker.this, trackingRange); + npc.data().set("last-tracking-range", trackingRange); + } catch (Throwable e) { + e.printStackTrace(); + } + } + return false; + }, REQUIRES_SYNC); + + if (cancelled) + return; } super.updatePlayer(entityplayer); @@ -138,7 +152,7 @@ public class CitizensEntityTracker extends ChunkMap.TrackedEntity { private static final MethodHandle E = NMS.getGetter(ServerEntity.class, "e"); private static final MethodHandle F = NMS.getGetter(ServerEntity.class, "f"); - private static volatile boolean REQUIRES_SYNC = false; + private static volatile Boolean REQUIRES_SYNC = false; private static final MethodHandle TRACKER = NMS.getFirstGetter(TrackedEntity.class, Entity.class); private static final MethodHandle TRACKER_ENTRY = NMS.getFirstGetter(TrackedEntity.class, ServerEntity.class); private static final MethodHandle TRACKING_RANGE = NMS.getFirstGetter(TrackedEntity.class, int.class); diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/BatController.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/BatController.java index c51c1504f..effbccc53 100644 --- a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/BatController.java +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/entity/BatController.java @@ -57,7 +57,7 @@ public class BatController extends MobEntityController { super(types, level); this.npc = (CitizensNPC) npc; if (npc != null) { - setFlying(false); + setResting(false); } } @@ -167,10 +167,6 @@ public class BatController extends MobEntityController { return npc == null ? super.save(save) : false; } - public void setFlying(boolean flying) { - setResting(flying); - } - @Override public Entity teleportTo(ServerLevel worldserver, PositionImpl location) { if (npc == null) diff --git a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/CitizensEntityTracker.java b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/CitizensEntityTracker.java index a6ff6daac..8b9e26e8a 100644 --- a/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/CitizensEntityTracker.java +++ b/v1_20_R1/src/main/java/net/citizensnpcs/nms/v1_20_R1/util/CitizensEntityTracker.java @@ -84,20 +84,31 @@ public class CitizensEntityTracker extends ChunkMap.TrackedEntity { if (REQUIRES_SYNC == null) { REQUIRES_SYNC = !Bukkit.isPrimaryThread(); } - NPCSeenByPlayerEvent event = new NPCSeenByPlayerEvent(npc, entityplayer.getBukkitEntity()); - REQUIRES_SYNC = Util.callEventPossiblySync(event, REQUIRES_SYNC); - if (event.isCancelled()) - return; - Integer trackingRange = npc.data(). get(NPC.Metadata.TRACKING_RANGE); - if (TRACKING_RANGE_SETTER != null && trackingRange != null - && npc.data().get("last-tracking-range", -1) != trackingRange.intValue()) { + boolean cancelled = Util.callPossiblySync(() -> { + NPCSeenByPlayerEvent event = new NPCSeenByPlayerEvent(npc, entityplayer.getBukkitEntity()); try { - TRACKING_RANGE_SETTER.invoke(this, trackingRange); - npc.data().set("last-tracking-range", trackingRange); - } catch (Throwable e) { - e.printStackTrace(); + Bukkit.getPluginManager().callEvent(event); + } catch (IllegalStateException e) { + REQUIRES_SYNC = true; + throw e; } - } + if (event.isCancelled()) + return true; + Integer trackingRange = npc.data(). get(NPC.Metadata.TRACKING_RANGE); + if (TRACKING_RANGE_SETTER != null && trackingRange != null + && npc.data().get("last-tracking-range", -1) != trackingRange.intValue()) { + try { + TRACKING_RANGE_SETTER.invoke(CitizensEntityTracker.this, trackingRange); + npc.data().set("last-tracking-range", trackingRange); + } catch (Throwable e) { + e.printStackTrace(); + } + } + return false; + }, REQUIRES_SYNC); + + if (cancelled) + return; } super.updatePlayer(entityplayer);