diff --git a/v1_21_R4/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R4/NMSPacketChannel.java b/v1_21_R4/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R4/NMSPacketChannel.java new file mode 100644 index 0000000..5eaa547 --- /dev/null +++ b/v1_21_R4/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R4/NMSPacketChannel.java @@ -0,0 +1,277 @@ +package me.lojosho.hibiscuscommons.nms.v1_21_R4; + +import com.mojang.datafixers.util.Pair; +import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import lombok.Getter; +import me.lojosho.hibiscuscommons.nms.NMSHandlers; +import me.lojosho.hibiscuscommons.packets.PacketAction; +import me.lojosho.hibiscuscommons.packets.wrapper.*; +import me.lojosho.hibiscuscommons.plugins.SubPlugins; +import me.lojosho.hibiscuscommons.util.MessagesUtil; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.game.*; +import net.minecraft.world.entity.ai.attributes.Attributes; +import net.minecraft.world.inventory.ClickType; +import net.minecraft.world.item.ItemStack; +import org.bukkit.craftbukkit.CraftEquipmentSlot; +import org.bukkit.craftbukkit.inventory.CraftItemStack; +import org.bukkit.entity.Player; +import org.bukkit.inventory.EquipmentSlot; +import org.jetbrains.annotations.NotNull; + +import java.util.*; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.Collectors; + +public class NMSPacketChannel extends ChannelDuplexHandler { + + @Getter + private final Player player; + + public NMSPacketChannel(Player player) { + this.player = player; + } + + @Override + public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { + if (!(msg instanceof Packet packet)) { + super.write(ctx, msg, promise); + return; + } + + switch (packet) { + case ClientboundContainerSetContentPacket setContentPacket -> msg = handleMenuChange(setContentPacket); + case ClientboundContainerSetSlotPacket setSlotPacket -> msg = handleSlotChange(setSlotPacket); + case ClientboundSetEquipmentPacket equipmentPacket -> msg = handlePlayerEquipment(equipmentPacket); + case ClientboundSetPassengersPacket passengerPacket -> msg = handlePassengerSet(passengerPacket); + case ClientboundUpdateAttributesPacket attributesPacket -> msg = handleScaleChange(attributesPacket); + default -> {} + } + + if (msg == null) return; + else super.write(ctx, msg, promise); + } + + private Packet handleMenuChange(@NotNull ClientboundContainerSetContentPacket packet) { + MessagesUtil.sendDebugMessages("ClientboundContainerSetContentPacket"); + MessagesUtil.sendDebugMessages("Menu Initial "); + + Integer windowId = packet.containerId(); + List slotData = packet.items(); + + List bukkitItems = new ArrayList<>(); + for (ItemStack nmsItem : slotData) { + if (nmsItem == null) { + slotData.add(null); + continue; + } + bukkitItems.add(CraftItemStack.asBukkitCopy(nmsItem)); + } + + AtomicReference action = new AtomicReference<>(PacketAction.NOTHING); + ContainerContentWrapper wrapper = new ContainerContentWrapper(windowId, bukkitItems); + SubPlugins.getSubPlugins().forEach(plugin -> { + + PacketAction pluginAction = plugin.getPacketInterface().writeContainerContent(player, wrapper); + if (pluginAction != PacketAction.NOTHING) action.set(pluginAction); + }); + + if (action.get() == PacketAction.CANCELLED) return null; + if (action.get() == PacketAction.NOTHING) return packet; + + List nmsItems = new ArrayList<>(); + for (org.bukkit.inventory.ItemStack bukkitItem : bukkitItems) { + if (bukkitItem == null) { + slotData.add(null); + continue; + } + nmsItems.add(CraftItemStack.asNMSCopy(bukkitItem)); + } + + return new ClientboundContainerSetContentPacket(wrapper.getWindowId(), packet.stateId(), nmsItems, packet.carriedItem()); + } + + private Packet handleSlotChange(@NotNull ClientboundContainerSetSlotPacket packet) { + MessagesUtil.sendDebugMessages("ClientboundContainerSetSlotPacket"); + + final int windowId = packet.getContainerId(); + final int slot = packet.getSlot(); + final ItemStack item = packet.getItem(); + + org.bukkit.inventory.ItemStack bukkitItem = CraftItemStack.asBukkitCopy(item); + + AtomicReference action = new AtomicReference<>(PacketAction.NOTHING); + SlotContentWrapper wrapper = new SlotContentWrapper(windowId, slot, bukkitItem); + + SubPlugins.getSubPlugins().forEach(plugin -> { + PacketAction pluginAction = plugin.getPacketInterface().writeSlotContent(player, wrapper); + if (pluginAction != PacketAction.NOTHING) action.set(pluginAction); + }); + + if (action.get() == PacketAction.CANCELLED) return null; + if (action.get() == PacketAction.NOTHING) return packet; + + final ItemStack nmsItem = CraftItemStack.asNMSCopy(wrapper.getItemStack()); + + return new ClientboundContainerSetSlotPacket(packet.getContainerId(), packet.getStateId(), wrapper.getSlot(), nmsItem); + } + + private Packet handlePlayerEquipment(@NotNull ClientboundSetEquipmentPacket packet) { + MessagesUtil.sendDebugMessages("ClientboundSetEquipmentPacket"); + final List> nmsArmor = packet.getSlots(); + final int entity = packet.getEntity(); + HashMap bukkitArmor = new HashMap<>(); + for (Pair piece : nmsArmor) { + EquipmentSlot slot = CraftEquipmentSlot.getSlot(piece.getFirst()); + org.bukkit.inventory.ItemStack itemStack = CraftItemStack.asBukkitCopy(piece.getSecond()); + bukkitArmor.put(slot, itemStack); + } + + AtomicReference action = new AtomicReference<>(PacketAction.NOTHING); + EntityEquipmentWrapper wrapper = new EntityEquipmentWrapper(entity, bukkitArmor); + + SubPlugins.getSubPlugins().forEach(plugin -> { + PacketAction pluginAction = plugin.getPacketInterface().writeEquipmentContent(player, wrapper); + if (pluginAction != PacketAction.NOTHING) action.set(pluginAction); + }); + + if (action.get() == PacketAction.CANCELLED) return null; + if (action.get() == PacketAction.NOTHING) return packet; + + List> newArmor = new ArrayList<>(); + for (Map.Entry entry : wrapper.getArmor().entrySet()) { + net.minecraft.world.entity.EquipmentSlot slot = CraftEquipmentSlot.getNMS(entry.getKey()); + ItemStack itemStack = CraftItemStack.asNMSCopy(entry.getValue()); + newArmor.add(new Pair<>(slot, itemStack)); + } + + return new ClientboundSetEquipmentPacket(packet.getEntity(), newArmor); + } + + private Packet handlePassengerSet(@NotNull ClientboundSetPassengersPacket packet) { + MessagesUtil.sendDebugMessages("ClientboundSetPassengersPacket"); + int ownerId = packet.getVehicle(); + List passengers = Arrays.stream(packet.getPassengers()).boxed().collect(Collectors.toList()); + MessagesUtil.sendDebugMessages("Mount Packet Sent - Read - EntityID: " + ownerId); + + AtomicReference action = new AtomicReference<>(PacketAction.NOTHING); + PassengerWrapper wrapper = new PassengerWrapper(ownerId, passengers); + SubPlugins.getSubPlugins().forEach(plugin -> { + PacketAction pluginAction = plugin.getPacketInterface().writePassengerContent(player, wrapper); + if (pluginAction != PacketAction.NOTHING) { + action.set(pluginAction); + } + }); + + if (action.get() == PacketAction.CANCELLED) return null; + if (action.get() == PacketAction.NOTHING) return packet; + return (Packet) NMSHandlers.getHandler().getPacketHandler().createMountPacket(ownerId, passengers.stream().mapToInt(Integer::intValue).toArray()); + } + + private Packet handleScaleChange(@NotNull ClientboundUpdateAttributesPacket packet) { + final List nmsAttributes = packet.getValues(); + final ClientboundUpdateAttributesPacket.AttributeSnapshot nmsScaleAttribute = nmsAttributes.stream() + .filter(attribute -> attribute.attribute().equals(Attributes.SCALE)) + .findFirst() + .orElse(null); + + if (nmsScaleAttribute == null) { + return packet; + } + + AtomicReference action = new AtomicReference<>(PacketAction.NOTHING); + PlayerScaleWrapper wrapper = new PlayerScaleWrapper(packet.getEntityId(), nmsScaleAttribute.base()); + + SubPlugins.getSubPlugins().forEach(plugin -> { + PacketAction pluginAction = plugin.getPacketInterface().readPlayerScale(player, wrapper); + if (pluginAction != PacketAction.NOTHING) action.set(pluginAction); + }); + + if (action.get() == PacketAction.CANCELLED) return null; + if (action.get() == PacketAction.NOTHING) return packet; + return packet; + } + + @Override + public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception { + if (!(msg instanceof Packet packet)) { + super.channelRead(ctx, msg); + return; + } + + switch (packet) { + case ServerboundContainerClickPacket clickPacket -> msg = handleInventoryClick(clickPacket); + case ServerboundPlayerActionPacket playerActionPacket -> msg = handlePlayerAction(playerActionPacket); + case ServerboundSwingPacket swingPacket -> msg = handlePlayerArm(swingPacket); + case ServerboundInteractPacket interactPacket -> msg = handleInteract(interactPacket); + default -> {} + } + + if (msg == null) return; + else super.channelRead(ctx, msg); + } + + private Packet handleInventoryClick(@NotNull ServerboundContainerClickPacket packet) { + MessagesUtil.sendDebugMessages("ServerboundContainerClickPacket"); + ClickType clickType = packet.clickType(); + int slotClicked = packet.slotNum(); + + AtomicReference action = new AtomicReference<>(PacketAction.NOTHING); + SubPlugins.getSubPlugins().forEach(plugin -> { + + PacketAction pluginAction = plugin.getPacketInterface().readInventoryClick(player, new InventoryClickWrapper(clickType.id(), slotClicked)); + if (pluginAction != PacketAction.NOTHING) action.set(pluginAction); + + }); + if (action.get() == PacketAction.CANCELLED) return null; + return packet; + } + + private Packet handlePlayerAction(ServerboundPlayerActionPacket packet) { + MessagesUtil.sendDebugMessages("ServerboundPlayerActionPacket"); + ServerboundPlayerActionPacket.Action playerAction = packet.getAction(); + + AtomicReference action = new AtomicReference<>(PacketAction.NOTHING); + SubPlugins.getSubPlugins().forEach(plugin -> { + + PacketAction pluginAction = plugin.getPacketInterface().readPlayerAction(player, new PlayerActionWrapper(playerAction.name())); + if (pluginAction != PacketAction.NOTHING) action.set(pluginAction); + + }); + if (action.get() == PacketAction.CANCELLED) return null; + return packet; + } + + private Packet handlePlayerArm(@NotNull ServerboundSwingPacket packet) { + MessagesUtil.sendDebugMessages("ServerboundSwingPacket"); + PlayerSwingWrapper wrapper = new PlayerSwingWrapper(packet.getHand().name()); + + AtomicReference action = new AtomicReference<>(PacketAction.NOTHING); + SubPlugins.getSubPlugins().forEach(plugin -> { + + PacketAction pluginAction = plugin.getPacketInterface().readPlayerArm(player, wrapper); + if (pluginAction != PacketAction.NOTHING) action.set(pluginAction); + + }); + if (action.get() == PacketAction.CANCELLED) return null; + return packet; + } + + private Packet handleInteract(@NotNull ServerboundInteractPacket packet) { + MessagesUtil.sendDebugMessages("ServerboundInteractPacket"); + + PlayerInteractWrapper wrapper = new PlayerInteractWrapper(packet.getEntityId()); + + AtomicReference action = new AtomicReference<>(PacketAction.NOTHING); + SubPlugins.getSubPlugins().forEach(plugin -> { + + PacketAction pluginAction = plugin.getPacketInterface().readEntityHandle(player, wrapper); + if (pluginAction != PacketAction.NOTHING) action.set(pluginAction); + + }); + if (action.get() == PacketAction.CANCELLED) return null; + return packet; + } +} \ No newline at end of file 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 c89328a..0d13d1e 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 @@ -7,24 +7,21 @@ import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; import com.mojang.datafixers.util.Pair; import com.mojang.serialization.JsonOps; -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 me.lojosho.hibiscuscommons.util.MessagesUtil; 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.core.HolderLookup; -import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.commands.arguments.EntityAnchorArgument; import net.minecraft.network.chat.RemoteChatSession; 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; @@ -40,17 +37,16 @@ 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.*; import org.bukkit.craftbukkit.CraftEquipmentSlot; 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.*; +import org.bukkit.entity.Display; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.ItemDisplay; +import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.inventory.meta.components.CustomModelDataComponent; @@ -144,6 +140,14 @@ public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons. sendPacket(player, packet); } + @Override + public void sendLookAtPacket(int entityId, Location location, List sendTo) { + fakeNmsEntity.setId(entityId); + fakeNmsEntity.getBukkitEntity().teleport(location); + ClientboundPlayerLookAtPacket packet = new ClientboundPlayerLookAtPacket(EntityAnchorArgument.Anchor.EYES, fakeNmsEntity, EntityAnchorArgument.Anchor.EYES); + for (Player p : sendTo) sendPacket(p, packet); + } + @Override public void sendRotateHeadPacket(int entityId, Location location, List sendTo) { fakeNmsEntity.setId(entityId); @@ -154,10 +158,11 @@ public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons. } @Override - public void sendRotationPacket(int entityId, float yaw, float pitch, boolean onGround, List sendTo) { + public void sendRotationPacket(int entityId, float originalYaw, float pitch, boolean onGround, List sendTo) { float ROTATION_FACTOR = 256.0F / 360.0F; - yaw = (byte) (yaw * ROTATION_FACTOR); + byte yaw = (byte) (originalYaw * ROTATION_FACTOR); pitch = (byte) (pitch * ROTATION_FACTOR); + MessagesUtil.sendDebugMessages("sendRotationPacket. Original: " + originalYaw + " modified: " + yaw); ClientboundMoveEntityPacket.Rot packet = new ClientboundMoveEntityPacket.Rot(entityId, (byte) yaw, (byte) pitch, onGround); for (Player p : sendTo) sendPacket(p, packet); } @@ -257,6 +262,7 @@ public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons. //Adding players to the team (You have to use the NPC's name, and add it to a list) ClientboundSetPlayerTeamPacket createPlayerTeamPacket = ClientboundSetPlayerTeamPacket.createMultiplePlayerPacket(team, new ArrayList() {{ add(name); + add(player.getName()); }}, ClientboundSetPlayerTeamPacket.Action.ADD); sendPacket(player, createPlayerTeamPacket); } @@ -269,6 +275,7 @@ public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons. passenger.setId(id); return passenger; }).toList(); + fakeNmsEntity.setId(mountId); fakeNmsEntity.passengers = ImmutableList.copyOf(passengers); ClientboundSetPassengersPacket packet = new ClientboundSetPassengersPacket(fakeNmsEntity); fakeNmsEntity.passengers = ImmutableList.of(); @@ -438,6 +445,11 @@ public class NMSPackets extends NMSCommon implements me.lojosho.hibiscuscommons. components.add("minecraft:custom_model_data", customModelDataComponentJson); } + NamespacedKey itemModel = meta.getItemModel(); + if (itemModel != null) { + components.addProperty("minecraft:item_model", itemModel.toString()); + } + iconObj.add("components", components); } diff --git a/v1_21_R4/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R4/NMSUtils.java b/v1_21_R4/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R4/NMSUtils.java index 1b314be..6150903 100644 --- a/v1_21_R4/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R4/NMSUtils.java +++ b/v1_21_R4/src/main/java/me/lojosho/hibiscuscommons/nms/v1_21_R4/NMSUtils.java @@ -1,12 +1,17 @@ package me.lojosho.hibiscuscommons.nms.v1_21_R4; +import io.netty.channel.Channel; +import io.netty.channel.ChannelPipeline; import net.minecraft.core.component.DataComponents; +import net.minecraft.network.Connection; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.item.component.DyedItemColor; import org.bukkit.Bukkit; import org.bukkit.Color; import org.bukkit.craftbukkit.CraftServer; +import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.craftbukkit.inventory.CraftItemStack; +import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -51,4 +56,16 @@ public class NMSUtils extends NMSCommon implements me.lojosho.hibiscuscommons.nm } return null; } + + @Override + public void handleChannelOpen(@NotNull Player player) { + Channel channel = ((CraftPlayer) player).getHandle().connection.connection.channel; + ChannelPipeline pipeline = channel.pipeline(); + + NMSPacketChannel channelHandler = new NMSPacketChannel(player); + for (String key : pipeline.toMap().keySet()) { + if (!(pipeline.get(key) instanceof Connection)) continue; + pipeline.addBefore(key, "hibiscus_channel_handler", channelHandler); + } + } }