Add /npc hologram viewrange, add /npc playerfilter --applywithin, work towards auto-hologram-sneak

This commit is contained in:
fullwall 2023-11-05 20:58:37 +08:00
parent de885501cd
commit 07fb13c284
1454 changed files with 964 additions and 14929 deletions

View File

@ -102,7 +102,7 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
@Override
public OfflinePlayer getPlayer(BlockCommandSender sender) {
Entity entity = NMS.getSource(sender);
return entity != null && entity instanceof OfflinePlayer ? (OfflinePlayer) entity : null;
return entity instanceof OfflinePlayer ? (OfflinePlayer) entity : null;
}
@Override
@ -182,11 +182,9 @@ 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;
@ -195,8 +193,9 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
private void despawnNPCs(boolean save) {
for (NPCRegistry registry : Iterables.concat(Arrays.asList(npcRegistry), citizensBackedRegistries)) {
if (registry == null)
if (registry == null) {
continue;
}
if (save) {
if (registry == npcRegistry) {
storeNPCs(false);
@ -237,33 +236,27 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
@Override
public Iterable<NPCRegistry> getNPCRegistries() {
return new Iterable<NPCRegistry>() {
return () -> new Iterator<NPCRegistry>() {
Iterator<NPCRegistry> stored;
@Override
public Iterator<NPCRegistry> iterator() {
return new Iterator<NPCRegistry>() {
Iterator<NPCRegistry> stored;
public boolean hasNext() {
return stored == null ? true : stored.hasNext();
}
@Override
public boolean hasNext() {
return stored == null ? true : stored.hasNext();
}
@Override
public NPCRegistry next() {
if (stored == null) {
stored = Iterables.concat(storedRegistries.values(), anonymousRegistries, citizensBackedRegistries)
.iterator();
return npcRegistry;
}
return stored.next();
}
@Override
public NPCRegistry next() {
if (stored == null) {
stored = Iterables
.concat(storedRegistries.values(), anonymousRegistries, citizensBackedRegistries)
.iterator();
return npcRegistry;
}
return stored.next();
}
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
@Override
public void remove() {
throw new UnsupportedOperationException();
}
};
}
@ -392,7 +385,6 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
Bukkit.getPluginManager().disablePlugin(this);
return;
}
registerScriptHelpers();
saves = createStorage(getDataFolder());
@ -402,15 +394,12 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
Bukkit.getPluginManager().disablePlugin(this);
return;
}
locationLookup = new LocationLookup();
locationLookup.runTaskTimer(CitizensAPI.getPlugin(), 0, 5);
npcRegistry = new CitizensNPCRegistry(saves, "citizens");
traitFactory = new CitizensTraitFactory(this);
traitFactory.registerTrait(TraitInfo.create(ShopTrait.class).withSupplier(() -> {
return new ShopTrait(shops);
}));
traitFactory.registerTrait(TraitInfo.create(ShopTrait.class).withSupplier(() -> new ShopTrait(shops)));
selector = new NPCSelector(this);
Bukkit.getPluginManager().registerEvents(new EventListen(), this);
@ -426,7 +415,6 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
if (papi != null && papi.isEnabled()) {
new CitizensPlaceholders(selector).register();
}
setupEconomy();
registerCommands();
@ -506,12 +494,11 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
@Override
public void setDefaultNPCDataStore(NPCDataStore store) {
if (store == null) {
if (store == null)
throw new IllegalArgumentException("must be non-null");
}
despawnNPCs(true);
this.saves = store;
this.npcRegistry = new CitizensNPCRegistry(saves, "citizens-global-" + UUID.randomUUID().toString());
saves = store;
npcRegistry = new CitizensNPCRegistry(saves, "citizens-global-" + UUID.randomUUID().toString());
saves.loadInto(npcRegistry);
}
@ -614,7 +601,6 @@ public class Citizens extends JavaPlugin implements CitizensPlugin {
}
}
}
saves.loadInto(npcRegistry);
shops.load();

View File

@ -55,7 +55,6 @@ public class CitizensPlaceholders extends PlaceholderExpansion {
b.getEntity().getLocation().distanceSquared(location)));
return closestNPC.isPresent() ? Integer.toString(closestNPC.get().getId()) : "";
}
return null;
}

View File

