diff --git a/src/main/java/fr/openmc/core/features/dream/DreamManager.java b/src/main/java/fr/openmc/core/features/dream/DreamManager.java index f664c90e7..a4982d16d 100644 --- a/src/main/java/fr/openmc/core/features/dream/DreamManager.java +++ b/src/main/java/fr/openmc/core/features/dream/DreamManager.java @@ -29,7 +29,8 @@ import fr.openmc.core.features.dream.mecanism.cold.ColdManager; import fr.openmc.core.features.dream.mecanism.metaldetector.MetalDetectorManager; import fr.openmc.core.features.dream.mecanism.rng.DreamLootListener; -import fr.openmc.core.features.dream.mecanism.sfx.PlayerCloneNpc; +import fr.openmc.core.features.dream.mecanism.sfx.clone.PlayerCloneNpc; +import fr.openmc.core.features.dream.mecanism.sfx.ghost.DreamGhostManager; import fr.openmc.core.features.dream.mecanism.singularity.SingularityCraftListener; import fr.openmc.core.features.dream.mecanism.singularity.SingularityManager; import fr.openmc.core.features.dream.mecanism.tradernpc.GlaciteNpcManager; @@ -83,6 +84,7 @@ public void init() { MetalDetectorManager.init(); ColdManager.init(); SingularityManager.init(); + DreamGhostManager.init(); // ** LOAD DATAS ** loadAllDreamPlayerData(); @@ -120,7 +122,8 @@ public Set getListeners() { new SingularityCraftListener(), new PlayerDreamStructureListener(), new PlayerFoodChangeListener(), - new DreamLootListener() + new DreamLootListener(), + new PlayerPickupListener() ); } diff --git a/src/main/java/fr/openmc/core/features/dream/listeners/dream/PlayerChangeWorldListener.java b/src/main/java/fr/openmc/core/features/dream/listeners/dream/PlayerChangeWorldListener.java index bb85a6d0c..947755669 100644 --- a/src/main/java/fr/openmc/core/features/dream/listeners/dream/PlayerChangeWorldListener.java +++ b/src/main/java/fr/openmc/core/features/dream/listeners/dream/PlayerChangeWorldListener.java @@ -4,7 +4,7 @@ import fr.openmc.core.features.dream.DreamManager; import fr.openmc.core.features.dream.DreamUtils; import fr.openmc.core.features.dream.events.DreamEnterEvent; -import fr.openmc.core.features.dream.mecanism.sfx.PlayerCloneNpc; +import fr.openmc.core.features.dream.mecanism.sfx.clone.PlayerCloneNpc; import fr.openmc.core.features.dream.models.db.DreamPlayer; import fr.openmc.core.utils.bukkit.ParticleUtils; import org.bukkit.Bukkit; diff --git a/src/main/java/fr/openmc/core/features/dream/listeners/dream/PlayerDreamTimeEndListener.java b/src/main/java/fr/openmc/core/features/dream/listeners/dream/PlayerDreamTimeEndListener.java index d0566b044..435e77b7c 100644 --- a/src/main/java/fr/openmc/core/features/dream/listeners/dream/PlayerDreamTimeEndListener.java +++ b/src/main/java/fr/openmc/core/features/dream/listeners/dream/PlayerDreamTimeEndListener.java @@ -2,7 +2,7 @@ import fr.openmc.core.features.dream.DreamManager; import fr.openmc.core.features.dream.events.DreamEndEvent; -import fr.openmc.core.features.dream.mecanism.sfx.PlayerCloneNpc; +import fr.openmc.core.features.dream.mecanism.sfx.clone.PlayerCloneNpc; import fr.openmc.core.features.dream.models.db.DreamPlayer; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; diff --git a/src/main/java/fr/openmc/core/features/dream/listeners/dream/PlayerPickupListener.java b/src/main/java/fr/openmc/core/features/dream/listeners/dream/PlayerPickupListener.java new file mode 100644 index 000000000..4511ce33a --- /dev/null +++ b/src/main/java/fr/openmc/core/features/dream/listeners/dream/PlayerPickupListener.java @@ -0,0 +1,27 @@ +package fr.openmc.core.features.dream.listeners.dream; + +import fr.openmc.core.features.dream.DreamUtils; +import org.bukkit.entity.Item; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityPickupItemEvent; + +import java.util.UUID; + +public class PlayerPickupListener implements Listener { + + @EventHandler + public void onPickup(EntityPickupItemEvent event) { + if (!(event.getEntity() instanceof Player player)) return; + if (!DreamUtils.isInDreamWorld(player)) return; + + Item item = event.getItem(); + + UUID thrower = item.getThrower(); + + if (thrower != null && !thrower.equals(player.getUniqueId())) { + event.setCancelled(true); + } + } +} diff --git a/src/main/java/fr/openmc/core/features/dream/listeners/dream/PlayerQuitListener.java b/src/main/java/fr/openmc/core/features/dream/listeners/dream/PlayerQuitListener.java index 518f94866..e8cea779e 100644 --- a/src/main/java/fr/openmc/core/features/dream/listeners/dream/PlayerQuitListener.java +++ b/src/main/java/fr/openmc/core/features/dream/listeners/dream/PlayerQuitListener.java @@ -2,7 +2,7 @@ import fr.openmc.core.features.dream.DreamManager; import fr.openmc.core.features.dream.DreamUtils; -import fr.openmc.core.features.dream.mecanism.sfx.PlayerCloneNpc; +import fr.openmc.core.features.dream.mecanism.sfx.clone.PlayerCloneNpc; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; diff --git a/src/main/java/fr/openmc/core/features/dream/listeners/dream/PlayerSleepListener.java b/src/main/java/fr/openmc/core/features/dream/listeners/dream/PlayerSleepListener.java index b039aab15..46cb7045b 100644 --- a/src/main/java/fr/openmc/core/features/dream/listeners/dream/PlayerSleepListener.java +++ b/src/main/java/fr/openmc/core/features/dream/listeners/dream/PlayerSleepListener.java @@ -2,7 +2,7 @@ import fr.openmc.core.OMCPlugin; import fr.openmc.core.features.dream.DreamManager; -import fr.openmc.core.features.dream.mecanism.sfx.PlayerCloneNpc; +import fr.openmc.core.features.dream.mecanism.sfx.clone.PlayerCloneNpc; import fr.openmc.core.features.dream.models.db.DBDreamPlayer; import org.bukkit.entity.Player; import org.bukkit.entity.Pose; diff --git a/src/main/java/fr/openmc/core/features/dream/mecanism/sfx/CloneParticlesTask.java b/src/main/java/fr/openmc/core/features/dream/mecanism/sfx/clone/CloneParticlesTask.java similarity index 88% rename from src/main/java/fr/openmc/core/features/dream/mecanism/sfx/CloneParticlesTask.java rename to src/main/java/fr/openmc/core/features/dream/mecanism/sfx/clone/CloneParticlesTask.java index b29ff5245..79351f842 100644 --- a/src/main/java/fr/openmc/core/features/dream/mecanism/sfx/CloneParticlesTask.java +++ b/src/main/java/fr/openmc/core/features/dream/mecanism/sfx/clone/CloneParticlesTask.java @@ -1,4 +1,4 @@ -package fr.openmc.core.features.dream.mecanism.sfx; +package fr.openmc.core.features.dream.mecanism.sfx.clone; import fr.openmc.core.utils.bukkit.ParticleUtils; import org.bukkit.Location; diff --git a/src/main/java/fr/openmc/core/features/dream/mecanism/sfx/PlayerCloneNpc.java b/src/main/java/fr/openmc/core/features/dream/mecanism/sfx/clone/PlayerCloneNpc.java similarity index 99% rename from src/main/java/fr/openmc/core/features/dream/mecanism/sfx/PlayerCloneNpc.java rename to src/main/java/fr/openmc/core/features/dream/mecanism/sfx/clone/PlayerCloneNpc.java index efb50f8e0..67e1872c1 100644 --- a/src/main/java/fr/openmc/core/features/dream/mecanism/sfx/PlayerCloneNpc.java +++ b/src/main/java/fr/openmc/core/features/dream/mecanism/sfx/clone/PlayerCloneNpc.java @@ -1,4 +1,4 @@ -package fr.openmc.core.features.dream.mecanism.sfx; +package fr.openmc.core.features.dream.mecanism.sfx.clone; import de.oliver.fancynpcs.api.FancyNpcsPlugin; import de.oliver.fancynpcs.api.Npc; diff --git a/src/main/java/fr/openmc/core/features/dream/mecanism/sfx/ghost/DreamGhostManager.java b/src/main/java/fr/openmc/core/features/dream/mecanism/sfx/ghost/DreamGhostManager.java new file mode 100644 index 000000000..bff143dce --- /dev/null +++ b/src/main/java/fr/openmc/core/features/dream/mecanism/sfx/ghost/DreamGhostManager.java @@ -0,0 +1,127 @@ +package fr.openmc.core.features.dream.mecanism.sfx.ghost; + +import fr.openmc.core.OMCPlugin; +import fr.openmc.core.features.dream.DreamDimensionManager; +import fr.openmc.core.features.dream.DreamUtils; +import fr.openmc.core.features.dream.mecanism.sfx.ghost.listeners.DreamPlayerEnteredListener; +import fr.openmc.core.utils.bukkit.ParticleUtils; +import fr.openmc.core.utils.nms.SkullNMS; +import fr.openmc.core.utils.nms.entity.*; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.entity.ai.attributes.AttributeInstance; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.entity.decoration.ArmorStand; +import org.bukkit.GameMode; +import org.bukkit.Location; +import org.bukkit.Particle; +import org.bukkit.World; +import org.bukkit.entity.Player; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +/** + * Gestion des intéractions joueurs dans les reves. + * + * Cache tous les joueurs + met juste leur tete d'affiché avec particule + */ +public class DreamGhostManager { + private static final Map playerGhost = new HashMap<>(); + + public static void init() { + OMCPlugin.registerEvents( + new DreamPlayerEnteredListener() + ); + } + + public static void setupGhost(Player player) { + int entityId = player.getEntityId() + 100000; + + ArmorStand stand = ArmorStandNMS.createFakeStand(player, entityId, player.getLocation()); + + AttributeInstance instance = stand.getAttribute(Attributes.SCALE); + if (instance == null) return; + instance.setBaseValue(1.7); + + playerGhost.put(player.getUniqueId(), new PlayerGhost(entityId, stand)); + + World world = player.getWorld(); + + for (Player other : world.getPlayers()) { + if (other.equals(player)) continue; + + hidePlayer(other, player); + hidePlayer(player, other); + + sendGhostTo(other, player, entityId, stand); + + PlayerGhost otherGhost = playerGhost.get(other.getUniqueId()); + if (otherGhost != null) { + sendGhostTo(player, other, otherGhost.entityId(), otherGhost.stand()); + } + } + + new BukkitRunnable() { + @Override + public void run() { + if (!player.isOnline() + || !DreamUtils.isInDreamWorld(player)) { + removeGhost(player); + this.cancel(); + return; + } + + if (player.getGameMode().equals(GameMode.SPECTATOR)) return; + + Location newStand = player.getLocation().subtract(0, 0.5, 0); + + Collection receivers = newStand.getNearbyEntitiesByType(Player.class, 20).stream() + .filter(p -> !p.equals(player)).toList(); + + ParticleUtils.spawnCloudParticlesToAll( + player.getLocation().add(0, 1.5, 0), Particle.SCULK_SOUL, + 1, 1, 2, receivers); + + Particle.SHRIEK.builder() + .location(newStand) + .data(10) + .receivers(receivers) + .spawn(); + + for (Player other : player.getWorld().getPlayers()) { + if (!other.equals(player)) { + EntityTeleportNMS.sendTeleportPacket(other, entityId, player.getLocation()); + } + } + } + }.runTaskTimer(OMCPlugin.getInstance(), 0L, 2L); + } + + private static void sendGhostTo(Player receiver, Player ghostOf, int entityId, ArmorStand stand) { + EntitySpawnNMS.sendSpawnPacket(receiver, EntityType.ARMOR_STAND, entityId, stand.getUUID(), ghostOf.getLocation()); + EntitySpawnNMS.sendMetaDataEntity(receiver, stand); + EntityEquipmentNMS.sendHelmetPacket(receiver, entityId, SkullNMS.getPlayerSkullNMS(ghostOf)); + } + + public static void removeGhost(Player player) { + if (!playerGhost.containsKey(player.getUniqueId())) return; + PlayerGhost ghost = playerGhost.remove(player.getUniqueId()); + + if (ghost.stand() == null) return; + ghost.stand().remove(Entity.RemovalReason.DISCARDED); + + for (Player other : DreamDimensionManager.DREAM_WORLD.getPlayers()) { + if (other.equals(player)) continue; + + EntityRemoveNMS.sendRemovePacket(other, ghost.entityId()); + } + } + + public static void hidePlayer(Player receiver, Player toHide) { + EntityRemoveNMS.sendRemovePacket(receiver, toHide.getEntityId()); + } +} diff --git a/src/main/java/fr/openmc/core/features/dream/mecanism/sfx/ghost/PlayerGhost.java b/src/main/java/fr/openmc/core/features/dream/mecanism/sfx/ghost/PlayerGhost.java new file mode 100644 index 000000000..31714ef48 --- /dev/null +++ b/src/main/java/fr/openmc/core/features/dream/mecanism/sfx/ghost/PlayerGhost.java @@ -0,0 +1,5 @@ +package fr.openmc.core.features.dream.mecanism.sfx.ghost; + +import net.minecraft.world.entity.decoration.ArmorStand; + +public record PlayerGhost(int entityId, ArmorStand stand) {} diff --git a/src/main/java/fr/openmc/core/features/dream/mecanism/sfx/ghost/listeners/DreamPlayerEnteredListener.java b/src/main/java/fr/openmc/core/features/dream/mecanism/sfx/ghost/listeners/DreamPlayerEnteredListener.java new file mode 100644 index 000000000..350fab35d --- /dev/null +++ b/src/main/java/fr/openmc/core/features/dream/mecanism/sfx/ghost/listeners/DreamPlayerEnteredListener.java @@ -0,0 +1,17 @@ +package fr.openmc.core.features.dream.mecanism.sfx.ghost.listeners; + +import fr.openmc.core.OMCPlugin; +import fr.openmc.core.features.dream.events.DreamEnterEvent; +import fr.openmc.core.features.dream.mecanism.sfx.ghost.DreamGhostManager; +import org.bukkit.Bukkit; +import org.bukkit.event.EventHandler; +import org.bukkit.event.Listener; + +public class DreamPlayerEnteredListener implements Listener { + + @EventHandler + public void onDreamEnter(DreamEnterEvent event) { + Bukkit.getScheduler().runTaskLater(OMCPlugin.getInstance(), () -> + DreamGhostManager.setupGhost(event.getPlayer()), 20L); + } +} diff --git a/src/main/java/fr/openmc/core/utils/bukkit/ParticleUtils.java b/src/main/java/fr/openmc/core/utils/bukkit/ParticleUtils.java index 05ea86948..c43415c99 100644 --- a/src/main/java/fr/openmc/core/utils/bukkit/ParticleUtils.java +++ b/src/main/java/fr/openmc/core/utils/bukkit/ParticleUtils.java @@ -38,7 +38,9 @@ public class ParticleUtils { public static Color color1; public static Color color2; - // based on org.bukkit.craftbukkit.CraftParticle + /** + * based on {@link org.bukkit.craftbukkit.CraftParticle} + */ private static final Map> PARTICLE_FALLBACKS; static { @@ -113,9 +115,11 @@ public void run() { } public static void sendParticlePacket(Particle particle, Location loc, int radius) { - Collection players = loc.getNearbyEntitiesByType(Player.class, radius); + sendParticlePacket(particle, loc, loc.getNearbyEntitiesByType(Player.class, radius)); + } - for (Player player : players) { + public static void sendParticlePacket(Particle particle, Location loc, Collection receivers) { + for (Player player : receivers) { sendParticlePacket(player, particle, loc, 3, 0.2f, 0.2f, 0.2f, 0.01f, null); } } @@ -264,9 +268,9 @@ public void run() { }.runTaskTimerAsynchronously(OMCPlugin.getInstance(), 0L, 1L); } - public static void spawnCloudParticles(Location center, Particle particle, int count, double radius, double height) { - for (Player player : center.getNearbyEntitiesByType(Player.class, radius)) { - spawnCloudParticles(player, particle, center, count, radius, height); + public static void spawnCloudParticlesToAll(Location center, Particle particle, int count, double radiusCloud, double height, Collection receivers) { + for (Player player : receivers) { + spawnCloudParticles(player, particle, center, count, radiusCloud, height); } } diff --git a/src/main/java/fr/openmc/core/utils/bukkit/SkullUtils.java b/src/main/java/fr/openmc/core/utils/bukkit/SkullUtils.java index 820d96f17..4d890ad27 100644 --- a/src/main/java/fr/openmc/core/utils/bukkit/SkullUtils.java +++ b/src/main/java/fr/openmc/core/utils/bukkit/SkullUtils.java @@ -2,6 +2,7 @@ import com.destroystokyo.paper.profile.PlayerProfile; import com.destroystokyo.paper.profile.ProfileProperty; +import fr.openmc.core.utils.cache.CachePlayerProfile; import io.papermc.paper.datacomponent.DataComponentTypes; import io.papermc.paper.datacomponent.item.ResolvableProfile; import net.kyori.adventure.text.Component; @@ -27,7 +28,7 @@ public class SkullUtils { */ public static ItemStack getPlayerSkull(UUID playerUUID) { ItemStack skull = new ItemStack(Material.PLAYER_HEAD); - PlayerProfile profile = Bukkit.createProfile(playerUUID); + PlayerProfile profile = CachePlayerProfile.getPlayerProfile(playerUUID); skull.setData(DataComponentTypes.PROFILE, ResolvableProfile.resolvableProfile(profile)); return skull; } diff --git a/src/main/java/fr/openmc/core/utils/nms/SkullNMS.java b/src/main/java/fr/openmc/core/utils/nms/SkullNMS.java new file mode 100644 index 000000000..27848b685 --- /dev/null +++ b/src/main/java/fr/openmc/core/utils/nms/SkullNMS.java @@ -0,0 +1,21 @@ +package fr.openmc.core.utils.nms; + +import net.minecraft.core.component.DataComponents; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.Items; +import net.minecraft.world.item.component.ResolvableProfile; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.entity.Player; + +public class SkullNMS { + public static ItemStack getPlayerSkullNMS(Player player) { + ServerPlayer nmsPlayer = ((CraftPlayer) player).getHandle(); + ItemStack skull = new ItemStack(Items.PLAYER_HEAD); + + ResolvableProfile profile = ResolvableProfile.createResolved(nmsPlayer.getGameProfile()); + + skull.set(DataComponents.PROFILE, profile); + return skull; + } +} diff --git a/src/main/java/fr/openmc/core/utils/nms/entity/ArmorStandNMS.java b/src/main/java/fr/openmc/core/utils/nms/entity/ArmorStandNMS.java new file mode 100644 index 000000000..f3d8d56d4 --- /dev/null +++ b/src/main/java/fr/openmc/core/utils/nms/entity/ArmorStandNMS.java @@ -0,0 +1,22 @@ +package fr.openmc.core.utils.nms.entity; + +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.entity.decoration.ArmorStand; +import org.bukkit.Location; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.entity.Player; + +public class ArmorStandNMS { + + public static ArmorStand createFakeStand(Player playerOf, int entityId, Location loc) { + ServerLevel level = ((CraftWorld) playerOf.getWorld()).getHandle(); + + ArmorStand stand = new ArmorStand(level, loc.getX(), loc.getY(), loc.getZ()); + stand.setId(entityId); + stand.setInvisible(true); + stand.setNoGravity(true); + stand.setMarker(false); + + return stand; + } +} diff --git a/src/main/java/fr/openmc/core/utils/nms/entity/EntityEquipmentNMS.java b/src/main/java/fr/openmc/core/utils/nms/entity/EntityEquipmentNMS.java new file mode 100644 index 000000000..1f1eee862 --- /dev/null +++ b/src/main/java/fr/openmc/core/utils/nms/entity/EntityEquipmentNMS.java @@ -0,0 +1,25 @@ +package fr.openmc.core.utils.nms.entity; + +import com.mojang.datafixers.util.Pair; +import net.minecraft.network.protocol.game.ClientboundSetEquipmentPacket; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.EquipmentSlot; +import net.minecraft.world.item.ItemStack; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import java.util.List; + +public class EntityEquipmentNMS { + + public static void sendHelmetPacket(Player receiver, int entityId, ItemStack itemStackNMS) { + ServerPlayer nmsReceiver = ((CraftPlayer) receiver).getHandle(); + + ClientboundSetEquipmentPacket packet = new ClientboundSetEquipmentPacket( + entityId, + List.of(Pair.of(EquipmentSlot.HEAD, itemStackNMS)) + ); + + nmsReceiver.connection.send(packet); + } +} diff --git a/src/main/java/fr/openmc/core/utils/nms/entity/EntityRemoveNMS.java b/src/main/java/fr/openmc/core/utils/nms/entity/EntityRemoveNMS.java new file mode 100644 index 000000000..35ea369f2 --- /dev/null +++ b/src/main/java/fr/openmc/core/utils/nms/entity/EntityRemoveNMS.java @@ -0,0 +1,16 @@ +package fr.openmc.core.utils.nms.entity; + +import net.minecraft.network.protocol.game.ClientboundRemoveEntitiesPacket; +import net.minecraft.server.level.ServerPlayer; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.entity.Player; + +public class EntityRemoveNMS { + + public static void sendRemovePacket(Player receiver, int entityId) { + ServerPlayer nmsReceiver = ((CraftPlayer) receiver).getHandle(); + + ClientboundRemoveEntitiesPacket packet = new ClientboundRemoveEntitiesPacket(entityId); + nmsReceiver.connection.send(packet); + } +} diff --git a/src/main/java/fr/openmc/core/utils/nms/entity/EntitySpawnNMS.java b/src/main/java/fr/openmc/core/utils/nms/entity/EntitySpawnNMS.java new file mode 100644 index 000000000..c12bd0852 --- /dev/null +++ b/src/main/java/fr/openmc/core/utils/nms/entity/EntitySpawnNMS.java @@ -0,0 +1,43 @@ +package fr.openmc.core.utils.nms.entity; + +import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; +import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket; +import net.minecraft.network.syncher.SynchedEntityData; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.EntityType; +import net.minecraft.world.phys.Vec3; +import org.bukkit.Location; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import java.util.List; +import java.util.UUID; + +public class EntitySpawnNMS { + + public static void sendSpawnPacket(Player receiver, EntityType entityType, int entityId, UUID entityUUID, Location loc) { + ServerPlayer nmsReceiver = ((CraftPlayer) receiver).getHandle(); + + ClientboundAddEntityPacket packet = new ClientboundAddEntityPacket( + entityId, + entityUUID, + loc.getX(), loc.getY(), loc.getZ(), + loc.getPitch(), loc.getYaw(), + entityType, + 0, + Vec3.ZERO, + loc.getYaw() + ); + + nmsReceiver.connection.send(packet); + } + + public static void sendMetaDataEntity(Player receiver, Entity entity) { + List> dataValues = entity.getEntityData().getNonDefaultValues(); + if (dataValues == null || dataValues.isEmpty()) return; + ClientboundSetEntityDataPacket entityDataPacket = new ClientboundSetEntityDataPacket(entity.getId(), dataValues); + ((CraftPlayer) receiver).getHandle().connection.send(entityDataPacket); + } + +} diff --git a/src/main/java/fr/openmc/core/utils/nms/entity/EntityTeleportNMS.java b/src/main/java/fr/openmc/core/utils/nms/entity/EntityTeleportNMS.java new file mode 100644 index 000000000..2a9ba0cc0 --- /dev/null +++ b/src/main/java/fr/openmc/core/utils/nms/entity/EntityTeleportNMS.java @@ -0,0 +1,28 @@ +package fr.openmc.core.utils.nms.entity; + +import net.minecraft.network.protocol.game.ClientboundEntityPositionSyncPacket; +import net.minecraft.server.level.ServerPlayer; +import net.minecraft.world.entity.PositionMoveRotation; +import net.minecraft.world.phys.Vec3; +import org.bukkit.Location; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.entity.Player; + +public class EntityTeleportNMS { + + public static void sendTeleportPacket(Player receiver, int entityId, Location loc) { + ServerPlayer nmsReceiver = ((CraftPlayer) receiver).getHandle(); + + ClientboundEntityPositionSyncPacket packet = new ClientboundEntityPositionSyncPacket( + entityId, + new PositionMoveRotation(new Vec3(loc.getX(), loc.getY(), loc.getZ()), + Vec3.ZERO, + loc.getYaw(), + loc.getPitch() + ), + false + ); + + nmsReceiver.connection.send(packet); + } +}