Misc small changes

This commit is contained in:
fullwall 2023-10-29 02:09:08 +08:00
parent dd247a9ee0
commit 751e2a28ac
26 changed files with 218 additions and 288 deletions

View File

@ -28,7 +28,6 @@ import com.comphenix.protocol.ProtocolLibrary;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.io.Files;
import com.mojang.authlib.GameProfile; import com.mojang.authlib.GameProfile;
import ch.ethz.globis.phtree.PhTreeHelper; 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.npc.skin.Skin;
import net.citizensnpcs.trait.ClickRedirectTrait; import net.citizensnpcs.trait.ClickRedirectTrait;
import net.citizensnpcs.trait.CommandTrait; import net.citizensnpcs.trait.CommandTrait;
import net.citizensnpcs.trait.HologramTrait;
import net.citizensnpcs.trait.ScriptTrait;
import net.citizensnpcs.trait.ShopTrait; import net.citizensnpcs.trait.ShopTrait;
import net.citizensnpcs.util.Messages; import net.citizensnpcs.util.Messages;
import net.citizensnpcs.util.NMS; import net.citizensnpcs.util.NMS;
@ -98,6 +95,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
private final CommandManager commands = new CommandManager(); private final CommandManager commands = new CommandManager();
private Settings config; private Settings config;
private boolean enabled; private boolean enabled;
private Locale locale;
private LocationLookup locationLookup; private LocationLookup locationLookup;
private final NMSHelper nmsHelper = new NMSHelper() { private final NMSHelper nmsHelper = new NMSHelper() {
private boolean SUPPORT_OWNER_PROFILE = true; private boolean SUPPORT_OWNER_PROFILE = true;
@ -185,11 +183,14 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
if (type.equalsIgnoreCase("nbt")) { if (type.equalsIgnoreCase("nbt")) {
saves = new NBTStorage(new File(folder, Setting.STORAGE_FILE.asString()), "Citizens NPC Storage"); saves = new NBTStorage(new File(folder, Setting.STORAGE_FILE.asString()), "Citizens NPC Storage");
} }
if (saves == null) { if (saves == null) {
saves = new YamlStorage(new File(folder, Setting.STORAGE_FILE.asString()), "Citizens NPC Storage"); saves = new YamlStorage(new File(folder, Setting.STORAGE_FILE.asString()), "Citizens NPC Storage");
} }
if (!saves.load()) if (!saves.load())
return null; return null;
return SimpleNPCDataStore.create(saves); return SimpleNPCDataStore.create(saves);
} }
@ -282,11 +283,6 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
return getClassLoader(); return getClassLoader();
} }
@Override
public File getScriptFolder() {
return new File(getDataFolder(), "scripts");
}
public StoredShops getShops() { public StoredShops getShops() {
return shops; return shops;
} }
@ -552,6 +548,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
} }
} }
Translator.setInstance(new File(getDataFolder(), "lang"), locale); Translator.setInstance(new File(getDataFolder(), "lang"), locale);
this.locale = locale;
} }
private void startMetrics() { private void startMetrics() {
@ -562,16 +559,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
return 0; return 0;
return Iterables.size(npcRegistry); return Iterables.size(npcRegistry);
})); }));
metrics.addCustomChart(new Metrics.AdvancedPie("hologram_direction", () -> { metrics.addCustomChart(new Metrics.SimplePie("locale", () -> locale.toString()));
Map<String, Integer> 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.AdvancedPie("traits", () -> { metrics.addCustomChart(new Metrics.AdvancedPie("traits", () -> {
Map<String, Integer> res = Maps.newHashMap(); Map<String, Integer> res = Maps.newHashMap();
for (NPC npc : npcRegistry) { for (NPC npc : npcRegistry) {
@ -583,19 +571,6 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
} }
return res; return res;
})); }));
metrics.addCustomChart(new Metrics.AdvancedPie("script_extensions", () -> {
Map<String, Integer> 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) { } catch (Exception e) {
Messaging.logTr(Messages.METRICS_ERROR_NOTIFICATION, e.getMessage()); Messaging.logTr(Messages.METRICS_ERROR_NOTIFICATION, e.getMessage());
} }
@ -630,7 +605,8 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
@Override @Override
public void run() { public void run() {
Plugin plib = Bukkit.getPluginManager().getPlugin("ProtocolLib"); 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 { try {
protocolListener = new ProtocolLibListener(Citizens.this); protocolListener = new ProtocolLibListener(Citizens.this);
} catch (Throwable t) { } catch (Throwable t) {

View File

@ -232,6 +232,7 @@ public class EventListen implements Listener {
public void onChunkUnload(final ChunkUnloadEvent event) { public void onChunkUnload(final ChunkUnloadEvent event) {
if (chunkEventListener != null) if (chunkEventListener != null)
return; return;
unloadNPCs(event, Arrays.asList(event.getChunk().getEntities())); unloadNPCs(event, Arrays.asList(event.getChunk().getEntities()));
} }
@ -401,6 +402,7 @@ public class EventListen implements Listener {
ChunkCoord coord = new ChunkCoord(event.getSpawnLocation()); ChunkCoord coord = new ChunkCoord(event.getSpawnLocation());
if (toRespawn.containsEntry(coord, event.getNPC())) if (toRespawn.containsEntry(coord, event.getNPC()))
return; return;
Messaging.debug("Stored", event.getNPC(), "for respawn from NPCNeedsRespawnEvent"); Messaging.debug("Stored", event.getNPC(), "for respawn from NPCNeedsRespawnEvent");
toRespawn.put(coord, event.getNPC()); toRespawn.put(coord, event.getNPC());
} }

View File

@ -74,6 +74,7 @@ public class ProtocolLibListener implements Listener {
NPC npc = getNPCFromPacket(event); NPC npc = getNPCFromPacket(event);
if (npc == null || !npc.data().has(NPC.Metadata.HOLOGRAM_LINE_SUPPLIER)) if (npc == null || !npc.data().has(NPC.Metadata.HOLOGRAM_LINE_SUPPLIER))
return; return;
Function<Player, String> hvs = npc.data().get(NPC.Metadata.HOLOGRAM_LINE_SUPPLIER); Function<Player, String> hvs = npc.data().get(NPC.Metadata.HOLOGRAM_LINE_SUPPLIER);
int version = manager.getProtocolVersion(event.getPlayer()); int version = manager.getProtocolVersion(event.getPlayer());
PacketContainer packet = event.getPacket(); PacketContainer packet = event.getPacket();
@ -81,6 +82,7 @@ public class ProtocolLibListener implements Listener {
List<WrappedWatchableObject> wwo = packet.getWatchableCollectionModifier().readSafely(0); List<WrappedWatchableObject> wwo = packet.getWatchableCollectionModifier().readSafely(0);
if (wwo == null) if (wwo == null)
return; return;
boolean delta = false; boolean delta = false;
String text = hvs.apply(event.getPlayer()); String text = hvs.apply(event.getPlayer());
for (WrappedWatchableObject wo : wwo) { for (WrappedWatchableObject wo : wwo) {
@ -94,6 +96,7 @@ public class ProtocolLibListener implements Listener {
delta = true; delta = true;
break; break;
} }
if (delta) { if (delta) {
packet.getWatchableCollectionModifier().write(0, wwo); packet.getWatchableCollectionModifier().write(0, wwo);
} }
@ -101,6 +104,7 @@ public class ProtocolLibListener implements Listener {
List<WrappedDataValue> wdvs = packet.getDataValueCollectionModifier().readSafely(0); List<WrappedDataValue> wdvs = packet.getDataValueCollectionModifier().readSafely(0);
if (wdvs == null) if (wdvs == null)
return; return;
boolean delta = false; boolean delta = false;
String text = hvs.apply(event.getPlayer()); String text = hvs.apply(event.getPlayer());
for (WrappedDataValue wdv : wdvs) { for (WrappedDataValue wdv : wdvs) {
@ -109,6 +113,7 @@ public class ProtocolLibListener implements Listener {
wdv.setValue(Optional.of(Messaging.minecraftComponentFromRawMessage(text))); wdv.setValue(Optional.of(Messaging.minecraftComponentFromRawMessage(text)));
break; break;
} }
if (delta) { if (delta) {
packet.getDataValueCollectionModifier().write(0, wdvs); packet.getDataValueCollectionModifier().write(0, wdvs);
} }
@ -138,6 +143,7 @@ public class ProtocolLibListener implements Listener {
PlayerInfoData npcInfo = list.get(i); PlayerInfoData npcInfo = list.get(i);
if (npcInfo == null) if (npcInfo == null)
continue; continue;
MirrorTrait trait = mirrorTraits.get(npcInfo.getProfile().getUUID()); MirrorTrait trait = mirrorTraits.get(npcInfo.getProfile().getUUID());
if (trait == null || !trait.isMirroring(event.getPlayer())) if (trait == null || !trait.isMirroring(event.getPlayer()))
continue; continue;
@ -239,6 +245,7 @@ public class ProtocolLibListener implements Listener {
Integer id = packet.getIntegers().readSafely(0); Integer id = packet.getIntegers().readSafely(0);
if (id == null) if (id == null)
return null; return null;
entity = manager.getEntityFromID(event.getPlayer().getWorld(), id); entity = manager.getEntityFromID(event.getPlayer().getWorld(), id);
} catch (FieldAccessException | IllegalArgumentException ex) { } catch (FieldAccessException | IllegalArgumentException ex) {
if (!LOGGED_ERROR) { if (!LOGGED_ERROR) {
@ -271,6 +278,7 @@ public class ProtocolLibListener implements Listener {
rotationTraits.put(event.getNPC().getEntity().getEntityId(), rotationTraits.put(event.getNPC().getEntity().getEntityId(),
event.getNPC().getTraitNullable(RotationTrait.class)); event.getNPC().getTraitNullable(RotationTrait.class));
} }
if (event.getNPC().hasTrait(MirrorTrait.class) if (event.getNPC().hasTrait(MirrorTrait.class)
&& event.getNPC().getOrAddTrait(MobType.class).getType() == EntityType.PLAYER) { && event.getNPC().getOrAddTrait(MobType.class).getType() == EntityType.PLAYER) {
mirrorTraits.put(event.getNPC().getEntity().getUniqueId(), mirrorTraits.put(event.getNPC().getEntity().getUniqueId(),

View File

@ -180,6 +180,7 @@ public class Settings {
"npc.hologram.always-update-position", false), "npc.hologram.always-update-position", false),
HOLOGRAM_UPDATE_RATE("How often to update hologram names (including placeholders)", HOLOGRAM_UPDATE_RATE("How often to update hologram names (including placeholders)",
"npc.hologram.update-rate-ticks", "npc.hologram.update-rate", "1s"), "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", 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"), "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), KEEP_CHUNKS_LOADED("Whether to keep NPC chunks loaded", "npc.chunks.always-keep-loaded", false),

View File

@ -123,7 +123,6 @@ import net.citizensnpcs.trait.FollowTrait;
import net.citizensnpcs.trait.GameModeTrait; import net.citizensnpcs.trait.GameModeTrait;
import net.citizensnpcs.trait.Gravity; import net.citizensnpcs.trait.Gravity;
import net.citizensnpcs.trait.HologramTrait; import net.citizensnpcs.trait.HologramTrait;
import net.citizensnpcs.trait.HologramTrait.HologramDirection;
import net.citizensnpcs.trait.HomeTrait; import net.citizensnpcs.trait.HomeTrait;
import net.citizensnpcs.trait.HorseModifiers; import net.citizensnpcs.trait.HorseModifiers;
import net.citizensnpcs.trait.LookClose; import net.citizensnpcs.trait.LookClose;
@ -138,7 +137,6 @@ import net.citizensnpcs.trait.Powered;
import net.citizensnpcs.trait.RabbitType; import net.citizensnpcs.trait.RabbitType;
import net.citizensnpcs.trait.RotationTrait; import net.citizensnpcs.trait.RotationTrait;
import net.citizensnpcs.trait.ScoreboardTrait; import net.citizensnpcs.trait.ScoreboardTrait;
import net.citizensnpcs.trait.ScriptTrait;
import net.citizensnpcs.trait.SheepTrait; import net.citizensnpcs.trait.SheepTrait;
import net.citizensnpcs.trait.ShopTrait; import net.citizensnpcs.trait.ShopTrait;
import net.citizensnpcs.trait.ShopTrait.NPCShop; import net.citizensnpcs.trait.ShopTrait.NPCShop;
@ -995,15 +993,15 @@ public class NPCCommands {
@Command( @Command(
aliases = { "npc" }, 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", desc = "Toggles NPC following you",
flags = "p", flags = "p",
modifiers = { "follow" }, modifiers = { "follow" },
min = 1, min = 1,
max = 2, max = 2,
permission = "citizens.npc.follow") permission = "citizens.npc.follow")
public void follow(CommandContext args, CommandSender sender, NPC npc, @Flag("margin") Double margin) public void follow(CommandContext args, CommandSender sender, NPC npc, @Flag("margin") Double margin,
throws CommandException { @Flag("enable") Boolean explicit) throws CommandException {
boolean protect = args.hasFlag('p'); boolean protect = args.hasFlag('p');
FollowTrait trait = npc.getOrAddTrait(FollowTrait.class); FollowTrait trait = npc.getOrAddTrait(FollowTrait.class);
if (margin != null) { if (margin != null) {
@ -1035,7 +1033,8 @@ public class NPCCommands {
args.getString(1)); args.getString(1));
return; return;
} }
boolean following = !trait.isEnabled();
boolean following = explicit == null ? !trait.isEnabled() : explicit;
trait.follow(following ? player.getPlayer() : null); trait.follow(following ? player.getPlayer() : null);
Messaging.sendTr(sender, following ? Messages.FOLLOW_SET : Messages.FOLLOW_UNSET, npc.getName(), Messaging.sendTr(sender, following ? Messages.FOLLOW_SET : Messages.FOLLOW_UNSET, npc.getName(),
player.getName()); player.getName());
@ -1129,17 +1128,15 @@ public class NPCCommands {
@Command( @Command(
aliases = { "npc" }, 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", desc = "Controls NPC hologram text",
modifiers = { "hologram" }, modifiers = { "hologram" },
min = 1, min = 1,
max = -1, max = -1,
permission = "citizens.npc.hologram") permission = "citizens.npc.hologram")
public void hologram(CommandContext args, CommandSender sender, NPC npc, public void hologram(CommandContext args, CommandSender sender, NPC npc, @Arg(
@Arg( value = 1,
value = 1, completions = { "add", "set", "remove", "clear", "lineheight", "margintop", "marginbottom" }) String action)
completions = { "add", "set", "remove", "clear", "lineheight", "direction", "margintop",
"marginbottom" }) String action)
throws CommandException { throws CommandException {
HologramTrait trait = npc.getOrAddTrait(HologramTrait.class); HologramTrait trait = npc.getOrAddTrait(HologramTrait.class);
if (args.argsLength() == 1) { if (args.argsLength() == 1) {
@ -1194,11 +1191,6 @@ public class NPCCommands {
} else if (action.equalsIgnoreCase("lineheight")) { } else if (action.equalsIgnoreCase("lineheight")) {
trait.setLineHeight(args.getDouble(2)); trait.setLineHeight(args.getDouble(2));
Messaging.sendTr(sender, Messages.HOLOGRAM_LINE_HEIGHT_SET, 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")) { } else if (action.equalsIgnoreCase("margintop")) {
if (args.argsLength() == 2) { if (args.argsLength() == 2) {
throw new CommandException(Messages.HOLOGRAM_INVALID_LINE); throw new CommandException(Messages.HOLOGRAM_INVALID_LINE);
@ -1385,20 +1377,24 @@ public class NPCCommands {
throws CommandException { throws CommandException {
EntityType type = npc.getOrAddTrait(MobType.class).getType(); EntityType type = npc.getOrAddTrait(MobType.class).getType();
if (!type.name().contains("ITEM_FRAME") && !type.name().contains("ITEM_DISPLAY") 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)); throw new CommandException(CommandMessages.REQUIREMENTS_INVALID_MOB_TYPE, Util.prettyEnum(type));
ItemStack stack = args.hasFlag('h') ? ((Player) sender).getItemInHand() : new ItemStack(mat, 1); ItemStack stack = args.hasFlag('h') ? ((Player) sender).getItemInHand() : new ItemStack(mat, 1);
if (modify != null) { if (modify != null) {
stack = Util.parseItemStack(stack, modify); stack = Util.parseItemStack(stack, modify);
} }
if (mat == null && !args.hasFlag('h')) if (mat == null && !args.hasFlag('h'))
throw new CommandException(Messages.UNKNOWN_MATERIAL); throw new CommandException(Messages.UNKNOWN_MATERIAL);
ItemStack fstack = stack.clone(); ItemStack fstack = stack.clone();
npc.setItemProvider(() -> fstack); npc.setItemProvider(() -> fstack);
if (npc.isSpawned()) { if (npc.isSpawned()) {
npc.despawn(DespawnReason.PENDING_RESPAWN); npc.despawn(DespawnReason.PENDING_RESPAWN);
npc.spawn(npc.getStoredLocation(), SpawnReason.RESPAWN); npc.spawn(npc.getStoredLocation(), SpawnReason.RESPAWN);
} }
Messaging.sendTr(sender, Messages.ITEM_SET, Util.prettyEnum(stack.getType())); 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<String> files = new ArrayList<String>();
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( @Command(
aliases = { "npc" }, aliases = { "npc" },
usage = "select|sel [id|name] (--range range) (--registry [name])", usage = "select|sel [id|name] (--range range) (--registry [name])",

View File

@ -343,6 +343,7 @@ public class CitizensNPC extends AbstractNPC {
Messaging.debug("Retrying spawn of", this, "later, SpawnReason." + reason + ". Was loaded", loaded, Messaging.debug("Retrying spawn of", this, "later, SpawnReason." + reason + ". Was loaded", loaded,
"is loaded", Util.isLoaded(at)); "is loaded", Util.isLoaded(at));
} }
// we need to wait before trying to spawn // we need to wait before trying to spawn
entityController.remove(); entityController.remove();
Bukkit.getPluginManager().callEvent(new NPCNeedsRespawnEvent(this, at)); Bukkit.getPluginManager().callEvent(new NPCNeedsRespawnEvent(this, at));

View File

@ -87,7 +87,8 @@ public class CitizensNPCRegistry implements NPCRegistry {
public NPC createNPCUsingItem(EntityType type, String name, ItemStack item) { public NPC createNPCUsingItem(EntityType type, String name, ItemStack item) {
NPC npc = createNPC(type, name); NPC npc = createNPC(type, name);
if (type == EntityType.DROPPED_ITEM || type == EntityType.FALLING_BLOCK || type == EntityType.ITEM_FRAME 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_AMOUNT, item.getAmount());
npc.data().set(NPC.Metadata.ITEM_ID, item.getType().name()); npc.data().set(NPC.Metadata.ITEM_ID, item.getType().name());
npc.data().set(NPC.Metadata.ITEM_DATA, item.getData().getData()); npc.data().set(NPC.Metadata.ITEM_DATA, item.getData().getData());

View File

@ -49,7 +49,6 @@ import net.citizensnpcs.trait.RabbitType;
import net.citizensnpcs.trait.RotationTrait; import net.citizensnpcs.trait.RotationTrait;
import net.citizensnpcs.trait.Saddle; import net.citizensnpcs.trait.Saddle;
import net.citizensnpcs.trait.ScoreboardTrait; import net.citizensnpcs.trait.ScoreboardTrait;
import net.citizensnpcs.trait.ScriptTrait;
import net.citizensnpcs.trait.SheepTrait; import net.citizensnpcs.trait.SheepTrait;
import net.citizensnpcs.trait.SitTrait; import net.citizensnpcs.trait.SitTrait;
import net.citizensnpcs.trait.SkinLayers; import net.citizensnpcs.trait.SkinLayers;
@ -117,7 +116,6 @@ public class CitizensTraitFactory implements TraitFactory {
registerTrait(TraitInfo.create(RotationTrait.class)); registerTrait(TraitInfo.create(RotationTrait.class));
registerTrait(TraitInfo.create(Saddle.class)); registerTrait(TraitInfo.create(Saddle.class));
registerTrait(TraitInfo.create(ScoreboardTrait.class)); registerTrait(TraitInfo.create(ScoreboardTrait.class));
registerTrait(TraitInfo.create(ScriptTrait.class).optInToStats());
registerTrait(TraitInfo.create(SitTrait.class).optInToStats()); registerTrait(TraitInfo.create(SitTrait.class).optInToStats());
registerTrait(TraitInfo.create(SleepTrait.class)); registerTrait(TraitInfo.create(SleepTrait.class));
registerTrait(TraitInfo.create(SheepTrait.class)); registerTrait(TraitInfo.create(SheepTrait.class));

View File

@ -45,6 +45,7 @@ public class DropsTrait extends Trait {
public void onNPCDeath(NPCDeathEvent event) { public void onNPCDeath(NPCDeathEvent event) {
if (!event.getNPC().equals(npc)) if (!event.getNPC().equals(npc))
return; return;
Random random = Util.getFastRandom(); Random random = Util.getFastRandom();
for (ItemDrop drop : drops) { for (ItemDrop drop : drops) {
if (random.nextDouble() < drop.chance) { if (random.nextDouble() < drop.chance) {

View File

@ -43,8 +43,6 @@ import net.citizensnpcs.util.Util;
public class HologramTrait extends Trait { public class HologramTrait extends Trait {
private Location currentLoc; private Location currentLoc;
private BiFunction<String, Player, String> customHologramSupplier; private BiFunction<String, Player, String> customHologramSupplier;
@Persist
private HologramDirection direction = HologramDirection.BOTTOM_UP;
private double lastEntityHeight = 0; private double lastEntityHeight = 0;
private boolean lastNameplateVisible; private boolean lastNameplateVisible;
@Persist @Persist
@ -110,10 +108,7 @@ public class HologramTrait extends Trait {
hologramNPC.addTrait(PacketNPC.class); hologramNPC.addTrait(PacketNPC.class);
} }
hologramNPC.spawn(currentLoc.clone().add(0, hologramNPC.spawn(currentLoc.clone().add(0, getEntityHeight() + heightOffset, 0));
getEntityHeight()
+ (direction == HologramDirection.BOTTOM_UP ? heightOffset : getMaxHeight() - heightOffset),
0));
if (useDisplayEntities) { if (useDisplayEntities) {
((Interaction) hologramNPC.getEntity()).setInteractionWidth(0); ((Interaction) hologramNPC.getEntity()).setInteractionWidth(0);
@ -150,13 +145,6 @@ public class HologramTrait extends Trait {
return hologramNPC; return hologramNPC;
} }
/**
* @return The direction that hologram lines are displayed in
*/
public HologramDirection getDirection() {
return direction;
}
private double getEntityHeight() { private double getEntityHeight() {
return NMS.getHeight(npc.getEntity()); return NMS.getHeight(npc.getEntity());
} }
@ -195,10 +183,6 @@ public class HologramTrait extends Trait {
return Lists.transform(lines, l -> l.text); 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. * 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) { if (updatePosition && !useDisplayEntities) {
Location tp = npcLoc.clone().add(0, lastEntityHeight Location tp = npcLoc.clone().add(0, lastEntityHeight + getHeight(i), 0);
+ (direction == HologramDirection.BOTTOM_UP ? getHeight(i) : getMaxHeight() - getHeight(i)), 0);
hologramNPC.teleport(tp, TeleportCause.PLUGIN); 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 * Sets the hologram line at a specific index
* *
@ -461,11 +433,6 @@ public class HologramTrait extends Trait {
reloadLineHolograms(); reloadLineHolograms();
} }
public enum HologramDirection {
BOTTOM_UP,
TOP_DOWN;
}
private class HologramLine implements Function<Player, String> { private class HologramLine implements Function<Player, String> {
NPC hologram; NPC hologram;
double mb, mt; double mb, mt;

View File

@ -109,6 +109,7 @@ public class RotationTrait extends Trait {
PacketRotationSession session = itr.next(); PacketRotationSession session = itr.next();
if (ran.contains(session)) if (ran.contains(session))
continue; continue;
ran.add(session); ran.add(session);
session.run(npc.getEntity()); session.run(npc.getEntity());
if (!session.isActive()) { if (!session.isActive()) {
@ -192,6 +193,7 @@ public class RotationTrait extends Trait {
if (triple == null) { if (triple == null) {
triple = new PacketRotationTriple(entity); triple = new PacketRotationTriple(entity);
} }
session.run(triple); session.run(triple);
if (!session.isActive()) { if (!session.isActive()) {
triple = null; triple = null;

View File

@ -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<String> files = new ArrayList<String>();
private final List<RunnableScript> runnableScripts = new ArrayList<RunnableScript>();
public ScriptTrait() {
super("scripttrait");
}
/**
* Add and load all given script file names
*
* @see #loadScript(String)
*/
public void addScripts(List<String> scripts) {
for (String f : scripts) {
if (!files.contains(f) && validateFile(f)) {
loadScript(f);
files.add(f);
}
}
}
public List<String> 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<String> scripts) {
files.removeAll(scripts);
Iterator<RunnableScript> itr = runnableScripts.iterator();
while (itr.hasNext()) {
if (scripts.remove(itr.next().file)) {
itr.remove();
}
}
}
@Override
public void run() {
Iterator<RunnableScript> 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;
}
}
}

View File

@ -7,6 +7,7 @@ import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender; import org.bukkit.command.CommandSender;
import org.bukkit.entity.Entity; import org.bukkit.entity.Entity;
import org.bukkit.entity.EntityType; import org.bukkit.entity.EntityType;
import org.bukkit.entity.Pose;
import org.bukkit.entity.Warden; import org.bukkit.entity.Warden;
import com.google.common.collect.Maps; 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.Trait;
import net.citizensnpcs.api.trait.TraitName; import net.citizensnpcs.api.trait.TraitName;
import net.citizensnpcs.api.util.Messaging; import net.citizensnpcs.api.util.Messaging;
import net.citizensnpcs.util.Messages;
import net.citizensnpcs.util.NMS;
@TraitName("wardentrait") @TraitName("wardentrait")
public class WardenTrait extends Trait { public class WardenTrait extends Trait {
@ -46,16 +49,16 @@ public class WardenTrait extends Trait {
@Command( @Command(
aliases = { "npc" }, 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", desc = "Sets warden modifiers",
modifiers = { "warden" }, modifiers = { "warden" },
min = 1, min = 1,
max = 4, max = 4,
permission = "citizens.npc.warden") permission = "citizens.npc.warden")
@Requirements(selected = true, ownership = true, types = EntityType.WARDEN) @Requirements(selected = true, ownership = true, types = EntityType.WARDEN)
public static void Warden(CommandContext args, CommandSender sender, NPC npc, 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) @Arg(value = 1, completions = { "anger", "dig", "emerge", "roar" }) String command, @Arg(2) String player,
throws CommandException { @Arg(3) Integer anger) throws CommandException {
WardenTrait trait = npc.getOrAddTrait(WardenTrait.class); WardenTrait trait = npc.getOrAddTrait(WardenTrait.class);
String output = ""; String output = "";
if (command.equalsIgnoreCase("anger")) { if (command.equalsIgnoreCase("anger")) {
@ -68,9 +71,20 @@ public class WardenTrait extends Trait {
} catch (IllegalArgumentException iae) { } catch (IllegalArgumentException iae) {
entity = Bukkit.getOfflinePlayer(player).getPlayer(); entity = Bukkit.getOfflinePlayer(player).getPlayer();
} }
if (entity != null) { if (entity != null) {
trait.addAnger(entity, anger); 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()) { if (!output.isEmpty()) {

View File

@ -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_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_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 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_ADDED = "citizens.commands.waypoints.add.waypoint-added";
public static final String WAYPOINT_PROVIDER_SET = "citizens.waypoints.set-provider"; public static final String WAYPOINT_PROVIDER_SET = "citizens.waypoints.set-provider";
public static final String WAYPOINT_REMOVED = "citizens.commands.waypoints.waypoint-removed"; public static final String WAYPOINT_REMOVED = "citizens.commands.waypoints.waypoint-removed";

View File

@ -852,10 +852,14 @@ public class NMS {
BRIDGE.setTeamNameTagVisible(team, visible); 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); BRIDGE.setVerticalMovement(bukkitEntity, d);
} }
public static void setWardenPose(Entity entity, Object pose) {
BRIDGE.setWardenPose(entity, pose);
}
public static void setWitherInvulnerable(Wither wither, boolean charged) { public static void setWitherInvulnerable(Wither wither, boolean charged) {
BRIDGE.setWitherCharged(wither, charged); BRIDGE.setWitherCharged(wither, charged);
} }

View File

@ -48,7 +48,7 @@ import net.citizensnpcs.util.EntityPacketTracker.PacketAggregator;
public interface NMSBridge { public interface NMSBridge {
default void activate(Entity entity) { default void activate(Entity entity) {
}; }
public boolean addEntityToWorld(Entity entity, SpawnReason custom); public boolean addEntityToWorld(Entity entity, SpawnReason custom);
@ -60,9 +60,9 @@ public interface NMSBridge {
public default Iterable<Object> createBundlePacket(List<Object> packets) { public default Iterable<Object> createBundlePacket(List<Object> packets) {
return 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; public GameProfile fillProfileProperties(GameProfile profile, boolean requireSecure) throws Throwable;
@ -82,9 +82,9 @@ public interface NMSBridge {
public float getHeadYaw(Entity entity); 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); public CompoundTag getNBT(ItemStack item);
@ -147,9 +147,9 @@ public interface NMSBridge {
public Runnable playerTicker(Player entity); 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); public void removeFromServerPlayerList(Player player);
@ -165,7 +165,7 @@ public interface NMSBridge {
public void sendTabListRemove(Player recipient, Collection<? extends SkinnableEntity> skinnableNPCs); public void sendTabListRemove(Player recipient, Collection<? extends SkinnableEntity> skinnableNPCs);
public void sendTabListRemove(Player recipient, Player listPlayer); public void sendTabListRemove(Player recipient, Player listPlayer);;
public void sendTeamPacket(Player recipient, Team team, int mode);; public void sendTeamPacket(Player recipient, Team team, int mode);;
@ -174,11 +174,11 @@ public interface NMSBridge {
public default void setAllayDancing(Entity entity, boolean dancing) { public default void setAllayDancing(Entity entity, boolean dancing) {
throw new UnsupportedOperationException(); 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) { public default void setCamelPose(Entity entity, CamelPose pose) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
@ -245,6 +245,9 @@ public interface NMSBridge {
public void setVerticalMovement(Entity bukkitEntity, double d); public void setVerticalMovement(Entity bukkitEntity, double d);
public default void setWardenPose(Entity entity, Object pose) {
}
public void setWitherCharged(Wither wither, boolean charged); public void setWitherCharged(Wither wither, boolean charged);
public boolean shouldJump(Entity entity); public boolean shouldJump(Entity entity);
@ -264,5 +267,5 @@ public interface NMSBridge {
public void updateNavigationWorld(Entity entity, World world); public void updateNavigationWorld(Entity entity, World world);
public void updatePathfindingRange(NPC npc, float pathfindingRange);; public void updatePathfindingRange(NPC npc, float pathfindingRange);
} }

View File

@ -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.useitem.offhand-item-toggled=Using offhand item set to [[{0}]].
citizens.commands.npc.vulnerable.set=[[{0}]] is now vulnerable. citizens.commands.npc.vulnerable.set=[[{0}]] is now vulnerable.
citizens.commands.npc.vulnerable.stopped=[[{0}]] is no longer 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.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.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}]]. citizens.commands.npc.villager.level-set=Level set to [[{0}]].

View File

@ -116,5 +116,6 @@ public class PlayerControllerMove extends ControllerMove {
@Override @Override
public double f() { public double f() {
return thi return this.e;
}
} }

View File

@ -159,9 +159,9 @@ public class EntityHumanNPC extends EntityPlayer implements NPCHolder, Skinnable
public void die(DamageSource damagesource) { public void die(DamageSource damagesource) {
// players that die are not normally removed from the world. when the // 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. // NPC dies, we are done with the instance and it should be removed.
if (dead) { if (dead)
return; return;
}
super.die(damagesource); super.die(damagesource);
Bukkit.getScheduler().runTaskLater(CitizensAPI.getPlugin(), new Runnable() { Bukkit.getScheduler().runTaskLater(CitizensAPI.getPlugin(), new Runnable() {
@Override @Override
@ -389,11 +389,13 @@ public class EntityHumanNPC extends EntityPlayer implements NPCHolder, Skinnable
super.tick(); super.tick();
if (npc == null) if (npc == null)
return; return;
noclip = isSpectator(); noclip = isSpectator();
Bukkit.getServer().getPluginManager().unsubscribeFromPermission("bukkit.broadcast.user", getBukkitEntity()); Bukkit.getServer().getPluginManager().unsubscribeFromPermission("bukkit.broadcast.user", getBukkitEntity());
boolean navigating = npc.getNavigator().isNavigating(); boolean navigating = npc.getNavigator().isNavigating();
updatePackets(navigating); updatePackets(navigating);
npc.update(); npc.update();
if (npc.data().get(NPC.Metadata.PICKUP_ITEMS, false)) { if (npc.data().get(NPC.Metadata.PICKUP_ITEMS, false)) {
AxisAlignedBB axisalignedbb; AxisAlignedBB axisalignedbb;
if (this.isPassenger() && !this.getVehicle().dead) { if (this.isPassenger() && !this.getVehicle().dead) {
@ -401,6 +403,7 @@ public class EntityHumanNPC extends EntityPlayer implements NPCHolder, Skinnable
} else { } else {
axisalignedbb = this.getBoundingBox().grow(1.0, 0.5, 1.0); axisalignedbb = this.getBoundingBox().grow(1.0, 0.5, 1.0);
} }
for (Entity entity : this.world.getEntities(this, axisalignedbb)) { for (Entity entity : this.world.getEntities(this, axisalignedbb)) {
if (!entity.dead) { if (!entity.dead) {
entity.pickup(this); entity.pickup(this);

View File

@ -147,9 +147,9 @@ public class EntityHumanNPC extends EntityPlayer implements NPCHolder, Skinnable
public void die(DamageSource damagesource) { public void die(DamageSource damagesource) {
// players that die are not normally removed from the world. when the // 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. // NPC dies, we are done with the instance and it should be removed.
if (dead) { if (dead)
return; return;
}
super.die(damagesource); super.die(damagesource);
Bukkit.getScheduler().runTaskLater(CitizensAPI.getPlugin(), new Runnable() { Bukkit.getScheduler().runTaskLater(CitizensAPI.getPlugin(), new Runnable() {
@Override @Override

View File

@ -6,7 +6,7 @@
<parent> <parent>
<groupId>net.citizensnpcs</groupId> <groupId>net.citizensnpcs</groupId>
<artifactId>citizens-parent</artifactId> <artifactId>citizens-parent</artifactId>
<version>2.0.32-SNAPSHOT</version> <version>2.0.33-SNAPSHOT</version>
</parent> </parent>
<artifactId>citizens-v1_17_R1</artifactId> <artifactId>citizens-v1_17_R1</artifactId>
<properties> <properties>

View File

@ -1,7 +1,9 @@
package net.citizensnpcs.nms.v1_19_R3.entity.nonliving; package net.citizensnpcs.nms.v1_19_R3.entity.nonliving;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_19_R3.CraftServer; 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.CraftBlockDisplay;
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftEntity; import org.bukkit.craftbukkit.v1_19_R3.entity.CraftEntity;
import org.bukkit.util.Vector; import org.bukkit.util.Vector;
@ -32,6 +34,17 @@ public class BlockDisplayController extends MobEntityController {
super(EntityBlockDisplayNPC.class); 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 @Override
public org.bukkit.entity.BlockDisplay getBukkitEntity() { public org.bukkit.entity.BlockDisplay getBukkitEntity() {
return (org.bukkit.entity.BlockDisplay) super.getBukkitEntity(); return (org.bukkit.entity.BlockDisplay) super.getBukkitEntity();

View File

@ -297,6 +297,7 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerPlayerConnection; import net.minecraft.server.network.ServerPlayerConnection;
import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.tags.FluidTags; import net.minecraft.tags.FluidTags;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.world.Container; 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.EnderMan;
import net.minecraft.world.entity.monster.Shulker; import net.minecraft.world.entity.monster.Shulker;
import net.minecraft.world.entity.monster.piglin.Piglin; 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.projectile.FishingHook;
import net.minecraft.world.entity.vehicle.AbstractMinecart; import net.minecraft.world.entity.vehicle.AbstractMinecart;
import net.minecraft.world.inventory.AnvilMenu; import net.minecraft.world.inventory.AnvilMenu;
@ -1665,6 +1667,44 @@ public class NMSImpl implements NMSBridge {
handle.xxa = (float) d; 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 @Override
public void setWitherCharged(Wither wither, boolean charged) { public void setWitherCharged(Wither wither, boolean charged) {
WitherBoss handle = ((CraftWither) wither).getHandle(); WitherBoss handle = ((CraftWither) wither).getHandle();

View File

@ -15,7 +15,6 @@ import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.NMS; import net.citizensnpcs.util.NMS;
import net.citizensnpcs.util.Util; import net.citizensnpcs.util.Util;
import net.minecraft.core.BlockPos; import net.minecraft.core.BlockPos;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvent;
@ -94,6 +93,7 @@ public class WardenController extends MobEntityController {
super.customServerAiStep(); super.customServerAiStep();
return; return;
} }
NMSImpl.updateMinecraftAIState(npc, this); NMSImpl.updateMinecraftAIState(npc, this);
npc.update(); npc.update();
if (npc.useMinecraftAI()) { if (npc.useMinecraftAI()) {

View File

@ -1,7 +1,9 @@
package net.citizensnpcs.nms.v1_20_R2.entity.nonliving; package net.citizensnpcs.nms.v1_20_R2.entity.nonliving;
import org.bukkit.Bukkit; import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_20_R2.CraftServer; 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.CraftBlockDisplay;
import org.bukkit.craftbukkit.v1_20_R2.entity.CraftEntity; import org.bukkit.craftbukkit.v1_20_R2.entity.CraftEntity;
import org.bukkit.util.Vector; 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.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder; import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.Util; import net.citizensnpcs.util.Util;
import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.TagKey; import net.minecraft.tags.TagKey;
@ -32,6 +33,17 @@ public class BlockDisplayController extends MobEntityController {
super(EntityBlockDisplayNPC.class); 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 @Override
public org.bukkit.entity.BlockDisplay getBukkitEntity() { public org.bukkit.entity.BlockDisplay getBukkitEntity() {
return (org.bukkit.entity.BlockDisplay) super.getBukkitEntity(); return (org.bukkit.entity.BlockDisplay) super.getBukkitEntity();
@ -111,6 +123,7 @@ public class BlockDisplayController extends MobEntityController {
public Entity teleportTo(ServerLevel worldserver, Vec3 location) { public Entity teleportTo(ServerLevel worldserver, Vec3 location) {
if (npc == null) if (npc == null)
return super.teleportTo(worldserver, location); return super.teleportTo(worldserver, location);
return NMSImpl.teleportAcrossWorld(this, worldserver, location); return NMSImpl.teleportAcrossWorld(this, worldserver, location);
} }

View File

@ -287,6 +287,7 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer; import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerPlayerConnection; import net.minecraft.server.network.ServerPlayerConnection;
import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.tags.FluidTags; import net.minecraft.tags.FluidTags;
import net.minecraft.util.Mth; import net.minecraft.util.Mth;
import net.minecraft.world.Container; 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.EnderMan;
import net.minecraft.world.entity.monster.Shulker; import net.minecraft.world.entity.monster.Shulker;
import net.minecraft.world.entity.monster.piglin.Piglin; 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.projectile.FishingHook;
import net.minecraft.world.entity.vehicle.AbstractMinecart; import net.minecraft.world.entity.vehicle.AbstractMinecart;
import net.minecraft.world.inventory.AnvilMenu; import net.minecraft.world.inventory.AnvilMenu;
@ -457,7 +459,7 @@ public class NMSImpl implements NMSBridge {
} }
EnchantmentHelper.doPostHurtEffects(source, target); EnchantmentHelper.doPostHurtEffects(source, target);
EnchantmentHelper.doPostDamageEffects(target, source); EnchantmentHelper.doPostDamageEffects(target, source);
}; }
@Override @Override
public void cancelMoveDestination(org.bukkit.entity.Entity entity) { public void cancelMoveDestination(org.bukkit.entity.Entity entity) {
@ -473,7 +475,7 @@ public class NMSImpl implements NMSBridge {
t.printStackTrace(); t.printStackTrace();
} }
} }
} };
@Override @Override
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
@ -1641,6 +1643,44 @@ public class NMSImpl implements NMSBridge {
handle.xxa = (float) d; 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 @Override
public void setWitherCharged(Wither wither, boolean charged) { public void setWitherCharged(Wither wither, boolean charged) {
WitherBoss handle = ((CraftWither) wither).getHandle(); WitherBoss handle = ((CraftWither) wither).getHandle();
@ -1672,7 +1712,7 @@ public class NMSImpl implements NMSBridge {
@Override @Override
public void sleep(org.bukkit.entity.Player player, boolean sleeping) { public void sleep(org.bukkit.entity.Player player, boolean sleeping) {
getHandle(player).setPose(sleeping ? Pose.SLEEPING : Pose.STANDING); getHandle(player).setPose(sleeping ? Pose.SLEEPING : Pose.STANDING);
} };
@Override @Override
public void trySwim(org.bukkit.entity.Entity entity) { public void trySwim(org.bukkit.entity.Entity entity) {
@ -2197,17 +2237,30 @@ public class NMSImpl implements NMSBridge {
if (pitch == null) { if (pitch == null) {
pitch = handle.getXRot(); pitch = handle.getXRot();
} }
List<Packet<?>> toSend = Lists.newArrayList(); List<Packet<?>> toSend = Lists.newArrayList();
if (position) { if (position) {
TrackedEntity entry = ((ServerLevel) handle.level()).getChunkSource().chunkMap.entityMap TrackedEntity entry = ((ServerLevel) handle.level()).getChunkSource().chunkMap.entityMap
.get(handle.getId()); .get(handle.getId());
if (entry == null) {
Messaging.debug("Null tracker entity for ", from);
return Collections.emptyList();
}
VecDeltaCodec vdc = null; VecDeltaCodec vdc = null;
try { 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) { } catch (Throwable e) {
e.printStackTrace(); e.printStackTrace();
return Collections.emptyList(); return Collections.emptyList();
} }
Vec3 pos = handle.trackingPosition(); Vec3 pos = handle.trackingPosition();
toSend.add(new ClientboundMoveEntityPacket.PosRot(handle.getId(), (short) vdc.encodeX(pos), 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), (short) vdc.encodeY(pos), (short) vdc.encodeZ(pos), (byte) (bodyYaw * 256.0F / 360.0F),