Implement new PlayerFilter method, async-friendly chunk trackers

This commit is contained in:
fullwall 2023-06-25 21:58:09 +08:00
parent a2d7284fbc
commit 46f4444c10
27 changed files with 196 additions and 164 deletions

View File

@ -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();
}

View File

@ -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),

View File

@ -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(), () -> {

View File

@ -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<ChunkCoord, NPC> CHUNK_LOADERS = HashMultimap.create();
private static boolean SUPPORT_GLOWING = true;
private static boolean SUPPORT_NODAMAGE_TICKS = true;

View File

@ -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) {

View File

@ -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<VectorNode, Path> ASTAR = AStarMachine.createWithDefaultStorage();
private static final Location NPC_LOCATION = new Location(null, 0, 0, 0);
}

View File

@ -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;
}

View File

@ -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<VectorNode, Path> ASTAR = AStarMachine.createWithDefaultStorage();
private static final Location NPC_LOCATION = new Location(null, 0, 0, 0);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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();

View File

@ -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<Player> 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);
}

View File

@ -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");

View File

@ -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();

View File

@ -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<Player> getNearbyPlayers() {
List<Player> options = Lists.newArrayList();
Location npcLoc = npc.getStoredLocation();
Iterable<Player> 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);
}

View File

@ -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

View File

@ -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;

View File

@ -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> T callPossiblySync(Callable<T> 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();

View File

@ -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<Fluid> Tag, double d0) {
if (npc == null) {

View File

@ -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().<Integer> 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().<Integer> 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);

View File

@ -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)

View File

@ -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().<Integer> 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().<Integer> 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);

View File

@ -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)

View File

@ -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().<Integer> 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().<Integer> 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);

View File

@ -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)

View File

@ -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().<Integer> 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().<Integer> 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);