From 32402bd44b68c563cbd14f19a87e480febd14f81 Mon Sep 17 00:00:00 2001 From: Boy Date: Thu, 1 May 2025 13:54:20 +0200 Subject: [PATCH] refactor: move even more packets from hmcc to nms --- .../hibiscuscommons/nms/NMSPackets.java | 14 +++ .../nms/v1_20_R3/NMSPackets.java | 81 +++++++++++++- .../nms/v1_20_R4/NMSPackets.java | 82 +++++++++++++- .../nms/v1_21_R1/NMSPackets.java | 82 +++++++++++++- .../nms/v1_21_R2/NMSPackets.java | 84 +++++++++++++-- .../nms/v1_21_R3/NMSPackets.java | 88 +++++++++++++-- .../nms/v1_21_R4/NMSPackets.java | 101 +++++++++++++++--- 7 files changed, 488 insertions(+), 44 deletions(-) diff --git a/common/src/main/java/me/lojosho/hibiscuscommons/nms/NMSPackets.java b/common/src/main/java/me/lojosho/hibiscuscommons/nms/NMSPackets.java index d6db71a..990b785 100644 --- a/common/src/main/java/me/lojosho/hibiscuscommons/nms/NMSPackets.java +++ b/common/src/main/java/me/lojosho/hibiscuscommons/nms/NMSPackets.java @@ -1,5 +1,6 @@ package me.lojosho.hibiscuscommons.nms; +import it.unimi.dsi.fastutil.Pair; import it.unimi.dsi.fastutil.ints.IntList; import net.kyori.adventure.text.Component; import org.bukkit.GameMode; @@ -10,21 +11,34 @@ import org.bukkit.entity.ItemDisplay; import org.bukkit.entity.Player; import org.bukkit.inventory.EquipmentSlot; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import org.joml.Quaternionf; import org.joml.Vector3f; import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.UUID; public interface NMSPackets { static int POSITION_INTERPOLATION_DURATION = 2; + static int SHARED_ENTITY_METADATA = 0; + + void sendSharedEntityData(int entityId, Map dataValues, List sendTo); + + void sendFakePlayerInfoPacket(final Player skinnedPlayer, final int entityId, final UUID uuid, final String npcName, final List sendTo); + + void sendPlayerInfoRemovePacket(final UUID uuid, final List sendTo); + + void sendMovePacket(final int entityId, final @NotNull Location from, final @NotNull Location to, final boolean onGround, @NotNull List sendTo); void sendGamemodeChange(Player player, GameMode gameMode); void sendRotateHeadPacket(int entityId, Location location, List sendTo); + void sendRotationPacket(int entityId, float yaw, float pitch, boolean onGround, List sendTo); + void sendRotationPacket(int entityId, Location location, boolean onGround, List sendTo); void sendSlotUpdate(Player player, int slot); diff --git a/v1_20_R3/src/main/java/me/lojosho/hibiscuscommons/nms/v1_20_R3/NMSPackets.java b/v1_20_R3/src/main/java/me/lojosho/hibiscuscommons/nms/v1_20_R3/NMSPackets.java index b150ead..6bbe400 100644 --- a/v1_20_R3/src/main/java/me/lojosho/hibiscuscommons/nms/v1_20_R3/NMSPackets.java +++ b/v1_20_R3/src/main/java/me/lojosho/hibiscuscommons/nms/v1_20_R3/NMSPackets.java @@ -1,13 +1,16 @@ package me.lojosho.hibiscuscommons.nms.v1_20_R3; import com.google.common.collect.ImmutableList; +import com.mojang.authlib.GameProfile; import com.mojang.datafixers.util.Pair; -import io.netty.buffer.Unpooled; +import io.papermc.paper.adventure.PaperAdventure; import it.unimi.dsi.fastutil.ints.IntList; +import me.lojosho.hibiscuscommons.HibiscusCommonsPlugin; +import me.lojosho.hibiscuscommons.util.AdventureUtils; import net.kyori.adventure.text.Component; -import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.*; +import net.minecraft.network.syncher.EntityDataSerializer; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.server.MinecraftServer; @@ -17,6 +20,7 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.decoration.ArmorStand; import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.level.GameType; import net.minecraft.world.phys.Vec3; import net.minecraft.world.scores.PlayerTeam; import net.minecraft.world.scores.Team; @@ -33,17 +37,79 @@ import org.bukkit.entity.EntityType; import org.bukkit.entity.ItemDisplay; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; +import org.jetbrains.annotations.NotNull; import org.joml.Quaternionf; import org.joml.Vector3f; -import java.lang.reflect.Constructor; import java.util.*; +import java.util.stream.Collectors; public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons.nms.NMSPackets { private static ServerLevel level = MinecraftServer.getServer().overworld(); private static Entity fakeNmsEntity = new ArmorStand(net.minecraft.world.entity.EntityType.ARMOR_STAND, level); + @Override @SuppressWarnings("unchecked") + public void sendSharedEntityData(int entityId, Map dataValues, List sendTo) { + List> nmsDataValues = dataValues.entrySet().stream().map(entry -> { + int index = entry.getKey(); + Number value = entry.getValue(); + return switch (value) { + case Byte byteVal -> new SynchedEntityData.DataValue<>(index, EntityDataSerializers.BYTE, byteVal); + case Float floatVal -> new SynchedEntityData.DataValue<>(index, EntityDataSerializers.FLOAT, floatVal); + case Integer intVal -> new SynchedEntityData.DataValue<>(index, EntityDataSerializers.INT, intVal); + default -> + throw new IllegalArgumentException("Unsupported data value type: " + value.getClass().getSimpleName()); + }; + }).collect(Collectors.toList()); + + ClientboundSetEntityDataPacket packet = new ClientboundSetEntityDataPacket(entityId, nmsDataValues); + for (Player player : sendTo) sendPacket(player, packet); + } + + @Override + public void sendFakePlayerInfoPacket( + final Player skinnedPlayer, + final int entityId, + final UUID uuid, + final String npcName, + final List sendTo + ) { + ServerPlayer player = ((CraftPlayer) skinnedPlayer).getHandle(); + String name = npcName.substring(0, 15); + GameProfile profile = new GameProfile(uuid, name); + + Component component = AdventureUtils.MINI_MESSAGE.deserialize(name); + net.minecraft.network.chat.Component nmsComponent = HibiscusCommonsPlugin.isOnPaper() ? PaperAdventure.asVanilla(component) : net.minecraft.network.chat.Component.literal(name); + + ClientboundPlayerInfoUpdatePacket.Entry entry = new ClientboundPlayerInfoUpdatePacket.Entry(uuid, profile, false, 0, GameType.CREATIVE, nmsComponent, player.getChatSession().asData()); + EnumSet actions = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER); + ClientboundPlayerInfoUpdatePacket packet = new ClientboundPlayerInfoUpdatePacket(actions, entry); + for (Player p : sendTo) sendPacket(p, packet); + } + + @Override + public void sendPlayerInfoRemovePacket(final UUID uuid, final List sendTo) { + ClientboundPlayerInfoRemovePacket packet = new ClientboundPlayerInfoRemovePacket(List.of(uuid)); + for (Player player : sendTo) sendPacket(player, packet); + } + + @Override + public void sendMovePacket( + final int entityId, + final @NotNull Location from, + final @NotNull Location to, + final boolean onGround, + @NotNull List sendTo + ) { + byte dx = (byte) (to.getX() - from.getX()); + byte dy = (byte) (to.getY() - from.getY()); + byte dz = (byte) (to.getZ() - from.getZ()); + + ClientboundMoveEntityPacket.Pos packet = new ClientboundMoveEntityPacket.Pos(entityId, dx, dy, dz, onGround); + for (Player p : sendTo) sendPacket(p, packet); + } + @Override public void sendGamemodeChange(Player player, GameMode gameMode) { ClientboundGameEventPacket.Type type = ClientboundGameEventPacket.CHANGE_GAME_MODE; @@ -62,6 +128,15 @@ public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons. for (Player p : sendTo) sendPacket(p, packet); } + @Override + public void sendRotationPacket(int entityId, float yaw, float pitch, boolean onGround, List sendTo) { + float ROTATION_FACTOR = 256.0F / 360.0F; + yaw = (byte) (yaw * ROTATION_FACTOR); + pitch = (byte) (pitch * ROTATION_FACTOR); + ClientboundMoveEntityPacket.Rot packet = new ClientboundMoveEntityPacket.Rot(entityId, (byte) yaw, (byte) pitch, onGround); + for (Player p : sendTo) sendPacket(p, packet); + } + @Override public void sendRotationPacket(int entityId, Location location, boolean onGround, List sendTo) { float ROTATION_FACTOR = 256.0F / 360.0F; diff --git a/v1_20_R4/src/main/java/me/lojosho/hibiscuscommons/nms/v1_20_R4/NMSPackets.java b/v1_20_R4/src/main/java/me/lojosho/hibiscuscommons/nms/v1_20_R4/NMSPackets.java index 1ea61a9..9ac73d0 100644 --- a/v1_20_R4/src/main/java/me/lojosho/hibiscuscommons/nms/v1_20_R4/NMSPackets.java +++ b/v1_20_R4/src/main/java/me/lojosho/hibiscuscommons/nms/v1_20_R4/NMSPackets.java @@ -2,18 +2,20 @@ package me.lojosho.hibiscuscommons.nms.v1_20_R4; import com.google.common.collect.ImmutableList; import com.google.gson.JsonObject; +import com.mojang.authlib.GameProfile; import com.mojang.datafixers.util.Pair; import com.mojang.serialization.JsonOps; -import io.netty.buffer.Unpooled; +import io.papermc.paper.adventure.PaperAdventure; import it.unimi.dsi.fastutil.ints.IntList; import me.lojosho.hibiscuscommons.HibiscusCommonsPlugin; +import me.lojosho.hibiscuscommons.util.AdventureUtils; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.minecraft.advancements.Advancement; import net.minecraft.advancements.AdvancementHolder; -import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.*; +import net.minecraft.network.syncher.EntityDataSerializer; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.resources.ResourceLocation; @@ -24,6 +26,7 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.decoration.ArmorStand; import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.level.GameType; import net.minecraft.world.phys.Vec3; import net.minecraft.world.scores.PlayerTeam; import net.minecraft.world.scores.Team; @@ -31,7 +34,6 @@ import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.craftbukkit.CraftEquipmentSlot; -import org.bukkit.craftbukkit.entity.CraftEntity; import org.bukkit.craftbukkit.entity.CraftEntityType; import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.craftbukkit.inventory.CraftItemStack; @@ -42,18 +44,79 @@ import org.bukkit.entity.ItemDisplay; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; import org.joml.Quaternionf; import org.joml.Vector3f; -import java.lang.reflect.Constructor; -import java.nio.ByteBuffer; import java.util.*; +import java.util.stream.Collectors; public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons.nms.NMSPackets { private static ServerLevel level = MinecraftServer.getServer().overworld(); private static Entity fakeNmsEntity = new ArmorStand(net.minecraft.world.entity.EntityType.ARMOR_STAND, level); + @Override @SuppressWarnings("unchecked") + public void sendSharedEntityData(int entityId, Map dataValues, List sendTo) { + List> nmsDataValues = dataValues.entrySet().stream().map(entry -> { + int index = entry.getKey(); + Number value = entry.getValue(); + return switch (value) { + case Byte byteVal -> new SynchedEntityData.DataValue<>(index, EntityDataSerializers.BYTE, byteVal); + case Float floatVal -> new SynchedEntityData.DataValue<>(index, EntityDataSerializers.FLOAT, floatVal); + case Integer intVal -> new SynchedEntityData.DataValue<>(index, EntityDataSerializers.INT, intVal); + default -> + throw new IllegalArgumentException("Unsupported data value type: " + value.getClass().getSimpleName()); + }; + }).collect(Collectors.toList()); + + ClientboundSetEntityDataPacket packet = new ClientboundSetEntityDataPacket(entityId, nmsDataValues); + for (Player player : sendTo) sendPacket(player, packet); + } + + @Override + public void sendFakePlayerInfoPacket( + final Player skinnedPlayer, + final int entityId, + final UUID uuid, + final String npcName, + final List sendTo + ) { + ServerPlayer player = ((CraftPlayer) skinnedPlayer).getHandle(); + String name = npcName.substring(0, 15); + GameProfile profile = new GameProfile(uuid, name); + + Component component = AdventureUtils.MINI_MESSAGE.deserialize(name); + net.minecraft.network.chat.Component nmsComponent = HibiscusCommonsPlugin.isOnPaper() ? PaperAdventure.asVanilla(component) : net.minecraft.network.chat.Component.literal(name); + + ClientboundPlayerInfoUpdatePacket.Entry entry = new ClientboundPlayerInfoUpdatePacket.Entry(uuid, profile, false, 0, GameType.CREATIVE, nmsComponent, player.getChatSession().asData()); + EnumSet actions = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER); + ClientboundPlayerInfoUpdatePacket packet = new ClientboundPlayerInfoUpdatePacket(actions, entry); + for (Player p : sendTo) sendPacket(p, packet); + } + + @Override + public void sendPlayerInfoRemovePacket(final UUID uuid, final List sendTo) { + ClientboundPlayerInfoRemovePacket packet = new ClientboundPlayerInfoRemovePacket(List.of(uuid)); + for (Player player : sendTo) sendPacket(player, packet); + } + + @Override + public void sendMovePacket( + final int entityId, + final @NotNull Location from, + final @NotNull Location to, + final boolean onGround, + @NotNull List sendTo + ) { + byte dx = (byte) (to.getX() - from.getX()); + byte dy = (byte) (to.getY() - from.getY()); + byte dz = (byte) (to.getZ() - from.getZ()); + + ClientboundMoveEntityPacket.Pos packet = new ClientboundMoveEntityPacket.Pos(entityId, dx, dy, dz, onGround); + for (Player p : sendTo) sendPacket(p, packet); + } + @Override public void sendGamemodeChange(Player player, GameMode gameMode) { ClientboundGameEventPacket.Type type = ClientboundGameEventPacket.CHANGE_GAME_MODE; @@ -72,6 +135,15 @@ public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons. for (Player p : sendTo) sendPacket(p, packet); } + @Override + public void sendRotationPacket(int entityId, float yaw, float pitch, boolean onGround, List sendTo) { + float ROTATION_FACTOR = 256.0F / 360.0F; + yaw = (byte) (yaw * ROTATION_FACTOR); + pitch = (byte) (pitch * ROTATION_FACTOR); + ClientboundMoveEntityPacket.Rot packet = new ClientboundMoveEntityPacket.Rot(entityId, (byte) yaw, (byte) pitch, onGround); + for (Player p : sendTo) sendPacket(p, packet); + } + @Override public void sendRotationPacket(int entityId, Location location, boolean onGround, List sendTo) { float ROTATION_FACTOR = 256.0F / 360.0F; diff --git a/v1_21_R1/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R1/NMSPackets.java b/v1_21_R1/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R1/NMSPackets.java index 04bf957..bedd00e 100644 --- a/v1_21_R1/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R1/NMSPackets.java +++ b/v1_21_R1/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R1/NMSPackets.java @@ -2,19 +2,20 @@ package me.lojosho.hibiscuscommons.nms.v1_21_R1; import com.google.common.collect.ImmutableList; import com.google.gson.JsonObject; -import com.mojang.datafixers.kinds.Const; +import com.mojang.authlib.GameProfile; import com.mojang.datafixers.util.Pair; import com.mojang.serialization.JsonOps; -import io.netty.buffer.Unpooled; +import io.papermc.paper.adventure.PaperAdventure; import it.unimi.dsi.fastutil.ints.IntList; import me.lojosho.hibiscuscommons.HibiscusCommonsPlugin; +import me.lojosho.hibiscuscommons.util.AdventureUtils; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.minecraft.advancements.Advancement; import net.minecraft.advancements.AdvancementHolder; -import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.*; +import net.minecraft.network.syncher.EntityDataSerializer; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.resources.ResourceLocation; @@ -25,6 +26,7 @@ import net.minecraft.world.entity.Entity; import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.decoration.ArmorStand; import net.minecraft.world.entity.player.Inventory; +import net.minecraft.world.level.GameType; import net.minecraft.world.phys.Vec3; import net.minecraft.world.scores.PlayerTeam; import net.minecraft.world.scores.Team; @@ -32,7 +34,6 @@ import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.craftbukkit.CraftEquipmentSlot; -import org.bukkit.craftbukkit.entity.CraftEntity; import org.bukkit.craftbukkit.entity.CraftEntityType; import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.craftbukkit.inventory.CraftItemStack; @@ -43,17 +44,79 @@ import org.bukkit.entity.ItemDisplay; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; import org.joml.Quaternionf; import org.joml.Vector3f; -import java.lang.reflect.Constructor; import java.util.*; +import java.util.stream.Collectors; public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons.nms.NMSPackets { private static ServerLevel level = MinecraftServer.getServer().overworld(); private static Entity fakeNmsEntity = new ArmorStand(net.minecraft.world.entity.EntityType.ARMOR_STAND, level); + @Override @SuppressWarnings("unchecked") + public void sendSharedEntityData(int entityId, Map dataValues, List sendTo) { + List> nmsDataValues = dataValues.entrySet().stream().map(entry -> { + int index = entry.getKey(); + Number value = entry.getValue(); + return switch (value) { + case Byte byteVal -> new SynchedEntityData.DataValue<>(index, EntityDataSerializers.BYTE, byteVal); + case Float floatVal -> new SynchedEntityData.DataValue<>(index, EntityDataSerializers.FLOAT, floatVal); + case Integer intVal -> new SynchedEntityData.DataValue<>(index, EntityDataSerializers.INT, intVal); + default -> + throw new IllegalArgumentException("Unsupported data value type: " + value.getClass().getSimpleName()); + }; + }).collect(Collectors.toList()); + + ClientboundSetEntityDataPacket packet = new ClientboundSetEntityDataPacket(entityId, nmsDataValues); + for (Player player : sendTo) sendPacket(player, packet); + } + + @Override + public void sendFakePlayerInfoPacket( + final Player skinnedPlayer, + final int entityId, + final UUID uuid, + final String npcName, + final List sendTo + ) { + ServerPlayer player = ((CraftPlayer) skinnedPlayer).getHandle(); + String name = npcName.substring(0, 15); + GameProfile profile = new GameProfile(uuid, name); + + Component component = AdventureUtils.MINI_MESSAGE.deserialize(name); + net.minecraft.network.chat.Component nmsComponent = HibiscusCommonsPlugin.isOnPaper() ? PaperAdventure.asVanilla(component) : net.minecraft.network.chat.Component.literal(name); + + ClientboundPlayerInfoUpdatePacket.Entry entry = new ClientboundPlayerInfoUpdatePacket.Entry(uuid, profile, false, 0, GameType.CREATIVE, nmsComponent, player.getChatSession().asData()); + EnumSet actions = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER); + ClientboundPlayerInfoUpdatePacket packet = new ClientboundPlayerInfoUpdatePacket(actions, entry); + for (Player p : sendTo) sendPacket(p, packet); + } + + @Override + public void sendPlayerInfoRemovePacket(final UUID uuid, final List sendTo) { + ClientboundPlayerInfoRemovePacket packet = new ClientboundPlayerInfoRemovePacket(List.of(uuid)); + for (Player player : sendTo) sendPacket(player, packet); + } + + @Override + public void sendMovePacket( + final int entityId, + final @NotNull Location from, + final @NotNull Location to, + final boolean onGround, + @NotNull List sendTo + ) { + byte dx = (byte) (to.getX() - from.getX()); + byte dy = (byte) (to.getY() - from.getY()); + byte dz = (byte) (to.getZ() - from.getZ()); + + ClientboundMoveEntityPacket.Pos packet = new ClientboundMoveEntityPacket.Pos(entityId, dx, dy, dz, onGround); + for (Player p : sendTo) sendPacket(p, packet); + } + @Override public void sendGamemodeChange(Player player, GameMode gameMode) { ClientboundGameEventPacket.Type type = ClientboundGameEventPacket.CHANGE_GAME_MODE; @@ -72,6 +135,15 @@ public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons. for (Player p : sendTo) sendPacket(p, packet); } + @Override + public void sendRotationPacket(int entityId, float yaw, float pitch, boolean onGround, List sendTo) { + float ROTATION_FACTOR = 256.0F / 360.0F; + yaw = (byte) (yaw * ROTATION_FACTOR); + pitch = (byte) (pitch * ROTATION_FACTOR); + ClientboundMoveEntityPacket.Rot packet = new ClientboundMoveEntityPacket.Rot(entityId, (byte) yaw, (byte) pitch, onGround); + for (Player p : sendTo) sendPacket(p, packet); + } + @Override public void sendRotationPacket(int entityId, Location location, boolean onGround, List sendTo) { float ROTATION_FACTOR = 256.0F / 360.0F; diff --git a/v1_21_R2/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R2/NMSPackets.java b/v1_21_R2/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R2/NMSPackets.java index b33a26b..09fe21a 100644 --- a/v1_21_R2/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R2/NMSPackets.java +++ b/v1_21_R2/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R2/NMSPackets.java @@ -2,18 +2,20 @@ package me.lojosho.hibiscuscommons.nms.v1_21_R2; import com.google.common.collect.ImmutableList; import com.google.gson.JsonObject; +import com.mojang.authlib.GameProfile; import com.mojang.datafixers.util.Pair; import com.mojang.serialization.JsonOps; -import io.netty.buffer.Unpooled; +import io.papermc.paper.adventure.PaperAdventure; import it.unimi.dsi.fastutil.ints.IntList; import me.lojosho.hibiscuscommons.HibiscusCommonsPlugin; +import me.lojosho.hibiscuscommons.util.AdventureUtils; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; import net.minecraft.advancements.Advancement; import net.minecraft.advancements.AdvancementHolder; -import net.minecraft.network.FriendlyByteBuf; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.*; +import net.minecraft.network.syncher.EntityDataSerializer; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.resources.ResourceLocation; @@ -25,7 +27,7 @@ import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.PositionMoveRotation; import net.minecraft.world.entity.decoration.ArmorStand; import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.level.portal.TeleportTransition; +import net.minecraft.world.level.GameType; import net.minecraft.world.phys.Vec3; import net.minecraft.world.scores.PlayerTeam; import net.minecraft.world.scores.Team; @@ -33,7 +35,6 @@ import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.craftbukkit.CraftEquipmentSlot; -import org.bukkit.craftbukkit.entity.CraftEntity; import org.bukkit.craftbukkit.entity.CraftEntityType; import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.craftbukkit.inventory.CraftItemStack; @@ -42,21 +43,81 @@ import org.bukkit.entity.Display; import org.bukkit.entity.EntityType; import org.bukkit.entity.ItemDisplay; import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; +import org.jetbrains.annotations.NotNull; import org.joml.Quaternionf; import org.joml.Vector3f; -import java.lang.reflect.Constructor; -import java.nio.ByteBuffer; import java.util.*; +import java.util.stream.Collectors; public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons.nms.NMSPackets { private static ServerLevel level = MinecraftServer.getServer().overworld(); private static Entity fakeNmsEntity = new ArmorStand(net.minecraft.world.entity.EntityType.ARMOR_STAND, level); + @Override @SuppressWarnings("unchecked") + public void sendSharedEntityData(int entityId, Map dataValues, List sendTo) { + List> nmsDataValues = dataValues.entrySet().stream().map(entry -> { + int index = entry.getKey(); + Number value = entry.getValue(); + return switch (value) { + case Byte byteVal -> new SynchedEntityData.DataValue<>(index, EntityDataSerializers.BYTE, byteVal); + case Float floatVal -> new SynchedEntityData.DataValue<>(index, EntityDataSerializers.FLOAT, floatVal); + case Integer intVal -> new SynchedEntityData.DataValue<>(index, EntityDataSerializers.INT, intVal); + default -> + throw new IllegalArgumentException("Unsupported data value type: " + value.getClass().getSimpleName()); + }; + }).collect(Collectors.toList()); + + ClientboundSetEntityDataPacket packet = new ClientboundSetEntityDataPacket(entityId, nmsDataValues); + for (Player player : sendTo) sendPacket(player, packet); + } + + @Override + public void sendFakePlayerInfoPacket( + final Player skinnedPlayer, + final int entityId, + final UUID uuid, + final String npcName, + final List sendTo + ) { + ServerPlayer player = ((CraftPlayer) skinnedPlayer).getHandle(); + String name = npcName.substring(0, 15); + GameProfile profile = new GameProfile(uuid, name); + + Component component = AdventureUtils.MINI_MESSAGE.deserialize(name); + net.minecraft.network.chat.Component nmsComponent = HibiscusCommonsPlugin.isOnPaper() ? PaperAdventure.asVanilla(component) : net.minecraft.network.chat.Component.literal(name); + + ClientboundPlayerInfoUpdatePacket.Entry entry = new ClientboundPlayerInfoUpdatePacket.Entry(uuid, profile, false, 0, GameType.CREATIVE, nmsComponent, player.listOrder, player.getChatSession().asData()); + EnumSet actions = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER); + ClientboundPlayerInfoUpdatePacket packet = new ClientboundPlayerInfoUpdatePacket(actions, entry); + for (Player p : sendTo) sendPacket(p, packet); + } + + @Override + public void sendPlayerInfoRemovePacket(final UUID uuid, final List sendTo) { + ClientboundPlayerInfoRemovePacket packet = new ClientboundPlayerInfoRemovePacket(List.of(uuid)); + for (Player player : sendTo) sendPacket(player, packet); + } + + @Override + public void sendMovePacket( + final int entityId, + final @NotNull Location from, + final @NotNull Location to, + final boolean onGround, + @NotNull List sendTo + ) { + byte dx = (byte) (to.getX() - from.getX()); + byte dy = (byte) (to.getY() - from.getY()); + byte dz = (byte) (to.getZ() - from.getZ()); + + ClientboundMoveEntityPacket.Pos packet = new ClientboundMoveEntityPacket.Pos(entityId, dx, dy, dz, onGround); + for (Player p : sendTo) sendPacket(p, packet); + } + @Override public void sendGamemodeChange(Player player, GameMode gameMode) { ClientboundGameEventPacket.Type type = ClientboundGameEventPacket.CHANGE_GAME_MODE; @@ -75,6 +136,15 @@ public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons. for (Player p : sendTo) sendPacket(p, packet); } + @Override + public void sendRotationPacket(int entityId, float yaw, float pitch, boolean onGround, List sendTo) { + float ROTATION_FACTOR = 256.0F / 360.0F; + yaw = (byte) (yaw * ROTATION_FACTOR); + pitch = (byte) (pitch * ROTATION_FACTOR); + ClientboundMoveEntityPacket.Rot packet = new ClientboundMoveEntityPacket.Rot(entityId, (byte) yaw, (byte) pitch, onGround); + for (Player p : sendTo) sendPacket(p, packet); + } + @Override public void sendRotationPacket(int entityId, Location location, boolean onGround, List sendTo) { float ROTATION_FACTOR = 256.0F / 360.0F; diff --git a/v1_21_R3/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R3/NMSPackets.java b/v1_21_R3/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R3/NMSPackets.java index 42d8fc7..0347060 100644 --- a/v1_21_R3/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R3/NMSPackets.java +++ b/v1_21_R3/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R3/NMSPackets.java @@ -3,18 +3,20 @@ package me.lojosho.hibiscuscommons.nms.v1_21_R3; import com.google.common.collect.ImmutableList; import com.google.gson.JsonArray; import com.google.gson.JsonObject; +import com.mojang.authlib.GameProfile; import com.mojang.datafixers.util.Pair; import com.mojang.serialization.JsonOps; -import io.netty.buffer.Unpooled; +import io.papermc.paper.adventure.PaperAdventure; import it.unimi.dsi.fastutil.ints.IntList; import me.lojosho.hibiscuscommons.HibiscusCommonsPlugin; +import me.lojosho.hibiscuscommons.util.AdventureUtils; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; -import net.kyori.adventure.text.serializer.json.JSONComponentSerializer; -import net.minecraft.advancements.*; -import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.advancements.Advancement; +import net.minecraft.advancements.AdvancementHolder; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.*; +import net.minecraft.network.syncher.EntityDataSerializer; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.resources.ResourceLocation; @@ -26,7 +28,7 @@ import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.PositionMoveRotation; import net.minecraft.world.entity.decoration.ArmorStand; import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.level.portal.TeleportTransition; +import net.minecraft.world.level.GameType; import net.minecraft.world.phys.Vec3; import net.minecraft.world.scores.PlayerTeam; import net.minecraft.world.scores.Team; @@ -35,7 +37,6 @@ import org.bukkit.Color; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.craftbukkit.CraftEquipmentSlot; -import org.bukkit.craftbukkit.entity.CraftEntity; import org.bukkit.craftbukkit.entity.CraftEntityType; import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.craftbukkit.inventory.CraftItemStack; @@ -44,22 +45,82 @@ import org.bukkit.entity.Display; import org.bukkit.entity.EntityType; import org.bukkit.entity.ItemDisplay; import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerTeleportEvent; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.components.CustomModelDataComponent; +import org.jetbrains.annotations.NotNull; import org.joml.Quaternionf; import org.joml.Vector3f; -import java.lang.reflect.Constructor; -import java.nio.ByteBuffer; import java.util.*; +import java.util.stream.Collectors; public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons.nms.NMSPackets { private static ServerLevel level = MinecraftServer.getServer().overworld(); private static Entity fakeNmsEntity = new ArmorStand(net.minecraft.world.entity.EntityType.ARMOR_STAND, level); + @Override @SuppressWarnings("unchecked") + public void sendSharedEntityData(int entityId, Map dataValues, List sendTo) { + List> nmsDataValues = dataValues.entrySet().stream().map(entry -> { + int index = entry.getKey(); + Number value = entry.getValue(); + return switch (value) { + case Byte byteVal -> new SynchedEntityData.DataValue<>(index, EntityDataSerializers.BYTE, byteVal); + case Float floatVal -> new SynchedEntityData.DataValue<>(index, EntityDataSerializers.FLOAT, floatVal); + case Integer intVal -> new SynchedEntityData.DataValue<>(index, EntityDataSerializers.INT, intVal); + default -> + throw new IllegalArgumentException("Unsupported data value type: " + value.getClass().getSimpleName()); + }; + }).collect(Collectors.toList()); + + ClientboundSetEntityDataPacket packet = new ClientboundSetEntityDataPacket(entityId, nmsDataValues); + for (Player player : sendTo) sendPacket(player, packet); + } + + @Override + public void sendFakePlayerInfoPacket( + final Player skinnedPlayer, + final int entityId, + final UUID uuid, + final String npcName, + final List sendTo + ) { + ServerPlayer player = ((CraftPlayer) skinnedPlayer).getHandle(); + String name = npcName.substring(0, 15); + GameProfile profile = new GameProfile(uuid, name); + + Component component = AdventureUtils.MINI_MESSAGE.deserialize(name); + net.minecraft.network.chat.Component nmsComponent = HibiscusCommonsPlugin.isOnPaper() ? PaperAdventure.asVanilla(component) : net.minecraft.network.chat.Component.literal(name); + + ClientboundPlayerInfoUpdatePacket.Entry entry = new ClientboundPlayerInfoUpdatePacket.Entry(uuid, profile, false, 0, GameType.CREATIVE, nmsComponent, true, player.listOrder, player.getChatSession().asData()); + EnumSet actions = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER); + ClientboundPlayerInfoUpdatePacket packet = new ClientboundPlayerInfoUpdatePacket(actions, entry); + for (Player p : sendTo) sendPacket(p, packet); + } + + @Override + public void sendPlayerInfoRemovePacket(final UUID uuid, final List sendTo) { + ClientboundPlayerInfoRemovePacket packet = new ClientboundPlayerInfoRemovePacket(List.of(uuid)); + for (Player player : sendTo) sendPacket(player, packet); + } + + @Override + public void sendMovePacket( + final int entityId, + final @NotNull Location from, + final @NotNull Location to, + final boolean onGround, + @NotNull List sendTo + ) { + byte dx = (byte) (to.getX() - from.getX()); + byte dy = (byte) (to.getY() - from.getY()); + byte dz = (byte) (to.getZ() - from.getZ()); + + ClientboundMoveEntityPacket.Pos packet = new ClientboundMoveEntityPacket.Pos(entityId, dx, dy, dz, onGround); + for (Player p : sendTo) sendPacket(p, packet); + } + @Override public void sendGamemodeChange(Player player, GameMode gameMode) { ClientboundGameEventPacket.Type type = ClientboundGameEventPacket.CHANGE_GAME_MODE; @@ -78,6 +139,15 @@ public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons. for (Player p : sendTo) sendPacket(p, packet); } + @Override + public void sendRotationPacket(int entityId, float yaw, float pitch, boolean onGround, List sendTo) { + float ROTATION_FACTOR = 256.0F / 360.0F; + yaw = (byte) (yaw * ROTATION_FACTOR); + pitch = (byte) (pitch * ROTATION_FACTOR); + ClientboundMoveEntityPacket.Rot packet = new ClientboundMoveEntityPacket.Rot(entityId, (byte) yaw, (byte) pitch, onGround); + for (Player p : sendTo) sendPacket(p, packet); + } + @Override public void sendRotationPacket(int entityId, Location location, boolean onGround, List sendTo) { float ROTATION_FACTOR = 256.0F / 360.0F; diff --git a/v1_21_R4/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R4/NMSPackets.java b/v1_21_R4/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R4/NMSPackets.java index 892b509..d4d7197 100644 --- a/v1_21_R4/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R4/NMSPackets.java +++ b/v1_21_R4/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R4/NMSPackets.java @@ -3,22 +3,26 @@ package me.lojosho.hibiscuscommons.nms.v1_21_R4; import com.google.common.collect.ImmutableList; import com.google.gson.JsonArray; import com.google.gson.JsonObject; +import com.mojang.authlib.GameProfile; import com.mojang.datafixers.util.Pair; import com.mojang.serialization.JsonOps; -import io.lumine.mythic.bukkit.utils.redis.jedis.Client; -import io.netty.buffer.Unpooled; +import io.papermc.paper.adventure.AdventureComponent; +import io.papermc.paper.adventure.PaperAdventure; import it.unimi.dsi.fastutil.ints.IntList; import me.lojosho.hibiscuscommons.HibiscusCommonsPlugin; +import me.lojosho.hibiscuscommons.util.AdventureUtils; import net.kyori.adventure.text.Component; import net.kyori.adventure.text.serializer.gson.GsonComponentSerializer; -import net.kyori.adventure.text.serializer.json.JSONComponentSerializer; -import net.minecraft.advancements.*; -import net.minecraft.commands.arguments.EntityAnchorArgument; -import net.minecraft.network.FriendlyByteBuf; +import net.minecraft.advancements.Advancement; +import net.minecraft.advancements.AdvancementHolder; +import net.minecraft.core.HolderLookup; +import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.network.protocol.Packet; import net.minecraft.network.protocol.game.*; +import net.minecraft.network.syncher.EntityDataSerializer; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; +import net.minecraft.resources.RegistryOps; import net.minecraft.resources.ResourceLocation; import net.minecraft.server.MinecraftServer; import net.minecraft.server.level.ServerLevel; @@ -28,39 +32,97 @@ import net.minecraft.world.entity.EquipmentSlot; import net.minecraft.world.entity.PositionMoveRotation; import net.minecraft.world.entity.decoration.ArmorStand; import net.minecraft.world.entity.player.Inventory; -import net.minecraft.world.level.portal.TeleportTransition; +import net.minecraft.world.level.GameType; import net.minecraft.world.phys.Vec3; import net.minecraft.world.scores.PlayerTeam; import net.minecraft.world.scores.Team; +import org.apache.commons.lang3.tuple.Triple; import org.bukkit.Bukkit; import org.bukkit.Color; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.craftbukkit.CraftEquipmentSlot; -import org.bukkit.craftbukkit.entity.CraftEntity; import org.bukkit.craftbukkit.entity.CraftEntityType; import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.craftbukkit.inventory.CraftItemStack; import org.bukkit.craftbukkit.scoreboard.CraftScoreboard; -import org.bukkit.entity.Display; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.ItemDisplay; -import org.bukkit.entity.Player; -import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.entity.*; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.components.CustomModelDataComponent; +import org.jetbrains.annotations.NotNull; import org.joml.Quaternionf; import org.joml.Vector3f; -import java.lang.reflect.Constructor; import java.util.*; +import java.util.stream.Collectors; public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons.nms.NMSPackets { private static ServerLevel level = MinecraftServer.getServer().overworld(); private static Entity fakeNmsEntity = new ArmorStand(net.minecraft.world.entity.EntityType.ARMOR_STAND, level); + @Override @SuppressWarnings("unchecked") + public void sendSharedEntityData(int entityId, Map dataValues, List sendTo) { + List> nmsDataValues = dataValues.entrySet().stream().map(entry -> { + int index = entry.getKey(); + Number value = entry.getValue(); + return switch (value) { + case Byte byteVal -> new SynchedEntityData.DataValue<>(index, EntityDataSerializers.BYTE, byteVal); + case Float floatVal -> new SynchedEntityData.DataValue<>(index, EntityDataSerializers.FLOAT, floatVal); + case Integer intVal -> new SynchedEntityData.DataValue<>(index, EntityDataSerializers.INT, intVal); + default -> + throw new IllegalArgumentException("Unsupported data value type: " + value.getClass().getSimpleName()); + }; + }).collect(Collectors.toList()); + + ClientboundSetEntityDataPacket packet = new ClientboundSetEntityDataPacket(entityId, nmsDataValues); + for (Player player : sendTo) sendPacket(player, packet); + } + + @Override + public void sendFakePlayerInfoPacket( + final Player skinnedPlayer, + final int entityId, + final UUID uuid, + final String npcName, + final List sendTo + ) { + ServerPlayer player = ((CraftPlayer) skinnedPlayer).getHandle(); + String name = npcName.substring(0, 15); + GameProfile profile = new GameProfile(uuid, name); + + Component component = AdventureUtils.MINI_MESSAGE.deserialize(name); + net.minecraft.network.chat.Component nmsComponent = HibiscusCommonsPlugin.isOnPaper() ? PaperAdventure.asVanilla(component) : net.minecraft.network.chat.Component.literal(name); + + ClientboundPlayerInfoUpdatePacket.Entry entry = new ClientboundPlayerInfoUpdatePacket.Entry(uuid, profile, false, 0, GameType.CREATIVE, nmsComponent, true, player.listOrder, player.getChatSession().asData()); + EnumSet actions = EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER); + ClientboundPlayerInfoUpdatePacket packet = new ClientboundPlayerInfoUpdatePacket(actions, entry); + for (Player p : sendTo) sendPacket(p, packet); + } + + @Override + public void sendPlayerInfoRemovePacket(final UUID uuid, final List sendTo) { + ClientboundPlayerInfoRemovePacket packet = new ClientboundPlayerInfoRemovePacket(List.of(uuid)); + for (Player player : sendTo) sendPacket(player, packet); + } + + @Override + public void sendMovePacket( + final int entityId, + final @NotNull Location from, + final @NotNull Location to, + final boolean onGround, + @NotNull List sendTo + ) { + byte dx = (byte) (to.getX() - from.getX()); + byte dy = (byte) (to.getY() - from.getY()); + byte dz = (byte) (to.getZ() - from.getZ()); + + ClientboundMoveEntityPacket.Pos packet = new ClientboundMoveEntityPacket.Pos(entityId, dx, dy, dz, onGround); + for (Player p : sendTo) sendPacket(p, packet); + } + @Override public void sendGamemodeChange(Player player, GameMode gameMode) { ClientboundGameEventPacket.Type type = ClientboundGameEventPacket.CHANGE_GAME_MODE; @@ -79,6 +141,15 @@ public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons. for (Player p : sendTo) sendPacket(p, packet); } + @Override + public void sendRotationPacket(int entityId, float yaw, float pitch, boolean onGround, List sendTo) { + float ROTATION_FACTOR = 256.0F / 360.0F; + yaw = (byte) (yaw * ROTATION_FACTOR); + pitch = (byte) (pitch * ROTATION_FACTOR); + ClientboundMoveEntityPacket.Rot packet = new ClientboundMoveEntityPacket.Rot(entityId, (byte) yaw, (byte) pitch, onGround); + for (Player p : sendTo) sendPacket(p, packet); + } + @Override public void sendRotationPacket(int entityId, Location location, boolean onGround, List sendTo) { float ROTATION_FACTOR = 256.0F / 360.0F; @@ -217,7 +288,7 @@ public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons. List sendTo ) { try { - ClientboundTeleportEntityPacket packet = ClientboundTeleportEntityPacket.teleport(entityId, new PositionMoveRotation(new Vec3(x, y, z), Vec3.ZERO, yaw, pitch), java.util.Set.of(), onGround); + ClientboundTeleportEntityPacket packet = ClientboundTeleportEntityPacket.teleport(entityId, new PositionMoveRotation(new Vec3(x, y, z), Vec3.ZERO, yaw, pitch), Set.of(), onGround); for (Player p : sendTo) sendPacket(p, packet); } catch (Exception e) { e.printStackTrace();