Add /npc mirror for skins

This commit is contained in:
fullwall 2022-12-25 01:37:54 +08:00
parent 886d83eeb4
commit 27603afdf4
22 changed files with 217 additions and 45 deletions

View File

@ -43,6 +43,10 @@
<id>AlessioDP</id>
<url>https://repo.alessiodp.com/releases/</url>
</repository>
<repository>
<id>viaversion-repo</id>
<url>https://repo.viaversion.com</url>
</repository>
</repositories>
<dependencies>
<dependency>
@ -76,6 +80,12 @@
<version>4.7.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.viaversion</groupId>
<artifactId>viaversion-api</artifactId>
<version>4.5.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>ch.ethz.globis.phtree</groupId>
<artifactId>phtree</artifactId>

View File

@ -1,5 +1,6 @@
package net.citizensnpcs;
import java.util.Collection;
import java.util.List;
import java.util.Set;
@ -18,14 +19,20 @@ import com.comphenix.protocol.reflect.StructureModifier;
import com.comphenix.protocol.utility.MinecraftReflection;
import com.comphenix.protocol.wrappers.EnumWrappers;
import com.comphenix.protocol.wrappers.PlayerInfoData;
import com.google.common.collect.Lists;
import com.comphenix.protocol.wrappers.WrappedSignedProperty;
import com.google.common.collect.Iterables;
import com.mojang.authlib.GameProfile;
import com.mojang.authlib.properties.Property;
import com.viaversion.viaversion.api.Via;
import net.citizensnpcs.api.CitizensAPI;
import net.citizensnpcs.api.npc.NPC;
import net.citizensnpcs.api.util.Messaging;
import net.citizensnpcs.npc.ai.NPCHolder;
import net.citizensnpcs.trait.MirrorTrait;
import net.citizensnpcs.trait.RotationTrait;
import net.citizensnpcs.trait.RotationTrait.PacketRotationSession;
import net.citizensnpcs.util.NMS;
public class ProtocolLibListener {
private final Class<?> flagsClass;
@ -38,18 +45,51 @@ public class ProtocolLibListener {
flagsClass = MinecraftReflection.getMinecraftClass("EnumPlayerTeleportFlags",
"PacketPlayOutPosition$EnumPlayerTeleportFlags",
"network.protocol.game.PacketPlayOutPosition$EnumPlayerTeleportFlags");
try {
Via.getAPI();
} catch (Throwable t) {
VIA_ENABLED = false;
}
manager.addPacketListener(new PacketAdapter(plugin, ListenerPriority.MONITOR, Server.PLAYER_INFO) {
@Override
public void onPacketSending(PacketEvent event) {
List<PlayerInfoData> list = event.getPacket().getPlayerInfoDataLists().readSafely(0);
if (event.getPlayer().hasMetadata("NPC"))
return;
int version = VIA_ENABLED ? Via.getAPI().getPlayerVersion(event.getPlayer())
: manager.getProtocolVersion(event.getPlayer());
List<PlayerInfoData> list = event.getPacket().getPlayerInfoDataLists()
.readSafely(version < 761 ? 0 : 1);
if (list == null)
return;
for (PlayerInfoData data : Lists.newArrayList(list)) {
boolean changed = false;
for (int i = 0; i < list.size(); i++) {
PlayerInfoData data = list.get(i);
if (data == null)
continue;
NPC npc = CitizensAPI.getNPCRegistry().getByUniqueId(data.getProfile().getUUID());
if (npc == null)
if (data.getProfile().getUUID().version() != 2)
continue;
NPC npc = CitizensAPI.getNPCRegistry().getByUniqueIdGlobal(data.getProfile().getUUID());
if (npc == null || !npc.isSpawned())
continue;
MirrorTrait trait = npc.getTraitNullable(MirrorTrait.class);
if (trait == null || !trait.isMirroring(event.getPlayer()))
continue;
GameProfile profile = NMS.getProfile(event.getPlayer());
Collection<Property> textures = profile.getProperties().get("textures");
if (textures == null || textures.size() == 0)
continue;
data.getProfile().getProperties().clear();
for (String key : profile.getProperties().keySet()) {
data.getProfile().getProperties().putAll(key,
Iterables.transform(profile.getProperties().get(key),
skin -> new WrappedSignedProperty(skin.getName(), skin.getValue(),
skin.getSignature())));
}
changed = true;
}
if (changed) {
event.getPacket().getPlayerInfoDataLists().write(version < 761 ? 0 : 1, list);
}
}
});
@ -57,6 +97,9 @@ public class ProtocolLibListener {
new PacketAdapter(plugin, ListenerPriority.MONITOR, Server.ENTITY_HEAD_ROTATION, Server.ENTITY_LOOK) {
@Override
public void onPacketSending(PacketEvent event) {
if (event.getPlayer().hasMetadata("NPC"))
return;
NPC npc = getNPCFromPacket(event);
if (npc == null)
return;
@ -131,4 +174,5 @@ public class ProtocolLibListener {
}
private static boolean LOGGED_ERROR = false;
private static boolean VIA_ENABLED = true;
}

View File

@ -117,6 +117,7 @@ import net.citizensnpcs.trait.HologramTrait;
import net.citizensnpcs.trait.HologramTrait.HologramDirection;
import net.citizensnpcs.trait.HorseModifiers;
import net.citizensnpcs.trait.LookClose;
import net.citizensnpcs.trait.MirrorTrait;
import net.citizensnpcs.trait.MountTrait;
import net.citizensnpcs.trait.OcelotModifiers;
import net.citizensnpcs.trait.Poses;
@ -1512,6 +1513,22 @@ public class NPCCommands {
npc.data().get(NPC.MINECART_ITEM_DATA_METADATA, 0), npc.data().get(NPC.MINECART_OFFSET_METADATA, 0));
}
@Command(
aliases = { "npc" },
modifiers = { "mirror" },
usage = "mirror",
desc = "Controls mirroring of NPC skins and more",
min = 1,
max = 1,
permission = "citizens.npc.mirror")
@Requirements(selected = true, ownership = true)
public void mirror(CommandContext args, CommandSender sender, NPC npc) {
MirrorTrait trait = npc.getOrAddTrait(MirrorTrait.class);
boolean enabled = !trait.isEnabled();
trait.setEnabled(enabled);
Messaging.sendTr(sender, enabled ? Messages.MIRROR_SET : Messages.MIRROR_UNSET, npc.getName());
}
@Command(
aliases = { "npc" },
usage = "mount (--onnpc <npc id>) (-c (ancel))",

View File

@ -2,7 +2,6 @@ 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;
@ -55,7 +54,7 @@ public class CitizensNPCRegistry implements NPCRegistry {
@Override
public NPC createNPC(EntityType type, String name) {
return createNPC(type, UUID.randomUUID(), generateUniqueId(), name);
return createNPC(type, UUID.randomUUID(), generateIntegerId(), name);
}
@Override
@ -142,7 +141,7 @@ public class CitizensNPCRegistry implements NPCRegistry {
}
}
private int generateUniqueId() {
private int generateIntegerId() {
return saves.createUniqueNPCId(this);
}
@ -155,22 +154,35 @@ public class CitizensNPCRegistry implements NPCRegistry {
@Override
public NPC getByUniqueId(UUID uuid) {
if (uuid.version() == 2) {
long msb = uuid.getMostSignificantBits();
msb &= ~0x0000000000002000L;
msb |= 0x0000000000004000L;
uuid = new UUID(msb, uuid.getLeastSignificantBits());
}
return uniqueNPCs.get(uuid);
}
@Override
public NPC getByUniqueIdGlobal(UUID uuid) {
if (uuid.version() == 2) {
long msb = uuid.getMostSignificantBits();
msb &= ~0x0000000000002000L;
msb |= 0x0000000000004000L;
uuid = new UUID(msb, uuid.getLeastSignificantBits());
}
NPC npc = getByUniqueId(uuid);
if (npc != null)
return npc;
for (NPCRegistry registry : CitizensAPI.getNPCRegistries()) {
if (registry != this) {
NPC other = registry.getByUniqueId(uuid);
if (other != null) {
return other;
}
if (registry == this)
continue;
NPC other = registry.getByUniqueId(uuid);
if (other != null) {
return other;
}
}
return null;
}
@ -233,14 +245,7 @@ public class CitizensNPCRegistry implements NPCRegistry {
@Override
public Iterable<NPC> sorted() {
List<NPC> vals = new ArrayList<NPC>(npcs.valueCollection());
Collections.sort(vals, NPC_COMPARATOR);
Collections.sort(vals, (a, b) -> Integer.compare(a.getId(), b.getId()));
return vals;
}
private static final Comparator<NPC> NPC_COMPARATOR = new Comparator<NPC>() {
@Override
public int compare(NPC o1, NPC o2) {
return o1.getId() - o2.getId();
}
};
}

View File

@ -34,6 +34,7 @@ import net.citizensnpcs.trait.Gravity;
import net.citizensnpcs.trait.HologramTrait;
import net.citizensnpcs.trait.HorseModifiers;
import net.citizensnpcs.trait.LookClose;
import net.citizensnpcs.trait.MirrorTrait;
import net.citizensnpcs.trait.MountTrait;
import net.citizensnpcs.trait.OcelotModifiers;
import net.citizensnpcs.trait.Poses;
@ -80,6 +81,7 @@ public class CitizensTraitFactory implements TraitFactory {
registerTrait(TraitInfo.create(HologramTrait.class));
registerTrait(TraitInfo.create(Inventory.class));
registerTrait(TraitInfo.create(LookClose.class));
registerTrait(TraitInfo.create(MirrorTrait.class));
registerTrait(TraitInfo.create(MountTrait.class));
registerTrait(TraitInfo.create(MobType.class).asDefaultTrait());
registerTrait(TraitInfo.create(OcelotModifiers.class));

View File

@ -0,0 +1,35 @@
package net.citizensnpcs.trait;
import org.bukkit.entity.Player;
import net.citizensnpcs.api.event.DespawnReason;
import net.citizensnpcs.api.event.SpawnReason;
import net.citizensnpcs.api.persistence.Persist;
import net.citizensnpcs.api.trait.Trait;
import net.citizensnpcs.api.trait.TraitName;
@TraitName("mirrortrait")
public class MirrorTrait extends Trait {
@Persist
private boolean enabled;
public MirrorTrait() {
super("mirrortrait");
}
public boolean isEnabled() {
return enabled;
}
public boolean isMirroring(Player player) {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
if (npc.isSpawned()) {
npc.despawn(DespawnReason.PENDING_RESPAWN);
npc.spawn(npc.getStoredLocation(), SpawnReason.RESPAWN);
}
}
}

View File

@ -230,6 +230,8 @@ public class Messages {
public static final String METRICS_ERROR_NOTIFICATION = "citizens.notifications.metrics-load-error";
public static final String MINECART_SET = "citizens.commands.npc.minecart.set";
public static final String MINIMUM_COST_REQUIRED = "citizens.economy.minimum-cost-required";
public static final String MIRROR_SET = "citizens.commands.npc.mirror.set";
public static final String MIRROR_UNSET = "citizens.commands.npc.mirror.unset";
public static final String MISSING_TP_CURSOR_BLOCK = "citizens.commands.npc.tphere.missing-cursor-block";
public static final String MISSING_TRANSLATIONS = "citizens.notifications.missing-translations";
public static final String MOBTYPE_CANNOT_BE_AGED = "citizens.commands.npc.age.cannot-be-aged";

View File

@ -346,6 +346,10 @@ public class NMS {
return BRIDGE.getPassengers(entity);
}
public static GameProfile getProfile(Player player) {
return BRIDGE.getProfile(player);
}
public static GameProfile getProfile(SkullMeta meta) {
return BRIDGE.getProfile(meta);
}

View File

@ -79,6 +79,8 @@ public interface NMSBridge {
public List<Entity> getPassengers(Entity entity);
public GameProfile getProfile(Player player);
public GameProfile getProfile(SkullMeta meta);
public String getSound(String flag) throws CommandException;
@ -145,11 +147,11 @@ public interface NMSBridge {
public boolean sendTabListAdd(Player recipient, Player listPlayer);
public void sendTabListRemove(Player recipient, Collection<? extends SkinnableEntity> skinnableNPCs);
public void sendTabListRemove(Player recipient, Collection<? extends SkinnableEntity> skinnableNPCs);;
public void sendTabListRemove(Player recipient, Player listPlayer);
public void sendTeamPacket(Player recipient, Team team, int mode);;
public void sendTeamPacket(Player recipient, Team team, int mode);
public default void setAllayDancing(Entity entity, boolean dancing) {
throw new UnsupportedOperationException();
@ -165,23 +167,23 @@ public interface NMSBridge {
public void setDestination(Entity entity, double x, double y, double z, float speed);
public void setEndermanAngry(Enderman enderman, boolean angry);
public void setEndermanAngry(Enderman enderman, boolean angry);;
public void setHeadYaw(Entity entity, float yaw);
public void setKnockbackResistance(LivingEntity entity, double d);;
public void setKnockbackResistance(LivingEntity entity, double d);
public default void setLyingDown(Entity cat, boolean lying) {
throw new UnsupportedOperationException();
}
};
public void setNavigationTarget(Entity handle, Entity target, float speed);
public void setNavigationTarget(Entity handle, Entity target, float speed);;
public void setNoGravity(Entity entity, boolean nogravity);;
public default void setPandaSitting(Entity entity, boolean sitting) {
throw new UnsupportedOperationException();
};
}
public default void setPeekShulker(Entity entity, int peek) {
throw new UnsupportedOperationException();
@ -191,7 +193,7 @@ public interface NMSBridge {
throw new UnsupportedOperationException();
}
public void setPitch(Entity entity, float pitch);;
public void setPitch(Entity entity, float pitch);
public default void setPolarBearRearing(Entity entity, boolean rearing) {
throw new UnsupportedOperationException();

View File

@ -161,6 +161,8 @@ citizens.commands.npc.lookclose.stopped=[[{0}]] will no longer rotate when playe
citizens.commands.npc.metadata.set=[[{0}]] set to [[{1}]].
citizens.commands.npc.metadata.unset=Removed [[{0}]] from [[{1}]].
citizens.commands.npc.minecart.set=[[{0}]] now has item [[{1}]]:[[{2}]] with offset [[{3}]].
citizens.commands.npc.mirror.set=[[{0}]] is now mirroring player skins.
citizens.commands.npc.mirror.unset=[[{0}]] is no longer mirroring player skins.
citizens.commands.npc.mount.failed=Couldn''t mount [[{0}]].
citizens.commands.npc.mount.must-be-spawned=Couldn''t mount [[{0}]]. Make sure that the destination NPC ID is correct and it is spawned.
citizens.commands.npc.moveto.format=Format is x:y:z(:world) or x y z( world).

View File

@ -458,6 +458,11 @@ public class NMSImpl implements NMSBridge {
});
}
@Override
public GameProfile getProfile(Player player) {
return ((EntityHuman) getHandle(player)).getProfile();
}
@Override
public GameProfile getProfile(SkullMeta meta) {
if (SKULL_PROFILE_FIELD == null) {
@ -1207,7 +1212,7 @@ public class NMSImpl implements NMSBridge {
List<Player> nearbyPlayers = Lists.newArrayList(Iterables
.filter(CitizensAPI.getLocationLookup().getNearbyPlayers(entity.getLocation(), 64), (p) -> {
Long time = meta.getMarker(p.getUniqueId(), entity.getUniqueId().toString());
return time == null || Math.abs(entity.getWorld().getFullTime() - time) > 100;
return time == null || Math.abs(System.currentTimeMillis() - time) > 5000;
}));
if (nearbyPlayers.size() == 0)
return;
@ -1242,7 +1247,7 @@ public class NMSImpl implements NMSBridge {
for (Player nearby : nearbyPlayers) {
nearby.sendBlockChange(bedLoc, Material.BED_BLOCK, facingByte);
list.forEach((packet) -> sendPacket(nearby, packet));
meta.set(nearby.getUniqueId(), entity.getUniqueId().toString(), nearby.getWorld().getFullTime());
meta.set(nearby.getUniqueId(), entity.getUniqueId().toString(), System.currentTimeMillis());
}
} else {
PacketPlayOutAnimation packet = new PacketPlayOutAnimation(from, 2);

View File

@ -479,6 +479,11 @@ public class NMSImpl implements NMSBridge {
});
}
@Override
public GameProfile getProfile(Player player) {
return ((EntityHuman) getHandle(player)).getProfile();
}
@Override
public GameProfile getProfile(SkullMeta meta) {
if (SKULL_PROFILE_FIELD == null) {
@ -1274,7 +1279,7 @@ public class NMSImpl implements NMSBridge {
List<Player> nearbyPlayers = Lists.newArrayList(Iterables
.filter(CitizensAPI.getLocationLookup().getNearbyPlayers(entity.getLocation(), 64), (p) -> {
Long time = meta.getMarker(p.getUniqueId(), entity.getUniqueId().toString());
return time == null || Math.abs(entity.getWorld().getFullTime() - time) > 100;
return time == null || Math.abs(System.currentTimeMillis() - time) > 5000;
}));
if (nearbyPlayers.size() == 0)
return;
@ -1309,7 +1314,7 @@ public class NMSImpl implements NMSBridge {
for (Player nearby : nearbyPlayers) {
nearby.sendBlockChange(bedLoc, Material.BED_BLOCK, facingByte);
list.forEach((packet) -> sendPacket(nearby, packet));
meta.set(nearby.getUniqueId(), entity.getUniqueId().toString(), nearby.getWorld().getFullTime());
meta.set(nearby.getUniqueId(), entity.getUniqueId().toString(), System.currentTimeMillis());
}
} else {
PacketPlayOutAnimation packet = new PacketPlayOutAnimation(from, 2);

View File

@ -483,6 +483,11 @@ public class NMSImpl implements NMSBridge {
});
}
@Override
public GameProfile getProfile(Player player) {
return ((EntityHuman) getHandle(player)).getProfile();
}
@Override
public GameProfile getProfile(SkullMeta meta) {
if (SKULL_PROFILE_FIELD == null) {
@ -1284,7 +1289,7 @@ public class NMSImpl implements NMSBridge {
List<Player> nearbyPlayers = Lists.newArrayList(Iterables
.filter(CitizensAPI.getLocationLookup().getNearbyPlayers(entity.getLocation(), 64), (p) -> {
Long time = meta.getMarker(p.getUniqueId(), entity.getUniqueId().toString());
return time == null || Math.abs(entity.getWorld().getFullTime() - time) > 100;
return time == null || Math.abs(System.currentTimeMillis() - time) > 5000;
}));
if (nearbyPlayers.size() == 0)
return;
@ -1319,7 +1324,7 @@ public class NMSImpl implements NMSBridge {
for (Player nearby : nearbyPlayers) {
nearby.sendBlockChange(bedLoc, Material.BED_BLOCK, facingByte);
list.forEach((packet) -> sendPacket(nearby, packet));
meta.set(nearby.getUniqueId(), entity.getUniqueId().toString(), nearby.getWorld().getFullTime());
meta.set(nearby.getUniqueId(), entity.getUniqueId().toString(), System.currentTimeMillis());
}
} else {
PacketPlayOutAnimation packet = new PacketPlayOutAnimation(from, 2);

View File

@ -506,6 +506,11 @@ public class NMSImpl implements NMSBridge {
});
}
@Override
public GameProfile getProfile(Player player) {
return ((EntityHuman) getHandle(player)).getProfile();
}
@Override
public GameProfile getProfile(SkullMeta meta) {
if (SKULL_PROFILE_FIELD == null) {
@ -1324,7 +1329,7 @@ public class NMSImpl implements NMSBridge {
List<Player> nearbyPlayers = Lists.newArrayList(Iterables
.filter(CitizensAPI.getLocationLookup().getNearbyPlayers(entity.getLocation(), 64), (p) -> {
Long time = meta.getMarker(p.getUniqueId(), entity.getUniqueId().toString());
return time == null || Math.abs(entity.getWorld().getFullTime() - time) > 100;
return time == null || Math.abs(System.currentTimeMillis() - time) > 5000;
}));
if (nearbyPlayers.size() == 0)
return;
@ -1359,7 +1364,7 @@ public class NMSImpl implements NMSBridge {
for (Player nearby : nearbyPlayers) {
nearby.sendBlockChange(bedLoc, Material.BLACK_BED, facingByte);
list.forEach((packet) -> sendPacket(nearby, packet));
meta.set(nearby.getUniqueId(), entity.getUniqueId().toString(), nearby.getWorld().getFullTime());
meta.set(nearby.getUniqueId(), entity.getUniqueId().toString(), System.currentTimeMillis());
}
} else {
PacketPlayOutAnimation packet = new PacketPlayOutAnimation(from, 2);

View File

@ -544,6 +544,11 @@ public class NMSImpl implements NMSBridge {
});
}
@Override
public GameProfile getProfile(Player player) {
return ((EntityHuman) getHandle(player)).getProfile();
}
@Override
public GameProfile getProfile(SkullMeta meta) {
if (SKULL_PROFILE_FIELD == null) {

View File

@ -559,6 +559,11 @@ public class NMSImpl implements NMSBridge {
});
}
@Override
public GameProfile getProfile(Player player) {
return ((EntityHuman) getHandle(player)).getProfile();
}
@Override
public GameProfile getProfile(SkullMeta meta) {
if (SKULL_PROFILE_FIELD == null) {

View File

@ -568,6 +568,11 @@ public class NMSImpl implements NMSBridge {
});
}
@Override
public GameProfile getProfile(Player player) {
return ((EntityHuman) getHandle(player)).getProfile();
}
@Override
public GameProfile getProfile(SkullMeta meta) {
if (SKULL_PROFILE_FIELD == null) {

View File

@ -582,6 +582,11 @@ public class NMSImpl implements NMSBridge {
});
}
@Override
public GameProfile getProfile(Player player) {
return ((net.minecraft.world.entity.player.Player) getHandle(player)).getGameProfile();
}
@Override
public GameProfile getProfile(SkullMeta meta) {
if (SKULL_PROFILE_FIELD == null) {

View File

@ -587,6 +587,11 @@ public class NMSImpl implements NMSBridge {
});
}
@Override
public GameProfile getProfile(Player player) {
return ((net.minecraft.world.entity.player.Player) getHandle(player)).getGameProfile();
}
@Override
public GameProfile getProfile(SkullMeta meta) {
if (SKULL_PROFILE_FIELD == null) {

View File

@ -6,21 +6,17 @@
<artifactId>citizens-parent</artifactId>
<version>2.0.30-SNAPSHOT</version>
</parent>
<artifactId>citizens-v1_19_R2</artifactId>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<craftbukkit.version>1.19.3-R0.1-SNAPSHOT</craftbukkit.version>
</properties>
<repositories>
<repository>
<id>viaversion-repo</id>
<url>https://repo.viaversion.com</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>${project.groupId}</groupId>
@ -42,7 +38,6 @@
<scope>provided</scope>
</dependency>
</dependencies>
<build>
<defaultGoal>clean package install</defaultGoal>
<sourceDirectory>${basedir}/src/main/java</sourceDirectory>

View File

@ -606,6 +606,11 @@ public class NMSImpl implements NMSBridge {
});
}
@Override
public GameProfile getProfile(Player player) {
return ((net.minecraft.world.entity.player.Player) getHandle(player)).getGameProfile();
}
@Override
public GameProfile getProfile(SkullMeta meta) {
if (SKULL_PROFILE_FIELD == null) {
@ -1255,7 +1260,6 @@ public class NMSImpl implements NMSBridge {
if (VIA_ENABLED == false)
return false;
@SuppressWarnings("unchecked")
int version = Via.getAPI().getPlayerVersion(recipient);
return version < 761;
}

View File

@ -412,6 +412,11 @@ public class NMSImpl implements NMSBridge {
return Lists.<org.bukkit.entity.Entity> newArrayList(passenger.getBukkitEntity());
}
@Override
public GameProfile getProfile(Player player) {
return ((EntityHuman) getHandle(player)).getProfile();
}
@Override
public GameProfile getProfile(SkullMeta meta) {
if (SKULL_PROFILE_FIELD == null) {
@ -1144,7 +1149,7 @@ public class NMSImpl implements NMSBridge {
List<Player> nearbyPlayers = Lists.newArrayList(Iterables
.filter(CitizensAPI.getLocationLookup().getNearbyPlayers(entity.getLocation(), 64), (p) -> {
Long time = meta.getMarker(p.getUniqueId(), entity.getUniqueId().toString());
return time == null || Math.abs(entity.getWorld().getFullTime() - time) > 100;
return time == null || Math.abs(System.currentTimeMillis() - time) > 5000;
}));
if (nearbyPlayers.size() == 0)
return;
@ -1179,7 +1184,7 @@ public class NMSImpl implements NMSBridge {
for (Player nearby : nearbyPlayers) {
nearby.sendBlockChange(bedLoc, Material.BED_BLOCK, facingByte);
list.forEach((packet) -> sendPacket(nearby, packet));
meta.set(nearby.getUniqueId(), entity.getUniqueId().toString(), nearby.getWorld().getFullTime());
meta.set(nearby.getUniqueId(), entity.getUniqueId().toString(), System.currentTimeMillis());
}
} else {
PacketPlayOutAnimation packet = new PacketPlayOutAnimation(from, 2);