@ -120,11 +120,11 @@ import net.citizensnpcs.util.Util;
public class EventListen implements Listener {
private Listener chunkEventListener;
private final SkinUpdateTracker skinUpdateTracker;
private SkinUpdateTracker skinUpdateTracker;
private final ListMultimap<ChunkCoord, NPC> toRespawn = ArrayListMultimap.create(64, 4);
EventListen() {
this.skinUpdateTracker = new SkinUpdateTracker();
skinUpdateTracker = new SkinUpdateTracker();
try {
Class.forName("org.bukkit.event.world.EntitiesLoadEvent");
Bukkit.getPluginManager().registerEvents(new Listener() {
@ -140,7 +140,6 @@ public class EventListen implements Listener {
}, CitizensAPI.getPlugin());
} catch (Throwable ex) {
}
try {
Class.forName("org.bukkit.event.entity.EntityTransformEvent");
Bukkit.getPluginManager().registerEvents(new Listener() {
@ -156,23 +155,19 @@ public class EventListen implements Listener {
}, CitizensAPI.getPlugin());
} catch (Throwable ex) {
}
Class<?> kbc = null;
try {
kbc = Class.forName("com.destroystokyo.paper.event.entity.EntityKnockbackByEntityEvent");
} catch (ClassNotFoundException e) {
}
if (kbc != null) {
registerKnockbackEvent(kbc);
}
Class<?> pbeac = null;
try {
pbeac = Class.forName("io.papermc.paper.event.entity.EntityPushedByEntityAttackEvent");
} catch (ClassNotFoundException e) {
}
if (pbeac != null) {
registerPushEvent(pbeac);
}
@ -184,8 +179,9 @@ public class EventListen implements Listener {
int limit = Setting.DEFAULT_NPC_LIMIT.asInt();
int maxChecks = Setting.MAX_NPC_LIMIT_CHECKS.asInt();
for (int i = maxChecks; i >= 0; i--) {
if (!event.getCreator().hasPermission("citizens.npc.limit." + i))
if (!event.getCreator().hasPermission("citizens.npc.limit." + i)) {
continue;
}
limit = i;
break;
}
@ -215,7 +211,6 @@ public class EventListen implements Listener {
if (Messaging.isDebugging() && Setting.DEBUG_CHUNK_LOADS.asBoolean() && toRespawn.containsKey(coord)) {
new Exception("CITIZENS CHUNK LOAD DEBUG " + coord).printStackTrace();
}
if (event instanceof Cancellable) {
runnable.run();
} else {
@ -231,7 +226,7 @@ public class EventListen implements Listener {
}
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onChunkUnload(final ChunkUnloadEvent event) {
public void onChunkUnload(ChunkUnloadEvent event) {
if (chunkEventListener != null)
return;
@ -290,7 +285,6 @@ public class EventListen implements Listener {
}
return;
}
event.setCancelled(npc.isProtected());
if (event instanceof EntityDamageByEntityEvent) {
@ -306,7 +300,6 @@ public class EventListen implements Listener {
if (npc == null)
return;
}
NPCLeftClickEvent leftClickEvent = new NPCLeftClickEvent(npc, damager);
Bukkit.getPluginManager().callEvent(leftClickEvent);
if (npc.hasTrait(CommandTrait.class)) {
@ -321,15 +314,14 @@ public class EventListen implements Listener {
@EventHandler(ignoreCancelled = true)
public void onEntityDeath(EntityDeathEvent event) {
final NPC npc = CitizensAPI.getNPCRegistry().getNPC(event.getEntity());
NPC npc = CitizensAPI.getNPCRegistry().getNPC(event.getEntity());
if (npc == null)
return;
if (!npc.data().get(NPC.Metadata.DROPS_ITEMS, false)) {
event.getDrops().clear();
}
final Location location = npc.getStoredLocation();
Location location = npc.getStoredLocation();
Bukkit.getPluginManager().callEvent(new NPCDeathEvent(npc, event));
npc.despawn(DespawnReason.DEATH);
@ -438,7 +430,6 @@ public class EventListen implements Listener {
if (npc.isSpawned() && npc.getEntity().getType() == EntityType.PLAYER) {
onNPCPlayerLinkToPlayer(event);
}
ClickRedirectTrait crt = npc.getTraitNullable(ClickRedirectTrait.class);
if (crt != null) {
HologramTrait ht = crt.getRedirectNPC().getTraitNullable(HologramTrait.class);
@ -468,7 +459,6 @@ public class EventListen implements Listener {
}
return;
}
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), () -> {
if (!tracker.isValid() || !event.getPlayer().isValid())
return;
@ -488,12 +478,15 @@ public class EventListen implements Listener {
@EventHandler(ignoreCancelled = true)
public void onNPCSeenByPlayer(NPCSeenByPlayerEvent event) {
NPC npc = event.getNPC();
PlayerFilter pf = npc.getTraitNullable(PlayerFilter.class);
if (pf != null) {
event.setCancelled(pf.onSeenByPlayer(event.getPlayer()));
}
ClickRedirectTrait crt = npc.getTraitNullable(ClickRedirectTrait.class);
if (crt != null) {
npc = crt.getRedirectNPC();
}
PlayerFilter pf = npc.getTraitNullable(PlayerFilter.class);
pf = npc.getTraitNullable(PlayerFilter.class);
if (pf != null) {
event.setCancelled(pf.onSeenByPlayer(event.getPlayer()));
}
@ -561,27 +554,22 @@ public class EventListen implements Listener {
if (event.getPlayer().getItemInHand().getType() == Material.NAME_TAG) {
rightClickEvent.setCancelled(npc.isProtected());
}
Bukkit.getPluginManager().callEvent(rightClickEvent);
if (rightClickEvent.isCancelled()) {
event.setCancelled(true);
return;
}
if (npc.hasTrait(CommandTrait.class)) {
npc.getTraitNullable(CommandTrait.class).dispatch(player, CommandTrait.Hand.RIGHT);
rightClickEvent.setDelayedCancellation(true);
}
if (npc.hasTrait(ShopTrait.class)) {
npc.getTraitNullable(ShopTrait.class).onRightClick(player);
rightClickEvent.setDelayedCancellation(true);
}
if (rightClickEvent.isDelayedCancellation()) {
event.setCancelled(true);
}
if (event.isCancelled()) {
if (SUPPORT_STOP_USE_ITEM) {
try {
@ -617,7 +605,7 @@ public class EventListen implements Listener {
// recalculate player NPCs the first time a player moves and every time
// a player moves a certain distance from their last position.
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onPlayerMove(final PlayerMoveEvent event) {
public void onPlayerMove(PlayerMoveEvent event) {
skinUpdateTracker.onPlayerMove(event.getPlayer());
}
@ -630,7 +618,6 @@ public class EventListen implements Listener {
event.getPlayer().leaveVehicle();
}
}
skinUpdateTracker.removePlayer(event.getPlayer().getUniqueId());
CitizensAPI.getLocationLookup().onQuit(event);
}
@ -641,7 +628,7 @@ public class EventListen implements Listener {
}
@EventHandler(ignoreCancelled = true)
public void onPlayerTeleport(final PlayerTeleportEvent event) {
public void onPlayerTeleport(PlayerTeleportEvent event) {
NPC npc = CitizensAPI.getNPCRegistry().getNPC(event.getPlayer());
if (event.getCause() == TeleportCause.PLUGIN && npc != null && !npc.data().has("citizens-force-teleporting")
&& Setting.PLAYER_TELEPORT_DELAY.asTicks() > 0) {
@ -652,7 +639,6 @@ public class EventListen implements Listener {
npc.data().remove("citizens-force-teleporting");
}, Setting.PLAYER_TELEPORT_DELAY.asTicks());
}
skinUpdateTracker.updatePlayer(event.getPlayer(), 15, true);
}
@ -673,9 +659,9 @@ public class EventListen implements Listener {
public void onPotionSplashEvent(PotionSplashEvent event) {
for (LivingEntity entity : event.getAffectedEntities()) {
NPC npc = CitizensAPI.getNPCRegistry().getNPC(entity);
if (npc == null)
if (npc == null) {
continue;
}
if (npc.isProtected()) {
event.setIntensity(entity, 0);
}
@ -683,7 +669,7 @@ public class EventListen implements Listener {
}
@EventHandler(ignoreCancelled = true)
public void onProjectileHit(final ProjectileHitEvent event) {
public void onProjectileHit(ProjectileHitEvent event) {
if (!(event.getEntity() instanceof FishHook))
return;
NMS.removeHookIfNecessary((FishHook) event.getEntity());
@ -696,7 +682,6 @@ public class EventListen implements Listener {
cancel();
return;
}
NMS.removeHookIfNecessary((FishHook) event.getEntity());
}
}.runTaskTimer(CitizensAPI.getPlugin(), 0, 1);
@ -735,7 +720,7 @@ public class EventListen implements Listener {
}
@EventHandler(ignoreCancelled = true)
public void onVehicleEnter(final VehicleEnterEvent event) {
public void onVehicleEnter(VehicleEnterEvent event) {
NPC npc = CitizensAPI.getNPCRegistry().getNPC(event.getVehicle());
NPC rider = CitizensAPI.getNPCRegistry().getNPC(event.getEntered());
if (npc == null) {
@ -743,10 +728,8 @@ public class EventListen implements Listener {
|| event.getVehicle() instanceof Minecart)) {
event.setCancelled(true);
}
return;
}
if (rider != null || !(npc instanceof Vehicle))
return;
@ -758,8 +741,10 @@ public class EventListen implements Listener {
@EventHandler(ignoreCancelled = true)
public void onWorldLoad(WorldLoadEvent event) {
for (ChunkCoord chunk : toRespawn.keySet()) {
if (!chunk.worldUUID.equals(event.getWorld().getUID()) || !event.getWorld().isChunkLoaded(chunk.x, chunk.z))
if (!chunk.worldUUID.equals(event.getWorld().getUID())
|| !event.getWorld().isChunkLoaded(chunk.x, chunk.z)) {
continue;
}
respawnAllFromCoord(chunk, event);
}
}
@ -767,9 +752,9 @@ public class EventListen implements Listener {
@EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true)
public void onWorldUnload(WorldUnloadEvent event) {
for (NPC npc : getAllNPCs()) {
if (npc == null || !npc.isSpawned() || !npc.getEntity().getWorld().equals(event.getWorld()))
if (npc == null || !npc.isSpawned() || !npc.getEntity().getWorld().equals(event.getWorld())) {
continue;
}
boolean despawned = npc.despawn(DespawnReason.WORLD_UNLOAD);
if (event.isCancelled() || !despawned) {
for (ChunkCoord coord : toRespawn.keySet()) {
@ -780,7 +765,6 @@ public class EventListen implements Listener {
event.setCancelled(true);
return;
}
if (npc.isSpawned()) {
toRespawn.put(new ChunkCoord(npc.getEntity().getLocation()), npc);
Messaging.debug("Despawned", npc, "due to world unload at", event.getWorld().getName());
@ -829,9 +813,7 @@ public class EventListen implements Listener {
Method getAcceleration = clazz.getMethod("getAcceleration");
handlers.register(new RegisteredListener(new Listener() {
}, (listener, event) -> {
if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0)
return;
if (event.getClass() != clazz)
if (NPCPushEvent.getHandlerList().getRegisteredListeners().length == 0 || event.getClass() != clazz)
return;
try {
Entity entity = (Entity) getEntity.invoke(event);
@ -858,26 +840,22 @@ public class EventListen implements Listener {
if (ids.size() > 0) {
Messaging.debug("Respawning all NPCs at", coord, "due to", event);
}
for (int i = 0; i < ids.size(); i++) {
NPC npc = ids.get(i);
if (npc.getOwningRegistry().getById(npc.getId()) != npc) {
Messaging.idebug(() -> "Prevented deregistered NPC from respawning " + npc);
continue;
}
if (npc.isSpawned()) {
Messaging.idebug(() -> "Can't respawn NPC " + npc + ": already spawned");
continue;
}
boolean success = spawn(npc);
if (!success) {
ids.remove(i--);
Messaging.idebug(() -> Joiner.on(' ').join("Couldn't respawn", npc, "during", event, "at", coord));
continue;
}
Messaging.idebug(() -> Joiner.on(' ').join("Spawned", npc, "during", event, "at", coord));
}
for (NPC npc : ids) {
@ -895,16 +873,16 @@ public class EventListen implements Listener {
}
void unloadNPCs(ChunkEvent event, List<Entity> entities) {
final List<NPC> toDespawn = Lists.newArrayList();
List<NPC> toDespawn = Lists.newArrayList();
for (Entity entity : entities) {
NPC npc = CitizensAPI.getNPCRegistry().getNPC(entity);
// XXX : npc#isSpawned() checks entity valid status which is now inconsistent on chunk unload between
// different server software (e.g. Paper and Spigot), so check for npc.getEntity() == null instead.
if (npc == null || npc.getEntity() == null)
if (npc == null || npc.getEntity() == null) {
continue;
}
toDespawn.add(npc);
}
if (toDespawn.isEmpty())
return;
@ -918,7 +896,6 @@ public class EventListen implements Listener {
toRespawn.put(coord, npc);
continue;
}
((Cancellable) event).setCancelled(true);
Messaging.debug("Cancelled chunk unload at", coord);
respawnAllFromCoord(coord, event);
@ -930,7 +907,6 @@ public class EventListen implements Listener {
if (Messaging.isDebugging() && Setting.DEBUG_CHUNK_LOADS.asBoolean()) {
new Exception("CITIZENS CHUNK UNLOAD DEBUG " + coord).printStackTrace();
}
if (loadChunk) {
Messaging.idebug(() -> Joiner.on(' ').join("Loading chunk in 10 ticks due to forced chunk load at", coord));
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), () -> {

View File

@ -91,7 +91,7 @@ public class Metrics {
metricsBase = new MetricsBase("bukkit", serverUUID, serviceId, enabled, this::appendPlatformData,
this::appendServiceData, submitDataTask -> Bukkit.getScheduler().runTask(plugin, submitDataTask),
plugin::isEnabled, (message, error) -> this.plugin.getLogger().log(Level.WARNING, message, error),
(message) -> this.plugin.getLogger().log(Level.INFO, message), logErrors, logSentData,
message -> this.plugin.getLogger().log(Level.INFO, message), logErrors, logSentData,
logResponseStatusText);
}
@ -156,10 +156,9 @@ public class Metrics {
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, int[]> map = callable.call();
if (map == null || map.isEmpty()) {
if (map == null || map.isEmpty())
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, int[]> entry : map.entrySet()) {
if (entry.getValue().length == 0) {
@ -169,10 +168,9 @@ public class Metrics {
allSkipped = false;
valuesBuilder.appendField(entry.getKey(), entry.getValue());
}
if (allSkipped) {
if (allSkipped)
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
@ -198,10 +196,9 @@ public class Metrics {
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
if (map == null || map.isEmpty())
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, Integer> entry : map.entrySet()) {
if (entry.getValue() == 0) {
@ -211,10 +208,9 @@ public class Metrics {
allSkipped = false;
valuesBuilder.appendField(entry.getKey(), entry.getValue());
}
if (allSkipped) {
if (allSkipped)
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
@ -224,9 +220,8 @@ public class Metrics {
private final String chartId;
protected CustomChart(String chartId) {
if (chartId == null) {
if (chartId == null)
throw new IllegalArgumentException("chartId must not be null");
}
this.chartId = chartId;
}
@ -238,10 +233,9 @@ public class Metrics {
builder.appendField("chartId", chartId);
try {
JsonObjectBuilder.JsonObject data = getChartData();
if (data == null) {
if (data == null)
// If the data is null we don't send the chart.
return null;
}
builder.appendField("data", data);
} catch (Throwable t) {
if (logErrors) {
@ -274,10 +268,9 @@ public class Metrics {
public JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Map<String, Integer>> map = callable.call();
if (map == null || map.isEmpty()) {
if (map == null || map.isEmpty())
// Null = skip the chart
return null;
}
boolean reallyAllSkipped = true;
for (Map.Entry<String, Map<String, Integer>> entryValues : map.entrySet()) {
JsonObjectBuilder valueBuilder = new JsonObjectBuilder();
@ -291,10 +284,9 @@ public class Metrics {
valuesBuilder.appendField(entryValues.getKey(), valueBuilder.build());
}
}
if (reallyAllSkipped) {
if (reallyAllSkipped)
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
@ -339,9 +331,8 @@ public class Metrics {
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, int[] values) {
if (values == null) {
if (values == null)
throw new IllegalArgumentException("JSON values must not be null");
}
String escapedValues = Arrays.stream(values).mapToObj(String::valueOf).collect(Collectors.joining(","));
appendFieldUnescaped(key, "[" + escapedValues + "]");
return this;
@ -357,9 +348,8 @@ public class Metrics {
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, JsonObject object) {
if (object == null) {
if (object == null)
throw new IllegalArgumentException("JSON object must not be null");
}
appendFieldUnescaped(key, object.toString());
return this;
}
@ -374,9 +364,8 @@ public class Metrics {
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, JsonObject[] values) {
if (values == null) {
if (values == null)
throw new IllegalArgumentException("JSON values must not be null");
}
String escapedValues = Arrays.stream(values).map(JsonObject::toString).collect(Collectors.joining(","));
appendFieldUnescaped(key, "[" + escapedValues + "]");
return this;
@ -392,9 +381,8 @@ public class Metrics {
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, String value) {
if (value == null) {
if (value == null)
throw new IllegalArgumentException("JSON value must not be null");
}
appendFieldUnescaped(key, "\"" + escape(value) + "\"");
return this;
}
@ -409,9 +397,8 @@ public class Metrics {
* @return A reference to this object.
*/
public JsonObjectBuilder appendField(String key, String[] values) {
if (values == null) {
if (values == null)
throw new IllegalArgumentException("JSON values must not be null");
}
String escapedValues = Arrays.stream(values).map(value -> "\"" + escape(value) + "\"")
.collect(Collectors.joining(","));
appendFieldUnescaped(key, "[" + escapedValues + "]");
@ -427,12 +414,10 @@ public class Metrics {
* The escaped value of the field.
*/
private void appendFieldUnescaped(String key, String escapedValue) {
if (builder == null) {
if (builder == null)
throw new IllegalStateException("JSON has already been built");
}
if (key == null) {
if (key == null)
throw new IllegalArgumentException("JSON key must not be null");
}
if (hasAtLeastOneField) {
builder.append(",");
}
@ -458,9 +443,8 @@ public class Metrics {
* @return The built JSON string.
*/
public JsonObject build() {
if (builder == null) {
if (builder == null)
throw new IllegalStateException("JSON has already been built");
}
JsonObject object = new JsonObject(builder.append("}").toString());
builder = null;
return object;
@ -499,7 +483,7 @@ public class Metrics {
* @return The escaped value.
*/
private static String escape(String value) {
final StringBuilder builder = new StringBuilder();
StringBuilder builder = new StringBuilder();
for (int i = 0; i < value.length(); i++) {
char c = value.charAt(i);
if (c == '"') {
@ -605,7 +589,7 @@ public class Metrics {
}
public void addCustomChart(CustomChart chart) {
this.customCharts.add(chart);
customCharts.add(chart);
}
/** Checks that the class was properly relocated. */
@ -615,16 +599,14 @@ public class Metrics {
|| !System.getProperty("bstats.relocatecheck").equals("false")) {
// Maven's Relocate is clever and changes strings, too. So we have to use this little
// "trick" ... :D
final String defaultPackage = new String(
new byte[] { 'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's' });
final String examplePackage = new String(
String defaultPackage = new String(new byte[] { 'o', 'r', 'g', '.', 'b', 's', 't', 'a', 't', 's' });
String examplePackage = new String(
new byte[] { 'y', 'o', 'u', 'r', '.', 'p', 'a', 'c', 'k', 'a', 'g', 'e' });
// We want to make sure no one just copy & pastes the example and uses the wrong package
// names
if (MetricsBase.class.getPackage().getName().startsWith(defaultPackage)
|| MetricsBase.class.getPackage().getName().startsWith(examplePackage)) {
|| MetricsBase.class.getPackage().getName().startsWith(examplePackage))
throw new IllegalStateException("bStats Metrics class has not been relocated correctly!");
}
}
}
@ -661,7 +643,7 @@ public class Metrics {
}
private void startSubmitting() {
final Runnable submitTask = () -> {
Runnable submitTask = () -> {
if (!enabled || !checkServiceEnabledSupplier.get()) {
// Submitting data or service is disabled
scheduler.shutdown();
@ -670,7 +652,7 @@ public class Metrics {
if (submitTaskConsumer != null) {
submitTaskConsumer.accept(this::submitData);
} else {
this.submitData();
submitData();
}
};
// Many servers tend to restart at a fixed time at xx:00 which causes an uneven distribution
@ -688,9 +670,9 @@ public class Metrics {
}
private void submitData() {
final JsonObjectBuilder baseJsonBuilder = new JsonObjectBuilder();
JsonObjectBuilder baseJsonBuilder = new JsonObjectBuilder();
appendPlatformDataConsumer.accept(baseJsonBuilder);
final JsonObjectBuilder serviceJsonBuilder = new JsonObjectBuilder();
JsonObjectBuilder serviceJsonBuilder = new JsonObjectBuilder();
appendServiceDataConsumer.accept(serviceJsonBuilder);
JsonObjectBuilder.JsonObject[] chartData = customCharts.stream()
.map(customChart -> customChart.getRequestJsonObject(errorLogger, logErrors))
@ -721,10 +703,9 @@ public class Metrics {
* The string to gzip.
* @return The gzipped string.
*/
private static byte[] compress(final String str) throws IOException {
if (str == null) {
private static byte[] compress(String str) throws IOException {
if (str == null)
return null;
}
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
try (GZIPOutputStream gzip = new GZIPOutputStream(outputStream)) {
gzip.write(str.getBytes(StandardCharsets.UTF_8));
@ -733,11 +714,11 @@ public class Metrics {
}
/** The version of the Metrics class. */
public static final String METRICS_VERSION = "3.0.0";
public static String METRICS_VERSION = "3.0.0";
private static final String REPORT_URL = "https://bStats.org/api/v2/data/%s";
private static String REPORT_URL = "https://bStats.org/api/v2/data/%s";
private static final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1,
private static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1,
task -> new Thread(task, "bStats-Metrics"));
}
@ -762,10 +743,9 @@ public class Metrics {
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
if (map == null || map.isEmpty())
// Null = skip the chart
return null;
}
boolean allSkipped = true;
for (Map.Entry<String, Integer> entry : map.entrySet()) {
if (entry.getValue() == 0) {
@ -775,10 +755,9 @@ public class Metrics {
allSkipped = false;
valuesBuilder.appendField(entry.getKey(), entry.getValue());
}
if (allSkipped) {
if (allSkipped)
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("values", valuesBuilder.build()).build();
}
}
@ -804,10 +783,9 @@ public class Metrics {
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
JsonObjectBuilder valuesBuilder = new JsonObjectBuilder();
Map<String, Integer> map = callable.call();
if (map == null || map.isEmpty()) {
if (map == null || map.isEmpty())
// Null = skip the chart
return null;
}
for (Map.Entry<String, Integer> entry : map.entrySet()) {
valuesBuilder.appendField(entry.getKey(), new int[] { entry.getValue() });
}
@ -835,10 +813,9 @@ public class Metrics {
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
String value = callable.call();
if (value == null || value.isEmpty()) {
if (value == null || value.isEmpty())
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("value", value).build();
}
}
@ -863,10 +840,9 @@ public class Metrics {
@Override
protected JsonObjectBuilder.JsonObject getChartData() throws Exception {
int value = callable.call();
if (value == 0) {
if (value == 0)
// Null = skip the chart
return null;
}
return new JsonObjectBuilder().appendField("value", value).build();
}
}

View File

@ -11,7 +11,7 @@ public class NPCNeedsRespawnEvent extends NPCEvent {
public NPCNeedsRespawnEvent(NPC npc, Location at) {
super(npc);
this.spawn = at;
spawn = at;
}
@Override
@ -27,5 +27,5 @@ public class NPCNeedsRespawnEvent extends NPCEvent {
return handlers;
}
private static final HandlerList handlers = new HandlerList();
private static HandlerList handlers = new HandlerList();
}

View File

@ -48,6 +48,8 @@ import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.trait.trait.MobType;
import net.citizensnpcs.api.util.Messaging;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.trait.ClickRedirectTrait;
import net.citizensnpcs.trait.HologramTrait;
import net.citizensnpcs.trait.MirrorTrait;
import net.citizensnpcs.trait.RotationTrait;
import net.citizensnpcs.trait.RotationTrait.PacketRotationSession;
@ -55,15 +57,15 @@ import net.citizensnpcs.util.NMS;
import net.citizensnpcs.util.SkinProperty;
public class ProtocolLibListener implements Listener {
private final Class<?> flagsClass;
private final ProtocolManager manager;
private Class<?> flagsClass;
private ProtocolManager manager;
private final Map<UUID, MirrorTrait> mirrorTraits = Maps.newConcurrentMap();
private final Citizens plugin;
private Citizens plugin;
private final Map<Integer, RotationTrait> rotationTraits = Maps.newConcurrentMap();
public ProtocolLibListener(Citizens plugin) {
this.plugin = plugin;
this.manager = ProtocolLibrary.getProtocolManager();
manager = ProtocolLibrary.getProtocolManager();
flagsClass = MinecraftReflection.getMinecraftClass("RelativeMovement", "world.entity.RelativeMovement",
"EnumPlayerTeleportFlags", "PacketPlayOutPosition$EnumPlayerTeleportFlags",
"network.protocol.game.PacketPlayOutPosition$EnumPlayerTeleportFlags");
@ -72,50 +74,59 @@ public class ProtocolLibListener implements Listener {
@Override
public void onPacketSending(PacketEvent event) {
NPC npc = getNPCFromPacket(event);
if (npc == null || !npc.data().has(NPC.Metadata.HOLOGRAM_LINE_SUPPLIER))
if (npc == null)
return;
Function<Player, String> hvs = npc.data().get(NPC.Metadata.HOLOGRAM_LINE_SUPPLIER);
int version = manager.getProtocolVersion(event.getPlayer());
PacketContainer packet = event.getPacket();
if (version < 761) {
List<WrappedWatchableObject> wwo = packet.getWatchableCollectionModifier().readSafely(0);
if (wwo == null)
return;
int version = manager.getProtocolVersion(event.getPlayer());
if (npc.data().has(NPC.Metadata.HOLOGRAM_FOR) || npc.data().has(NPC.Metadata.HOLOGRAM_LINE_SUPPLIER)) {
Function<Player, String> hvs = npc.data().get(NPC.Metadata.HOLOGRAM_LINE_SUPPLIER);
Object fakeName = null;
if (hvs != null) {
String suppliedName = hvs.apply(event.getPlayer());
fakeName = version <= 340 ? suppliedName
: Optional.of(Messaging.minecraftComponentFromRawMessage(suppliedName));
}
boolean sneaking = npc.getOrAddTrait(ClickRedirectTrait.class).getRedirectNPC()
.getOrAddTrait(HologramTrait.class).isHologramSneaking(npc, event.getPlayer());
boolean delta = false;
String text = hvs.apply(event.getPlayer());
for (WrappedWatchableObject wo : wwo) {
if (wo.getIndex() != 2)
continue;
if (version <= 340) {
wo.setValue(text);
} else {
wo.setValue(Optional.of(Messaging.minecraftComponentFromRawMessage(text)));
if (version < 761) {
List<WrappedWatchableObject> wwo = packet.getWatchableCollectionModifier().readSafely(0);
if (wwo == null)
return;
for (WrappedWatchableObject wo : wwo) {
if (fakeName != null && wo.getIndex() == 2) {
wo.setValue(fakeName);
delta = true;
} else if (sneaking && wo.getIndex() == 0) {
byte b = (byte) (((Number) wo.getValue()).byteValue() | 0x02);
wo.setValue(b);
delta = true;
}
}
delta = true;
break;
}
if (delta) {
packet.getWatchableCollectionModifier().write(0, wwo);
}
} else {
List<WrappedDataValue> wdvs = packet.getDataValueCollectionModifier().readSafely(0);
if (wdvs == null)
return;
if (delta) {
packet.getWatchableCollectionModifier().write(0, wwo);
}
} else {
List<WrappedDataValue> wdvs = packet.getDataValueCollectionModifier().readSafely(0);
if (wdvs == null)
return;
boolean delta = false;
String text = hvs.apply(event.getPlayer());
for (WrappedDataValue wdv : wdvs) {
if (wdv.getIndex() != 2)
continue;
wdv.setValue(Optional.of(Messaging.minecraftComponentFromRawMessage(text)));
break;
}
if (delta) {
packet.getDataValueCollectionModifier().write(0, wdvs);
for (WrappedDataValue wdv : wdvs) {
if (fakeName != null && wdv.getIndex() == 2) {
wdv.setValue(fakeName);
delta = true;
} else if (sneaking && wdv.getIndex() == 0) {
byte b = (byte) (((Number) wdv.getValue()).byteValue() | 0x02);
wdv.setValue(b);
delta = true;
}
}
if (delta) {
packet.getDataValueCollectionModifier().write(0, wdvs);
}
}
}
}
@ -130,7 +141,6 @@ public class ProtocolLibListener implements Listener {
uuid -> mirrorTraits.get(uuid));
return;
}
List<PlayerInfoData> list = event.getPacket().getPlayerInfoDataLists().readSafely(0);
if (list == null)
return;
@ -153,13 +163,11 @@ public class ProtocolLibListener implements Listener {
wgp = WrappedGameProfile.fromPlayer(event.getPlayer());
playerName = WrappedChatComponent.fromText(event.getPlayer().getDisplayName());
}
if (trait.mirrorName()) {
list.set(i, new PlayerInfoData(wgp.withId(npcInfo.getProfile().getId()), npcInfo.getLatency(),
npcInfo.getGameMode(), playerName));
continue;
}
Collection<Property> textures = playerProfile.getProperties().get("textures");
if (textures == null || textures.size() == 0)
continue;
@ -174,7 +182,6 @@ public class ProtocolLibListener implements Listener {
}
changed = true;
}
if (changed) {
event.getPacket().getPlayerInfoDataLists().write(0, list);
}
@ -202,7 +209,6 @@ public class ProtocolLibListener implements Listener {
}
return;
}
RotationTrait trait = rotationTraits.get(eid);
if (trait == null)
return;
@ -215,10 +221,8 @@ public class ProtocolLibListener implements Listener {
PacketType type = event.getPacketType();
if (type == Server.ENTITY_HEAD_ROTATION) {
packet.getBytes().write(0, degToByte(session.getHeadYaw()));
} else if (type == Server.ENTITY_LOOK) {
packet.getBytes().write(0, degToByte(session.getBodyYaw()));
packet.getBytes().write(1, degToByte(session.getPitch()));
} else if (type == Server.ENTITY_MOVE_LOOK || type == Server.REL_ENTITY_MOVE_LOOK) {
} else if (type == Server.ENTITY_LOOK || type == Server.ENTITY_MOVE_LOOK
|| type == Server.REL_ENTITY_MOVE_LOOK) {
packet.getBytes().write(0, degToByte(session.getBodyYaw()));
packet.getBytes().write(1, degToByte(session.getPitch()));
} else if (type == Server.POSITION) {
@ -231,7 +235,6 @@ public class ProtocolLibListener implements Listener {
packet.getFloat().write(0, session.getBodyYaw());
packet.getFloat().write(1, session.getPitch());
}
session.onPacketOverwritten();
Messaging.debug("OVERWRITTEN " + type + " " + packet.getHandle());
}
@ -258,7 +261,6 @@ public class ProtocolLibListener implements Listener {
}
return null;
}
return entity instanceof NPCHolder ? ((NPCHolder) entity).getNPC() : null;
}
@ -278,7 +280,6 @@ 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

@ -147,7 +147,7 @@ public class Settings {
DEFAULT_TEXT("npc.default.talk-close.text.0", "Hi, I'm <npc>!") {
@Override
public void loadFromKey(DataKey root) {
List<String> list = new ArrayList<String>();
List<String> list = new ArrayList<>();
for (DataKey key : root.getRelative("npc.default.talk-close.text").getSubKeys()) {
list.add(key.getString(""));
}
@ -290,7 +290,7 @@ public class Settings {
if (migrate.contains(".")) {
this.migrate = migrate;
} else {
this.comments = migrate;
comments = migrate;
}
this.path = path;
this.value = value;
@ -316,9 +316,8 @@ public class Settings {
}
public int asInt() {
if (value instanceof String) {
if (value instanceof String)
return Integer.parseInt(value.toString());
}
return ((Number) value).intValue();
}

View File

@ -38,9 +38,8 @@ public class StoredShops {
}
public NPCShop getShop(String name) {
if (npcShops.containsKey(name)) {
if (npcShops.containsKey(name))
return npcShops.get(name);
}
return getGlobalShop(name);
}

View File

@ -20,7 +20,7 @@ import net.citizensnpcs.util.StringHelper;
@Requirements
public class AdminCommands {
private final Citizens plugin;
private final Map<CommandSender, Long> reloadTimeouts = new WeakHashMap<CommandSender, Long>();
private final Map<CommandSender, Long> reloadTimeouts = new WeakHashMap<>();
public AdminCommands(Citizens plugin) {
this.plugin = plugin;
@ -51,7 +51,6 @@ public class AdminCommands {
return;
}
}
Messaging.sendTr(sender, Messages.CITIZENS_RELOADING);
try {
plugin.reload();

View File

@ -60,7 +60,6 @@ public class EditorCommands {
player.acceptConversationInput(args.getJoinedStrings(1));
return;
}
Editor.enterOrLeave(player, editor);
}

View File

@ -34,7 +34,7 @@ public class NPCCommandSelector extends NumericPrompt {
public NPCCommandSelector(Callback callback, List<NPC> possible) {
this.callback = callback;
this.choices = possible;
choices = possible;
}
@Override
@ -86,7 +86,7 @@ public class NPCCommandSelector extends NumericPrompt {
}
public static void start(Callback callback, Conversable player, List<NPC> possible) {
final Conversation conversation = new ConversationFactory(CitizensAPI.getPlugin()).withLocalEcho(false)
Conversation conversation = new ConversationFactory(CitizensAPI.getPlugin()).withLocalEcho(false)
.withEscapeSequence("exit").withModality(false)
.withFirstPrompt(new NPCCommandSelector(callback, possible)).buildConversation(player);
conversation.begin();
@ -100,7 +100,6 @@ public class NPCCommandSelector extends NumericPrompt {
return;
} catch (IllegalArgumentException e) {
}
Integer id = Ints.tryParse(raw);
if (id != null) {
callback.run(npcRegistry.getById(id));
@ -112,12 +111,12 @@ public class NPCCommandSelector extends NumericPrompt {
if (args.hasValueFlag("range")) {
range = Math.abs(args.getFlagDouble("range"));
}
for (NPC test : npcRegistry) {
if (test.getName().equalsIgnoreCase(name)) {
if (range > 0 && test.isSpawned()
&& !Util.locationWithinRange(args.getSenderLocation(), test.getEntity().getLocation(), range))
&& !Util.locationWithinRange(args.getSenderLocation(), test.getEntity().getLocation(), range)) {
continue;
}
possible.add(test);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -42,7 +42,6 @@ public class TraitCommands {
failed.add(String.format("%s: No permission", traitName));
continue;
}
Class<? extends Trait> clazz = CitizensAPI.getTraitFactory().getTraitClass(traitName);
if (clazz == null) {
failed.add(String.format("%s: Trait not found", traitName));
@ -108,7 +107,6 @@ public class TraitCommands {
failed.add(String.format("%s: No permission", traitName));
continue;
}
Class<? extends Trait> clazz = CitizensAPI.getTraitFactory().getTraitClass(traitName);
if (clazz == null) {
failed.add(String.format("%s: Trait not found", traitName));
@ -122,10 +120,12 @@ public class TraitCommands {
removeTrait(npc, clazz, sender);
removed.add(StringHelper.wrap(traitName));
}
if (removed.size() > 0)
if (removed.size() > 0) {
Messaging.sendTr(sender, Messages.TRAITS_REMOVED, Joiner.on(", ").join(removed));
if (failed.size() > 0)
}
if (failed.size() > 0) {
Messaging.sendTr(sender, Messages.FAILED_TO_REMOVE, Joiner.on(", ").join(failed));
}
}
private void removeTrait(NPC npc, Class<? extends Trait> clazz, CommandSender sender) {
@ -150,7 +150,6 @@ public class TraitCommands {
failed.add(String.format("%s: No permission", traitName));
continue;
}
Class<? extends Trait> clazz = CitizensAPI.getTraitFactory().getTraitClass(traitName);
if (clazz == null) {
failed.add(String.format("%s: Trait not found", traitName));

View File

@ -130,8 +130,8 @@ public class WaypointCommands {
waypoints.describeProviders(sender);
return;
}
if (sender instanceof Player && Editor.hasEditor(((Player) sender))) {
Editor.leave(((Player) sender));
if (sender instanceof Player && Editor.hasEditor((Player) sender)) {
Editor.leave((Player) sender);
}
boolean success = waypoints.setWaypointProvider(args.getString(1));
if (!success)

View File

@ -20,7 +20,7 @@ import net.citizensnpcs.util.Util;
@Menu(title = "Configure NPC", type = InventoryType.CHEST, dimensions = { 5, 9 })
public class NPCConfigurator extends InventoryMenuPage {
private final NPC npc;
private NPC npc;
private NPCConfigurator() {
throw new UnsupportedOperationException();
@ -36,7 +36,7 @@ public class NPCConfigurator extends InventoryMenuPage {
ConfiguratorInfo info = entry.getValue();
InventoryMenuSlot slot = ctx.getSlot(entry.getKey());
slot.setItemStack(new ItemStack(info.material, 1));
slot.setClickHandler((evt) -> info.clickHandler.accept(new ConfiguratorEvent(ctx, npc, slot, evt)));
slot.setClickHandler(evt -> info.clickHandler.accept(new ConfiguratorEvent(ctx, npc, slot, evt)));
info.clickHandler.accept(new ConfiguratorEvent(ctx, npc, slot, null));
}
}
@ -51,7 +51,7 @@ public class NPCConfigurator extends InventoryMenuPage {
this.ctx = ctx;
this.npc = npc;
this.slot = slot;
this.event = evt;
event = evt;
}
}
@ -60,18 +60,18 @@ public class NPCConfigurator extends InventoryMenuPage {
private final Material material;
public ConfiguratorInfo(Material mat, Consumer<ConfiguratorEvent> con) {
this.material = mat;
this.clickHandler = con;
material = mat;
clickHandler = con;
}
}
private static final Map<Integer, ConfiguratorInfo> SLOT_MAP = Maps.newHashMap();
static {
SLOT_MAP.put(0, new ConfiguratorInfo(Util.getFallbackMaterial("OAK_SIGN", "SIGN"), (evt) -> {
SLOT_MAP.put(0, new ConfiguratorInfo(Util.getFallbackMaterial("OAK_SIGN", "SIGN"), evt -> {
evt.slot.setDescription("Edit NPC name\n" + evt.npc.getName());
if (evt.event != null) {
evt.ctx.getMenu().transition(
InputMenus.stringSetter(() -> evt.npc.getName(), (input) -> evt.npc.setName(input)));
evt.ctx.getMenu()
.transition(InputMenus.stringSetter(() -> evt.npc.getName(), input -> evt.npc.setName(input)));
}
}));
}

View File

@ -12,7 +12,7 @@ public class CreateNPCHistoryItem implements CommandHistoryItem {
private final UUID uuid;
public CreateNPCHistoryItem(NPC npc) {
this.uuid = npc.getUniqueId();
uuid = npc.getUniqueId();
}
@Override

View File

@ -19,11 +19,11 @@ public class RemoveNPCHistoryItem implements CommandHistoryItem {
private final UUID uuid;
public RemoveNPCHistoryItem(NPC from) {
this.key = new MemoryDataKey();
key = new MemoryDataKey();
from.save(key);
this.type = from.getOrAddTrait(MobType.class).getType();
this.uuid = from.getUniqueId();
this.id = from.getId();
type = from.getOrAddTrait(MobType.class).getType();
uuid = from.getUniqueId();
id = from.getId();
}
@Override

View File

@ -19,7 +19,7 @@ public class CopierEditor extends Editor {
public CopierEditor(Player player, NPC npc) {
this.player = player;
this.npc = npc;
this.name = npc.getRawName();
name = npc.getRawName();
}
@Override
@ -41,7 +41,6 @@ public class CopierEditor extends Editor {
if (!copy.getRawName().equals(name)) {
copy.setName(name);
}
if (copy.isSpawned() && player.isOnline()) {
Location location = event.getClickedBlock().getLocation();
location.setYaw(player.getLocation().getYaw());
@ -50,7 +49,6 @@ public class CopierEditor extends Editor {
copy.teleport(location, TeleportCause.PLUGIN);
copy.getOrAddTrait(CurrentLocation.class).setLocation(location);
}
Messaging.sendTr(player, Messages.NPC_COPIED, npc.getName());
event.setCancelled(true);
}

View File

@ -58,5 +58,5 @@ public abstract class Editor implements Listener {
EDITING.clear();
}
private static final Map<UUID, Editor> EDITING = new HashMap<UUID, Editor>();
private static final Map<UUID, Editor> EDITING = new HashMap<>();
}

View File

@ -73,32 +73,32 @@ public class GenericEquipperGUI extends InventoryMenuPage {
@ClickHandler(slot = { 1, 5 })
public void setBoots(InventoryMenuSlot slot, CitizensInventoryClickEvent event) {
set(EquipmentSlot.BOOTS, event, (type) -> type == Material.AIR || type.name().endsWith("BOOTS"));
set(EquipmentSlot.BOOTS, event, type -> type == Material.AIR || type.name().endsWith("BOOTS"));
}
@ClickHandler(slot = { 1, 3 })
public void setChest(InventoryMenuSlot slot, CitizensInventoryClickEvent event) {
set(EquipmentSlot.CHESTPLATE, event,
(type) -> type == Material.AIR || type.name().endsWith("CHESTPLATE") || type.name().equals("ELYTRA"));
type -> type == Material.AIR || type.name().endsWith("CHESTPLATE") || type.name().equals("ELYTRA"));
}
@ClickHandler(slot = { 1, 0 })
public void setHand(InventoryMenuSlot slot, CitizensInventoryClickEvent event) {
set(EquipmentSlot.HAND, event, (type) -> true);
set(EquipmentSlot.HAND, event, type -> true);
}
@ClickHandler(slot = { 1, 2 })
public void setHelmet(InventoryMenuSlot slot, CitizensInventoryClickEvent event) {
set(EquipmentSlot.HELMET, event, (type) -> true);
set(EquipmentSlot.HELMET, event, type -> true);
}
@ClickHandler(slot = { 1, 4 })
public void setLeggings(InventoryMenuSlot slot, CitizensInventoryClickEvent event) {
set(EquipmentSlot.LEGGINGS, event, (type) -> type == Material.AIR || type.name().endsWith("LEGGINGS"));
set(EquipmentSlot.LEGGINGS, event, type -> type == Material.AIR || type.name().endsWith("LEGGINGS"));
}
@ClickHandler(slot = { 1, 1 })
public void setOffhand(InventoryMenuSlot slot, CitizensInventoryClickEvent event) {
set(EquipmentSlot.OFF_HAND, event, (type) -> true);
set(EquipmentSlot.OFF_HAND, event, type -> true);
}
}

View File

@ -43,11 +43,10 @@ public abstract class AbstractEntityController implements EntityController {
if (bukkitEntity instanceof Player) {
NMS.removeFromWorld(bukkitEntity);
NMS.remove(bukkitEntity);
bukkitEntity = null;
} else {
bukkitEntity.remove();
bukkitEntity = null;
}
bukkitEntity = null;
}
@Override

View File

@ -82,54 +82,44 @@ public class CitizensNPC extends AbstractNPC {
}
return true;
}
NPCDespawnEvent event = new NPCDespawnEvent(this, reason);
if (reason == DespawnReason.CHUNK_UNLOAD) {
event.setCancelled(data().get(NPC.Metadata.KEEP_CHUNK_LOADED, Setting.KEEP_CHUNKS_LOADED.asBoolean()));
}
Bukkit.getPluginManager().callEvent(event);
if (event.isCancelled() && reason != DespawnReason.DEATH) {
Messaging.debug("Couldn't despawn", this, "due to despawn event cancellation. Will load chunk.",
getEntity().isValid(), ", DespawnReason." + reason);
return false;
}
boolean keepSelected = getOrAddTrait(Spawned.class).shouldSpawn();
if (!keepSelected) {
data().remove("selectors");
}
if (getEntity() != null) {
getEntity().removeMetadata("NPC", CitizensAPI.getPlugin());
getEntity().removeMetadata("NPC-ID", CitizensAPI.getPlugin());
}
if (getEntity() instanceof Player) {
PlayerUpdateTask.deregisterPlayer(getEntity());
}
navigator.onDespawn();
if (reason == DespawnReason.RELOAD) {
unloadEvents();
}
for (Trait trait : new ArrayList<Trait>(traits.values())) {
for (Trait trait : new ArrayList<>(traits.values())) {
trait.onDespawn(reason);
}
Messaging.debug("Despawned", this, "DespawnReason." + reason);
if (getEntity() instanceof SkinnableEntity) {
((SkinnableEntity) getEntity()).getSkinTracker().onRemoveNPC();
}
if (reason == DespawnReason.DEATH) {
entityController.die();
} else {
entityController.remove();
}
return true;
}
@ -190,7 +180,7 @@ public class CitizensNPC extends AbstractNPC {
}
@Override
public void load(final DataKey root) {
public void load(DataKey root) {
super.load(root);
CurrentLocation spawnLocation = getOrAddTrait(CurrentLocation.class);
@ -201,14 +191,13 @@ public class CitizensNPC extends AbstractNPC {
Messaging.debug("Tried to spawn", this, "on load but world was null");
}
}
navigator.load(root.getRelative("navigator"));
}
@Override
public boolean requiresNameHologram() {
return super.requiresNameHologram()
|| (Setting.ALWAYS_USE_NAME_HOLOGRAM.asBoolean() && !data().has(NPC.Metadata.HOLOGRAM_FOR));
|| Setting.ALWAYS_USE_NAME_HOLOGRAM.asBoolean() && !data().has(NPC.Metadata.HOLOGRAM_FOR);
}
private void resetCachedCoord() {
@ -255,12 +244,10 @@ public class CitizensNPC extends AbstractNPC {
prev = getEntity().getLocation();
despawn(DespawnReason.PENDING_RESPAWN);
}
PacketNPC packet = getTraitNullable(PacketNPC.class);
if (packet != null) {
newController = packet.wrap(newController);
}
entityController = newController;
if (wasSpawned) {
spawn(prev, SpawnReason.RESPAWN);
@ -315,7 +302,6 @@ public class CitizensNPC extends AbstractNPC {
if (reason == SpawnReason.CHUNK_LOAD || reason == SpawnReason.COMMAND) {
at.getChunk().load();
}
getOrAddTrait(CurrentLocation.class).setLocation(at);
entityController.create(at.clone(), this);
getEntity().setMetadata("NPC", new FixedMetadataValue(CitizensAPI.getPlugin(), true));
@ -324,7 +310,6 @@ public class CitizensNPC extends AbstractNPC {
if (getEntity() instanceof SkinnableEntity && !hasTrait(SkinLayers.class)) {
((SkinnableEntity) getEntity()).setSkinFlags(EnumSet.allOf(SkinLayers.Layer.class));
}
Collection<Trait> onPreSpawn = traits.values();
for (Trait trait : onPreSpawn.toArray(new Trait[onPreSpawn.size()])) {
try {
@ -334,7 +319,6 @@ public class CitizensNPC extends AbstractNPC {
ex.printStackTrace();
}
}
boolean loaded = Messaging.isDebugging() ? false : Util.isLoaded(at);
boolean couldSpawn = entityController.spawn(at);
@ -343,30 +327,27 @@ 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));
return false;
}
// send skin packets, if applicable, before other NMS packets are sent
SkinnableEntity skinnable = getEntity() instanceof SkinnableEntity ? ((SkinnableEntity) getEntity()) : null;
SkinnableEntity skinnable = getEntity() instanceof SkinnableEntity ? (SkinnableEntity) getEntity() : null;
if (skinnable != null) {
skinnable.getSkinTracker().onSpawnNPC();
}
NMS.setLocationDirectly(getEntity(), at);
NMS.setHeadYaw(getEntity(), at.getYaw());
NMS.setBodyYaw(getEntity(), at.getYaw());
final Location to = at;
Location to = at;
Consumer<Runnable> postSpawn = new Consumer<Runnable>() {
private int timer;
@Override
public void accept(Runnable cancel) {
if (getEntity() == null || (!hasTrait(PacketNPC.class) && !getEntity().isValid())) {
if (getEntity() == null || !hasTrait(PacketNPC.class) && !getEntity().isValid()) {
if (timer++ > Setting.ENTITY_SPAWN_WAIT_DURATION.asTicks()) {
Messaging.debug("Couldn't spawn ", CitizensNPC.this, "waited", timer,
"ticks but entity not added to world");
@ -374,10 +355,8 @@ public class CitizensNPC extends AbstractNPC {
cancel.run();
Bukkit.getPluginManager().callEvent(new NPCNeedsRespawnEvent(CitizensNPC.this, to));
}
return;
}
// Set the spawned state
getOrAddTrait(CurrentLocation.class).setLocation(to);
getOrAddTrait(Spawned.class).setSpawned(true);
@ -392,7 +371,6 @@ public class CitizensNPC extends AbstractNPC {
cancel.run();
return;
}
navigator.onSpawn();
for (Trait trait : Iterables.toArray(traits.values(), Trait.class)) {
@ -403,7 +381,6 @@ public class CitizensNPC extends AbstractNPC {
ex.printStackTrace();
}
}
EntityType type = getEntity().getType();
NMS.replaceTracker(getEntity());
@ -414,13 +391,11 @@ public class CitizensNPC extends AbstractNPC {
if (NMS.getStepHeight(entity) < 1) {
NMS.setStepHeight(entity, 1);
}
if (type == EntityType.PLAYER) {
PlayerUpdateTask.registerPlayer(getEntity());
} else if (data().has(NPC.Metadata.AGGRESSIVE)) {
NMS.setAggressive(entity, data().<Boolean> get(NPC.Metadata.AGGRESSIVE));
}
if (SUPPORT_NODAMAGE_TICKS && (Setting.DEFAULT_SPAWN_NODAMAGE_DURATION.asTicks() != 20
|| data().has(NPC.Metadata.SPAWN_NODAMAGE_TICKS))) {
try {
@ -431,11 +406,9 @@ public class CitizensNPC extends AbstractNPC {
}
}
}
if (requiresNameHologram() && !hasTrait(HologramTrait.class)) {
addTrait(HologramTrait.class);
}
updateFlyableState();
updateCustomNameVisibility();
updateScoreboard();
@ -451,11 +424,10 @@ public class CitizensNPC extends AbstractNPC {
new BukkitRunnable() {
@Override
public void run() {
postSpawn.accept(() -> cancel());
postSpawn.accept(this::cancel);
}
}.runTaskTimer(CitizensAPI.getPlugin(), 0, 1);
}
return true;
}
@ -467,13 +439,11 @@ public class CitizensNPC extends AbstractNPC {
if (hasTrait(SitTrait.class) && getOrAddTrait(SitTrait.class).isSitting()) {
getOrAddTrait(SitTrait.class).setSitting(location);
}
Location npcLoc = getEntity().getLocation();
if (isSpawned() && npcLoc.getWorld() == location.getWorld()) {
if (npcLoc.distance(location) < 1) {
NMS.setHeadYaw(getEntity(), location.getYaw());
}
if (getEntity().getType() == EntityType.PLAYER && !getEntity().isInsideVehicle()
&& NMS.getPassengers(getEntity()).size() == 0) {
NPCTeleportEvent event = new NPCTeleportEvent(this, location);
@ -484,7 +454,6 @@ public class CitizensNPC extends AbstractNPC {
return;
}
}
super.teleport(location, reason);
}
@ -502,7 +471,6 @@ public class CitizensNPC extends AbstractNPC {
resetCachedCoord();
return;
}
if (data().has(NPC.Metadata.ACTIVATION_RANGE)) {
int range = data().get(NPC.Metadata.ACTIVATION_RANGE);
if (range == -1 || CitizensAPI.getLocationLookup().getNearbyPlayers(getStoredLocation(), range)
@ -510,7 +478,6 @@ public class CitizensNPC extends AbstractNPC {
NMS.activate(getEntity());
}
}
boolean shouldSwim = data().get(NPC.Metadata.SWIMMING, SwimmingExaminer.isWaterMob(getEntity()))
&& MinecraftBlockExaminer.isLiquid(getEntity().getLocation().getBlock().getType());
if (navigator.isNavigating()) {
@ -528,7 +495,6 @@ public class CitizensNPC extends AbstractNPC {
NMS.trySwim(getEntity());
}
}
if (SUPPORT_GLOWING && data().has(NPC.Metadata.GLOWING)) {
try {
getEntity().setGlowing(data().get(NPC.Metadata.GLOWING, false));
@ -536,7 +502,6 @@ public class CitizensNPC extends AbstractNPC {
SUPPORT_GLOWING = false;
}
}
if (SUPPORT_SILENT && data().has(NPC.Metadata.SILENT)) {
try {
getEntity().setSilent(Boolean.parseBoolean(data().get(NPC.Metadata.SILENT).toString()));
@ -544,7 +509,6 @@ public class CitizensNPC extends AbstractNPC {
SUPPORT_SILENT = false;
}
}
boolean isLiving = getEntity() instanceof LivingEntity;
if (isUpdating(NPCUpdate.PACKET)) {
if (data().get(NPC.Metadata.KEEP_CHUNK_LOADED, Setting.KEEP_CHUNKS_LOADED.asBoolean())) {
@ -572,7 +536,6 @@ public class CitizensNPC extends AbstractNPC {
SUPPORT_PICKUP_ITEMS = false;
}
}
if (getEntity() instanceof Player) {
updateUsingItemState((Player) getEntity());
if (data().has(NPC.Metadata.SNEAKING) && !hasTrait(SneakTrait.class)) {
@ -580,7 +543,6 @@ public class CitizensNPC extends AbstractNPC {
}
}
}
navigator.run();
updateCounter++;
@ -616,16 +578,12 @@ public class CitizensNPC extends AbstractNPC {
return;
EntityType type = isSpawned() ? getEntity().getType() : getOrAddTrait(MobType.class).getType();
if (type == null)
return;
if (!Util.isAlwaysFlyable(type))
if (type == null || !Util.isAlwaysFlyable(type))
return;
if (!data().has(NPC.Metadata.FLYABLE)) {
data().setPersistent(NPC.Metadata.FLYABLE, true);
}
if (!hasTrait(Gravity.class)) {
getOrAddTrait(Gravity.class).setEnabled(true);
}
@ -657,7 +615,7 @@ public class CitizensNPC extends AbstractNPC {
}
}
private static final SetMultimap<ChunkCoord, NPC> CHUNK_LOADERS = HashMultimap.create();
private static SetMultimap<ChunkCoord, NPC> CHUNK_LOADERS = HashMultimap.create();
private static boolean SUPPORT_GLOWING = true;
private static boolean SUPPORT_NODAMAGE_TICKS = true;
private static boolean SUPPORT_PICKUP_ITEMS = true;

View File

@ -2,6 +2,7 @@ package net.citizensnpcs.npc;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
@ -37,7 +38,7 @@ import net.citizensnpcs.util.NMS;
public class CitizensNPCRegistry implements NPCRegistry {
private final String name;
private final TIntObjectHashMap<NPC> npcs = new TIntObjectHashMap<NPC>();
private final TIntObjectHashMap<NPC> npcs = new TIntObjectHashMap<>();
private final NPCDataStore saves;
private final Map<UUID, NPC> uniqueNPCs = Maps.newHashMap();
@ -74,11 +75,9 @@ public class CitizensNPCRegistry implements NPCRegistry {
if (type == EntityType.ARMOR_STAND && !npc.hasTrait(ArmorStandTrait.class)) {
npc.addTrait(ArmorStandTrait.class);
}
if (Setting.DEFAULT_LOOK_CLOSE.asBoolean()) {
npc.addTrait(LookClose.class);
}
npc.addTrait(MountTrait.class);
return npc;
}
@ -93,9 +92,8 @@ public class CitizensNPCRegistry implements NPCRegistry {
npc.data().set(NPC.Metadata.ITEM_ID, item.getType().name());
npc.data().set(NPC.Metadata.ITEM_DATA, item.getData().getData());
npc.setItemProvider(() -> item);
} else {
} else
throw new UnsupportedOperationException("Not an item entity type");
}
return npc;
}
@ -174,14 +172,13 @@ public class CitizensNPCRegistry implements NPCRegistry {
if (npc != null)
return npc;
for (NPCRegistry registry : CitizensAPI.getNPCRegistries()) {
if (registry == this)
if (registry == this) {
continue;
NPC other = registry.getByUniqueId(uuid);
if (other != null) {
return other;
}
NPC other = registry.getByUniqueId(uuid);
if (other != null)
return other;
}
return null;
}
@ -243,8 +240,8 @@ public class CitizensNPCRegistry implements NPCRegistry {
@Override
public Iterable<NPC> sorted() {
List<NPC> vals = new ArrayList<NPC>(npcs.valueCollection());
Collections.sort(vals, (a, b) -> Integer.compare(a.getId(), b.getId()));
List<NPC> vals = new ArrayList<>(npcs.valueCollection());
Collections.sort(vals, Comparator.comparing(NPC::getId));
return vals;
}
}

View File

@ -157,9 +157,8 @@ public class CitizensTraitFactory implements TraitFactory {
@Override
public <T extends Trait> T getTrait(Class<T> clazz) {
for (TraitInfo entry : registered.values()) {
if (clazz == entry.getTraitClass()) {
if (clazz == entry.getTraitClass())
return create(entry);
}
}
return null;
}
@ -183,9 +182,8 @@ public class CitizensTraitFactory implements TraitFactory {
public void registerTrait(TraitInfo info) {
Preconditions.checkNotNull(info, "info cannot be null");
info.checkValid();
if (registered.containsKey(info.getTraitName())) {
if (registered.containsKey(info.getTraitName()))
throw new IllegalArgumentException("Trait name " + info.getTraitName() + " already registered");
}
registered.put(info.getTraitName(), info);
if (info.isDefaultTrait()) {
defaultTraits.add(info);

View File

@ -37,6 +37,5 @@ public class EntityControllers {
}
}
private static final Map<EntityType, Constructor<? extends EntityController>> TYPES = Maps
.newEnumMap(EntityType.class);
private static Map<EntityType, Constructor<? extends EntityController>> TYPES = Maps.newEnumMap(EntityType.class);
}

View File

@ -57,11 +57,11 @@ public class NPCSelector implements Listener, net.citizensnpcs.api.npc.NPCSelect
if (event.getSelected() != null)
return event.getSelected();
if (sender instanceof Player) {
if (sender instanceof Player)
return getSelectedFromMetadatable((Player) sender);
} else if (sender instanceof BlockCommandSender) {
else if (sender instanceof BlockCommandSender)
return getSelectedFromMetadatable(((BlockCommandSender) sender).getBlock());
} else if (sender instanceof ConsoleCommandSender) {
else if (sender instanceof ConsoleCommandSender) {
if (consoleSelectedNPC == null)
return null;
return CitizensAPI.getNPCRegistry().getByUniqueIdGlobal(consoleSelectedNPC);
@ -90,7 +90,7 @@ public class NPCSelector implements Listener, net.citizensnpcs.api.npc.NPCSelect
if (value.equals("console")) {
consoleSelectedNPC = null;
} else if (value.startsWith("@")) {
String[] parts = value.substring(1, value.length()).split(":");
String[] parts = value.substring(1).split(":");
World world = Bukkit.getWorld(parts[0]);
if (world != null) {
Block block = world.getBlockAt(Integer.parseInt(parts[1]), Integer.parseInt(parts[2]),
@ -159,7 +159,6 @@ public class NPCSelector implements Listener, net.citizensnpcs.api.npc.NPCSelect
consoleSelectedNPC = npc.getUniqueId();
selectors.add("console");
}
Bukkit.getPluginManager().callEvent(new NPCSelectEvent(npc, sender));
}

View File

@ -50,9 +50,10 @@ public class Template {
queue.add(new Node(fullKey, (Map<String, Object>) entry.getValue()));
continue;
}
boolean overwrite = memoryKey.keyExists(fullKey) | override;
if (!overwrite || fullKey.equals("uuid"))
boolean overwrite = memoryKey.keyExists(fullKey) || override;
if (!overwrite || fullKey.equals("uuid")) {
continue;
}
memoryKey.setRaw(fullKey, entry.getValue());
}
}

View File

@ -40,15 +40,15 @@ public class AStarNavigationStrategy extends AbstractPathStrategy {
super(TargetType.LOCATION);
List<Vector> list = Lists.newArrayList(path);
this.params = params;
this.destination = list.get(list.size() - 1).toLocation(npc.getStoredLocation().getWorld());
destination = list.get(list.size() - 1).toLocation(npc.getStoredLocation().getWorld());
this.npc = npc;
this.plan = new Path(list);
plan = new Path(list);
}
public AStarNavigationStrategy(NPC npc, Location dest, NavigatorParameters params) {
super(TargetType.LOCATION);
this.params = params;
this.destination = dest;
destination = dest;
this.npc = npc;
}
@ -91,9 +91,8 @@ public class AStarNavigationStrategy extends AbstractPathStrategy {
planner = null;
}
}
if (getCancelReason() != null || plan == null || plan.isComplete()) {
if (getCancelReason() != null || plan == null || plan.isComplete())
return true;
}
if (vector == null) {
vector = plan.getCurrentVector();
}
@ -116,23 +115,20 @@ public class AStarNavigationStrategy extends AbstractPathStrategy {
double xzDistance = dX * dX + dZ * dZ;
if (Math.abs(dY) < 1 && Math.sqrt(xzDistance) <= params.distanceMargin()) {
plan.update(npc);
if (plan.isComplete()) {
if (plan.isComplete())
return true;
}
vector = plan.getCurrentVector();
return false;
}
if (params.debug()) {
npc.getEntity().getWorld().playEffect(dest, Effect.ENDER_SIGNAL, 0);
}
if (npc.getEntity() instanceof LivingEntity && !npc.getEntity().getType().name().contains("ARMOR_STAND")) {
NMS.setDestination(npc.getEntity(), dest.getX(), dest.getY(), dest.getZ(), params.speed());
} else {
Vector dir = dest.toVector().subtract(npc.getEntity().getLocation().toVector()).normalize().multiply(0.2);
boolean liquidOrInLiquid = MinecraftBlockExaminer.isLiquidOrInLiquid(loc.getBlock());
if ((dY >= 1 && Math.sqrt(xzDistance) <= 0.4) || (dY >= 0.2 && liquidOrInLiquid)) {
if (dY >= 1 && Math.sqrt(xzDistance) <= 0.4 || dY >= 0.2 && liquidOrInLiquid) {
dir.add(new Vector(0, 0.75, 0));
}
npc.getEntity().setVelocity(dir);
@ -176,18 +172,16 @@ public class AStarNavigationStrategy extends AbstractPathStrategy {
}
public CancelReason tick(int iterationsPerTick, int maxIterations) {
if (this.plan != null)
if (plan != null)
return null;
Path plan = ASTAR.run(state, iterationsPerTick);
if (plan == null) {
if (state.isEmpty()) {
if (state.isEmpty())
return CancelReason.STUCK;
}
if (iterationsPerTick > 0 && maxIterations > 0) {
iterations += iterationsPerTick;
if (iterations > maxIterations) {
if (iterations > maxIterations)
return CancelReason.STUCK;
}
}
} else {
this.plan = plan;
@ -200,5 +194,5 @@ public class AStarNavigationStrategy extends AbstractPathStrategy {
}
}
private static final AStarMachine<VectorNode, Path> ASTAR = AStarMachine.createWithDefaultStorage();
private static AStarMachine<VectorNode, Path> ASTAR = AStarMachine.createWithDefaultStorage();
}

View File

@ -18,8 +18,8 @@ public class BoundingBoxExaminer implements BlockExaminer {
public BoundingBoxExaminer(Entity entity) {
if (entity != null) {
this.height = NMS.getHeight(entity);
this.width = NMS.getWidth(entity);
height = NMS.getHeight(entity);
width = NMS.getWidth(entity);
}
}

View File

@ -73,7 +73,6 @@ public class CitizensNavigator implements Navigator, Runnable {
!Setting.DEFAULT_STUCK_ACTION.asString().contains("teleport"))) {
defaultParams.stuckAction(null);
}
defaultParams.examiner(new SwimmingExaminer(npc));
}
@ -116,9 +115,8 @@ public class CitizensNavigator implements Navigator, Runnable {
@Override
public NavigatorParameters getLocalParameters() {
if (!isNavigating()) {
if (!isNavigating())
return defaultParams;
}
return localParams;
}
@ -156,23 +154,18 @@ public class CitizensNavigator implements Navigator, Runnable {
if (root.keyExists("pathfindingrange")) {
defaultParams.range((float) root.getDouble("pathfindingrange"));
}
if (root.keyExists("stationaryticks")) {
defaultParams.stationaryTicks(root.getInt("stationaryticks"));
}
if (root.keyExists("distancemargin")) {
defaultParams.distanceMargin(root.getDouble("distancemargin"));
}
if (root.keyExists("destinationteleportmargin")) {
defaultParams.destinationTeleportMargin(root.getDouble("destinationteleportmargin"));
}
if (root.keyExists("updatepathrate")) {
defaultParams.updatePathRate(root.getInt("updatepathrate"));
}
defaultParams.speedModifier((float) root.getDouble("speedmodifier", 1F));
defaultParams.avoidWater(root.getBoolean("avoidwater"));
if (!root.getBoolean("usedefaultstuckaction") && defaultParams.stuckAction() == TeleportStuckAction.INSTANCE) {
@ -188,7 +181,6 @@ public class CitizensNavigator implements Navigator, Runnable {
if (defaultParams.baseSpeed() == UNINITIALISED_SPEED) {
defaultParams.baseSpeed(NMS.getSpeedFor(npc));
}
updatePathfindingRange();
}
@ -205,7 +197,6 @@ public class CitizensNavigator implements Navigator, Runnable {
stopNavigating(CancelReason.STUCK);
return;
}
if (updateStationaryStatus())
return;
@ -214,7 +205,6 @@ public class CitizensNavigator implements Navigator, Runnable {
if (!finished) {
localParams.run();
}
if (localParams.lookAtFunction() != null) {
if (session == null) {
RotationTrait trait = npc.getOrAddTrait(RotationTrait.class);
@ -223,14 +213,12 @@ public class CitizensNavigator implements Navigator, Runnable {
}
session.getSession().rotateToFace(localParams.lookAtFunction().apply(this));
}
if (localParams.destinationTeleportMargin() > 0
&& npcLoc.distance(targetLoc) <= localParams.destinationTeleportMargin()) {
// TODO: easing?
npc.teleport(targetLoc, TeleportCause.PLUGIN);
finished = true;
}
if (!finished)
return;
@ -252,37 +240,31 @@ public class CitizensNavigator implements Navigator, Runnable {
} else {
root.removeKey("pathfindingrange");
}
if (defaultParams.stationaryTicks() != Setting.DEFAULT_STATIONARY_DURATION.asTicks()) {
root.setInt("stationaryticks", defaultParams.stationaryTicks());
} else {
root.removeKey("stationaryticks");
}
if (defaultParams.destinationTeleportMargin() != Setting.DEFAULT_DESTINATION_TELEPORT_MARGIN.asDouble()) {
root.setDouble("destinationteleportmargin", defaultParams.destinationTeleportMargin());
} else {
root.removeKey("destinationteleportmargin");
}
if (defaultParams.distanceMargin() != Setting.DEFAULT_DISTANCE_MARGIN.asDouble()) {
root.setDouble("distancemargin", defaultParams.distanceMargin());
} else {
root.removeKey("distancemargin");
}
if (defaultParams.updatePathRate() != Setting.DEFAULT_PATHFINDER_UPDATE_PATH_RATE.asTicks()) {
root.setInt("updatepathrate", defaultParams.updatePathRate());
} else {
root.removeKey("updatepathrate");
}
if (defaultParams.useNewPathfinder() != Setting.USE_NEW_PATHFINDER.asBoolean()) {
root.setBoolean("usenewpathfinder", defaultParams.useNewPathfinder());
} else {
root.removeKey("usenewpathfinder");
}
root.setDouble("speedmodifier", defaultParams.speedModifier());
root.setBoolean("avoidwater", defaultParams.avoidWater());
root.setBoolean("usedefaultstuckaction", defaultParams.stuckAction() == TeleportStuckAction.INSTANCE);
@ -305,7 +287,6 @@ public class CitizensNavigator implements Navigator, Runnable {
cancelNavigation();
return;
}
setTarget(params -> {
params.straightLineTargetingDistance(100000);
return new MCTargetStrategy(npc, target, aggressive, params);
@ -321,7 +302,6 @@ public class CitizensNavigator implements Navigator, Runnable {
cancelNavigation();
return;
}
setTarget(params -> new StraightLineNavigationStrategy(npc, target.clone(), params));
}
@ -334,7 +314,6 @@ public class CitizensNavigator implements Navigator, Runnable {
cancelNavigation();
return;
}
setTarget(params -> new MCTargetStrategy(npc, target, aggressive, params));
}
@ -354,15 +333,13 @@ public class CitizensNavigator implements Navigator, Runnable {
cancelNavigation();
return;
}
setTarget(params -> {
if (npc.isFlyable()) {
if (npc.isFlyable())
return new FlyingAStarNavigationStrategy(npc, path, params);
} else if (params.useNewPathfinder() || !(npc.getEntity() instanceof LivingEntity)) {
else if (params.useNewPathfinder() || !(npc.getEntity() instanceof LivingEntity))
return new AStarNavigationStrategy(npc, path, params);
} else {
else
return new MCNavigationStrategy(npc, path, params);
}
});
}
@ -374,16 +351,14 @@ public class CitizensNavigator implements Navigator, Runnable {
cancelNavigation();
return;
}
final Location target = targetIn.clone();
Location target = targetIn.clone();
setTarget(params -> {
if (npc.isFlyable()) {
if (npc.isFlyable())
return new FlyingAStarNavigationStrategy(npc, target, params);
} else if (params.useNewPathfinder() || !(npc.getEntity() instanceof LivingEntity)) {
else if (params.useNewPathfinder() || !(npc.getEntity() instanceof LivingEntity))
return new AStarNavigationStrategy(npc, target, params);
} else {
else
return new MCNavigationStrategy(npc, target, params);
}
});
}
@ -391,7 +366,6 @@ public class CitizensNavigator implements Navigator, Runnable {
if (executing != null) {
executing.stop();
}
executing = null;
localParams = defaultParams;
@ -402,16 +376,11 @@ public class CitizensNavigator implements Navigator, Runnable {
npc.getEntity().setVelocity(velocity);
NMS.cancelMoveDestination(npc.getEntity());
}
if (!SUPPORT_CHUNK_TICKETS || !CitizensAPI.hasImplementation() || !CitizensAPI.getPlugin().isEnabled())
return;
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() {
@Override
public void run() {
updateTicket(isNavigating() ? executing.getTargetAsLocation() : null);
}
}, 10);
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(),
() -> updateTicket(isNavigating() ? executing.getTargetAsLocation() : null), 10);
// Location loc = npc.getEntity().getLocation(STATIONARY_LOCATION);
// NMS.look(npc.getEntity(), loc.getYaw(), 0);
@ -424,28 +393,23 @@ public class CitizensNavigator implements Navigator, Runnable {
if (reason == CancelReason.STUCK && Messaging.isDebugging()) {
Messaging.debug(npc, "navigation ended, stuck", executing);
}
if (session != null) {
session.end();
session = null;
}
Iterator<NavigatorCallback> itr = localParams.callbacks().iterator();
List<NavigatorCallback> callbacks = new ArrayList<NavigatorCallback>();
List<NavigatorCallback> callbacks = new ArrayList<>();
while (itr.hasNext()) {
callbacks.add(itr.next());
itr.remove();
}
for (NavigatorCallback callback : callbacks) {
callback.onCompletion(reason);
}
if (reason == null) {
stopNavigating();
return;
}
if (reason == CancelReason.STUCK) {
StuckAction action = localParams.stuckAction();
NavigationStuckEvent event = new NavigationStuckEvent(this, action);
@ -458,7 +422,6 @@ public class CitizensNavigator implements Navigator, Runnable {
return;
}
}
NavigationCancelEvent event = new NavigationCancelEvent(this, reason);
PathStrategy old = executing;
Bukkit.getPluginManager().callEvent(event);
@ -534,7 +497,6 @@ public class CitizensNavigator implements Navigator, Runnable {
stopNavigating(CancelReason.STUCK);
return true;
}
if (lastX == current.getBlockX() && lastY == current.getBlockY() && lastZ == current.getBlockZ()) {
if (++stationaryTicks >= localParams.stationaryTicks()) {
stopNavigating(CancelReason.STUCK);
@ -543,7 +505,6 @@ public class CitizensNavigator implements Navigator, Runnable {
} else {
stationaryTicks = 0;
}
lastX = current.getBlockX();
lastY = current.getBlockY();
lastZ = current.getBlockZ();
@ -554,32 +515,29 @@ public class CitizensNavigator implements Navigator, Runnable {
if (!SUPPORT_CHUNK_TICKETS || !CitizensAPI.hasImplementation() || !CitizensAPI.getPlugin().isEnabled())
return;
if (target != null && this.activeTicket != null
&& new ChunkCoord(target.getChunk()).equals(new ChunkCoord(this.activeTicket.getChunk()))) {
this.activeTicket = target.clone();
if (target != null && activeTicket != null
&& new ChunkCoord(target.getChunk()).equals(new ChunkCoord(activeTicket.getChunk()))) {
activeTicket = target.clone();
return;
}
if (this.activeTicket != null) {
if (activeTicket != null) {
try {
this.activeTicket.getChunk().removePluginChunkTicket(CitizensAPI.getPlugin());
activeTicket.getChunk().removePluginChunkTicket(CitizensAPI.getPlugin());
} catch (NoSuchMethodError e) {
SUPPORT_CHUNK_TICKETS = false;
this.activeTicket = null;
activeTicket = null;
}
}
if (target == null) {
this.activeTicket = null;
activeTicket = null;
return;
}
this.activeTicket = target.clone();
activeTicket = target.clone();
try {
this.activeTicket.getChunk().addPluginChunkTicket(CitizensAPI.getPlugin());
activeTicket.getChunk().addPluginChunkTicket(CitizensAPI.getPlugin());
} catch (NoSuchMethodError e) {
SUPPORT_CHUNK_TICKETS = false;
this.activeTicket = null;
activeTicket = null;
}
}

View File

@ -43,16 +43,16 @@ public class FlyingAStarNavigationStrategy extends AbstractPathStrategy {
public FlyingAStarNavigationStrategy(NPC npc, Iterable<Vector> path, NavigatorParameters params) {
super(TargetType.LOCATION);
List<Vector> list = Lists.newArrayList(path);
this.target = list.get(list.size() - 1).toLocation(npc.getStoredLocation().getWorld());
this.parameters = params;
target = list.get(list.size() - 1).toLocation(npc.getStoredLocation().getWorld());
parameters = params;
this.npc = npc;
setPlan(new Path(list));
}
public FlyingAStarNavigationStrategy(final NPC npc, Location dest, NavigatorParameters params) {
public FlyingAStarNavigationStrategy(NPC npc, Location dest, NavigatorParameters params) {
super(TargetType.LOCATION);
this.target = dest;
this.parameters = params;
target = dest;
parameters = params;
this.npc = npc;
}
@ -89,7 +89,7 @@ public class FlyingAStarNavigationStrategy extends AbstractPathStrategy {
}
public void setPlan(Path path) {
this.plan = path;
plan = path;
if (plan == null || plan.isComplete()) {
setCancelReason(CancelReason.STUCK);
} else {
@ -133,15 +133,13 @@ public class FlyingAStarNavigationStrategy extends AbstractPathStrategy {
setPlan(plan);
}
}
if (getCancelReason() != null || plan == null || plan.isComplete()) {
if (getCancelReason() != null || plan == null || plan.isComplete())
return true;
}
Location current = npc.getEntity().getLocation();
if (current.toVector().distance(vector) <= parameters.distanceMargin()) {
plan.update(npc);
if (plan.isComplete()) {
if (plan.isComplete())
return true;
}
vector = plan.getCurrentVector();
}
if (parameters.debug()) {
@ -159,7 +157,6 @@ public class FlyingAStarNavigationStrategy extends AbstractPathStrategy {
// 1.8 compatibility
}
}
Vector centeredDest = new Vector(vector.getX() + 0.5D, vector.getY() + 0.1D, vector.getZ() + 0.5D);
double d0 = centeredDest.getX() - current.getX();
double d1 = centeredDest.getY() - current.getY();
@ -178,10 +175,9 @@ public class FlyingAStarNavigationStrategy extends AbstractPathStrategy {
NMS.setVerticalMovement(npc.getEntity(), 0.5);
Util.faceLocation(npc.getEntity(), centeredDest.toLocation(npc.getEntity().getWorld()));
}
plan.run(npc);
return false;
}
private static final AStarMachine<VectorNode, Path> ASTAR = AStarMachine.createWithDefaultStorage();
private static AStarMachine<VectorNode, Path> ASTAR = AStarMachine.createWithDefaultStorage();
}

View File

@ -23,24 +23,24 @@ public class MCNavigationStrategy extends AbstractPathStrategy {
private final NavigatorParameters parameters;
private final Location target;
MCNavigationStrategy(final NPC npc, Iterable<Vector> path, NavigatorParameters params) {
MCNavigationStrategy(NPC npc, Iterable<Vector> path, NavigatorParameters params) {
super(TargetType.LOCATION);
List<Vector> list = Lists.newArrayList(path);
this.target = list.get(list.size() - 1).toLocation(npc.getStoredLocation().getWorld());
this.parameters = params;
target = list.get(list.size() - 1).toLocation(npc.getStoredLocation().getWorld());
parameters = params;
entity = npc.getEntity();
this.navigator = NMS.getTargetNavigator(npc.getEntity(), list, params);
navigator = NMS.getTargetNavigator(npc.getEntity(), list, params);
}
MCNavigationStrategy(final NPC npc, Location dest, NavigatorParameters params) {
MCNavigationStrategy(NPC npc, Location dest, NavigatorParameters params) {
super(TargetType.LOCATION);
if (!MinecraftBlockExaminer.canStandIn(dest.getBlock())) {
dest = MinecraftBlockExaminer.findValidLocationAbove(dest, 2);
}
this.target = Util.getCenterLocation(dest.getBlock());
this.parameters = params;
target = Util.getCenterLocation(dest.getBlock());
parameters = params;
entity = npc.getEntity();
this.navigator = NMS.getTargetNavigator(entity, target, params);
navigator = NMS.getTargetNavigator(entity, target, params);
}
@Override

View File

@ -31,17 +31,17 @@ public class MCTargetStrategy implements PathStrategy, EntityTarget {
public MCTargetStrategy(NPC npc, org.bukkit.entity.Entity target, boolean aggro, NavigatorParameters params) {
this.npc = npc;
this.parameters = params;
this.handle = npc.getEntity();
parameters = params;
handle = npc.getEntity();
this.target = target;
TargetNavigator nms = NMS.getTargetNavigator(npc.getEntity(), target, params);
this.targetNavigator = nms != null && !params.useNewPathfinder() ? nms : new AStarTargeter();
targetNavigator = nms != null && !params.useNewPathfinder() ? nms : new AStarTargeter();
this.aggro = aggro;
}
private boolean canAttack() {
BoundingBox handleBB = NMS.getBoundingBox(handle), targetBB = NMS.getBoundingBox(target);
return attackTicks <= 0 && (handleBB.maxY > targetBB.minY && handleBB.minY < targetBB.maxY)
return attackTicks <= 0 && handleBB.maxY > targetBB.minY && handleBB.minY < targetBB.maxY
&& distance() <= parameters.attackRange() && ((LivingEntity) handle).hasLineOfSight(target);
}
@ -105,19 +105,16 @@ public class MCTargetStrategy implements PathStrategy, EntityTarget {
cancelReason = CancelReason.TARGET_DIED;
return true;
}
if (target.getWorld() != handle.getWorld()) {
cancelReason = CancelReason.TARGET_MOVED_WORLD;
return true;
}
if (cancelReason != null)
return true;
if (parameters.straightLineTargetingDistance() > 0 && !(targetNavigator instanceof StraightLineTargeter)) {
targetNavigator = new StraightLineTargeter(targetNavigator);
}
if (!aggro && distance() <= parameters.distanceMargin()) {
stop();
return false;
@ -125,7 +122,6 @@ public class MCTargetStrategy implements PathStrategy, EntityTarget {
targetNavigator.setPath();
updateCounter = 0;
}
targetNavigator.update();
NMS.look(handle, target);
@ -137,11 +133,9 @@ public class MCTargetStrategy implements PathStrategy, EntityTarget {
}
attackTicks = parameters.attackDelayTicks();
}
if (attackTicks > 0) {
attackTicks--;
}
return false;
}
@ -179,9 +173,8 @@ public class MCTargetStrategy implements PathStrategy, EntityTarget {
private void setStrategy() {
Location location = parameters.entityTargetLocationMapper().apply(target);
if (location == null) {
if (location == null)
throw new IllegalStateException("mapper should not return null");
}
if (!npc.isFlyable()) {
Block block = location.getBlock();
while (!MinecraftBlockExaminer.canStandOn(block.getRelative(BlockFace.DOWN))) {
@ -239,7 +232,6 @@ public class MCTargetStrategy implements PathStrategy, EntityTarget {
active = new StraightLineNavigationStrategy(npc, target, parameters);
return;
}
active = null;
fallback.setPath();
}

View File

@ -27,13 +27,13 @@ public class StraightLineNavigationStrategy extends AbstractPathStrategy {
this.params = params;
this.target = target;
this.npc = npc;
this.destination = params.entityTargetLocationMapper().apply(target);
destination = params.entityTargetLocationMapper().apply(target);
}
public StraightLineNavigationStrategy(NPC npc, Location dest, NavigatorParameters params) {
super(TargetType.LOCATION);
this.params = params;
this.destination = dest;
destination = dest;
this.npc = npc;
}
@ -68,7 +68,6 @@ public class StraightLineNavigationStrategy extends AbstractPathStrategy {
if (target != null) {
destination = params.entityTargetLocationMapper().apply(target);
}
Vector destVector = currLoc.toVector().add(destination.toVector().subtract(currLoc.toVector()).normalize());
Location destLoc = destVector.toLocation(destination.getWorld());
if (!npc.isFlyable() && destVector.getBlockY() > currLoc.getBlockY()) {
@ -84,7 +83,6 @@ public class StraightLineNavigationStrategy extends AbstractPathStrategy {
destLoc = block.getLocation();
destVector = destLoc.toVector();
}
double dX = destVector.getX() - currLoc.getX();
double dZ = destVector.getZ() - currLoc.getZ();
double dY = destVector.getY() - currLoc.getY();
@ -105,11 +103,9 @@ public class StraightLineNavigationStrategy extends AbstractPathStrategy {
while (normalisedTargetYaw >= 180.0F) {
normalisedTargetYaw -= 360.0F;
}
while (normalisedTargetYaw < -180.0F) {
normalisedTargetYaw += 360.0F;
}
if (npc.getEntity().getType() != EntityType.ENDER_DRAGON) {
NMS.setVerticalMovement(npc.getEntity(), 0.5);
NMS.setHeadYaw(npc.getEntity(), currLoc.getYaw() + normalisedTargetYaw);
@ -121,7 +117,7 @@ public class StraightLineNavigationStrategy extends AbstractPathStrategy {
Vector dir = destVector.subtract(currLoc.toVector()).normalize().multiply(0.2);
Block in = currLoc.getBlock();
if (distance > 0 && dY >= 1 && xzDistance <= 2.75
|| (dY >= 0.2 && MinecraftBlockExaminer.isLiquidOrInLiquid(in))) {
|| dY >= 0.2 && MinecraftBlockExaminer.isLiquidOrInLiquid(in)) {
dir.add(new Vector(0, 0.75, 0));
}
Util.faceLocation(npc.getEntity(), destLoc);

View File

@ -4,14 +4,6 @@ package net.citizensnpcs.npc.profile;
* The result status of a profile fetch.
*/
public enum ProfileFetchResult {
/**
* The profile has not been fetched yet.
*/
PENDING,
/**
* The profile was successfully fetched.
*/
SUCCESS,
/**
* The profile request failed for unknown reasons.
*/
@ -20,6 +12,14 @@ public enum ProfileFetchResult {
* The profile request failed because the profile was not found.
*/
NOT_FOUND,
/**
* The profile has not been fetched yet.
*/
PENDING,
/**
* The profile was successfully fetched.
*/
SUCCESS,
/**
* The profile request failed because too many requests were sent.
*/

View File

@ -31,8 +31,8 @@ import net.citizensnpcs.util.NMS;
* @see ProfileFetcher
*/
class ProfileFetchThread implements Runnable {
private final Deque<ProfileRequest> queue = new ArrayDeque<ProfileRequest>();
private final Map<String, ProfileRequest> requested = new HashMap<String, ProfileRequest>(40);
private final Deque<ProfileRequest> queue = new ArrayDeque<>();
private final Map<String, ProfileRequest> requested = new HashMap<>(40);
private final Object sync = new Object(); // sync for queue & requested fields
ProfileFetchThread() {
@ -65,7 +65,6 @@ class ProfileFetchThread implements Runnable {
queue.add(request);
}
}
if (handler != null) {
if (request.getResult() == ProfileFetchResult.PENDING
|| request.getResult() == ProfileFetchResult.TOO_MANY_REQUESTS) {
@ -100,7 +99,6 @@ class ProfileFetchThread implements Runnable {
return;
}
}
if (handler != null) {
if (request.getResult() == ProfileFetchResult.PENDING
|| request.getResult() == ProfileFetchResult.TOO_MANY_REQUESTS) {
@ -117,7 +115,7 @@ class ProfileFetchThread implements Runnable {
* @param requests
* The profile requests.
*/
private void fetchRequests(final Collection<ProfileRequest> requests) {
private void fetchRequests(Collection<ProfileRequest> requests) {
Preconditions.checkNotNull(requests);
String[] playerNames = new String[requests.size()];
@ -126,7 +124,6 @@ class ProfileFetchThread implements Runnable {
for (ProfileRequest request : requests) {
playerNames[i++] = request.getPlayerName();
}
NMS.findProfilesByNames(playerNames, new ProfileLookupCallback() {
@SuppressWarnings("unused")
public void onProfileLookupFailed(GameProfile profile, Exception e) {
@ -139,7 +136,6 @@ class ProfileFetchThread implements Runnable {
Messaging.debug("Profile lookup for player '" + profileName + "' failed: " + getExceptionMsg(e));
Messaging.debug(Throwables.getStackTraceAsString(e));
}
ProfileRequest request = findRequest(profileName, requests);
if (request == null)
return;
@ -154,7 +150,7 @@ class ProfileFetchThread implements Runnable {
}
@Override
public void onProfileLookupSucceeded(final GameProfile profile) {
public void onProfileLookupSucceeded(GameProfile profile) {
Messaging.idebug(() -> "Fetched profile " + profile.getId() + " for player " + profile.getName());
ProfileRequest request = findRequest(profile.getName(), requests);
@ -169,7 +165,6 @@ class ProfileFetchThread implements Runnable {
+ getExceptionMsg(e) + " " + isTooManyRequests(e));
Messaging.debug(Throwables.getStackTraceAsString(e));
}
if (isTooManyRequests(e)) {
request.setResult(null, ProfileFetchResult.TOO_MANY_REQUESTS);
} else {
@ -188,10 +183,9 @@ class ProfileFetchThread implements Runnable {
if (queue.isEmpty())
return;
requests = new ArrayList<ProfileRequest>(queue);
requests = new ArrayList<>(queue);
queue.clear();
}
try {
fetchRequests(requests);
} catch (Exception ex) {
@ -202,7 +196,7 @@ class ProfileFetchThread implements Runnable {
}
}
private static void addHandler(final ProfileRequest request, final ProfileFetchHandler handler) {
private static void addHandler(ProfileRequest request, ProfileFetchHandler handler) {
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), () -> request.addHandler(handler), 1);
}
@ -211,9 +205,8 @@ class ProfileFetchThread implements Runnable {
name = name.toLowerCase();
for (ProfileRequest request : requests) {
if (request.getPlayerName().equals(name)) {
if (request.getPlayerName().equals(name))
return request;
}
}
return null;
}
@ -226,19 +219,18 @@ class ProfileFetchThread implements Runnable {
String message = e.getMessage();
String cause = e.getCause() != null ? e.getCause().getMessage() : null;
return (message != null && message.contains("did not find"))
|| (cause != null && cause.contains("did not find"));
return message != null && message.contains("did not find") || cause != null && cause.contains("did not find");
}
private static boolean isTooManyRequests(Throwable e) {
String message = e.getMessage();
String cause = e.getCause() != null ? e.getCause().getMessage() : null;
return (message != null && message.contains("too many requests"))
|| (cause != null && cause.contains("too many requests"));
return message != null && message.contains("too many requests")
|| cause != null && cause.contains("too many requests");
}
private static void sendResult(final ProfileFetchHandler handler, final ProfileRequest request) {
private static void sendResult(ProfileFetchHandler handler, ProfileRequest request) {
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), () -> handler.onResult(request), 1);
}
}

View File

@ -48,7 +48,6 @@ public class ProfileFetcher {
if (THREAD_TASK != null) {
THREAD_TASK.cancel();
}
PROFILE_THREAD = new ProfileFetchThread();
THREAD_TASK = Bukkit.getScheduler().runTaskTimerAsynchronously(CitizensAPI.getPlugin(), PROFILE_THREAD, 21, 20);
}

View File

@ -61,10 +61,9 @@ public class ProfileRequest {
handler.onResult(this);
return;
}
if (handlers == null)
handlers = new ArrayDeque<ProfileFetchHandler>();
if (handlers == null) {
handlers = new ArrayDeque<>();
}
handlers.addLast(handler);
}
@ -105,24 +104,20 @@ public class ProfileRequest {
* @param result
* The result of the request.
*/
void setResult(final @Nullable GameProfile profile, final ProfileFetchResult result) {
void setResult(@Nullable GameProfile profile, ProfileFetchResult result) {
if (!CitizensAPI.hasImplementation())
return;
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), new Runnable() {
@Override
public void run() {
ProfileRequest.this.profile = profile;
ProfileRequest.this.result = result;
Bukkit.getScheduler().scheduleSyncDelayedTask(CitizensAPI.getPlugin(), () -> {
ProfileRequest.this.profile = profile;
ProfileRequest.this.result = result;
if (handlers == null)
return;
if (handlers == null)
return;
while (!handlers.isEmpty()) {
handlers.removeFirst().onResult(ProfileRequest.this);
}
handlers = null;
while (!handlers.isEmpty()) {
handlers.removeFirst().onResult(ProfileRequest.this);
}
handlers = null;
});
}
}

View File

@ -22,9 +22,7 @@ import net.citizensnpcs.api.event.DespawnReason;
import net.citizensnpcs.api.event.SpawnReason;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.util.Messaging;
import net.citizensnpcs.npc.profile.ProfileFetchHandler;
import net.citizensnpcs.npc.profile.ProfileFetcher;
import net.citizensnpcs.npc.profile.ProfileRequest;
import net.citizensnpcs.trait.SkinTrait;
import net.citizensnpcs.util.SkinProperty;
@ -36,7 +34,7 @@ public class Skin {
private int fetchRetries = -1;
private boolean hasFetched;
private volatile boolean isValid = true;
private final Map<SkinnableEntity, Void> pending = new WeakHashMap<SkinnableEntity, Void>(15);
private final Map<SkinnableEntity, Void> pending = new WeakHashMap<>(15);
private BukkitTask retryTask;
private volatile SkinProperty skinData;
private volatile UUID skinId;
@ -58,7 +56,6 @@ public class Skin {
CACHE.put(this.skinName, this);
}
// fetch();
}
@ -84,29 +81,27 @@ public class Skin {
// If npc requires latest skin, cache is used for faster availability until the latest skin can be loaded.
String cachedName = npc.data().get(CACHED_SKIN_UUID_NAME_METADATA);
String texture = skinTrait.getTexture();
if (this.skinName.equals(cachedName) && texture != null && !texture.equals("cache")) {
if (skinName.equals(cachedName) && texture != null && !texture.equals("cache")) {
setNPCTexture(entity, new SkinProperty("textures", texture, skinTrait.getSignature()));
// check if NPC prefers to use cached skin over the latest skin.
if (entity.getNPC().data().has("player-skin-use-latest")) {
entity.getNPC().data().remove("player-skin-use-latest");
}
if (!skinTrait.shouldUpdateSkins()) {
if (!skinTrait.shouldUpdateSkins())
// cache preferred
return true;
}
}
if (!hasSkinData()) {
String defaultSkinName = ChatColor.stripColor(npc.getName()).toLowerCase();
if (npc.hasTrait(SkinTrait.class) && this.skinName.equals(defaultSkinName)
if (npc.hasTrait(SkinTrait.class) && skinName.equals(defaultSkinName)
&& !npc.getOrAddTrait(SkinTrait.class).fetchDefaultSkin())
return false;
if (hasFetched) {
if (hasFetched)
return true;
} else {
else {
if (!fetching) {
fetch();
}
@ -114,7 +109,6 @@ public class Skin {
return false;
}
}
setNPCSkinData(entity, skinName, skinId, skinData);
return true;
@ -144,64 +138,54 @@ public class Skin {
}
private void fetch() {
final int maxRetries = Setting.MAX_NPC_SKIN_RETRIES.asInt();
int maxRetries = Setting.MAX_NPC_SKIN_RETRIES.asInt();
if (maxRetries > -1 && fetchRetries >= maxRetries) {
if (Messaging.isDebugging()) {
Messaging.debug("Reached max skin fetch retries for '" + skinName + "'");
}
return;
}
if (skinName.length() < 3 || skinName.length() > 16) {
if (Messaging.isDebugging()) {
Messaging.debug("Skin name invalid length '" + skinName + "'");
}
return;
}
if (skinName.toLowerCase().startsWith("cit-")) {
if (skinName.toLowerCase().startsWith("cit-"))
return;
}
fetching = true;
ProfileFetcher.fetch(this.skinName, new ProfileFetchHandler() {
@Override
public void onResult(ProfileRequest request) {
hasFetched = true;
ProfileFetcher.fetch(skinName, request -> {
hasFetched = true;
switch (request.getResult()) {
case NOT_FOUND:
isValid = false;
switch (request.getResult()) {
case NOT_FOUND:
isValid = false;
break;
case TOO_MANY_REQUESTS:
if (maxRetries == 0) {
break;
case TOO_MANY_REQUESTS:
if (maxRetries == 0) {
break;
}
fetchRetries++;
long delay = Setting.NPC_SKIN_RETRY_DELAY.asTicks();
retryTask = Bukkit.getScheduler().runTaskLater(CitizensAPI.getPlugin(), new Runnable() {
@Override
public void run() {
fetch();
}
}, delay);
}
fetchRetries++;
long delay = Setting.NPC_SKIN_RETRY_DELAY.asTicks();
retryTask = Bukkit.getScheduler().runTaskLater(CitizensAPI.getPlugin(), (Runnable) this::fetch,
delay);
Messaging.idebug(() -> "Retrying skin fetch for '" + skinName + "' in " + delay + " ticks.");
break;
case SUCCESS:
GameProfile profile = request.getProfile();
setData(profile);
break;
default:
break;
}
Messaging.idebug(() -> "Retrying skin fetch for '" + skinName + "' in " + delay + " ticks.");
break;
case SUCCESS:
GameProfile profile = request.getProfile();
setData(profile);
break;
default:
break;
}
});
}
private void fetchForced() {
final int maxRetries = Setting.MAX_NPC_SKIN_RETRIES.asInt();
int maxRetries = Setting.MAX_NPC_SKIN_RETRIES.asInt();
if (maxRetries > -1 && fetchRetries >= maxRetries) {
Messaging.idebug(() -> "Reached max skin fetch retries for '" + skinName + "'");
return;
@ -210,44 +194,35 @@ public class Skin {
Messaging.idebug(() -> "Skin name invalid length '" + skinName + "'");
return;
}
if (skinName.toLowerCase().startsWith("cit-")) {
if (skinName.toLowerCase().startsWith("cit-"))
return;
}
fetching = true;
ProfileFetcher.fetchForced(this.skinName, new ProfileFetchHandler() {
@Override
public void onResult(ProfileRequest request) {
hasFetched = true;
ProfileFetcher.fetchForced(skinName, request -> {
hasFetched = true;
switch (request.getResult()) {
case NOT_FOUND:
isValid = false;
switch (request.getResult()) {
case NOT_FOUND:
isValid = false;
break;
case TOO_MANY_REQUESTS:
if (maxRetries == 0) {
break;
case TOO_MANY_REQUESTS:
if (maxRetries == 0) {
break;
}
fetchRetries++;
int delay = Setting.NPC_SKIN_RETRY_DELAY.asTicks();
retryTask = Bukkit.getScheduler().runTaskLater(CitizensAPI.getPlugin(), new Runnable() {
@Override
public void run() {
fetchForced();
}
}, delay);
}
fetchRetries++;
int delay = Setting.NPC_SKIN_RETRY_DELAY.asTicks();
retryTask = Bukkit.getScheduler().runTaskLater(CitizensAPI.getPlugin(),
(Runnable) this::fetchForced, delay);
Messaging.idebug(() -> "Retrying skin fetch for '" + skinName + "' in " + delay + " ticks.");
break;
case SUCCESS:
GameProfile profile = request.getProfile();
setData(profile);
break;
default:
break;
}
Messaging.idebug(() -> "Retrying skin fetch for '" + skinName + "' in " + delay + " ticks.");
break;
case SUCCESS:
GameProfile profile = request.getProfile();
setData(profile);
break;
default:
break;
}
});
}
@ -288,16 +263,14 @@ public class Skin {
isValid = false;
return;
}
if (!profile.getName().toLowerCase().equals(skinName)) {
Messaging.debug("GameProfile name (" + profile.getName() + ") and " + "skin name (" + skinName
+ ") do not match. Has the user renamed recently?");
}
skinId = profile.getId();
skinData = SkinProperty.fromMojangProfile(profile);
List<SkinnableEntity> entities = new ArrayList<SkinnableEntity>(pending.keySet());
List<SkinnableEntity> entities = new ArrayList<>(pending.keySet());
for (SkinnableEntity entity : entities) {
applyAndRespawn(entity);
}
@ -371,13 +344,11 @@ public class Skin {
synchronized (CACHE) {
skin = CACHE.get(skinName);
}
if (skin == null) {
skin = new Skin(skinName);
} else if (forceUpdate) {
skin.fetchForced();
}
return skin;
}
@ -405,14 +376,13 @@ public class Skin {
// packet errors that disconnect the client.
SkinProperty current = SkinProperty.fromMojangProfile(profile);
if (current != null && current.value.equals(skinProperty.value) && current.signature != null
&& current.signature.equals(skinProperty.signature)) {
&& current.signature.equals(skinProperty.signature))
return;
}
skinProperty.apply(profile);
}
private static final Map<String, Skin> CACHE = new HashMap<String, Skin>(20);
public static final String CACHED_SKIN_UUID_METADATA = "cached-skin-uuid";
public static final String CACHED_SKIN_UUID_NAME_METADATA = "cached-skin-uuid-name";
private static Map<String, Skin> CACHE = new HashMap<>(20);
public static String CACHED_SKIN_UUID_METADATA = "cached-skin-uuid";
public static String CACHED_SKIN_UUID_NAME_METADATA = "cached-skin-uuid-name";
}

View File

@ -28,7 +28,7 @@ import net.citizensnpcs.util.NMS;
*/
public class SkinPacketTracker {
private final SkinnableEntity entity;
private final Map<UUID, PlayerEntry> inProgress = new HashMap<UUID, PlayerEntry>(
private final Map<UUID, PlayerEntry> inProgress = new HashMap<>(
Math.max(128, Math.min(1024, Bukkit.getMaxPlayers() / 2)));
private boolean isRemoved;
private Skin skin;
@ -43,7 +43,7 @@ public class SkinPacketTracker {
Preconditions.checkNotNull(entity);
this.entity = entity;
this.skin = Skin.get(entity);
skin = Skin.get(entity);
if (LISTENER == null) {
LISTENER = new PlayerListener();
@ -76,10 +76,7 @@ public class SkinPacketTracker {
*/
void notifyRemovePacketSent(UUID playerId) {
PlayerEntry entry = inProgress.get(playerId);
if (entry == null)
return;
if (entry.removeCount == 0)
if (entry == null || entry.removeCount == 0)
return;
entry.removeCount -= 1;
@ -94,7 +91,7 @@ public class SkinPacketTracker {
* Notify that the NPC skin has been changed.
*/
public void notifySkinChange(boolean forceUpdate) {
this.skin = Skin.get(entity, forceUpdate);
skin = Skin.get(entity, forceUpdate);
skin.applyAndRespawn(entity);
}
@ -111,9 +108,9 @@ public class SkinPacketTracker {
Collection<? extends Player> players = Bukkit.getOnlinePlayers();
for (Player player : players) {
if (player.hasMetadata("NPC"))
if (player.hasMetadata("NPC")) {
continue;
}
// send packet now and later to ensure removal from player list
NMS.sendTabListRemove(player, entity.getBukkitEntity());
TAB_LIST_REMOVER.sendPacket(player, entity);
@ -137,7 +134,7 @@ public class SkinPacketTracker {
}.runTaskLater(CitizensAPI.getPlugin(), 15);
}
private void scheduleRemovePacket(final PlayerEntry entry) {
private void scheduleRemovePacket(PlayerEntry entry) {
if (isRemoved || !CitizensAPI.hasImplementation() || !CitizensAPI.getPlugin().isEnabled()
|| !shouldRemoveFromTabList())
return;
@ -177,7 +174,7 @@ public class SkinPacketTracker {
* @param player
* The player.
*/
public void updateViewer(final Player player) {
public void updateViewer(Player player) {
Preconditions.checkNotNull(player);
if (isRemoved || player.hasMetadata("NPC"))
@ -189,7 +186,6 @@ public class SkinPacketTracker {
} else {
entry = new PlayerEntry(player);
}
TAB_LIST_REMOVER.cancelPackets(player, entity);
inProgress.put(player.getUniqueId(), entry);
@ -199,7 +195,7 @@ public class SkinPacketTracker {
}
}
private class PlayerEntry {
private static class PlayerEntry {
Player player;
int removeCount;
BukkitTask removeTask;
@ -228,6 +224,6 @@ public class SkinPacketTracker {
}
private static PlayerListener LISTENER;
private static final int PACKET_DELAY_REMOVE = 2;
private static final TabListRemover TAB_LIST_REMOVER = new TabListRemover();
private static int PACKET_DELAY_REMOVE = 2;
private static TabListRemover TAB_LIST_REMOVER = new TabListRemover();
}

View File

@ -37,8 +37,8 @@ import net.citizensnpcs.util.Util;
* @see net.citizensnpcs.EventListen
*/
public class SkinUpdateTracker {
private final Map<SkinnableEntity, Void> navigating = new WeakHashMap<SkinnableEntity, Void>(25);
private final Map<UUID, PlayerTracker> playerTrackers = new HashMap<UUID, PlayerTracker>(
private final Map<SkinnableEntity, Void> navigating = new WeakHashMap<>(25);
private final Map<UUID, PlayerTracker> playerTrackers = new HashMap<>(
Math.max(128, Math.min(1024, Bukkit.getMaxPlayers() / 2)));
private final NPCNavigationUpdater updater = new NPCNavigationUpdater();
@ -57,13 +57,7 @@ public class SkinUpdateTracker {
// skinnable entity is within the player's field of view.
private boolean canSee(Player player, SkinnableEntity skinnable, boolean checkFov) {
Player entity = skinnable.getBukkitEntity();
if (entity == null)
return false;
if (!player.canSee(entity))
return false;
if (!player.getWorld().equals(entity.getWorld()))
if (entity == null || !player.canSee(entity) || !player.getWorld().equals(entity.getWorld()))
return false;
Location playerLoc = player.getLocation();
@ -92,7 +86,6 @@ public class SkinUpdateTracker {
}
return hasMoved;
}
return true;
}
@ -101,17 +94,14 @@ public class SkinUpdateTracker {
}
private List<SkinnableEntity> getNearbyNPCs(Player player, boolean reset, boolean checkFov) {
List<SkinnableEntity> results = new ArrayList<SkinnableEntity>();
List<SkinnableEntity> results = new ArrayList<>();
PlayerTracker tracker = getTracker(player, reset);
for (NPC npc : getAllNPCs()) {
SkinnableEntity skinnable = getSkinnable(npc);
if (skinnable == null)
continue;
// if checking field of view, don't add skins that have already been updated for FOV
if (checkFov && tracker.fovVisibleSkins.contains(skinnable))
if (skinnable == null || checkFov && tracker.fovVisibleSkins.contains(skinnable)) {
continue;
}
if (canSee(player, skinnable, checkFov)) {
results.add(skinnable);
}
@ -126,9 +116,9 @@ public class SkinUpdateTracker {
for (SkinnableEntity skinnable : navigating.keySet()) {
// make sure player hasn't already been updated to prevent excessive tab list flashing
// while NPC's are navigating and to reduce the number of times #canSee is invoked.
if (tracker.fovVisibleSkins.contains(skinnable))
if (tracker.fovVisibleSkins.contains(skinnable)) {
continue;
}
if (canSee(player, skinnable, true)) {
output.add(skinnable);
}
@ -231,10 +221,7 @@ public class SkinUpdateTracker {
public void onPlayerMove(Player player) {
Preconditions.checkNotNull(player);
PlayerTracker updateTracker = playerTrackers.get(player.getUniqueId());
if (updateTracker == null)
return;
if (!updateTracker.shouldUpdate(player))
if (updateTracker == null || !updateTracker.shouldUpdate(player))
return;
updatePlayer(player, 10, false);
@ -277,14 +264,13 @@ public class SkinUpdateTracker {
Location location = entity.getLocation();
List<Player> players = entity.getWorld().getPlayers();
for (Player player : players) {
if (player.hasMetadata("NPC"))
if (player.hasMetadata("NPC")) {
continue;
}
Location ploc = player.getLocation();
if (ploc.getWorld() != location.getWorld())
if (ploc.getWorld() != location.getWorld() || ploc.distance(location) > viewDistance) {
continue;
if (ploc.distance(location) > viewDistance)
continue;
}
PlayerTracker tracker = playerTrackers.get(player.getUniqueId());
if (tracker != null) {
tracker.hardReset(player);
@ -302,7 +288,7 @@ public class SkinUpdateTracker {
* @param reset
* True to hard reset the players tracking info, otherwise false.
*/
public void updatePlayer(final Player player, long delay, final boolean reset) {
public void updatePlayer(Player player, long delay, boolean reset) {
if (player.hasMetadata("NPC"))
return;
@ -328,13 +314,13 @@ public class SkinUpdateTracker {
if (navigating.isEmpty() || playerTrackers.isEmpty())
return;
List<SkinnableEntity> nearby = new ArrayList<SkinnableEntity>(10);
List<SkinnableEntity> nearby = new ArrayList<>(10);
Set<UUID> seen = Sets.newHashSet();
for (Player player : Bukkit.getOnlinePlayers()) {
seen.add(player.getUniqueId());
if (player.hasMetadata("NPC"))
if (player.hasMetadata("NPC")) {
continue;
}
getNewVisibleNavigating(player, nearby);
for (SkinnableEntity skinnable : nearby) {
@ -342,7 +328,6 @@ public class SkinUpdateTracker {
tracker.fovVisibleSkins.add(skinnable);
updater.queue.offer(new UpdateInfo(player, skinnable));
}
nearby.clear();
}
playerTrackers.keySet().removeIf(uuid -> !seen.contains(uuid));
@ -351,8 +336,8 @@ public class SkinUpdateTracker {
// Updates players. Repeating task used to schedule updates without
// causing excessive scheduling.
private class NPCNavigationUpdater extends BukkitRunnable {
Queue<UpdateInfo> queue = new ArrayDeque<UpdateInfo>(20);
private static class NPCNavigationUpdater extends BukkitRunnable {
Queue<UpdateInfo> queue = new ArrayDeque<>(20);
@Override
public void run() {
@ -365,10 +350,10 @@ public class SkinUpdateTracker {
// Tracks player location and yaw to determine when the player should be updated
// with nearby skins.
private class PlayerTracker {
final Set<SkinnableEntity> fovVisibleSkins = new HashSet<SkinnableEntity>(10);
private static class PlayerTracker {
Set<SkinnableEntity> fovVisibleSkins = new HashSet<>(10);
boolean hasMoved;
final Location location = new Location(null, 0, 0, 0);
Location location = new Location(null, 0, 0, 0);
float lowerBound;
int rotationCount;
float startYaw;
@ -380,22 +365,22 @@ public class SkinUpdateTracker {
// reset all
void hardReset(Player player) {
this.hasMoved = false;
this.rotationCount = 0;
this.lowerBound = this.upperBound = this.startYaw = 0;
this.fovVisibleSkins.clear();
hasMoved = false;
rotationCount = 0;
lowerBound = upperBound = startYaw = 0;
fovVisibleSkins.clear();
reset(player);
}
// resets initial yaw and location to the players current location and yaw.
void reset(Player player) {
player.getLocation(this.location);
player.getLocation(location);
if (rotationCount < 3) {
float rotationDegrees = Setting.NPC_SKIN_ROTATION_UPDATE_DEGREES.asFloat();
float yaw = Util.clamp(this.location.getYaw());
this.startYaw = yaw;
this.upperBound = Util.clamp(yaw + rotationDegrees);
this.lowerBound = Util.clamp(yaw - rotationDegrees);
float yaw = Util.clamp(location.getYaw());
startYaw = yaw;
upperBound = Util.clamp(yaw + rotationDegrees);
lowerBound = Util.clamp(yaw - rotationDegrees);
if (upperBound == -180.0 && startYaw > 0) {
upperBound = 0;
}
@ -406,16 +391,14 @@ public class SkinUpdateTracker {
Location currentLoc = player.getLocation();
// make sure player is in same world
if (!currentLoc.getWorld().equals(this.location.getWorld())) {
if (!currentLoc.getWorld().equals(location.getWorld())) {
hardReset(player);
return true;
}
if (!hasMoved) {
hasMoved = true;
return true;
}
if (rotationCount < 3) {
float yaw = Util.clamp(currentLoc.getYaw());
boolean hasRotated;
@ -424,7 +407,6 @@ public class SkinUpdateTracker {
} else {
hasRotated = yaw < lowerBound || yaw > upperBound;
}
// update the first 3 times the player rotates. helps load skins around player
// after the player logs/teleports.
if (hasRotated) {
@ -433,14 +415,12 @@ public class SkinUpdateTracker {
return true;
}
}
// update every time a player moves a certain distance
if (currentLoc.distance(this.location) > MOVEMENT_SKIN_UPDATE_DISTANCE) {
if (currentLoc.distance(location) > MOVEMENT_SKIN_UPDATE_DISTANCE) {
reset(player);
return true;
} else {
} else
return false;
}
}
}
@ -454,6 +434,6 @@ public class SkinUpdateTracker {
}
}
private static final float FIELD_OF_VIEW = 70F;
private static final int MOVEMENT_SKIN_UPDATE_DISTANCE = 25;
private static float FIELD_OF_VIEW = 70F;
private static int MOVEMENT_SKIN_UPDATE_DISTANCE = 25;
}

View File

@ -26,7 +26,7 @@ import net.citizensnpcs.util.NMS;
* </p>
*/
public class TabListRemover {
private final Map<UUID, PlayerEntry> pending = new HashMap<UUID, PlayerEntry>(
private final Map<UUID, PlayerEntry> pending = new HashMap<>(
Math.max(128, Math.min(1024, Bukkit.getMaxPlayers() / 2)));
TabListRemover() {
@ -70,7 +70,6 @@ public class TabListRemover {
if (entry.toRemove.remove(skinnable)) {
skinnable.getSkinTracker().notifyRemovePacketCancelled(player.getUniqueId());
}
if (entry.toRemove.isEmpty()) {
pending.remove(player.getUniqueId());
}
@ -82,7 +81,6 @@ public class TabListRemover {
entry = new PlayerEntry(player);
pending.put(player.getUniqueId(), entry);
}
return entry;
}
@ -103,9 +101,9 @@ public class TabListRemover {
entry.toRemove.add(entity);
}
private class PlayerEntry {
private static class PlayerEntry {
Player player;
Set<SkinnableEntity> toRemove = new HashSet<SkinnableEntity>(20);
Set<SkinnableEntity> toRemove = new HashSet<>(20);
PlayerEntry(Player player) {
this.player = player;
@ -125,30 +123,27 @@ public class TabListRemover {
int listSize = Math.min(maxPacketEntries, entry.toRemove.size());
boolean sendAll = listSize == entry.toRemove.size();
List<SkinnableEntity> skinnableList = new ArrayList<SkinnableEntity>(listSize);
List<SkinnableEntity> skinnableList = new ArrayList<>(listSize);
int i = 0;
Iterator<SkinnableEntity> skinIterator = entry.toRemove.iterator();
while (skinIterator.hasNext()) {
if (i >= maxPacketEntries)
if (i >= maxPacketEntries) {
break;
}
SkinnableEntity skinnable = skinIterator.next();
skinnableList.add(skinnable);
skinIterator.remove();
i++;
}
if (entry.player.isOnline()) {
NMS.sendTabListRemove(entry.player, skinnableList);
}
// notify skin trackers that a remove packet has been sent to a player
for (SkinnableEntity entity : skinnableList) {
entity.getSkinTracker().notifyRemovePacketSent(entry.player.getUniqueId());
}
if (sendAll) {
entryIterator.remove();
}

View File

@ -50,13 +50,12 @@ public class Age extends Trait implements Toggleable {
entity.setAge(age);
entity.setAgeLock(locked);
ageable = entity;
} else if (npc.getEntity() instanceof Zombie) {
((Zombie) npc.getEntity()).setBaby(age < 0);
ageable = null;
} else if (npc.isSpawned() && npc.getEntity().getType().name().equals("TADPOLE")) {
((Tadpole) npc.getEntity()).setAge(age);
ageable = null;
} else {
if (npc.getEntity() instanceof Zombie) {
((Zombie) npc.getEntity()).setBaby(age < 0);
} else if (npc.isSpawned() && npc.getEntity().getType().name().equals("TADPOLE")) {
((Tadpole) npc.getEntity()).setAge(age);
}
ageable = null;
}
}
@ -78,7 +77,6 @@ public class Age extends Trait implements Toggleable {
if (isAgeable()) {
ageable.setAgeLock(locked);
}
}
/**

View File

@ -21,7 +21,7 @@ import net.citizensnpcs.util.Messages;
*/
@TraitName("anchors")
public class Anchors extends Trait {
private final List<Anchor> anchors = new ArrayList<Anchor>();
private final List<Anchor> anchors = new ArrayList<>();
public Anchors() {
super("anchors");
@ -61,8 +61,8 @@ public class Anchors extends Trait {
String[] parts = sub.getString("").split(";");
Location location;
try {
location = new Location(Bukkit.getServer().getWorld(parts[1]), Double.valueOf(parts[2]),
Double.valueOf(parts[3]), Double.valueOf(parts[4]));
location = new Location(Bukkit.getServer().getWorld(parts[1]), Double.parseDouble(parts[2]),
Double.parseDouble(parts[3]), Double.parseDouble(parts[4]));
anchors.add(new Anchor(parts[0], location));
} catch (NumberFormatException e) {
Messaging.logTr(Messages.SKIPPING_INVALID_ANCHOR, sub.name(), e.getMessage());
@ -85,8 +85,9 @@ public class Anchors extends Trait {
@Override
public void save(DataKey key) {
key.removeKey("list");
for (int i = 0; i < anchors.size(); i++)
for (int i = 0; i < anchors.size(); i++) {
key.setString("list." + String.valueOf(i), anchors.get(i).stringValue());
}
}
}

View File

@ -158,14 +158,14 @@ public class ArmorStandTrait extends Trait {
* @see ArmorStand#setArms(boolean)
*/
public void setHasArms(boolean arms) {
this.hasarms = arms;
hasarms = arms;
}
/**
* @see ArmorStand#setBasePlate(boolean)
*/
public void setHasBaseplate(boolean baseplate) {
this.hasbaseplate = baseplate;
hasbaseplate = baseplate;
}
/**

View File

@ -67,7 +67,7 @@ public class BoundingBoxTrait extends Trait implements Supplier<BoundingBox> {
}
public void setBoundingBoxFunction(Function<EntityDim, BoundingBox> func) {
this.function = func;
function = func;
}
public void setHeight(float height) {

View File

@ -25,7 +25,7 @@ public class ClickRedirectTrait extends Trait {
public ClickRedirectTrait(NPC npc) {
this();
this.redirectNPC = npc;
redirectNPC = npc;
if (redirectNPC != null && redirectNPC.hasTrait(PlayerFilter.class)) {
redirectNPC.getOrAddTrait(PlayerFilter.class).addChildNPC(npc);
}

View File

@ -3,6 +3,7 @@ package net.citizensnpcs.trait;
import java.time.Duration;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.EnumSet;
import java.util.Iterator;
import java.util.List;
@ -218,13 +219,11 @@ public class CommandTrait extends Trait {
} else {
outputList.add(0, executionMode.toString());
}
StringBuilder output = new StringBuilder();
for (String item : outputList) {
output.append(item);
output.append(" ");
}
Messaging.send(sender, output.toString().trim());
}
@ -252,9 +251,9 @@ public class CommandTrait extends Trait {
return output;
}
public void dispatch(final Player player, Hand handIn) {
final Hand hand = player.isSneaking()
? (handIn == CommandTrait.Hand.LEFT ? CommandTrait.Hand.SHIFT_LEFT : CommandTrait.Hand.SHIFT_RIGHT)
public void dispatch(Player player, Hand handIn) {
Hand hand = player.isSneaking()
? handIn == CommandTrait.Hand.LEFT ? CommandTrait.Hand.SHIFT_LEFT : CommandTrait.Hand.SHIFT_RIGHT
: handIn;
NPCCommandDispatchEvent event = new NPCCommandDispatchEvent(npc, player);
Bukkit.getServer().getPluginManager().callEvent(event);
@ -266,9 +265,8 @@ public class CommandTrait extends Trait {
@Override
public void run() {
List<NPCCommand> commandList = Lists.newArrayList(Iterables.filter(commands.values(), command -> {
return command.hand == hand || command.hand == Hand.BOTH;
}));
List<NPCCommand> commandList = Lists.newArrayList(Iterables.filter(commands.values(),
command -> (command.hand == hand || command.hand == Hand.BOTH)));
if (executionMode == ExecutionMode.RANDOM) {
if (commandList.size() > 0) {
runCommand(player, commandList.get(Util.getFastRandom().nextInt(commandList.size())));
@ -277,7 +275,7 @@ public class CommandTrait extends Trait {
}
int max = -1;
if (executionMode == ExecutionMode.SEQUENTIAL) {
Collections.sort(commandList, (o1, o2) -> Integer.compare(o1.id, o2.id));
Collections.sort(commandList, Comparator.comparing(o1 -> o1.id));
max = commandList.size() > 0 ? commandList.get(commandList.size() - 1).id : -1;
}
if (executionMode == ExecutionMode.LINEAR) {
@ -299,13 +297,13 @@ public class CommandTrait extends Trait {
}
}
runCommand(player, command);
if (executionMode == ExecutionMode.SEQUENTIAL || (charged != null && charged == false)) {
if (executionMode == ExecutionMode.SEQUENTIAL || charged != null && !charged) {
break;
}
}
}
private void runCommand(final Player player, NPCCommand command) {
private void runCommand(Player player, NPCCommand command) {
Runnable runnable = () -> {
PlayerNPCCommand info = playerTracking.get(player.getUniqueId());
if (info == null && (executionMode == ExecutionMode.SEQUENTIAL
@ -320,14 +318,12 @@ public class CommandTrait extends Trait {
return;
}
}
if (info != null && !info.canUse(CommandTrait.this, player, command))
return;
if (charged == null) {
charge.run();
}
if (temporaryPermissions.size() > 0) {
PermissionAttachment attachment = player.addAttachment(CitizensAPI.getPlugin());
if (attachment != null) {
@ -434,9 +430,8 @@ public class CommandTrait extends Trait {
private void sendErrorMessage(Player player, CommandTraitError msg, Function<String, String> transform,
Object... objects) {
if (hideErrorMessages) {
if (hideErrorMessages)
return;
}
Set<CommandTraitError> sent = executionErrors.get(player.getUniqueId().toString());
if (sent != null) {
if (sent.contains(msg))
@ -465,7 +460,7 @@ public class CommandTrait extends Trait {
}
public void setExecutionMode(ExecutionMode mode) {
this.executionMode = mode;
executionMode = mode;
}
public void setExperienceCost(int experienceCost) {
@ -477,7 +472,7 @@ public class CommandTrait extends Trait {
}
public void setHideErrorMessages(boolean hide) {
this.hideErrorMessages = hide;
hideErrorMessages = hide;
}
public void setItemCost(List<ItemStack> itemCost, int id) {
@ -550,7 +545,7 @@ public class CommandTrait extends Trait {
@Override
public void initialise(MenuContext ctx) {
this.inventory = ctx.getInventory();
inventory = ctx.getInventory();
if (id == -1) {
for (ItemStack stack : trait.itemRequirements) {
inventory.addItem(stack.clone());
@ -576,10 +571,10 @@ public class CommandTrait extends Trait {
}
}
if (id == -1) {
this.trait.itemRequirements.clear();
this.trait.itemRequirements.addAll(requirements);
trait.itemRequirements.clear();
trait.itemRequirements.addAll(requirements);
} else {
this.trait.setItemCost(requirements, id);
trait.setItemCost(requirements, id);
}
}
}
@ -649,7 +644,7 @@ public class CommandTrait extends Trait {
}
public NPCCommandBuilder addPerm(String permission) {
this.perms.add(permission);
perms.add(permission);
return this;
}
@ -697,7 +692,7 @@ public class CommandTrait extends Trait {
}
public NPCCommandBuilder globalCooldown(int cooldown) {
this.globalCooldown = cooldown;
globalCooldown = cooldown;
return this;
}
@ -739,8 +734,8 @@ public class CommandTrait extends Trait {
double cost = root.keyExists("cost") ? root.getDouble("cost") : -1;
int exp = root.keyExists("experienceCost") ? root.getInt("experienceCost") : -1;
return new NPCCommand(Integer.parseInt(root.name()), root.getString("command"),
Hand.valueOf(root.getString("hand")), Boolean.valueOf(root.getString("player")),
Boolean.valueOf(root.getString("op")), root.getInt("cooldown"), perms, root.getInt("n"),
Hand.valueOf(root.getString("hand")), Boolean.parseBoolean(root.getString("player")),
Boolean.parseBoolean(root.getString("op")), root.getInt("cooldown"), perms, root.getInt("n"),
root.getInt("delay"), root.getInt("globalcooldown"), cost, exp, items);
}
@ -848,14 +843,12 @@ public class CommandTrait extends Trait {
}
}
}
Set<String> diff = Sets.newHashSet(lastUsed.keySet());
diff.removeAll(commandKeys);
for (String key : diff) {
lastUsed.remove(key);
nUsed.remove(key);
}
if (globalCooldowns != null) {
diff = Sets.newHashSet(globalCooldowns.keySet());
diff.removeAll(commandKeys);
@ -867,7 +860,7 @@ public class CommandTrait extends Trait {
public static boolean requiresTracking(NPCCommand command) {
return command.globalCooldown > 0 || command.cooldown > 0 || command.n > 0
|| (command.perms != null && command.perms.size() > 0)
|| command.perms != null && command.perms.size() > 0
|| Setting.NPC_COMMAND_GLOBAL_COMMAND_COOLDOWN.asSeconds() > 0;
}
}

View File

@ -74,7 +74,6 @@ public class Controllable extends Trait implements Toggleable, CommandConfigurab
} else if (args.hasValueFlag("explicittype")) {
explicitType = Util.matchEnum(EntityType.values(), args.getFlag("explicittype"));
}
if (npc.isSpawned()) {
loadController();
}
@ -90,10 +89,8 @@ public class Controllable extends Trait implements Toggleable, CommandConfigurab
}
if (!player.hasPermission(
"citizens.npc.controllable." + npc.getEntity().getType().name().toLowerCase().replace("_", ""))
|| !player.hasPermission("citizens.npc.controllable"))
return;
if (ownerRequired && !npc.getOrAddTrait(Owner.class).isOwnedBy(player))
|| !player.hasPermission("citizens.npc.controllable")
|| ownerRequired && !npc.getOrAddTrait(Owner.class).isOwnedBy(player))
return;
NMS.mount(npc.getEntity(), player);
@ -146,9 +143,8 @@ public class Controllable extends Trait implements Toggleable, CommandConfigurab
*/
public boolean mount(Player toMount) {
List<Entity> passengers = NMS.getPassengers(npc.getEntity());
if (passengers.size() != 0) {
if (passengers.size() != 0)
return false;
}
boolean found = false;
for (Entity passenger : passengers) {
if (passenger != null && passenger == toMount) {
@ -156,9 +152,8 @@ public class Controllable extends Trait implements Toggleable, CommandConfigurab
break;
}
}
if (found) {
if (found)
return false;
}
enterOrLeaveVehicle(toMount);
return true;
}
@ -232,7 +227,7 @@ public class Controllable extends Trait implements Toggleable, CommandConfigurab
* the explicit type
*/
public void setExplicitType(EntityType type) {
this.explicitType = type;
explicitType = type;
}
private void setMountedYaw(Entity entity) {
@ -240,9 +235,8 @@ public class Controllable extends Trait implements Toggleable, CommandConfigurab
return; // EnderDragon handles this separately
Location loc = entity.getLocation();
Vector vel = entity.getVelocity();
if (vel.lengthSquared() == 0) {
if (vel.lengthSquared() == 0)
return;
}
double tX = loc.getX() + vel.getX();
double tZ = loc.getZ() + vel.getZ();
@ -287,7 +281,6 @@ public class Controllable extends Trait implements Toggleable, CommandConfigurab
vel = vel.setX(dXcos * speed * speedMod).setZ(dXsin * speed * speedMod);
}
vel = vel.add(new Vector(
passenger.getVelocity().getX() * speedMod * Setting.CONTROLLABLE_GROUND_DIRECTION_MODIFIER.asDouble(),
0D,
@ -301,11 +294,10 @@ public class Controllable extends Trait implements Toggleable, CommandConfigurab
}
handle.setVelocity(vel);
if (newSpeed > oldSpeed && speed < maxSpeed) {
return (float) Math.min(maxSpeed, (speed + ((maxSpeed - speed) / 50.0D)));
} else {
return (float) Math.max(0, (speed - (speed / 50.0D)));
}
if (newSpeed > oldSpeed && speed < maxSpeed)
return (float) Math.min(maxSpeed, speed + (maxSpeed - speed) / 50.0D);
else
return (float) Math.max(0, speed - speed / 50.0D);
}
public class GroundController implements MovementController {
@ -329,13 +321,12 @@ public class Controllable extends Trait implements Toggleable, CommandConfigurab
public void run(Player rider) {
boolean onGround = NMS.isOnGround(npc.getEntity());
float speedMod = npc.getNavigator().getDefaultParameters()
.modifiedSpeed((onGround ? GROUND_SPEED : AIR_SPEED));
.modifiedSpeed(onGround ? GROUND_SPEED : AIR_SPEED);
if (!Util.isHorse(npc.getEntity().getType())) {
// use minecraft horse physics
speed = updateHorizontalSpeed(npc.getEntity(), rider, speed, speedMod,
Setting.MAX_CONTROLLABLE_GROUND_SPEED.asDouble());
}
boolean shouldJump = NMS.shouldJump(rider);
if (shouldJump) {
if (onGround && jumpTicks == 0) {
@ -420,14 +411,12 @@ public class Controllable extends Trait implements Toggleable, CommandConfigurab
npc.getEntity().setVelocity(npc.getEntity().getVelocity().setY(0.001F));
return;
}
speed = updateHorizontalSpeed(npc.getEntity(), rider, speed, 1F,
Setting.MAX_CONTROLLABLE_FLIGHT_SPEED.asDouble());
boolean shouldJump = NMS.shouldJump(rider);
if (shouldJump) {
npc.getEntity().setVelocity(npc.getEntity().getVelocity().setY(0.25F));
}
npc.getEntity().setVelocity(npc.getEntity().getVelocity().multiply(new Vector(1, 0.98, 1)));
setMountedYaw(npc.getEntity());
}
@ -461,7 +450,7 @@ public class Controllable extends Trait implements Toggleable, CommandConfigurab
}
}
private static final Map<EntityType, Constructor<? extends MovementController>> CONTROLLER_TYPES = Maps
private static Map<EntityType, Constructor<? extends MovementController>> CONTROLLER_TYPES = Maps
.newEnumMap(EntityType.class);
static {

View File

@ -51,7 +51,7 @@ public class CurrentLocation extends Trait {
}
public void setLocation(Location loc) {
this.location = loc.clone();
location = loc.clone();
}
@Override

View File

@ -70,7 +70,7 @@ public class DropsTrait extends Trait {
@Override
public void initialise(MenuContext ctx) {
this.inventory = ctx.getInventory();
inventory = ctx.getInventory();
int k = 0;
for (int i = 1; i < 5; i += 2) {
for (int j = 0; j < 9; j++) {
@ -87,7 +87,7 @@ public class DropsTrait extends Trait {
InventoryMenuSlot slot = ctx.getSlot(i * 9 + j);
slot.setItemStack(new ItemStack(Util.getFallbackMaterial("BARRIER", "FIRE")),
"Drop chance <e>" + chance + "%");
slot.setClickHandler(new PercentageSlotHandler((pct) -> {
slot.setClickHandler(new PercentageSlotHandler(pct -> {
if (chances.containsKey(islot)) {
chances.put(islot, pct / 100.0);
}
@ -116,12 +116,13 @@ public class DropsTrait extends Trait {
for (int j = 0; j < 9; j++) {
int slot = i * 9 + j;
ItemStack stack = inventory.getItem(slot);
if (stack == null || stack.getType() == Material.AIR)
if (stack == null || stack.getType() == Material.AIR) {
continue;
}
drops.add(new ItemDrop(stack.clone(), chances.getOrDefault(slot, 1.0)));
}
}
this.trait.drops = drops;
trait.drops = drops;
}
}

View File

@ -40,7 +40,7 @@ public class FollowTrait extends Trait {
* Sets the {@link Entity} to follow
*/
public void follow(Entity entity) {
this.followingUUID = entity == null ? null : entity.getUniqueId();
followingUUID = entity == null ? null : entity.getUniqueId();
if (npc.getNavigator().isNavigating() && this.entity != null && npc.getNavigator().getEntityTarget() != null
&& this.entity == npc.getNavigator().getEntityTarget().getTarget()) {
npc.getNavigator().cancelNavigation();
@ -112,13 +112,11 @@ public class FollowTrait extends Trait {
}
return;
}
if (!npc.getNavigator().isNavigating()) {
npc.getNavigator().setTarget(entity, false);
if (margin > 0) {
npc.getNavigator().getLocalParameters().distanceMargin(margin);
}
} else {
flock.run();
}

View File

@ -51,7 +51,7 @@ public class Gravity extends Trait implements Toggleable {
}
public void setEnabled(boolean enabled) {
this.nogravity = enabled;
nogravity = enabled;
}
@Override

View File

@ -35,7 +35,6 @@ import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.trait.TraitName;
import net.citizensnpcs.api.util.DataKey;
import net.citizensnpcs.api.util.Messaging;
import net.citizensnpcs.api.util.Placeholders;
import net.citizensnpcs.api.util.SpigotUtil;
import net.citizensnpcs.util.NMS;
@ -59,6 +58,8 @@ public class HologramTrait extends Trait {
private final NPCRegistry registry = CitizensAPI.createCitizensBackedNPCRegistry(new MemoryNPCDataStore());
private int t;
private boolean useDisplayEntities = Setting.DISPLAY_ENTITY_HOLOGRAMS.asBoolean();
@Persist
private int viewRange = -1;
public HologramTrait() {
super("hologramtrait");
@ -109,12 +110,13 @@ public class HologramTrait extends Trait {
hologramNPC = registry.createNPC(EntityType.ARMOR_STAND, line);
hologramNPC.getOrAddTrait(ArmorStandTrait.class).setAsHelperEntityWithName(npc);
}
if (Setting.PACKET_HOLOGRAMS.asBoolean()) {
hologramNPC.addTrait(PacketNPC.class);
}
hologramNPC.data().set(NPC.Metadata.HOLOGRAM_FOR, npc.getUniqueId().toString());
if (viewRange != -1) {
hologramNPC.data().set(NPC.Metadata.TRACKING_RANGE, viewRange);
}
hologramNPC.spawn(currentLoc.clone().add(0, getEntityHeight() + heightOffset, 0));
Matcher itemMatcher = ITEM_MATCHER.matcher(line);
@ -122,7 +124,7 @@ public class HologramTrait extends Trait {
Material item = SpigotUtil.isUsing1_13API() ? Material.matchMaterial(itemMatcher.group(1), false)
: Material.matchMaterial(itemMatcher.group(1));
ItemStack itemStack = new ItemStack(item, 1);
final NPC itemNPC = registry.createNPCUsingItem(EntityType.DROPPED_ITEM, "", itemStack);
NPC itemNPC = registry.createNPCUsingItem(EntityType.DROPPED_ITEM, "", itemStack);
itemNPC.data().setPersistent(NPC.Metadata.NAMEPLATE_VISIBLE, false);
if (itemMatcher.group(2) != null) {
if (itemMatcher.group(2).charAt(1) == '{') {
@ -135,14 +137,13 @@ public class HologramTrait extends Trait {
}
itemNPC.getOrAddTrait(MountTrait.class).setMountedOn(hologramNPC.getUniqueId());
itemNPC.spawn(currentLoc);
final NPC hn = hologramNPC;
NPC hn = hologramNPC;
itemNPC.addRunnable(() -> {
if (!itemNPC.isSpawned() || !hn.isSpawned()) {
itemNPC.destroy();
}
});
}
lastEntityHeight = getEntityHeight();
return hologramNPC;
}
@ -152,7 +153,7 @@ public class HologramTrait extends Trait {
}
private double getHeight(int lineNumber) {
double base = (lastNameplateVisible ? 0 : -getLineHeight());
double base = lastNameplateVisible ? 0 : -getLineHeight();
for (int i = 0; i <= lineNumber; i++) {
HologramLine line = lines.get(i);
base += line.mb + getLineHeight();
@ -192,6 +193,17 @@ public class HologramTrait extends Trait {
return nameLine != null && nameLine.hologram.isSpawned() ? nameLine.hologram.getEntity() : null;
}
public double getViewRange() {
return viewRange;
}
public boolean isHologramSneaking(NPC hologram, Player player) {
if (nameLine != null && hologram == nameLine.hologram && npc.getEntity() instanceof Player
&& ((Player) npc.getEntity()).isSneaking())
return true;
return false;
}
@Override
public void load(DataKey root) {
clear();
@ -210,7 +222,6 @@ public class HologramTrait extends Trait {
nameLine.removeNPC();
nameLine = null;
}
for (HologramLine line : lines) {
line.removeNPC();
}
@ -229,11 +240,9 @@ public class HologramTrait extends Trait {
}
}
}
if (height == -1)
return;
Messaging.debug(npc, "hologram interaction ", hologram.getEntity(), "height offset set to", height);
NMS.linkTextInteraction(player, hologram.getEntity(), npc.getEntity(), height);
}
}
@ -255,7 +264,6 @@ public class HologramTrait extends Trait {
nameLine = new HologramLine(npc.getRawName(), false);
nameLine.spawnNPC(0);
}
for (int i = 0; i < lines.size(); i++) {
lines.get(i).spawnNPC(getHeight(i));
}
@ -265,7 +273,6 @@ public class HologramTrait extends Trait {
for (HologramLine line : lines) {
line.removeNPC();
}
if (!npc.isSpawned())
return;
@ -294,11 +301,9 @@ public class HologramTrait extends Trait {
onDespawn();
return;
}
if (currentLoc == null) {
currentLoc = npc.getStoredLocation().clone();
}
boolean nameplateVisible = Boolean
.parseBoolean(npc.data().<Object> get(NPC.Metadata.NAMEPLATE_VISIBLE, true).toString());
if (npc.requiresNameHologram()) {
@ -310,7 +315,6 @@ public class HologramTrait extends Trait {
nameLine.spawnNPC(0);
}
}
Location npcLoc = npc.getStoredLocation();
boolean updatePosition = Setting.HOLOGRAM_ALWAYS_UPDATE_POSITION.asBoolean()
|| currentLoc.getWorld() != npcLoc.getWorld() || currentLoc.distance(npcLoc) >= 0.001
@ -321,59 +325,50 @@ public class HologramTrait extends Trait {
t = 0;
updateName = true;
}
lastNameplateVisible = nameplateVisible;
if (updatePosition) {
currentLoc = npcLoc.clone();
lastEntityHeight = getEntityHeight();
}
if (nameLine != null && nameLine.hologram.isSpawned()) {
if (updatePosition && !useDisplayEntities) {
nameLine.hologram.teleport(npcLoc.clone().add(0, getEntityHeight(), 0), TeleportCause.PLUGIN);
}
if (updateName) {
nameLine.setText(npc.getRawName());
}
if (useDisplayEntities && nameLine.hologram.getEntity().getVehicle() == null) {
npc.getEntity().addPassenger(nameLine.hologram.getEntity());
}
}
for (int i = 0; i < lines.size(); i++) {
HologramLine line = lines.get(i);
NPC hologramNPC = line.hologram;
if (hologramNPC == null || !hologramNPC.isSpawned())
if (hologramNPC == null || !hologramNPC.isSpawned()) {
continue;
}
if (line.ticks > 0 && --line.ticks == 0) {
line.removeNPC();
lines.remove(i--);
continue;
}
if (updatePosition && !useDisplayEntities) {
Location tp = npcLoc.clone().add(0, lastEntityHeight + getHeight(i), 0);
hologramNPC.teleport(tp, TeleportCause.PLUGIN);
}
if (useDisplayEntities && hologramNPC.getEntity().getVehicle() == null) {
npc.getEntity().addPassenger(hologramNPC.getEntity());
}
String text = line.text;
if (ITEM_MATCHER.matcher(text).matches()) {
hologramNPC.data().set(NPC.Metadata.NAMEPLATE_VISIBLE, false);
continue;
}
if (!updateName)
if (!updateName) {
continue;
}
line.setText(text);
}
}
@ -383,8 +378,9 @@ public class HologramTrait extends Trait {
root.removeKey("lines");
int i = 0;
for (HologramLine line : lines) {
if (!line.persist)
if (!line.persist) {
continue;
}
root.setString("lines." + i + ".text", line.text);
root.setDouble("lines." + i + ".margin.top", line.mt);
root.setDouble("lines." + i + ".margin.bottom", line.mb);
@ -405,7 +401,6 @@ public class HologramTrait extends Trait {
addLine(text);
return;
}
HologramLine line = lines.get(idx);
line.setText(text);
if (line.hologram == null) {
@ -441,7 +436,6 @@ public class HologramTrait extends Trait {
} else if (type.equalsIgnoreCase("bottom")) {
lines.get(idx).mb = margin;
}
reloadLineHolograms();
}
@ -449,11 +443,16 @@ public class HologramTrait extends Trait {
* Implementation-specific method: {@see NPC.Metadata#HOLOGRAM_LINE_SUPPLIER}
*/
public void setPerPlayerTextSupplier(BiFunction<String, Player, String> nameSupplier) {
this.customHologramSupplier = nameSupplier;
customHologramSupplier = nameSupplier;
}
public void setUseDisplayEntities(boolean use) {
this.useDisplayEntities = use;
useDisplayEntities = use;
reloadLineHolograms();
}
public void setViewRange(int range) {
this.viewRange = range;
reloadLineHolograms();
}
@ -508,7 +507,7 @@ public class HologramTrait extends Trait {
public void spawnNPC(double height) {
String name = Placeholders.replace(text, null, npc);
this.hologram = createHologram(name, height);
hologram = createHologram(name, height);
if (customHologramSupplier != null) {
hologram.data().set(NPC.Metadata.HOLOGRAM_LINE_SUPPLIER,
(Function<Player, String>) p -> customHologramSupplier.apply(text, p));
@ -529,8 +528,8 @@ public class HologramTrait extends Trait {
return Collections.emptyList();
}
private static final List<String> LINE_ARGS = ImmutableList.of("set", "remove", "margintop", "marginbottom");
private static List<String> LINE_ARGS = ImmutableList.of("set", "remove", "margintop", "marginbottom");
}
private static final Pattern ITEM_MATCHER = Pattern.compile("<item:(.*?)([:].*?)?>");
private static Pattern ITEM_MATCHER = Pattern.compile("<item:(.*?)([:].*?)?>");
}

View File

@ -125,7 +125,6 @@ public class LookClose extends Trait implements Toggleable {
}
sessions.clear();
}
if (lookingAt != null && !isValid(lookingAt)) {
NPCLookCloseChangeTargetEvent event = new NPCLookCloseChangeTargetEvent(npc, lookingAt, null);
Bukkit.getPluginManager().callEvent(event);
@ -135,7 +134,6 @@ public class LookClose extends Trait implements Toggleable {
lookingAt = null;
}
}
Player old = lookingAt;
if (lookingAt != null) {
if (randomSwitchTargets && t <= 0) {
@ -150,19 +148,18 @@ public class LookClose extends Trait implements Toggleable {
Location npcLoc = npc.getStoredLocation();
for (Player player : getNearbyPlayers()) {
double dist = player.getLocation().distance(npcLoc);
if (dist > min)
if (dist > min) {
continue;
}
min = dist;
lookingAt = player;
}
}
if (old != lookingAt) {
NPCLookCloseChangeTargetEvent event = new NPCLookCloseChangeTargetEvent(npc, old, lookingAt);
Bukkit.getPluginManager().callEvent(event);
if (lookingAt != event.getNewTarget() && event.getNewTarget() != null && !isValid(event.getNewTarget())) {
if (lookingAt != event.getNewTarget() && event.getNewTarget() != null && !isValid(event.getNewTarget()))
return;
}
lookingAt = event.getNewTarget();
}
}
@ -176,11 +173,12 @@ public class LookClose extends Trait implements Toggleable {
.map(e -> (Player) e).collect(Collectors.toList())
: CitizensAPI.getLocationLookup().getNearbyPlayers(npcLoc, range);
for (Player player : nearby) {
if (player == lookingAt || (!targetNPCs && CitizensAPI.getNPCRegistry().getNPC(player) != null))
if (player == lookingAt || !targetNPCs && CitizensAPI.getNPCRegistry().getNPC(player) != null) {
continue;
if (player.getLocation().getWorld() != npcLoc.getWorld() || isInvisible(player))
}
if (player.getLocation().getWorld() != npcLoc.getWorld() || isInvisible(player)) {
continue;
}
options.add(player);
}
return options;
@ -221,9 +219,8 @@ public class LookClose extends Trait implements Toggleable {
private boolean isPluginVanished(Player player) {
for (MetadataValue meta : player.getMetadata("vanished")) {
if (meta.asBoolean()) {
if (meta.asBoolean())
return true;
}
}
return false;
}
@ -274,7 +271,6 @@ public class LookClose extends Trait implements Toggleable {
lookingAt = null;
return;
}
if (enableRandomLook) {
if (!npc.getNavigator().isNavigating() && lookingAt == null && t <= 0) {
randomLook();
@ -283,22 +279,15 @@ public class LookClose extends Trait implements Toggleable {
}
t--;
if (!enabled) {
if (!enabled || npc.getNavigator().isNavigating() && disableWhileNavigating()) {
lookingAt = null;
return;
}
if (npc.getNavigator().isNavigating() && disableWhileNavigating()) {
lookingAt = null;
return;
}
findNewTarget();
if (npc.getNavigator().isNavigating() || npc.getNavigator().isPaused()) {
npc.getNavigator().setPaused(lookingAt != null);
}
if (lookingAt == null)
return;
@ -348,15 +337,15 @@ public class LookClose extends Trait implements Toggleable {
* Sets the delay between random looking in ticks
*/
public void setRandomLookDelay(int delay) {
this.randomLookDelay = delay;
randomLookDelay = delay;
}
public void setRandomLookPitchRange(float min, float max) {
this.randomPitchRange = new float[] { min, max };
randomPitchRange = new float[] { min, max };
}
public void setRandomLookYawRange(float min, float max) {
this.randomYawRange = new float[] { min, max };
randomYawRange = new float[] { min, max };
}
public void setRandomlySwitchTargets(boolean randomSwitchTargets) {
@ -374,11 +363,11 @@ public class LookClose extends Trait implements Toggleable {
* Enables/disables realistic looking (using line of sight checks). More computationally expensive.
*/
public void setRealisticLooking(boolean realistic) {
this.realisticLooking = realistic;
realisticLooking = realistic;
}
public void setTargetNPCs(boolean target) {
this.targetNPCs = target;
targetNPCs = target;
}
public boolean targetNPCs() {

View File

@ -35,7 +35,7 @@ public class OcelotModifiers extends Trait {
}
public void setSitting(boolean sit) {
this.sitting = sit;
sitting = sit;
updateModifiers();
}

View File

@ -64,9 +64,8 @@ public class PacketNPC extends Trait {
}
public EntityController wrap(EntityController controller) {
if (!(controller instanceof PacketController)) {
if (!(controller instanceof PacketController))
return new PacketController(controller);
}
return controller;
}
@ -74,7 +73,7 @@ public class PacketNPC extends Trait {
private final EntityController base;
public PacketController(EntityController controller) {
this.base = controller;
base = controller;
}
@Override

View File

@ -43,9 +43,7 @@ public class PausePathfindingTrait extends Trait {
@Override
public void run() {
if (playerRange == -1 || !npc.isSpawned())
return;
if (unpauseTaskId == -1 && !npc.getNavigator().isNavigating())
if (playerRange == -1 || !npc.isSpawned() || unpauseTaskId == -1 && !npc.getNavigator().isNavigating())
return;
if (CitizensAPI.getLocationLookup().getNearbyPlayers(npc.getStoredLocation(), playerRange).iterator()
.hasNext()) {
@ -58,7 +56,7 @@ public class PausePathfindingTrait extends Trait {
}
public void setPlayerRangeBlocks(double range) {
this.playerRange = range;
playerRange = range;
}
public void setRightClick(boolean rightclick) {

View File

@ -93,10 +93,8 @@ public class Poses extends Trait {
paginator.addLine(line);
i++;
}
if (!paginator.sendPage(sender, page)) {
if (!paginator.sendPage(sender, page))
throw new CommandException(Messages.COMMAND_PAGE_MISSING, page);
}
}
public Pose getPose(String name) {
@ -115,7 +113,8 @@ public class Poses extends Trait {
for (DataKey sub : key.getRelative("list").getIntegerSubKeys()) {
try {
String[] parts = sub.getString("").split(";");
poses.put(parts[0].toLowerCase(), new Pose(parts[0], Float.valueOf(parts[1]), Float.valueOf(parts[2])));
poses.put(parts[0].toLowerCase(),
new Pose(parts[0], Float.parseFloat(parts[1]), Float.parseFloat(parts[2])));
} catch (NumberFormatException e) {
Messaging.logTr(Messages.SKIPPING_INVALID_POSE, sub.name(), e.getMessage());
}
@ -149,6 +148,6 @@ public class Poses extends Trait {
}
public void setDefaultPose(String pose) {
this.defaultPose = pose;
defaultPose = pose;
}
}

View File

@ -20,6 +20,10 @@ public class Powered extends Trait implements Toggleable {
super("powered");
}
public boolean isPowered() {
return powered;
}
@Override
public void onSpawn() {
if (npc.getEntity() instanceof Creeper) {
@ -27,10 +31,6 @@ public class Powered extends Trait implements Toggleable {
}
}
public boolean isPowered() {
return powered;
}
@Override
public boolean toggle() {
powered = !powered;

View File

@ -60,7 +60,6 @@ public class RotationTrait extends Trait {
} else {
packetSessions.add(lrs);
}
return lrs;
}
@ -82,11 +81,9 @@ public class RotationTrait extends Trait {
return lrs;
for (PacketRotationSession session : packetSessions) {
if (session.accepts(player) && session.triple != null) {
if (session.accepts(player) && session.triple != null)
return session;
}
}
return null;
}
@ -102,31 +99,28 @@ public class RotationTrait extends Trait {
if (npc.data().get(NPC.Metadata.RESET_PITCH_ON_TICK, false)) {
NMS.setPitch(npc.getEntity(), 0);
}
Set<PacketRotationSession> ran = Sets.newHashSet();
for (Iterator<PacketRotationSession> itr = Iterables.concat(packetSessions, packetSessionsByUUID.values())
.iterator(); itr.hasNext();) {
PacketRotationSession session = itr.next();
if (ran.contains(session))
if (ran.contains(session)) {
continue;
}
ran.add(session);
session.run(npc.getEntity());
if (!session.isActive()) {
itr.remove();
}
}
if (npc.getNavigator().isNavigating()) {
if (npc.getNavigator().isNavigating())
// npc.yHeadRot = rotateIfNecessary(npc.yHeadRot, npc.yBodyRot, 75);
return;
}
globalSession.run(new EntityRotation(npc.getEntity()));
}
private static class EntityRotation extends RotationTriple {
protected final Entity entity;
protected Entity entity;
public EntityRotation(Entity entity) {
super(NMS.getYaw(entity), NMS.getHeadYaw(entity), entity.getLocation().getPitch());
@ -158,7 +152,7 @@ public class RotationTrait extends Trait {
}
public void end() {
this.ended = true;
ended = true;
}
public float getBodyYaw() {
@ -193,7 +187,6 @@ public class RotationTrait extends Trait {
if (triple == null) {
triple = new PacketRotationTriple(entity);
}
session.run(triple);
if (!session.isActive()) {
triple = null;
@ -265,7 +258,7 @@ public class RotationTrait extends Trait {
}
public RotationParams linkedBody(boolean linked) {
this.linkedBody = linked;
linkedBody = linked;
return this;
}
@ -297,12 +290,12 @@ public class RotationTrait extends Trait {
}
public RotationParams maxPitchPerTick(float val) {
this.maxPitchPerTick = val;
maxPitchPerTick = val;
return this;
}
public RotationParams maxYawPerTick(float val) {
this.maxYawPerTick = val;
maxYawPerTick = val;
return this;
}
@ -312,7 +305,7 @@ public class RotationTrait extends Trait {
}
public RotationParams pitchRange(float[] val) {
this.pitchRange = val;
pitchRange = val;
return this;
}
@ -343,29 +336,24 @@ public class RotationTrait extends Trait {
if (headOnly) {
key.setBoolean("headOnly", headOnly);
}
if (immediate) {
key.setBoolean("immediate", immediate);
}
if (maxPitchPerTick != 10) {
key.setDouble("maxPitchPerTick", maxPitchPerTick);
} else {
key.removeKey("maxPitchPerTick");
}
if (maxYawPerTick != 40) {
key.setDouble("maxYawPerTick", maxYawPerTick);
} else {
key.removeKey("maxYawPerTick");
}
if (pitchRange[0] != -180 || pitchRange[1] != 180) {
key.setString("pitchRange", pitchRange[0] + "," + pitchRange[1]);
} else {
key.removeKey("pitchRange");
}
if (yawRange[0] != -180 || yawRange[1] != 180) {
key.setString("yawRange", yawRange[0] + "," + yawRange[1]);
} else {
@ -374,7 +362,7 @@ public class RotationTrait extends Trait {
}
public RotationParams uuidFilter(List<UUID> uuids) {
this.uuidFilter = uuids;
uuidFilter = uuids;
return this;
}
@ -383,7 +371,7 @@ public class RotationTrait extends Trait {
}
public RotationParams yawRange(float[] val) {
this.yawRange = val;
yawRange = val;
return this;
}
}
@ -489,21 +477,18 @@ public class RotationTrait extends Trait {
rot.bodyYaw = Math.abs(body - lo) > Math.abs(body - hi) ? hi : lo;
}
}
rot.pitch = params.immediate ? getTargetPitch() : params.rotatePitchTowards(t, rot.pitch, getTargetPitch());
t++;
if (params.linkedBody) {
rot.bodyYaw = rot.headYaw;
}
if (Math.abs(rot.pitch - getTargetPitch()) + Math.abs(rot.headYaw - getTargetYaw()) < 0.1) {
t = -1;
if (!params.headOnly) {
rot.bodyYaw = rot.headYaw;
}
}
rot.apply();
}
}

View File

@ -35,18 +35,20 @@ public class ScoreboardTrait extends Trait {
private final PerPlayerMetadata<Boolean> metadata;
private ChatColor previousGlowingColor;
@Persist
private Set<String> tags = new HashSet<String>();
private Set<String> tags = new HashSet<>();
public ScoreboardTrait() {
super("scoreboardtrait");
metadata = CitizensAPI.getLocationLookup().<Boolean> registerMetadata("scoreboard", (meta, event) -> {
for (NPC npc : CitizensAPI.getNPCRegistry()) {
ScoreboardTrait trait = npc.getTraitNullable(ScoreboardTrait.class);
if (trait == null)
if (trait == null) {
continue;
}
Team team = trait.getTeam();
if (team == null || meta.has(event.getPlayer().getUniqueId(), team.getName()))
if (team == null || meta.has(event.getPlayer().getUniqueId(), team.getName())) {
continue;
}
NMS.sendTeamPacket(event.getPlayer(), team, 0);
meta.set(event.getPlayer().getUniqueId(), team.getName(), true);
}
@ -161,13 +163,11 @@ public class ScoreboardTrait extends Trait {
npc.data().remove(NPC.Metadata.SCOREBOARD_FAKE_TEAM_NAME);
return;
}
if (npc.isSpawned()) {
lastName = npc.getEntity() instanceof Player && npc.getEntity().getName() != null
? npc.getEntity().getName()
: npc.getUniqueId().toString();
}
if (SUPPORT_TAGS) {
try {
if (!npc.getEntity().getScoreboardTags().equals(tags)) {
@ -177,7 +177,6 @@ public class ScoreboardTrait extends Trait {
SUPPORT_TAGS = false;
}
}
if (SUPPORT_TEAM_SETOPTION) {
try {
OptionStatus visibility = nameVisibility ? OptionStatus.ALWAYS : OptionStatus.NEVER;
@ -193,7 +192,6 @@ public class ScoreboardTrait extends Trait {
} else {
NMS.setTeamNameTagVisible(team, nameVisibility);
}
if (SUPPORT_COLLIDABLE_SETOPTION) {
try {
OptionStatus collide = npc.data().<Boolean> get(NPC.Metadata.COLLIDABLE, !npc.isProtected())
@ -209,7 +207,6 @@ public class ScoreboardTrait extends Trait {
SUPPORT_COLLIDABLE_SETOPTION = false;
}
}
if (color != null) {
if (SUPPORT_GLOWING_COLOR && SpigotUtil.getMinecraftPackage().contains("1_12_R1")) {
SUPPORT_GLOWING_COLOR = false;
@ -217,7 +214,7 @@ public class ScoreboardTrait extends Trait {
if (SUPPORT_GLOWING_COLOR) {
try {
if (team.getColor() == null || previousGlowingColor == null
|| (previousGlowingColor != null && color != previousGlowingColor)) {
|| previousGlowingColor != null && color != previousGlowingColor) {
team.setColor(color);
previousGlowingColor = color;
changed = true;
@ -225,22 +222,19 @@ public class ScoreboardTrait extends Trait {
} catch (NoSuchMethodError err) {
SUPPORT_GLOWING_COLOR = false;
}
} else {
if (team.getPrefix() == null || team.getPrefix().length() == 0 || previousGlowingColor == null
|| (previousGlowingColor != null
&& !team.getPrefix().equals(previousGlowingColor.toString()))) {
team.setPrefix(color.toString());
previousGlowingColor = color;
changed = true;
}
} else if (team.getPrefix() == null || team.getPrefix().length() == 0 || previousGlowingColor == null
|| previousGlowingColor != null && !team.getPrefix().equals(previousGlowingColor.toString())) {
team.setPrefix(color.toString());
previousGlowingColor = color;
changed = true;
}
}
if (!changed)
return;
for (Player player : Bukkit.getOnlinePlayers()) {
if (player.hasMetadata("NPC"))
if (player.hasMetadata("NPC")) {
continue;
}
if (metadata.has(player.getUniqueId(), team.getName())) {
NMS.sendTeamPacket(player, team, 2);
} else {

View File

@ -34,7 +34,7 @@ public class SheepTrait extends Trait {
@EventHandler
private void onPlayerShearEntityEvent(PlayerShearEntityEvent event) {
if (npc != null && npc.equals(CitizensAPI.getNPCRegistry().getNPC(event.getEntity()))) {
if (npc != null && npc.isProtected() && npc.equals(CitizensAPI.getNPCRegistry().getNPC(event.getEntity()))) {
event.setCancelled(true);
}
}

View File

@ -35,7 +35,6 @@ public class SitTrait extends Trait {
((Sittable) npc.getEntity()).setSitting(false);
return;
}
if (chair != null) {
if (chair.getEntity() != null) {
chair.getEntity().eject();
@ -72,7 +71,6 @@ public class SitTrait extends Trait {
}
return;
}
if (chair == null) {
NPCRegistry registry = CitizensAPI.getNamedNPCRegistry("SitRegistry");
if (registry == null) {
@ -85,22 +83,19 @@ public class SitTrait extends Trait {
return;
}
}
if (chair.isSpawned() && !NMS.getPassengers(chair.getEntity()).contains(npc.getEntity())) {
NMS.mount(chair.getEntity(), npc.getEntity());
}
if (chair.getStoredLocation() != null && chair.getStoredLocation().distance(sittingAt) >= 0.03) {
chair.teleport(sittingAt.clone(), TeleportCause.PLUGIN);
}
}
public void setSitting(Location at) {
this.sittingAt = at != null ? at.clone() : null;
sittingAt = at != null ? at.clone() : null;
if (requiresPassengerOffsetCorrection()) {
sittingAt = sittingAt.add(0, 0.3, 0);
}
if (at == null) {
onDespawn();
}

View File

@ -258,10 +258,10 @@ public class SkinLayers extends Trait {
RIGHT_PANTS(5),
RIGHT_SLEEVE(3);
final int flag;
int flag;
Layer(int offset) {
this.flag = 1 << offset;
flag = 1 << offset;
}
public static byte toByte(Set<Layer> flags) {

View File

@ -109,14 +109,14 @@ public class SkinTrait extends Trait {
* @see #fetchDefaultSkin
*/
public void setFetchDefaultSkin(boolean fetch) {
this.fetchDefaultSkin = fetch;
fetchDefaultSkin = fetch;
}
/**
* @see #shouldUpdateSkins()
*/
public void setShouldUpdateSkins(boolean update) {
this.updateSkins = update;
updateSkins = update;
}
/**
@ -170,14 +170,14 @@ public class SkinTrait extends Trait {
throw new IllegalArgumentException("Invalid texture data");
this.signature = signature;
this.textureRaw = data;
this.updateSkins = false;
textureRaw = data;
updateSkins = false;
npc.data().setPersistent(Skin.CACHED_SKIN_UUID_NAME_METADATA, skinName.toLowerCase());
onSkinChange(false);
}
public void setTexture(String value, String signature) {
this.textureRaw = value;
textureRaw = value;
this.signature = signature;
}

View File

@ -36,7 +36,6 @@ public class SleepTrait extends Trait {
}
return;
}
if (SUPPORT_BLOCKDATA == null) {
try {
SUPPORT_BLOCKDATA = true;
@ -45,14 +44,13 @@ public class SleepTrait extends Trait {
SUPPORT_BLOCKDATA = false;
}
}
if (npc.getEntity() instanceof Player) {
Player player = (Player) npc.getEntity();
if (!SUPPORT_BLOCKSTATE) {
NMS.sleep(player, true);
} else {
try {
if ((SUPPORT_BLOCKDATA && at.getBlock().getBlockData() instanceof Bed)
if (SUPPORT_BLOCKDATA && at.getBlock().getBlockData() instanceof Bed
|| at.getBlock().getState() instanceof Bed) {
player.sleep(at, true);
} else {

View File

@ -39,7 +39,7 @@ public class SneakTrait extends Trait {
}
public void setSneaking(boolean sneak) {
this.sneaking = sneak;
sneaking = sneak;
apply();
}
}

View File

@ -54,7 +54,7 @@ public class WolfModifiers extends Trait {
}
public void setCollarColor(DyeColor color) {
this.collarColor = color;
collarColor = color;
updateModifiers();
}

View File

@ -98,7 +98,7 @@ public class CommandAction extends NPCShopAction {
@Override
public void initialise(MenuContext ctx) {
for (int i = 0; i < 3 * 9; i++) {
final int idx = i;
int idx = i;
ctx.getSlot(i).clear();
if (i < base.commands.size()) {
ctx.getSlot(i).setItemStack(new ItemStack(Material.FEATHER), "<f>Set command",
@ -114,7 +114,7 @@ public class CommandAction extends NPCShopAction {
return;
}
ctx.getMenu().transition(InputMenus
.stringSetter(() -> idx < base.commands.size() ? base.commands.get(idx) : "", (res) -> {
.stringSetter(() -> idx < base.commands.size() ? base.commands.get(idx) : "", res -> {
if (res == null) {
if (idx < base.commands.size()) {
base.commands.remove(idx);
@ -131,11 +131,11 @@ public class CommandAction extends NPCShopAction {
}
ctx.getSlot(3 * 9 + 3).setItemStack(new ItemStack(Util.getFallbackMaterial("COMMAND_BLOCK", "COMMAND")),
"Run commands as server", base.server ? ChatColor.GREEN + "On" : ChatColor.RED + "OFF");
ctx.getSlot(3 * 9 + 3).addClickHandler(InputMenus.toggler((res) -> base.server = res, base.server));
ctx.getSlot(3 * 9 + 3).addClickHandler(InputMenus.toggler(res -> base.server = res, base.server));
ctx.getSlot(3 * 9 + 4).setItemStack(
new ItemStack(Util.getFallbackMaterial("COMPARATOR", "REDSTONE_COMPARATOR")), "Run commands as op",
base.op ? ChatColor.GREEN + "On" : ChatColor.RED + "OFF");
ctx.getSlot(3 * 9 + 4).addClickHandler(InputMenus.clickToggle((res) -> {
ctx.getSlot(3 * 9 + 4).addClickHandler(InputMenus.clickToggle(res -> {
base.op = res;
return res ? ChatColor.GREEN + "On" : ChatColor.RED + "Off";
}, base.server));

View File

@ -20,7 +20,7 @@ public class ExperienceAction extends NPCShopAction {
}
public ExperienceAction(int cost) {
this.exp = cost;
exp = cost;
}
@Override
@ -32,6 +32,7 @@ public class ExperienceAction extends NPCShopAction {
public int getMaxRepeats(Entity entity) {
if (!(entity instanceof Player))
return 0;
return ((Player) entity).getLevel() / exp;
}
@ -39,11 +40,10 @@ public class ExperienceAction extends NPCShopAction {
public Transaction grant(Entity entity, int repeats) {
if (!(entity instanceof Player))
return Transaction.fail();
Player player = (Player) entity;
int amount = exp * repeats;
return Transaction.create(() -> {
return true;
}, () -> {
return Transaction.create(() -> true, () -> {
player.setLevel(player.getLevel() + amount);
}, () -> {
player.setLevel(player.getLevel() - amount);
@ -54,11 +54,10 @@ public class ExperienceAction extends NPCShopAction {
public Transaction take(Entity entity, int repeats) {
if (!(entity instanceof Player))
return Transaction.fail();
Player player = (Player) entity;
int amount = exp * repeats;
return Transaction.create(() -> {
return player.getLevel() >= amount;
}, () -> {
return Transaction.create(() -> (player.getLevel() >= amount), () -> {
player.setLevel(player.getLevel() - amount);
}, () -> {
player.setLevel(player.getLevel() + amount);
@ -68,12 +67,13 @@ public class ExperienceAction extends NPCShopAction {
public static class ExperienceActionGUI implements GUI {
@Override
public InventoryMenuPage createEditor(NPCShopAction previous, Consumer<NPCShopAction> callback) {
final ExperienceAction action = previous == null ? new ExperienceAction() : (ExperienceAction) previous;
ExperienceAction action = previous == null ? new ExperienceAction() : (ExperienceAction) previous;
return InputMenus.filteredStringSetter(() -> Integer.toString(action.exp), s -> {
try {
int result = Integer.parseInt(s);
if (result < 0)
return false;
action.exp = result;
} catch (NumberFormatException nfe) {
return false;

View File

@ -56,18 +56,18 @@ public class ItemAction extends NPCShopAction {
ItemStack[] contents = source.getContents();
for (int i = 0; i < contents.length; i++) {
ItemStack toMatch = contents[i];
if (toMatch == null || toMatch.getType() == Material.AIR)
continue;
if (tooDamaged(toMatch))
if (toMatch == null || toMatch.getType() == Material.AIR || tooDamaged(toMatch)) {
continue;
}
toMatch = toMatch.clone();
for (int j = 0; j < items.size(); j++) {
if (toMatch == null)
if (toMatch == null) {
break;
}
ItemStack item = items.get(j);
if (req.get(j) <= 0 || !matches(item, toMatch))
if (req.get(j) <= 0 || !matches(item, toMatch)) {
continue;
}
int remaining = req.get(j);
int taken = toMatch.getAmount() > remaining ? remaining : toMatch.getAmount();
@ -76,7 +76,6 @@ public class ItemAction extends NPCShopAction {
} else {
toMatch.setAmount(toMatch.getAmount() - taken);
}
if (modify) {
if (toMatch == null) {
source.clear(i);
@ -92,9 +91,8 @@ public class ItemAction extends NPCShopAction {
@Override
public String describe() {
if (items.size() == 1) {
if (items.size() == 1)
return items.get(0).getAmount() + " " + Util.prettyEnum(items.get(0).getType());
}
String description = items.size() + " items";
for (int i = 0; i < items.size(); i++) {
ItemStack item = items.get(i);
@ -113,24 +111,25 @@ public class ItemAction extends NPCShopAction {
return 0;
Inventory source = ((InventoryHolder) entity).getInventory();
List<Integer> req = items.stream().map(i -> i.getAmount()).collect(Collectors.toList());
List<Integer> req = items.stream().map(ItemStack::getAmount).collect(Collectors.toList());
List<Integer> has = items.stream().map(i -> 0).collect(Collectors.toList());
ItemStack[] contents = source.getContents();
for (int i = 0; i < contents.length; i++) {
ItemStack toMatch = contents[i];
if (toMatch == null || toMatch.getType() == Material.AIR)
continue;
if (tooDamaged(toMatch))
if (toMatch == null || toMatch.getType() == Material.AIR || tooDamaged(toMatch))
continue;
toMatch = toMatch.clone();
for (int j = 0; j < items.size(); j++) {
if (!matches(items.get(j), toMatch))
continue;
int remaining = req.get(j);
int taken = toMatch.getAmount() > remaining ? remaining : toMatch.getAmount();
has.set(j, has.get(j) + taken);
if (toMatch.getAmount() - taken <= 0)
if (toMatch.getAmount() - taken <= 0) {
break;
}
toMatch.setAmount(toMatch.getAmount() - taken);
}
}
@ -164,12 +163,12 @@ public class ItemAction extends NPCShopAction {
}
private boolean matches(ItemStack a, ItemStack b) {
if (a.getType() != b.getType())
return false;
if (metaFilter.size() > 0 && !metaMatches(a, b, metaFilter))
if (a.getType() != b.getType() || metaFilter.size() > 0 && !metaMatches(a, b, metaFilter))
return false;
if (compareSimilarity && !a.isSimilar(b))
return false;
return true;
}
@ -181,22 +180,20 @@ public class ItemAction extends NPCShopAction {
Tag acc = source;
Tag cmp = compare;
for (int i = 0; i < parts.length; i++) {
if (acc == null)
return false;
if (cmp == null)
if (acc == null || cmp == null)
return false;
if (i < parts.length - 1) {
if (!(acc instanceof CompoundTag) || !(cmp instanceof CompoundTag))
return false;
if (parts[i].equals(acc.getName()) && acc.getName().equals(cmp.getName()))
if (parts[i].equals(acc.getName()) && acc.getName().equals(cmp.getName())) {
continue;
}
acc = ((CompoundTag) acc).getValue().get(parts[i]);
cmp = ((CompoundTag) cmp).getValue().get(parts[i]);
continue;
}
if (!acc.getName().equals(parts[i]) || !cmp.getName().equals(parts[i]))
return false;
if (!acc.getValue().equals(cmp.getValue()))
if (!acc.getName().equals(parts[i]) || !cmp.getName().equals(parts[i])
|| !acc.getValue().equals(cmp.getValue()))
return false;
}
}
@ -207,10 +204,9 @@ public class ItemAction extends NPCShopAction {
public Transaction take(Entity entity, int repeats) {
if (!(entity instanceof InventoryHolder))
return Transaction.fail();
Inventory source = ((InventoryHolder) entity).getInventory();
return Transaction.create(() -> {
return containsItems(source, repeats, false);
}, () -> {
return Transaction.create(() -> containsItems(source, repeats, false), () -> {
containsItems(source, repeats, true);
}, () -> {
source.addItem(items.stream().map(ItemStack::clone).toArray(ItemStack[]::new));
@ -220,8 +216,10 @@ public class ItemAction extends NPCShopAction {
private boolean tooDamaged(ItemStack toMatch) {
if (!requireUndamaged)
return false;
if (SpigotUtil.isUsing1_13API())
return toMatch.getItemMeta() instanceof Damageable && ((Damageable) toMatch.getItemMeta()).getDamage() != 0;
return toMatch.getDurability() == toMatch.getType().getMaxDurability();
}
@ -253,20 +251,19 @@ public class ItemAction extends NPCShopAction {
event.setCancelled(true);
});
}
ctx.getSlot(3 * 9 + 1).setItemStack(new ItemStack(Material.ANVIL), "Must have no damage",
base.requireUndamaged ? ChatColor.GREEN + "On" : ChatColor.RED + "Off");
ctx.getSlot(3 * 9 + 1)
.addClickHandler(InputMenus.toggler((res) -> base.requireUndamaged = res, base.requireUndamaged));
.addClickHandler(InputMenus.toggler(res -> base.requireUndamaged = res, base.requireUndamaged));
ctx.getSlot(3 * 9 + 2).setItemStack(
new ItemStack(Util.getFallbackMaterial("COMPARATOR", "REDSTONE_COMPARATOR")),
"Compare item similarity", base.compareSimilarity ? ChatColor.GREEN + "On" : ChatColor.RED + "Off");
ctx.getSlot(3 * 9 + 2)
.addClickHandler(InputMenus.toggler((res) -> base.compareSimilarity = res, base.compareSimilarity));
.addClickHandler(InputMenus.toggler(res -> base.compareSimilarity = res, base.compareSimilarity));
ctx.getSlot(3 * 9 + 3).setItemStack(new ItemStack(Material.BOOK), "NBT comparison filter",
Joiner.on("\n").join(base.metaFilter));
ctx.getSlot(3 * 9 + 3)
.addClickHandler((event) -> ctx.getMenu()
.addClickHandler(event -> ctx.getMenu()
.transition(InputMenus.stringSetter(() -> Joiner.on(',').join(base.metaFilter),
res -> base.metaFilter = res == null ? null : Arrays.asList(res.split(",")))));
}

View File

@ -22,7 +22,7 @@ public class MoneyAction extends NPCShopAction {
}
public MoneyAction(double cost) {
this.money = cost;
money = cost;
}
@Override
@ -35,6 +35,7 @@ public class MoneyAction extends NPCShopAction {
public int getMaxRepeats(Entity entity) {
if (!(entity instanceof Player))
return 0;
Economy economy = Bukkit.getServicesManager().getRegistration(Economy.class).getProvider();
return (int) Math.floor(economy.getBalance((Player) entity) / money);
}
@ -43,12 +44,12 @@ public class MoneyAction extends NPCShopAction {
public Transaction grant(Entity entity, int repeats) {
if (!(entity instanceof Player))
return Transaction.fail();
Economy economy = Bukkit.getServicesManager().getRegistration(Economy.class).getProvider();
Player player = (Player) entity;
double amount = money * repeats;
return Transaction.create(() -> {
return true;
}, () -> {
return Transaction.create(() -> true, () -> {
economy.depositPlayer(player, amount);
}, () -> {
economy.withdrawPlayer(player, amount);
@ -59,12 +60,12 @@ public class MoneyAction extends NPCShopAction {
public Transaction take(Entity entity, int repeats) {
if (!(entity instanceof Player))
return Transaction.fail();
Economy economy = Bukkit.getServicesManager().getRegistration(Economy.class).getProvider();
Player player = (Player) entity;
double amount = money * repeats;
return Transaction.create(() -> {
return economy.has(player, amount);
}, () -> {
return Transaction.create(() -> economy.has(player, amount), () -> {
economy.withdrawPlayer(player, amount);
}, () -> {
economy.depositPlayer(player, amount);
@ -76,12 +77,13 @@ public class MoneyAction extends NPCShopAction {
@Override
public InventoryMenuPage createEditor(NPCShopAction previous, Consumer<NPCShopAction> callback) {
final MoneyAction action = previous == null ? new MoneyAction() : (MoneyAction) previous;
return InputMenus.filteredStringSetter(() -> Double.toString(action.money), (s) -> {
MoneyAction action = previous == null ? new MoneyAction() : (MoneyAction) previous;
return InputMenus.filteredStringSetter(() -> Double.toString(action.money), s -> {
try {
double result = Double.parseDouble(s);
if (result < 0)
return false;
action.money = result;
} catch (NumberFormatException nfe) {
return false;
@ -100,9 +102,9 @@ public class MoneyAction extends NPCShopAction {
supported = false;
}
}
if (!supported) {
if (!supported)
return null;
}
String description = null;
if (previous != null) {
MoneyAction old = (MoneyAction) previous;

View File

@ -45,7 +45,7 @@ public abstract class NPCShopAction implements Cloneable {
private final Runnable rollback;
public Transaction(Supplier<Boolean> isPossible, Runnable execute, Runnable rollback) {
this.possible = isPossible;
possible = isPossible;
this.execute = execute;
this.rollback = rollback;
}
@ -88,7 +88,6 @@ public abstract class NPCShopAction implements Cloneable {
GUI.add(gui);
}
private static final List<GUI> GUI = Lists.newArrayList();
private static final PersisterRegistry<NPCShopAction> REGISTRY = PersistenceLoader
.createRegistry(NPCShopAction.class);
private static List<GUI> GUI = Lists.newArrayList();
private static PersisterRegistry<NPCShopAction> REGISTRY = PersistenceLoader.createRegistry(NPCShopAction.class);
}

View File

@ -56,9 +56,7 @@ public class PermissionAction extends NPCShopAction {
return Transaction.fail();
Player player = (Player) entity;
Permission perm = Bukkit.getServicesManager().getRegistration(Permission.class).getProvider();
return Transaction.create(() -> {
return true;
}, () -> {
return Transaction.create(() -> true, () -> {
for (String permission : permissions) {
perm.playerAdd(null, player, Placeholders.replace(permission, player));
}
@ -77,9 +75,8 @@ public class PermissionAction extends NPCShopAction {
Permission perm = Bukkit.getServicesManager().getRegistration(Permission.class).getProvider();
return Transaction.create(() -> {
for (String permission : permissions) {
if (!perm.playerHas(player, Placeholders.replace(permission, player))) {
if (!perm.playerHas(player, Placeholders.replace(permission, player)))
return false;
}
}
return true;
}, () -> {
@ -109,7 +106,7 @@ public class PermissionAction extends NPCShopAction {
@Override
public void initialise(MenuContext ctx) {
for (int i = 0; i < 3 * 9; i++) {
final int idx = i;
int idx = i;
ctx.getSlot(i).clear();
if (i < base.permissions.size()) {
ctx.getSlot(i).setItemStack(new ItemStack(Material.FEATHER), "<f>Set permission",
@ -124,8 +121,8 @@ public class PermissionAction extends NPCShopAction {
}
return;
}
ctx.getMenu().transition(InputMenus.stringSetter(
() -> idx < base.permissions.size() ? base.permissions.get(idx) : "", (res) -> {
ctx.getMenu().transition(InputMenus
.stringSetter(() -> idx < base.permissions.size() ? base.permissions.get(idx) : "", res -> {
if (res == null) {
if (idx < base.permissions.size()) {
base.permissions.remove(idx);
@ -166,9 +163,8 @@ public class PermissionAction extends NPCShopAction {
supported = false;
}
}
if (!supported) {
if (!supported)
return null;
}
String description = null;
if (previous != null) {
PermissionAction old = (PermissionAction) previous;

View File

@ -55,11 +55,11 @@ public class Text extends Trait implements Runnable, Listener {
private boolean speechBubbles;
@Persist(value = "talk-close")
private boolean talkClose = Setting.DEFAULT_TALK_CLOSE.asBoolean();
private final List<String> text = new ArrayList<String>();
private final List<String> text = new ArrayList<>();
public Text() {
super("text");
this.plugin = CitizensAPI.getPlugin();
plugin = CitizensAPI.getPlugin();
}
/**
@ -87,10 +87,10 @@ public class Text extends Trait implements Runnable, Listener {
/**
* Builds a text editor in game for the supplied {@link Player}.
*/
public Editor getEditor(final Player player) {
final Conversation conversation = new ConversationFactory(plugin).withLocalEcho(false)
.withEscapeSequence("/npc text").withEscapeSequence("exit").withModality(false)
.withFirstPrompt(new TextBasePrompt(this)).buildConversation(player);
public Editor getEditor(Player player) {
Conversation conversation = new ConversationFactory(plugin).withLocalEcho(false).withEscapeSequence("/npc text")
.withEscapeSequence("exit").withModality(false).withFirstPrompt(new TextBasePrompt(this))
.buildConversation(player);
return new Editor() {
@Override
public void begin() {
@ -142,11 +142,9 @@ public class Text extends Trait implements Runnable, Listener {
for (DataKey sub : key.getRelative("text").getIntegerSubKeys()) {
text.add(sub.getString(""));
}
if (text.isEmpty()) {
populateDefaultText();
}
range = key.getDouble("range");
}
@ -178,8 +176,9 @@ public class Text extends Trait implements Runnable, Listener {
return;
for (Player player : CitizensAPI.getLocationLookup().getNearbyPlayers(npc.getEntity().getLocation(), range)) {
if (player.getGameMode() == GameMode.SPECTATOR)
if (player.getGameMode() == GameMode.SPECTATOR) {
continue;
}
talk(player);
}
}
@ -216,7 +215,6 @@ public class Text extends Trait implements Runnable, Listener {
}
index = currentIndex++;
}
if (speechBubbles) {
HologramTrait trait = npc.getOrAddTrait(HologramTrait.class);
trait.addTemporaryLine(Placeholders.replace(text.get(index), player, npc),
@ -271,7 +269,6 @@ public class Text extends Trait implements Runnable, Listener {
cooldowns.remove(player.getUniqueId());
}
sendText(player);
int delay = this.delay == -1
@ -280,35 +277,35 @@ public class Text extends Trait implements Runnable, Listener {
: this.delay;
if (delay <= 0)
return;
cooldowns.put(player.getUniqueId(), System.currentTimeMillis() + (delay * 50));
cooldowns.put(player.getUniqueId(), System.currentTimeMillis() + delay * 50);
}
/**
* Toggles talking at random intervals.
*/
public boolean toggleRandomTalker() {
return (randomTalker = !randomTalker);
return randomTalker = !randomTalker;
}
/**
* Toggles requiring line of sight before talking.
*/
public boolean toggleRealisticLooking() {
return (realisticLooker = !realisticLooker);
return realisticLooker = !realisticLooker;
}
/**
* Toggles using speech bubbles instead of messages.
*/
public boolean toggleSpeechBubbles() {
return (speechBubbles = !speechBubbles);
return speechBubbles = !speechBubbles;
}
/**
* Toggles talking to nearby Players.
*/
public boolean toggleTalkClose() {
return (talkClose = !talkClose);
return talkClose = !talkClose;
}
public boolean useRealisticLooking() {
@ -319,5 +316,5 @@ public class Text extends Trait implements Runnable, Listener {
return speechBubbles;
}
private static final Random RANDOM = Util.getFastRandom();
private static Random RANDOM = Util.getFastRandom();
}

View File

@ -60,7 +60,6 @@ public class TextBasePrompt extends StringPrompt {
Messaging.sendErrorTr(sender, Messages.TEXT_EDITOR_INVALID_PAGE);
}
}
Messaging.send(sender, getPromptText(context));
if (input.equalsIgnoreCase("delay")) {
@ -100,9 +99,7 @@ public class TextBasePrompt extends StringPrompt {
}
} else {
Messaging.sendErrorTr(sender, Messages.TEXT_EDITOR_INVALID_EDIT_TYPE);
return this;
}
return this;
}
@ -117,7 +114,7 @@ public class TextBasePrompt extends StringPrompt {
colorToggleableText(text.isRandomTalker()), colorToggleableText(text.useSpeechBubbles()),
colorToggleableText(text.useRealisticLooking())));
int page = context.getSessionData("page") == null ? 1 : (int) context.getSessionData("page");
text.sendPage(((Player) context.getForWhom()), page);
text.sendPage((Player) context.getForWhom(), page);
return "";
}
}

View File

@ -38,7 +38,7 @@ public class AllayTrait extends Trait {
}
public void setDancing(boolean dance) {
this.dancing = dance;
dancing = dance;
}
@Command(
@ -61,8 +61,7 @@ public class AllayTrait extends Trait {
}
if (!output.isEmpty()) {
Messaging.send(sender, output.trim());
} else {
} else
throw new CommandUsageException();
}
}
}

View File

@ -71,10 +71,9 @@ public class AxolotlTrait extends Trait {
AxolotlTrait trait = npc.getOrAddTrait(AxolotlTrait.class);
String output = "";
if (args.hasValueFlag("variant")) {
if (variant == null) {
if (variant == null)
throw new CommandException(Messages.INVALID_AXOLOTL_VARIANT,
Util.listValuesPretty(Axolotl.Variant.values()));
}
trait.setVariant(variant);
output += ' ' + Messaging.tr(Messages.AXOLOTL_VARIANT_SET, args.getFlag("variant"));
}
@ -85,8 +84,7 @@ public class AxolotlTrait extends Trait {
}
if (!output.isEmpty()) {
Messaging.send(sender, output.trim());
} else {
} else
throw new CommandUsageException();
}
}
}

View File

@ -75,9 +75,8 @@ public class BeeTrait extends Trait {
BeeTrait trait = npc.getOrAddTrait(BeeTrait.class);
String output = "";
if (anger != null) {
if (anger < 0) {
if (anger < 0)
throw new CommandException(Messages.INVALID_BEE_ANGER);
}
trait.setAnger(anger);
output += ' ' + Messaging.tr(Messages.BEE_ANGER_SET, args.getFlag("anger"));
}
@ -93,8 +92,7 @@ public class BeeTrait extends Trait {
}
if (!output.isEmpty()) {
Messaging.send(sender, output.trim());
} else {
} else
throw new CommandUsageException();
}
}
}

View File

@ -69,7 +69,6 @@ public class BossBarTrait extends Trait {
barCache = Bukkit.getServer().createBossBar(npc.getFullName(), color, style,
flags.toArray(new BarFlag[flags.size()]));
}
return barCache;
}
@ -106,7 +105,6 @@ public class BossBarTrait extends Trait {
if (isBoss) {
onDespawn();
}
return isBoss;
}
@ -164,35 +162,30 @@ public class BossBarTrait extends Trait {
bar.setProgress(Math.max(0, Math.min(1, number)));
}
}
bar.setTitle(title);
bar.setVisible(visible);
if (progressProvider != null) {
bar.setProgress(progressProvider.get());
}
if (style != null) {
bar.setStyle(style);
}
if (color != null) {
bar.setColor(color);
}
for (BarFlag flag : BarFlag.values()) {
bar.removeFlag(flag);
}
for (BarFlag flag : flags) {
bar.addFlag(flag);
}
bar.removeAll();
for (Player player : CitizensAPI.getLocationLookup().getNearbyPlayers(npc.getEntity().getLocation(),
range > 0 ? range : Setting.BOSSBAR_RANGE.asInt())) {
if (viewPermission != null && !player.hasPermission(viewPermission))
if (viewPermission != null && !player.hasPermission(viewPermission)) {
continue;
}
bar.addPlayer(player);
}
}
@ -210,7 +203,7 @@ public class BossBarTrait extends Trait {
}
public void setProgressProvider(Supplier<Double> provider) {
this.progressProvider = provider;
progressProvider = provider;
}
public void setRange(int range) {
@ -226,11 +219,11 @@ public class BossBarTrait extends Trait {
}
public void setTrackVariable(String variable) {
this.track = variable;
track = variable;
}
public void setViewPermission(String viewpermission) {
this.viewPermission = viewpermission;
viewPermission = viewpermission;
}
public void setVisible(boolean visible) {
@ -253,31 +246,24 @@ public class BossBarTrait extends Trait {
if (style != null) {
trait.setStyle(style);
}
if (color != null) {
trait.setColor(color);
}
if (track != null) {
trait.setTrackVariable(track);
}
if (title != null) {
trait.setTitle(Messaging.parseComponents(title));
}
if (visible != null) {
trait.setVisible(visible);
}
if (range != null) {
trait.setRange(range);
}
if (viewpermission != null) {
trait.setViewPermission(viewpermission);
}
if (flags != null) {
List<BarFlag> parsed = Lists.newArrayList();
for (String s : Splitter.on(',').omitEmptyStrings().trimResults().split(flags)) {

View File

@ -64,7 +64,6 @@ public class CamelTrait extends Trait {
trait.setPose(pose);
output += Messaging.tr(Messages.CAMEL_POSE_SET, pose);
}
if (!output.isEmpty()) {
Messaging.send(sender, output);
}

View File

@ -54,7 +54,7 @@ public class CatTrait extends Trait {
}
public void setCollarColor(DyeColor color) {
this.collarColor = color;
collarColor = color;
}
public void setLyingDown(boolean lying) {
@ -74,21 +74,21 @@ public class CatTrait extends Trait {
public void setType(Type type2) {
if (type2 == null) {
this.type = Cat.Type.BLACK;
type = Cat.Type.BLACK;
return;
}
switch (type2) {
case WILD_OCELOT:
this.type = Cat.Type.CALICO;
type = Cat.Type.CALICO;
break;
case BLACK_CAT:
this.type = Cat.Type.BLACK;
type = Cat.Type.BLACK;
break;
case RED_CAT:
this.type = Cat.Type.RED;
type = Cat.Type.RED;
break;
case SIAMESE_CAT:
this.type = Cat.Type.SIAMESE;
type = Cat.Type.SIAMESE;
break;
}
}
@ -108,22 +108,18 @@ public class CatTrait extends Trait {
CatTrait trait = npc.getOrAddTrait(CatTrait.class);
String output = "";
if (args.hasValueFlag("type")) {
if (type == null) {
if (type == null)
throw new CommandUsageException(Messages.INVALID_CAT_TYPE, Util.listValuesPretty(Cat.Type.values()));
}
trait.setType(type);
output += ' ' + Messaging.tr(Messages.CAT_TYPE_SET, args.getFlag("type"));
}
if (args.hasValueFlag("ccolor")) {
if (ccolor == null) {
if (ccolor == null)
throw new CommandUsageException(Messages.INVALID_CAT_COLLAR_COLOR,
Util.listValuesPretty(DyeColor.values()));
}
trait.setCollarColor(ccolor);
output += ' ' + Messaging.tr(Messages.CAT_COLLAR_COLOR_SET, args.getFlag("ccolor"));
}
if (args.hasFlag('s')) {
trait.setSitting(true);
output += ' ' + Messaging.tr(Messages.CAT_STARTED_SITTING, npc.getName());
@ -131,17 +127,14 @@ public class CatTrait extends Trait {
trait.setSitting(false);
output += ' ' + Messaging.tr(Messages.CAT_STOPPED_SITTING, npc.getName());
}
if (args.hasFlag('l')) {
trait.setLyingDown(!trait.isLyingDown());
output += ' ' + Messaging.tr(trait.isLyingDown() ? Messages.CAT_STARTED_LYING : Messages.CAT_STOPPED_LYING,
npc.getName());
}
if (!output.isEmpty()) {
Messaging.send(sender, output.trim());
} else {
} else
throw new CommandUsageException();
}
}
}

View File

@ -92,10 +92,9 @@ public class FoxTrait extends Trait {
String output = "";
if (rawtype != null) {
Fox.Type type = Util.matchEnum(Fox.Type.values(), args.getFlag("type"));
if (type == null) {
if (type == null)
throw new CommandUsageException(
Messaging.tr(Messages.INVALID_FOX_TYPE, Util.listValuesPretty(Fox.Type.values())), null);
}
trait.setType(type);
output += ' ' + Messaging.tr(Messages.FOX_TYPE_SET, args.getFlag("type"), npc.getName());
}
@ -116,8 +115,7 @@ public class FoxTrait extends Trait {
}
if (!output.isEmpty()) {
Messaging.send(sender, output.trim());
} else {
} else
throw new CommandUsageException();
}
}
}

View File

@ -57,9 +57,8 @@ public class FrogTrait extends Trait {
FrogTrait trait = npc.getOrAddTrait(FrogTrait.class);
String output = "";
if (args.hasValueFlag("variant")) {
if (variant == null) {
if (variant == null)
throw new CommandException(Messages.INVALID_FROG_VARIANT, Util.listValuesPretty(Frog.Variant.values()));
}
trait.setVariant(variant);
output += Messaging.tr(Messages.FROG_VARIANT_SET, Util.prettyEnum(variant));
}

View File

@ -50,11 +50,11 @@ public class GoatTrait extends Trait {
}
public void setLeftHorn(boolean horn) {
this.leftHorn = horn;
leftHorn = horn;
}
public void setRightHorn(boolean horn) {
this.rightHorn = horn;
rightHorn = horn;
}
@Command(

View File

@ -81,12 +81,10 @@ public class LlamaTrait extends Trait {
trait.setColor(color);
output += Messaging.tr(Messages.LLAMA_COLOR_SET, Util.prettyEnum(color));
}
if (strength != null) {
trait.setStrength(Math.max(1, Math.min(5, strength)));
output += Messaging.tr(Messages.LLAMA_STRENGTH_SET, trait.getStrength());
}
if (args.hasFlag('c')) {
npc.getOrAddTrait(HorseModifiers.class).setCarryingChest(true);
output += Messaging.tr(Messages.HORSE_CHEST_SET) + " ";
@ -94,7 +92,6 @@ public class LlamaTrait extends Trait {
npc.getOrAddTrait(HorseModifiers.class).setCarryingChest(false);
output += Messaging.tr(Messages.HORSE_CHEST_UNSET) + " ";
}
if (!output.isEmpty()) {
Messaging.send(sender, output);
}

View File

@ -71,8 +71,7 @@ public class MushroomCowTrait extends Trait {
Messaging.sendTr(sender, Messages.MUSHROOM_COW_VARIANT_SET, npc.getName(), variant);
hasArg = true;
}
if (!hasArg) {
if (!hasArg)
throw new CommandUsageException();
}
}
}

View File

@ -88,11 +88,11 @@ public class PandaTrait extends Trait {
}
public void setHiddenGene(Panda.Gene gene) {
this.hiddenGene = gene;
hiddenGene = gene;
}
public void setMainGene(Panda.Gene gene) {
this.mainGene = gene;
mainGene = gene;
}
public void setRolling(boolean rolling) {
@ -138,18 +138,16 @@ public class PandaTrait extends Trait {
PandaTrait trait = npc.getOrAddTrait(PandaTrait.class);
String output = "";
if (args.hasValueFlag("gene")) {
if (gene == null) {
if (gene == null)
throw new CommandUsageException(Messages.INVALID_PANDA_GENE,
Util.listValuesPretty(Panda.Gene.values()));
}
trait.setMainGene(gene);
output += ' ' + Messaging.tr(Messages.PANDA_MAIN_GENE_SET, args.getFlag("gene"));
}
if (args.hasValueFlag("hiddengene")) {
if (hiddengene == null) {
if (hiddengene == null)
throw new CommandUsageException(Messages.INVALID_PANDA_GENE,
Util.listValuesPretty(Panda.Gene.values()));
}
trait.setHiddenGene(hiddengene);
output += ' ' + Messaging.tr(Messages.PANDA_HIDDEN_GENE_SET, hiddengene);
}
@ -175,9 +173,8 @@ public class PandaTrait extends Trait {
}
if (!output.isEmpty()) {
Messaging.send(sender, output.trim());
} else {
} else
throw new CommandUsageException();
}
}
private static boolean SUPPORT_ROLLING_SNEEZING = true;

View File

@ -57,9 +57,8 @@ public class ParrotTrait extends Trait {
ParrotTrait trait = npc.getOrAddTrait(ParrotTrait.class);
String output = "";
if (args.hasValueFlag("variant")) {
if (variant == null) {
if (variant == null)
throw new CommandException(Messages.INVALID_PARROT_VARIANT, Util.listValuesPretty(Variant.values()));
}
trait.setVariant(variant);
output += Messaging.tr(Messages.PARROT_VARIANT_SET, Util.prettyEnum(variant));
}

View File

@ -56,16 +56,14 @@ public class PhantomTrait extends Trait {
PhantomTrait trait = npc.getOrAddTrait(PhantomTrait.class);
String output = "";
if (size != null) {
if (size <= 0) {
if (size <= 0)
throw new CommandUsageException();
}
trait.setSize(size);
output += Messaging.tr(Messages.PHANTOM_STATE_SET, size);
}
if (!output.isEmpty()) {
Messaging.send(sender, output);
} else {
} else
throw new CommandUsageException();
}
}
}

View File

@ -61,9 +61,8 @@ public class PiglinTrait extends Trait {
npc.getName());
hasArg = true;
}
if (!hasArg) {
if (!hasArg)
throw new CommandUsageException();
}
}
}

View File

@ -62,8 +62,7 @@ public class PolarBearTrait extends Trait {
}
if (!output.isEmpty()) {
Messaging.send(sender, output);
} else {
} else
throw new CommandUsageException();
}
}
}

View File

@ -29,7 +29,7 @@ public class PufferFishTrait extends Trait {
}
public void setPuffState(int state) {
this.puffState = state;
puffState = state;
}
@Command(

View File

@ -95,8 +95,7 @@ public class ShulkerTrait extends Trait {
Messaging.sendTr(sender, Messages.SHULKER_COLOR_SET, npc.getName(), Util.prettyEnum(color));
hasArg = true;
}
if (!hasArg) {
if (!hasArg)
throw new CommandUsageException();
}
}
}

View File

@ -71,8 +71,7 @@ public class SnifferTrait extends Trait {
}
if (!output.isEmpty()) {
Messaging.send(sender, output.trim());
} else {
} else
throw new CommandUsageException();
}
}
}

View File

@ -41,7 +41,7 @@ public class SnowmanTrait extends Trait {
}
public boolean toggleDerp() {
return this.derp = !this.derp;
return derp = !derp;
}
@Command(
@ -62,8 +62,7 @@ public class SnowmanTrait extends Trait {
Messaging.sendTr(sender, isDerp ? Messages.SNOWMAN_DERP_SET : Messages.SNOWMAN_DERP_STOPPED, npc.getName());
hasArg = true;
}
if (!hasArg) {
if (!hasArg)
throw new CommandUsageException();
}
}
}

View File

@ -38,7 +38,6 @@ public class SpellcasterTrait extends Trait {
if (spell != null) {
((Spellcaster) npc.getEntity()).setSpell(spell);
}
}
public void setSpell(Spell spell) {
@ -65,8 +64,7 @@ public class SpellcasterTrait extends Trait {
}
if (!output.isEmpty()) {
Messaging.send(sender, output.trim());
} else {
} else
throw new CommandUsageException();
}
}
}

View File

@ -56,7 +56,7 @@ public class TropicalFishTrait extends Trait {
}
public void setBodyColor(DyeColor color) {
this.bodyColor = color;
bodyColor = color;
}
public void setPattern(Pattern pattern) {
@ -64,7 +64,7 @@ public class TropicalFishTrait extends Trait {
}
public void setPatternColor(DyeColor color) {
this.patternColor = color;
patternColor = color;
}
@Command(
@ -81,33 +81,29 @@ public class TropicalFishTrait extends Trait {
TropicalFishTrait trait = npc.getOrAddTrait(TropicalFishTrait.class);
String output = "";
if (args.hasValueFlag("body")) {
if (body == null) {
if (body == null)
throw new CommandException(Messages.INVALID_TROPICALFISH_COLOR,
Util.listValuesPretty(DyeColor.values()));
}
trait.setBodyColor(body);
output += Messaging.tr(Messages.TROPICALFISH_BODY_COLOR_SET, Util.prettyEnum(body));
}
if (args.hasValueFlag("patterncolor")) {
if (patterncolor == null) {
if (patterncolor == null)
throw new CommandException(Messages.INVALID_TROPICALFISH_COLOR,
Util.listValuesPretty(DyeColor.values()));
}
trait.setPatternColor(patterncolor);
output += Messaging.tr(Messages.TROPICALFISH_PATTERN_COLOR_SET, Util.prettyEnum(patterncolor));
}
if (args.hasValueFlag("pattern")) {
if (pattern == null) {
if (pattern == null)
throw new CommandException(Messages.INVALID_TROPICALFISH_PATTERN,
Util.listValuesPretty(Pattern.values()));
}
trait.setPattern(pattern);
output += Messaging.tr(Messages.TROPICALFISH_PATTERN_SET, Util.prettyEnum(pattern));
}
if (!output.isEmpty()) {
Messaging.send(sender, output);
} else {
} else
throw new CommandUsageException();
}
}
}

View File

@ -76,25 +76,22 @@ public class VillagerTrait extends Trait {
VillagerTrait trait = npc.getOrAddTrait(VillagerTrait.class);
String output = "";
if (level != null) {
if (level < 0) {
if (level < 0)
throw new CommandUsageException();
}
trait.setLevel(level);
output += " " + Messaging.tr(Messages.VILLAGER_LEVEL_SET, level);
}
if (args.hasValueFlag("type")) {
if (type == null) {
if (type == null)
throw new CommandException(Messages.INVALID_VILLAGER_TYPE,
Util.listValuesPretty(Villager.Type.values()));
}
trait.setType(type);
output += " " + Messaging.tr(Messages.VILLAGER_TYPE_SET, args.getFlag("type"));
}
if (args.hasValueFlag("profession")) {
if (profession == null) {
if (profession == null)
throw new CommandException(Messages.INVALID_PROFESSION, args.getFlag("profession"),
Joiner.on(',').join(Profession.values()));
}
npc.getOrAddTrait(VillagerProfession.class).setProfession(profession);
output += " " + Messaging.tr(Messages.PROFESSION_SET, npc.getName(), args.getFlag("profession"));
}
@ -103,8 +100,7 @@ public class VillagerTrait extends Trait {
}
if (!output.isEmpty()) {
Messaging.send(sender, output.trim());
} else {
} else
throw new CommandUsageException();
}
}
}

Some files were not shown because too many files have changed in this diff Show More