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

View File

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

View File

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

View File

@ -180,6 +180,7 @@ public class Settings {
"npc.hologram.always-update-position", false),
HOLOGRAM_UPDATE_RATE("How often to update hologram names (including placeholders)",
"npc.hologram.update-rate-ticks", "npc.hologram.update-rate", "1s"),
HOOK_PROTOCOLLIB("Whether to hook into ProtocolLib", "general.interop.protocollib", true),
INITIAL_PLAYER_JOIN_SKIN_PACKET_DELAY("How long to wait before sending skins to joined players",
"npc.skins.player-join-update-delay-ticks", "npc.skins.player-join-update-delay", "1s"),
KEEP_CHUNKS_LOADED("Whether to keep NPC chunks loaded", "npc.chunks.always-keep-loaded", false),

View File

@ -123,7 +123,6 @@ import net.citizensnpcs.trait.FollowTrait;
import net.citizensnpcs.trait.GameModeTrait;
import net.citizensnpcs.trait.Gravity;
import net.citizensnpcs.trait.HologramTrait;
import net.citizensnpcs.trait.HologramTrait.HologramDirection;
import net.citizensnpcs.trait.HomeTrait;
import net.citizensnpcs.trait.HorseModifiers;
import net.citizensnpcs.trait.LookClose;
@ -138,7 +137,6 @@ import net.citizensnpcs.trait.Powered;
import net.citizensnpcs.trait.RabbitType;
import net.citizensnpcs.trait.RotationTrait;
import net.citizensnpcs.trait.ScoreboardTrait;
import net.citizensnpcs.trait.ScriptTrait;
import net.citizensnpcs.trait.SheepTrait;
import net.citizensnpcs.trait.ShopTrait;
import net.citizensnpcs.trait.ShopTrait.NPCShop;
@ -995,15 +993,15 @@ public class NPCCommands {
@Command(
aliases = { "npc" },
usage = "follow (player name|NPC id) (-p[rotect]) (--margin [margin])",
usage = "follow (player name|NPC id) (-p[rotect]) (--margin [margin]) (--enable [boolean])",
desc = "Toggles NPC following you",
flags = "p",
modifiers = { "follow" },
min = 1,
max = 2,
permission = "citizens.npc.follow")
public void follow(CommandContext args, CommandSender sender, NPC npc, @Flag("margin") Double margin)
throws CommandException {
public void follow(CommandContext args, CommandSender sender, NPC npc, @Flag("margin") Double margin,
@Flag("enable") Boolean explicit) throws CommandException {
boolean protect = args.hasFlag('p');
FollowTrait trait = npc.getOrAddTrait(FollowTrait.class);
if (margin != null) {
@ -1035,7 +1033,8 @@ public class NPCCommands {
args.getString(1));
return;
}
boolean following = !trait.isEnabled();
boolean following = explicit == null ? !trait.isEnabled() : explicit;
trait.follow(following ? player.getPlayer() : null);
Messaging.sendTr(sender, following ? Messages.FOLLOW_SET : Messages.FOLLOW_UNSET, npc.getName(),
player.getName());
@ -1129,17 +1128,15 @@ public class NPCCommands {
@Command(
aliases = { "npc" },
usage = "hologram add [text] | set [line #] [text] | remove [line #] | clear | lineheight [height] | direction [up|down] | margintop [line #] [margin] | marginbottom [line #] [margin]",
usage = "hologram add [text] | set [line #] [text] | remove [line #] | clear | lineheight [height] | margintop [line #] [margin] | marginbottom [line #] [margin]",
desc = "Controls NPC hologram text",
modifiers = { "hologram" },
min = 1,
max = -1,
permission = "citizens.npc.hologram")
public void hologram(CommandContext args, CommandSender sender, NPC npc,
@Arg(
value = 1,
completions = { "add", "set", "remove", "clear", "lineheight", "direction", "margintop",
"marginbottom" }) String action)
public void hologram(CommandContext args, CommandSender sender, NPC npc, @Arg(
value = 1,
completions = { "add", "set", "remove", "clear", "lineheight", "margintop", "marginbottom" }) String action)
throws CommandException {
HologramTrait trait = npc.getOrAddTrait(HologramTrait.class);
if (args.argsLength() == 1) {
@ -1194,11 +1191,6 @@ public class NPCCommands {
} else if (action.equalsIgnoreCase("lineheight")) {
trait.setLineHeight(args.getDouble(2));
Messaging.sendTr(sender, Messages.HOLOGRAM_LINE_HEIGHT_SET, args.getDouble(2));
} else if (action.equalsIgnoreCase("direction")) {
HologramDirection direction = args.getString(2).equalsIgnoreCase("up") ? HologramDirection.BOTTOM_UP
: HologramDirection.TOP_DOWN;
trait.setDirection(direction);
Messaging.sendTr(sender, Messages.HOLOGRAM_DIRECTION_SET, Util.prettyEnum(direction));
} else if (action.equalsIgnoreCase("margintop")) {
if (args.argsLength() == 2) {
throw new CommandException(Messages.HOLOGRAM_INVALID_LINE);
@ -1385,20 +1377,24 @@ public class NPCCommands {
throws CommandException {
EntityType type = npc.getOrAddTrait(MobType.class).getType();
if (!type.name().contains("ITEM_FRAME") && !type.name().contains("ITEM_DISPLAY")
&& type != EntityType.DROPPED_ITEM && type != EntityType.FALLING_BLOCK)
&& !type.name().contains("BLOCK_DISPLAY") && type != EntityType.DROPPED_ITEM
&& type != EntityType.FALLING_BLOCK)
throw new CommandException(CommandMessages.REQUIREMENTS_INVALID_MOB_TYPE, Util.prettyEnum(type));
ItemStack stack = args.hasFlag('h') ? ((Player) sender).getItemInHand() : new ItemStack(mat, 1);
if (modify != null) {
stack = Util.parseItemStack(stack, modify);
}
if (mat == null && !args.hasFlag('h'))
throw new CommandException(Messages.UNKNOWN_MATERIAL);
ItemStack fstack = stack.clone();
npc.setItemProvider(() -> fstack);
if (npc.isSpawned()) {
npc.despawn(DespawnReason.PENDING_RESPAWN);
npc.spawn(npc.getStoredLocation(), SpawnReason.RESPAWN);
}
Messaging.sendTr(sender, Messages.ITEM_SET, Util.prettyEnum(stack.getType()));
}
@ -2596,34 +2592,6 @@ public class NPCCommands {
}
}
@Command(
aliases = { "npc" },
usage = "script --add [files] --remove [files]",
desc = "Controls an NPC's scripts",
modifiers = { "script" },
min = 1,
max = 1,
permission = "citizens.npc.script")
public void script(CommandContext args, CommandSender sender, NPC npc, @Flag("add") String add,
@Flag("remove") String remove) {
ScriptTrait trait = npc.getOrAddTrait(ScriptTrait.class);
if (add != null) {
List<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(
aliases = { "npc" },
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,
"is loaded", Util.isLoaded(at));
}
// we need to wait before trying to spawn
entityController.remove();
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) {
NPC npc = createNPC(type, name);
if (type == EntityType.DROPPED_ITEM || type == EntityType.FALLING_BLOCK || type == EntityType.ITEM_FRAME
|| type.name().equals("GLOW_ITEM_FRAME") || type.name().equals("ITEM_DISPLAY")) {
|| type.name().equals("GLOW_ITEM_FRAME") || type.name().equals("ITEM_DISPLAY")
|| type.name().equals("BLOCK_DISPLAY")) {
npc.data().set(NPC.Metadata.ITEM_AMOUNT, item.getAmount());
npc.data().set(NPC.Metadata.ITEM_ID, item.getType().name());
npc.data().set(NPC.Metadata.ITEM_DATA, item.getData().getData());

View File

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

View File

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

View File

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

View File

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

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

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_WORLDGUARD_REGION_NOT_FOUND = "citizens.editors.waypoints.wander.worldguard-region-not-found";
public static final String WANDER_WAYPOINTS_WORLDGUARD_REGION_SET = "citizens.editors.waypoints.wander.worldguard-region-set";
public static final String WARDEN_ANGER_ADDED = "citizens.commands.npc.warden.anger-added";
public static final String WARDEN_POSE_SET = "citizens.commands.npc.warden.pose-set";
public static final String WAYPOINT_ADDED = "citizens.commands.waypoints.add.waypoint-added";
public static final String WAYPOINT_PROVIDER_SET = "citizens.waypoints.set-provider";
public static final String WAYPOINT_REMOVED = "citizens.commands.waypoints.waypoint-removed";

View File

@ -852,10 +852,14 @@ public class NMS {
BRIDGE.setTeamNameTagVisible(team, visible);
}
public static void setVerticalMovement(org.bukkit.entity.Entity bukkitEntity, double d) {
public static void setVerticalMovement(Entity bukkitEntity, double d) {
BRIDGE.setVerticalMovement(bukkitEntity, d);
}
public static void setWardenPose(Entity entity, Object pose) {
BRIDGE.setWardenPose(entity, pose);
}
public static void setWitherInvulnerable(Wither wither, boolean charged) {
BRIDGE.setWitherCharged(wither, charged);
}

View File

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

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.vulnerable.set=[[{0}]] is now vulnerable.
citizens.commands.npc.vulnerable.stopped=[[{0}]] is no longer vulnerable.
citizens.commands.npc.warden.anger-added=[[{1}]] anger added towards [[{0}]].
citizens.commands.npc.warden.pose-set=[[{0}]]''s pose set to [[{1}]].
citizens.commands.npc.wolf.unknown-collar-color=[[{0}]] is not an RGB-formatted collar color or the name of a DyeColor.
citizens.commands.npc.wolf.collar-color-unsupported=[[{0}]] is not a RGB color code that can be used on a wolf''s collar.
citizens.commands.npc.villager.level-set=Level set to [[{0}]].

View File

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

View File

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

View File

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

View File

@ -1,7 +1,9 @@
package net.citizensnpcs.nms.v1_19_R3.entity.nonliving;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_19_R3.CraftServer;
import org.bukkit.craftbukkit.v1_19_R3.CraftWorld;
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftBlockDisplay;
import org.bukkit.craftbukkit.v1_19_R3.entity.CraftEntity;
import org.bukkit.util.Vector;
@ -32,6 +34,17 @@ public class BlockDisplayController extends MobEntityController {
super(EntityBlockDisplayNPC.class);
}
@Override
protected org.bukkit.entity.Entity createEntity(Location at, NPC npc) {
final EntityBlockDisplayNPC handle = new EntityBlockDisplayNPC(EntityType.BLOCK_DISPLAY,
((CraftWorld) at.getWorld()).getHandle(), npc);
if (npc != null) {
((org.bukkit.entity.BlockDisplay) handle.getBukkitEntity())
.setBlock(npc.getItemProvider().get().getType().createBlockData());
}
return handle.getBukkitEntity();
}
@Override
public org.bukkit.entity.BlockDisplay getBukkitEntity() {
return (org.bukkit.entity.BlockDisplay) super.getBukkitEntity();

View File

@ -297,6 +297,7 @@ import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.server.network.ServerPlayerConnection;
import net.minecraft.sounds.SoundEvent;
import net.minecraft.sounds.SoundEvents;
import net.minecraft.tags.FluidTags;
import net.minecraft.util.Mth;
import net.minecraft.world.Container;
@ -342,6 +343,7 @@ import net.minecraft.world.entity.item.FallingBlockEntity;
import net.minecraft.world.entity.monster.EnderMan;
import net.minecraft.world.entity.monster.Shulker;
import net.minecraft.world.entity.monster.piglin.Piglin;
import net.minecraft.world.entity.monster.warden.Warden;
import net.minecraft.world.entity.projectile.FishingHook;
import net.minecraft.world.entity.vehicle.AbstractMinecart;
import net.minecraft.world.inventory.AnvilMenu;
@ -1665,6 +1667,44 @@ public class NMSImpl implements NMSBridge {
handle.xxa = (float) d;
}
@Override
public void setWardenPose(org.bukkit.entity.Entity entity, Object pose) {
Warden warden = (Warden) getHandle(entity);
if (pose == org.bukkit.entity.Pose.DIGGING) {
if (warden.hasPose(Pose.DIGGING))
return;
warden.setPose(Pose.DIGGING);
warden.playSound(SoundEvents.WARDEN_DIG, 5.0F, 1.0F);
} else if (pose == org.bukkit.entity.Pose.EMERGING) {
if (warden.hasPose(Pose.EMERGING))
return;
warden.setPose(Pose.EMERGING);
warden.playSound(SoundEvents.WARDEN_EMERGE, 5.0F, 1.0F);
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), () -> {
if (warden.hasPose(Pose.EMERGING)) {
warden.setPose(Pose.STANDING);
}
}, 134);
} else if (pose == org.bukkit.entity.Pose.ROARING) {
if (warden.hasPose(Pose.ROARING))
return;
warden.setPose(Pose.ROARING);
warden.playSound(SoundEvents.WARDEN_ROAR, 3.0F, 1.0F);
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), () -> {
if (warden.hasPose(Pose.ROARING)) {
warden.setPose(Pose.STANDING);
}
}, 84);
} else {
warden.setPose(Pose.STANDING);
}
}
@Override
public void setWitherCharged(Wither wither, boolean charged) {
WitherBoss handle = ((CraftWither) wither).getHandle();

View File

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

View File

@ -1,7 +1,9 @@
package net.citizensnpcs.nms.v1_20_R2.entity.nonliving;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.craftbukkit.v1_20_R2.CraftServer;
import org.bukkit.craftbukkit.v1_20_R2.CraftWorld;
import org.bukkit.craftbukkit.v1_20_R2.entity.CraftBlockDisplay;
import org.bukkit.craftbukkit.v1_20_R2.entity.CraftEntity;
import org.bukkit.util.Vector;
@ -14,7 +16,6 @@ import net.citizensnpcs.nms.v1_20_R2.util.NMSImpl;
import net.citizensnpcs.npc.CitizensNPC;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.util.Util;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.tags.TagKey;
@ -32,6 +33,17 @@ public class BlockDisplayController extends MobEntityController {
super(EntityBlockDisplayNPC.class);
}
@Override
protected org.bukkit.entity.Entity createEntity(Location at, NPC npc) {
final EntityBlockDisplayNPC handle = new EntityBlockDisplayNPC(EntityType.BLOCK_DISPLAY,
((CraftWorld) at.getWorld()).getHandle(), npc);
if (npc != null) {
((org.bukkit.entity.BlockDisplay) handle.getBukkitEntity())
.setBlock(npc.getItemProvider().get().getType().createBlockData());
}
return handle.getBukkitEntity();
}
@Override
public org.bukkit.entity.BlockDisplay getBukkitEntity() {
return (org.bukkit.entity.BlockDisplay) super.getBukkitEntity();
@ -111,6 +123,7 @@ public class BlockDisplayController extends MobEntityController {
public Entity teleportTo(ServerLevel worldserver, Vec3 location) {
if (npc == null)
return super.teleportTo(worldserver, location);
return NMSImpl.teleportAcrossWorld(this, worldserver, location);
}

View File

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