mirror of
https://github.com/CitizensDev/Citizens2.git
synced 2024-09-27 14:53:09 +02:00
Attempt to replace the entity tracker without sending packets for initial spawn. EXPERIMENTAL: needs testing. Also add /npc armorstand --headpose
This commit is contained in:
parent
4d1b3ee357
commit
19f08c4607
@ -106,6 +106,7 @@ import net.citizensnpcs.api.util.Messaging;
|
|||||||
import net.citizensnpcs.editor.Editor;
|
import net.citizensnpcs.editor.Editor;
|
||||||
import net.citizensnpcs.npc.ai.NPCHolder;
|
import net.citizensnpcs.npc.ai.NPCHolder;
|
||||||
import net.citizensnpcs.npc.skin.SkinUpdateTracker;
|
import net.citizensnpcs.npc.skin.SkinUpdateTracker;
|
||||||
|
import net.citizensnpcs.npc.skin.SkinnableEntity;
|
||||||
import net.citizensnpcs.trait.ClickRedirectTrait;
|
import net.citizensnpcs.trait.ClickRedirectTrait;
|
||||||
import net.citizensnpcs.trait.CommandTrait;
|
import net.citizensnpcs.trait.CommandTrait;
|
||||||
import net.citizensnpcs.trait.Controllable;
|
import net.citizensnpcs.trait.Controllable;
|
||||||
@ -462,6 +463,12 @@ public class EventListen implements Listener {
|
|||||||
@EventHandler(ignoreCancelled = true)
|
@EventHandler(ignoreCancelled = true)
|
||||||
public void onNPCLinkToPlayer(NPCLinkToPlayerEvent event) {
|
public void onNPCLinkToPlayer(NPCLinkToPlayerEvent event) {
|
||||||
NPC npc = event.getNPC();
|
NPC npc = event.getNPC();
|
||||||
|
if (npc.getEntity() instanceof SkinnableEntity) {
|
||||||
|
SkinnableEntity skinnable = (SkinnableEntity) npc.getEntity();
|
||||||
|
if (skinnable.getSkinTracker().getSkin() != null) {
|
||||||
|
skinnable.getSkinTracker().getSkin().apply(skinnable);
|
||||||
|
}
|
||||||
|
}
|
||||||
if (npc.isSpawned() && npc.getEntity().getType() == EntityType.PLAYER) {
|
if (npc.isSpawned() && npc.getEntity().getType() == EntityType.PLAYER) {
|
||||||
onNPCPlayerLinkToPlayer(event);
|
onNPCPlayerLinkToPlayer(event);
|
||||||
}
|
}
|
||||||
@ -483,7 +490,6 @@ public class EventListen implements Listener {
|
|||||||
|
|
||||||
NMS.sendPositionUpdateNearby(tracker, false, null, null, NMS.getHeadYaw(tracker));
|
NMS.sendPositionUpdateNearby(tracker, false, null, null, NMS.getHeadYaw(tracker));
|
||||||
}, Setting.TABLIST_REMOVE_PACKET_DELAY.asTicks() + 1);
|
}, Setting.TABLIST_REMOVE_PACKET_DELAY.asTicks() + 1);
|
||||||
|
|
||||||
boolean resetYaw = event.getNPC().data().get(NPC.Metadata.RESET_YAW_ON_SPAWN,
|
boolean resetYaw = event.getNPC().data().get(NPC.Metadata.RESET_YAW_ON_SPAWN,
|
||||||
Setting.RESET_YAW_ON_SPAWN.asBoolean());
|
Setting.RESET_YAW_ON_SPAWN.asBoolean());
|
||||||
boolean sendTabRemove = NMS.sendTabListAdd(event.getPlayer(), (Player) tracker);
|
boolean sendTabRemove = NMS.sendTabListAdd(event.getPlayer(), (Player) tracker);
|
||||||
|
@ -274,10 +274,10 @@ public class Settings {
|
|||||||
USE_SCOREBOARD_TEAMS("npc.scoreboard-teams.enable", true),
|
USE_SCOREBOARD_TEAMS("npc.scoreboard-teams.enable", true),
|
||||||
WARN_ON_RELOAD("general.reload-warning-enabled", true),;
|
WARN_ON_RELOAD("general.reload-warning-enabled", true),;
|
||||||
|
|
||||||
protected String comments;
|
private String comments;
|
||||||
private Duration duration;
|
private Duration duration;
|
||||||
protected String migrate;
|
private String migrate;
|
||||||
protected String path;
|
private final String path;
|
||||||
protected Object value;
|
protected Object value;
|
||||||
|
|
||||||
Setting(String path, Object value) {
|
Setting(String path, Object value) {
|
||||||
@ -347,14 +347,7 @@ public class Settings {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void loadFromKey(DataKey root) {
|
protected void loadFromKey(DataKey root) {
|
||||||
if (SUPPORTS_SET_COMMENTS && root.keyExists(path)) {
|
setComments(root);
|
||||||
try {
|
|
||||||
((YamlKey) root).getSection("").setComments(path,
|
|
||||||
comments == null ? null : Arrays.asList(comments.split("<br>")));
|
|
||||||
} catch (Throwable t) {
|
|
||||||
SUPPORTS_SET_COMMENTS = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (migrate != null && root.keyExists(migrate) && !root.keyExists(path)) {
|
if (migrate != null && root.keyExists(migrate) && !root.keyExists(path)) {
|
||||||
value = root.getRaw(migrate);
|
value = root.getRaw(migrate);
|
||||||
root.removeKey(migrate);
|
root.removeKey(migrate);
|
||||||
@ -365,6 +358,18 @@ public class Settings {
|
|||||||
|
|
||||||
protected void setAtKey(DataKey root) {
|
protected void setAtKey(DataKey root) {
|
||||||
root.setRaw(path, value);
|
root.setRaw(path, value);
|
||||||
|
setComments(root);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setComments(DataKey root) {
|
||||||
|
if (SUPPORTS_SET_COMMENTS && root.keyExists(path)) {
|
||||||
|
try {
|
||||||
|
((YamlKey) root).getSection("").setComments(path,
|
||||||
|
comments == null ? null : Arrays.asList(comments.split("<br>")));
|
||||||
|
} catch (Throwable t) {
|
||||||
|
SUPPORTS_SET_COMMENTS = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -339,7 +339,7 @@ public class NPCCommands {
|
|||||||
|
|
||||||
@Command(
|
@Command(
|
||||||
aliases = { "npc" },
|
aliases = { "npc" },
|
||||||
usage = "armorstand --visible [visible] --small [small] --marker [marker] --gravity [gravity] --arms [arms] --baseplate [baseplate] --(body|leftarm|leftleg|rightarm|rightleg)pose [angle x,y,z]",
|
usage = "armorstand --visible [visible] --small [small] --marker [marker] --gravity [gravity] --arms [arms] --baseplate [baseplate] --(head|body|leftarm|leftleg|rightarm|rightleg)pose [angle x,y,z]",
|
||||||
desc = "Edit armorstand properties",
|
desc = "Edit armorstand properties",
|
||||||
modifiers = { "armorstand" },
|
modifiers = { "armorstand" },
|
||||||
min = 1,
|
min = 1,
|
||||||
@ -370,6 +370,9 @@ public class NPCCommands {
|
|||||||
trait.setHasBaseplate(baseplate);
|
trait.setHasBaseplate(baseplate);
|
||||||
}
|
}
|
||||||
ArmorStand ent = (ArmorStand) npc.getEntity();
|
ArmorStand ent = (ArmorStand) npc.getEntity();
|
||||||
|
if (args.hasValueFlag("headpose")) {
|
||||||
|
ent.setHeadPose(args.parseEulerAngle(args.getFlag("headpose")));
|
||||||
|
}
|
||||||
if (args.hasValueFlag("bodypose")) {
|
if (args.hasValueFlag("bodypose")) {
|
||||||
ent.setBodyPose(args.parseEulerAngle(args.getFlag("bodypose")));
|
ent.setBodyPose(args.parseEulerAngle(args.getFlag("bodypose")));
|
||||||
}
|
}
|
||||||
|
@ -306,7 +306,20 @@ public class CitizensNPC extends AbstractNPC {
|
|||||||
entityController.create(at.clone(), this);
|
entityController.create(at.clone(), this);
|
||||||
getEntity().setMetadata("NPC", new FixedMetadataValue(CitizensAPI.getPlugin(), true));
|
getEntity().setMetadata("NPC", new FixedMetadataValue(CitizensAPI.getPlugin(), true));
|
||||||
getEntity().setMetadata("NPC-ID", new FixedMetadataValue(CitizensAPI.getPlugin(), getId()));
|
getEntity().setMetadata("NPC-ID", new FixedMetadataValue(CitizensAPI.getPlugin(), getId()));
|
||||||
|
// Spawning the entity will create an entity tracker that is not controlled by Citizens. This is fixed later in
|
||||||
|
// spawning; to avoid sending packets twice, try to hide the entity initially
|
||||||
|
if (SUPPORT_VISIBLE_BY_DEFAULT) {
|
||||||
|
try {
|
||||||
|
getEntity().setVisibleByDefault(false);
|
||||||
|
} catch (NoSuchMethodError err) {
|
||||||
|
SUPPORT_VISIBLE_BY_DEFAULT = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!SUPPORT_VISIBLE_BY_DEFAULT && getEntity().getType() == EntityType.PLAYER) {
|
||||||
|
for (Player player : Bukkit.getServer().getOnlinePlayers()) {
|
||||||
|
player.hidePlayer((Player) getEntity());
|
||||||
|
}
|
||||||
|
}
|
||||||
if (getEntity() instanceof SkinnableEntity && !hasTrait(SkinLayers.class)) {
|
if (getEntity() instanceof SkinnableEntity && !hasTrait(SkinLayers.class)) {
|
||||||
((SkinnableEntity) getEntity()).setSkinFlags(EnumSet.allOf(SkinLayers.Layer.class));
|
((SkinnableEntity) getEntity()).setSkinFlags(EnumSet.allOf(SkinLayers.Layer.class));
|
||||||
}
|
}
|
||||||
@ -331,15 +344,12 @@ public class CitizensNPC extends AbstractNPC {
|
|||||||
Bukkit.getPluginManager().callEvent(new NPCNeedsRespawnEvent(this, at));
|
Bukkit.getPluginManager().callEvent(new NPCNeedsRespawnEvent(this, at));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// send skin packets, if applicable, before other NMS packets are sent
|
|
||||||
SkinnableEntity skinnable = getEntity() instanceof SkinnableEntity ? (SkinnableEntity) getEntity() : null;
|
|
||||||
if (skinnable != null) {
|
|
||||||
skinnable.getSkinTracker().onSpawnNPC();
|
|
||||||
}
|
|
||||||
NMS.setLocationDirectly(getEntity(), at);
|
NMS.setLocationDirectly(getEntity(), at);
|
||||||
NMS.setHeadYaw(getEntity(), at.getYaw());
|
NMS.setHeadYaw(getEntity(), at.getYaw());
|
||||||
NMS.setBodyYaw(getEntity(), at.getYaw());
|
NMS.setBodyYaw(getEntity(), at.getYaw());
|
||||||
|
|
||||||
|
// Paper now doesn't actually set entities as valid for a few ticks while adding entities to chunks
|
||||||
|
// Need to check the entity is really valid for a few ticks before finalising spawning
|
||||||
Location to = at;
|
Location to = at;
|
||||||
Consumer<Runnable> postSpawn = new Consumer<Runnable>() {
|
Consumer<Runnable> postSpawn = new Consumer<Runnable>() {
|
||||||
private int timer;
|
private int timer;
|
||||||
@ -371,7 +381,6 @@ public class CitizensNPC extends AbstractNPC {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
navigator.onSpawn();
|
navigator.onSpawn();
|
||||||
|
|
||||||
for (Trait trait : Iterables.toArray(traits.values(), Trait.class)) {
|
for (Trait trait : Iterables.toArray(traits.values(), Trait.class)) {
|
||||||
try {
|
try {
|
||||||
trait.onSpawn();
|
trait.onSpawn();
|
||||||
@ -380,9 +389,16 @@ public class CitizensNPC extends AbstractNPC {
|
|||||||
ex.printStackTrace();
|
ex.printStackTrace();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
EntityType type = getEntity().getType();
|
// Replace the entity tracker and attempt to show the entity
|
||||||
NMS.replaceTracker(getEntity());
|
NMS.replaceTracker(getEntity());
|
||||||
|
if (SUPPORT_VISIBLE_BY_DEFAULT) {
|
||||||
|
getEntity().setVisibleByDefault(true);
|
||||||
|
} else if (getEntity().getType() == EntityType.PLAYER) {
|
||||||
|
for (Player player : Bukkit.getServer().getOnlinePlayers()) {
|
||||||
|
player.showPlayer((Player) getEntity());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EntityType type = getEntity().getType();
|
||||||
if (type.isAlive()) {
|
if (type.isAlive()) {
|
||||||
LivingEntity entity = (LivingEntity) getEntity();
|
LivingEntity entity = (LivingEntity) getEntity();
|
||||||
entity.setRemoveWhenFarAway(false);
|
entity.setRemoveWhenFarAway(false);
|
||||||
@ -617,4 +633,5 @@ public class CitizensNPC extends AbstractNPC {
|
|||||||
private static boolean SUPPORT_PICKUP_ITEMS = true;
|
private static boolean SUPPORT_PICKUP_ITEMS = true;
|
||||||
private static boolean SUPPORT_SILENT = true;
|
private static boolean SUPPORT_SILENT = true;
|
||||||
private static boolean SUPPORT_USE_ITEM = true;
|
private static boolean SUPPORT_USE_ITEM = true;
|
||||||
|
private static boolean SUPPORT_VISIBLE_BY_DEFAULT = true;
|
||||||
}
|
}
|
||||||
|
@ -99,9 +99,9 @@ public class Skin {
|
|||||||
&& !npc.getOrAddTrait(SkinTrait.class).fetchDefaultSkin())
|
&& !npc.getOrAddTrait(SkinTrait.class).fetchDefaultSkin())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (hasFetched)
|
if (hasFetched) {
|
||||||
return true;
|
return true;
|
||||||
else {
|
} else {
|
||||||
if (!fetching) {
|
if (!fetching) {
|
||||||
fetch();
|
fetch();
|
||||||
}
|
}
|
||||||
|
@ -191,7 +191,7 @@ public class SkinPacketTracker {
|
|||||||
inProgress.put(player.getUniqueId(), entry);
|
inProgress.put(player.getUniqueId(), entry);
|
||||||
skin.apply(entity);
|
skin.apply(entity);
|
||||||
if (NMS.sendTabListAdd(player, entity.getBukkitEntity())) {
|
if (NMS.sendTabListAdd(player, entity.getBukkitEntity())) {
|
||||||
scheduleRemovePacket(entry, 2);
|
scheduleRemovePacket(entry, Setting.TABLIST_REMOVE_PACKET_DELAY.asTicks());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -279,7 +279,7 @@ public class SkinUpdateTracker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Update a player with skin related packets from nearby skinnable NPC's.
|
* Update a player with skin related packets from nearby skinnable NPCs.
|
||||||
*
|
*
|
||||||
* @param player
|
* @param player
|
||||||
* The player to update.
|
* The player to update.
|
||||||
|
Loading…
Reference in New Issue
Block a user