NullValkyrie

Minecraft 1.19 multipurpose plugin for spigot servers with a lot of features where most modern servers have.
git clone https://codeberg.org/night0721/NullValkyrie
Log | Files | Refs | README | LICENSE

commit 993db89f09ec5ff7099e09fc62970556db9f8790
parent cb71751fed0d7609c82d62c9d3a68db0af05bddc
Author: NK <[email protected]>
Date:   Sat, 24 Dec 2022 02:35:17 +0000

using nms wrappers

Diffstat:
Asrc/main/java/IDEAS | 101+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/main/java/me/night/nullvalkyrie/commands/BetaCommand.java | 2++
Msrc/main/java/me/night/nullvalkyrie/entities/holograms/PerPlayerHologram.java | 15+++++----------
Msrc/main/java/me/night/nullvalkyrie/entities/npcs/NPCManager.java | 16+++++++---------
Msrc/main/java/me/night/nullvalkyrie/events/listeners/CustomItemEvents.java | 25++-----------------------
Msrc/main/java/me/night/nullvalkyrie/events/listeners/ServerEvents.java | 2+-
Dsrc/main/java/me/night/nullvalkyrie/packets/PacketHandler.java | 65-----------------------------------------------------------------
Dsrc/main/java/me/night/nullvalkyrie/packets/PacketInjector.java | 31-------------------------------
Asrc/main/java/me/night/nullvalkyrie/packets/handle/PacketHandler.java | 65+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/main/java/me/night/nullvalkyrie/packets/handle/PacketInjector.java | 30++++++++++++++++++++++++++++++
Asrc/main/java/me/night/nullvalkyrie/packets/protocol/Channel.java | 10++++++++++
Asrc/main/java/me/night/nullvalkyrie/packets/protocol/Packet.java | 4++++
Asrc/main/java/me/night/nullvalkyrie/packets/protocol/PacketPlayOutBlockBreakAnimation.java | 14++++++++++++++
Asrc/main/java/me/night/nullvalkyrie/packets/protocol/PacketPlayOutEntityMetadata.java | 15+++++++++++++++
Asrc/main/java/me/night/nullvalkyrie/packets/protocol/PacketPlayOutSpawnEntity.java | 13+++++++++++++
15 files changed, 269 insertions(+), 139 deletions(-)

diff --git a/src/main/java/IDEAS b/src/main/java/IDEAS @@ -0,0 +1,100 @@ +A teleportation plugin that allows players to easily and quickly travel to different locations on the server. +A rewards system that gives players rewards for reaching certain milestones, such as reaching a certain level or completing specific tasks. +A custom enchantments plugin that allows players to add unique enchantments to their gear. +A custom crafting system that adds new recipes and allows players to create unique items. +A minigame plugin that adds fun, engaging minigames for players to enjoy. +A player-run economy plugin that allows players to trade and sell items with one another. +A chat enhancement plugin that adds fun emotes, chat formatting options, and other features to improve the chat experience. +A pet plugin that allows players to tame and care for their own pets. +A player-run shop plugin that allows players to create their own shops and sell items to other players. +A dungeon generator plugin that randomly generates challenging dungeon experiences for players to explore. +A chat enhancement plugin that allows players to use custom emotes and chat formatting. +A teleportation plugin that allows players to set and teleport to waypoints. +A death tracker plugin that keeps track of how many times a player has died and displays it in chat. +A farming plugin that makes it easier for players to plant and grow crops. +A minigame plugin that adds new games for players to play, such as parkour challenges or capture the flag. +A voting plugin that allows players to vote on different options, such as which game mode to play next or which map to use. +A recipe book plugin that allows players to access a comprehensive list of all the crafting recipes in the game. +An economy plugin that adds a virtual currency and trading system to the game, allowing players to buy and sell items with one another. +A permissions plugin that allows server administrators to manage player permissions and control who can do what on the server. +A game mode plugin that adds new game modes, such as creative mode or adventure mode, for players to choose from. +A dungeon generation plugin that automatically generates new dungeon structures for players to explore and conquer. +A parkour plugin that adds new parkour maps and challenges for players to complete. +A mob spawning control plugin that allows players to customize mob spawning behavior on the server. +A music plugin that allows players to play music in-game using note blocks. +A custom crafting plugin that allows players to create their own custom crafting recipes. +A loot table editor plugin that allows players to customize the loot that mobs drop when they are killed. +A scoreboard plugin that allows players to create and customize their own in-game scoreboard. +A grief prevention plugin that allows players to protect their builds from being destroyed by other players. +A teleport request plugin that allows players to request teleportations to other players and requires the other player to accept the request before the teleportation occurs. +A weather control plugin that allows players to change the weather on the server, such as making it rain or clearing up the skies. +A plugin that adds new types of blocks, items, or mobs to the game. +A plugin that allows players to create and customize their own in-game homes or shops. +A plugin that introduces a new type of game mechanic, such as a crafting system or a trading system. +A plugin that adds new mini-games or challenges for players to complete. +A plugin that allows players to use custom skins or textures for their characters. +A plugin that introduces a new level of difficulty for players to experience, such as a "hardcore" mode. +A plugin that adds new, themed environments for players to explore, such as a jungle or a desert. +A plugin that allows players to create and manage their own in-game economy, with the ability to buy and sell items with each other. +A plugin that introduces new forms of transportation, such as minecart rail networks or boats. +A plugin that allows players to create and customize their own in-game maps, which can be shared with other players. +A plugin that allows players to create and customize their own in-game characters, including appearance, abilities, and stats. +A plugin that introduces new forms of combat, such as ranged weapons or magic spells. +A plugin that adds new dungeons or boss battles for players to challenge. +A plugin that allows players to create and join different factions or clans, and compete against each other in in-game events or challenges. +A plugin that adds new biomes or dimensions for players to explore, such as a Nether or a End-like dimension. +A plugin that introduces new environmental hazards or challenges, such as weather effects or dangerous mobs. +A plugin that allows players to create and customize their own in-game weapons, armor, or tools. +A plugin that adds new types of crops, food, or farming tools for players to use. +A plugin that allows players to create and customize their own in-game quests or objectives, which can be shared with other players. +A plugin that introduces new forms of transportation, such as flying mounts or teleportation spells. +A plugin that adds new forms of currency, such as virtual coins or tokens, which players can earn and spend in-game. +A plugin that introduces new forms of resource gathering or processing, such as mining, smelting, or crafting. +A plugin that allows players to create and customize their own in-game shops or markets, where they can buy and sell items with each other. +A plugin that adds new challenges or events for players to participate in, such as races, tournaments, or scavenger hunts. +A plugin that allows players to create and customize their own in-game pets or companions, which can provide various benefits or abilities. +A plugin that adds new environmental effects, such as day/night cycles or changing seasons. +A plugin that allows players to create and customize their own in-game vehicles, such as cars, planes, or boats. +A plugin that introduces new forms of player-versus-player (PvP) combat, such as team battles or capture the flag. +A plugin that allows players to create and customize their own in-game skills or abilities, which can be leveled up and improved over time. +A plugin that adds new types of terrain or structures for players to explore, such as caves, ruins, or abandoned buildings. +A player teleportation plugin +A plugin that adds custom crafting recipes +A plugin that adds new types of enemies and boss battles +A plugin that allows players to create and join guilds +A plugin that adds new types of weapons and armor +A plugin that allows players to create and customize their own houses +A plugin that adds a quest and adventure system +A plugin that adds new types of biomes and dimensions +A plugin that allows players to ride and breed different types of horses +A plugin that adds new types of crops and plants for players to farm +A plugin that allows players to fish and cook different types of food +A plugin that adds new types of pets and companions for players to tame +A plugin that allows players to create and customize their own NPC characters +A plugin that adds new types of weather and environmental effects +A plugin that allows players to craft and use magic spells +A plugin that adds new types of transportation, such as minecarts or boats +A plugin that allows players to build and customize their own vehicles +A plugin that adds new types of trades and professions for players to pursue +A plugin that allows players to play mini-games and challenges with other players +A plugin that adds new types of items and resources for players to collect and use. +A plugin that adds a new type of energy system for players to manage and use +A plugin that allows players to build and customize their own multi-block structures +A plugin that adds new types of dimensions, each with their own unique features and challenges +A plugin that allows players to build and customize their own custom weapons and armor +A plugin that adds new types of resources, such as ores, gems, and fluids, that players can extract and use +A plugin that allows players to create and customize their own custom enchantments and potion effects +A plugin that adds new types of machines and technology for players to build and use +A plugin that allows players to create and customize their own custom items and blocks +A plugin that adds new types of hazards and challenges, such as natural disasters or enemy attacks, for players to face +A plugin that allows players to build and customize their own transportation networks, such as railways or highways +A plugin that adds new types of terrain and landscape features, such as caves, ravines, and mountains +A plugin that allows players to create and customize their own custom game modes and rules +A plugin that adds new types of interactive objects and mechanisms for players to use and explore +A plugin that allows players to build and customize their own custom AI entities, such as guards or pets +A plugin that adds new types of environmental effects and physics, such as dynamic lighting or water simulation +A plugin that allows players to create and customize their own custom dimension and world generation settings +A plugin that adds new types of resources and materials for players to collect and use in their builds +A plugin that allows players to create and customize their own custom multiplayer game modes and rules +A plugin that adds new types of challenges and rewards for players to earn and unlock +A plugin that allows players to create and customize their own custom adventure maps and scenarios. +\ No newline at end of file diff --git a/src/main/java/me/night/nullvalkyrie/commands/BetaCommand.java b/src/main/java/me/night/nullvalkyrie/commands/BetaCommand.java @@ -1,5 +1,6 @@ package me.night.nullvalkyrie.commands; +import me.night.nullvalkyrie.entities.npcs.NPCManager; import me.night.nullvalkyrie.entities.pets.ZombiePet; import org.bukkit.Material; import org.bukkit.command.CommandSender; @@ -33,6 +34,7 @@ public class BetaCommand extends Command { itemMeta2.setCustomModelData(1010101); item2.setItemMeta(itemMeta2); player.getInventory().addItem(item2); + NPCManager.createNPC(player, args[0]); } } diff --git a/src/main/java/me/night/nullvalkyrie/entities/holograms/PerPlayerHologram.java b/src/main/java/me/night/nullvalkyrie/entities/holograms/PerPlayerHologram.java @@ -1,18 +1,16 @@ package me.night.nullvalkyrie.entities.holograms; +import me.night.nullvalkyrie.packets.protocol.PacketPlayOutEntityMetadata; +import me.night.nullvalkyrie.packets.protocol.PacketPlayOutSpawnEntity; import net.minecraft.network.chat.Component; -import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; -import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; import net.minecraft.server.level.ServerPlayer; -import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.world.entity.decoration.ArmorStand; import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer; import org.bukkit.entity.Player; -import java.util.List; import java.util.Optional; public class PerPlayerHologram { @@ -27,13 +25,10 @@ public class PerPlayerHologram { ServerPlayer p = ((CraftPlayer) player).getHandle(); ArmorStand stand = new ArmorStand(p.level, player.getLocation().getX(), y, player.getLocation().getZ()); stand.setInvisible(true); - ServerGamePacketListenerImpl connection = p.connection; - connection.send(new ClientboundAddEntityPacket(stand)); + new PacketPlayOutSpawnEntity(player, stand); SynchedEntityData watcher = stand.getEntityData(); - Optional<Component> optional = Optional.of(Component.nullToEmpty(line)); - watcher.set(new EntityDataAccessor<>(2, EntityDataSerializers.OPTIONAL_COMPONENT), optional); + watcher.set(new EntityDataAccessor<>(2, EntityDataSerializers.OPTIONAL_COMPONENT), Optional.of(Component.nullToEmpty(line))); watcher.set(new EntityDataAccessor<>(3, EntityDataSerializers.BOOLEAN), true); - List<SynchedEntityData.DataValue<?>> list = watcher.getNonDefaultValues(); - connection.send(new ClientboundSetEntityDataPacket(stand.getBukkitEntity().getEntityId(), list)); + new PacketPlayOutEntityMetadata(player, stand, watcher.getNonDefaultValues()); } } diff --git a/src/main/java/me/night/nullvalkyrie/entities/npcs/NPCManager.java b/src/main/java/me/night/nullvalkyrie/entities/npcs/NPCManager.java @@ -3,8 +3,9 @@ package me.night.nullvalkyrie.entities.npcs; import com.mojang.authlib.GameProfile; import com.mojang.authlib.properties.Property; import com.mojang.datafixers.util.Pair; -import me.night.nullvalkyrie.Main; import me.night.nullvalkyrie.database.NPCDataManager; +import me.night.nullvalkyrie.packets.protocol.PacketPlayOutEntityMetadata; +import me.night.nullvalkyrie.packets.protocol.PacketPlayOutSpawnEntity; import me.night.nullvalkyrie.util.*; import net.minecraft.network.protocol.game.*; import net.minecraft.network.syncher.*; @@ -35,6 +36,7 @@ public class NPCManager { return NPCs; } public static void createNPC(Player player, String name) { // name must be less than 16 characters including color codes + // TODO: npc not even spawning rn ServerPlayer sp = ((CraftPlayer) player).getHandle(); MinecraftServer server = sp.server; ServerLevel level = ((CraftWorld) player.getLocation().getWorld()).getHandle(); @@ -51,13 +53,11 @@ public class NPCManager { public static void addNPCPacket(ServerPlayer npc) { for (Player player : Bukkit.getOnlinePlayers()) { ServerGamePacketListenerImpl pc = ((CraftPlayer) player).getHandle().connection; - pc.send(new ClientboundAddPlayerPacket(npc)); + new PacketPlayOutSpawnEntity(player, npc); pc.send(new ClientboundRotateHeadPacket(npc, (byte) (npc.getBukkitYaw() * 256 / 360))); SynchedEntityData watcher = npc.getEntityData(); watcher.set(new EntityDataAccessor<>(17, EntityDataSerializers.BYTE), (byte) 127); - List<SynchedEntityData.DataValue<?>> list = watcher.getNonDefaultValues(); - pc.send(new ClientboundSetEntityDataPacket(npc.getBukkitEntity().getEntityId(), list)); - Bukkit.getScheduler().runTaskLaterAsynchronously(Main.getPlugin(Main.class), () -> pc.send(new ClientboundPlayerInfoRemovePacket(List.of(npc.getUUID()))), 50); + new PacketPlayOutEntityMetadata(player, npc, watcher.getNonDefaultValues()); ItemStack netheriteAxe = new ItemStack(Material.NETHERITE_AXE); ItemStack anotherAxe = new ItemStack(Material.NETHERITE_INGOT); List<Pair<EquipmentSlot, net.minecraft.world.item.ItemStack>> itemList = new ArrayList<>(); @@ -70,13 +70,11 @@ public class NPCManager { public static void addJoinPacket(Player player) { for (ServerPlayer npc : NPCs) { ServerGamePacketListenerImpl pc = ((CraftPlayer) player).getHandle().connection; - pc.send(new ClientboundAddPlayerPacket(npc)); + new PacketPlayOutSpawnEntity(player, npc); pc.send(new ClientboundRotateHeadPacket(npc, (byte) (npc.getBukkitYaw() * 256 / 360))); SynchedEntityData watcher = npc.getEntityData(); watcher.set(new EntityDataAccessor<>(17, EntityDataSerializers.BYTE), (byte) 127); - List<SynchedEntityData.DataValue<?>> list = watcher.getNonDefaultValues(); - pc.send(new ClientboundSetEntityDataPacket(npc.getBukkitEntity().getEntityId(), list)); - Bukkit.getScheduler().runTaskLaterAsynchronously(Main.getPlugin(Main.class), () -> pc.send(new ClientboundPlayerInfoRemovePacket(List.of(npc.getUUID()))), 50); + new PacketPlayOutEntityMetadata(player, npc, watcher.getNonDefaultValues()); ItemStack netheriteAxe = new ItemStack(Material.NETHERITE_AXE); ItemStack anotherAxe = new ItemStack(Material.NETHERITE_INGOT); List<Pair<EquipmentSlot, net.minecraft.world.item.ItemStack>> itemList = new ArrayList<>(); diff --git a/src/main/java/me/night/nullvalkyrie/events/listeners/CustomItemEvents.java b/src/main/java/me/night/nullvalkyrie/events/listeners/CustomItemEvents.java @@ -1,14 +1,10 @@ package me.night.nullvalkyrie.events.listeners; -import com.comphenix.protocol.PacketType; -import com.comphenix.protocol.ProtocolLibrary; -import com.comphenix.protocol.ProtocolManager; -import com.comphenix.protocol.events.PacketContainer; -import com.comphenix.protocol.wrappers.BlockPosition; import me.night.nullvalkyrie.entities.items.CustomItemManager; import me.night.nullvalkyrie.entities.items.Pickaxe; import me.night.nullvalkyrie.enums.Rarity; import me.night.nullvalkyrie.Main; +import me.night.nullvalkyrie.packets.protocol.PacketPlayOutBlockBreakAnimation; import net.md_5.bungee.api.ChatMessageType; import net.md_5.bungee.api.chat.TextComponent; import org.bukkit.*; @@ -26,7 +22,6 @@ import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.persistence.PersistentDataContainer; import org.bukkit.persistence.PersistentDataType; -import java.lang.reflect.InvocationTargetException; import java.util.*; public class CustomItemEvents implements Listener { @@ -327,26 +322,10 @@ public class CustomItemEvents implements Listener { int blockStage = blockStages.getOrDefault(block.getLocation(), 0); blockStage = blockStage == 10 ? 0 : blockStage + 1; blockStages.put(block.getLocation(), blockStage); - sendBlockDamage(player, block); + new PacketPlayOutBlockBreakAnimation(player, block.getLocation(), blockStages.get(block.getLocation())); if (blockStage == 0) { blockStages.remove(block.getLocation()); block.breakNaturally(); } } - - final ProtocolManager manager = ProtocolLibrary.getProtocolManager(); - - public void sendBlockDamage(Player player, Block block) { - Location location = block.getLocation(); - int locationId = location.getBlockX() + location.getBlockY() + location.getBlockZ(); - PacketContainer packet = manager.createPacket(PacketType.Play.Server.BLOCK_BREAK_ANIMATION); - packet.getIntegers().write(0, locationId); // set entity ID to the location - packet.getBlockPositionModifier().write(0, new BlockPosition(location.toVector())); // set the block location - packet.getIntegers().write(1, blockStages.get(location)); // set the damage to blockStage - try { - manager.sendServerPacket(player, packet); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - } } \ No newline at end of file diff --git a/src/main/java/me/night/nullvalkyrie/events/listeners/ServerEvents.java b/src/main/java/me/night/nullvalkyrie/events/listeners/ServerEvents.java @@ -1,7 +1,7 @@ package me.night.nullvalkyrie.events.listeners; import me.night.nullvalkyrie.events.custom.InteractHologramEvent; -import me.night.nullvalkyrie.packets.PacketInjector; +import me.night.nullvalkyrie.packets.handle.PacketInjector; import me.night.nullvalkyrie.util.Util; import org.bukkit.Bukkit; import org.bukkit.ChatColor; diff --git a/src/main/java/me/night/nullvalkyrie/packets/PacketHandler.java b/src/main/java/me/night/nullvalkyrie/packets/PacketHandler.java @@ -1,64 +0,0 @@ -package me.night.nullvalkyrie.packets; - -import io.netty.channel.ChannelDuplexHandler; -import io.netty.channel.ChannelHandlerContext; -import io.netty.channel.ChannelPromise; -import me.night.nullvalkyrie.Main; -import me.night.nullvalkyrie.entities.npcs.NPCManager; -import me.night.nullvalkyrie.events.custom.InteractHologramEvent; -import me.night.nullvalkyrie.events.custom.RightClickNPCEvent; -import me.night.nullvalkyrie.util.Util; -import net.minecraft.network.protocol.game.ServerboundInteractPacket; -import net.minecraft.server.level.ServerPlayer; -import org.bukkit.Bukkit; -import org.bukkit.entity.ArmorStand; -import org.bukkit.entity.Entity; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Player; - -public class PacketHandler extends ChannelDuplexHandler { - private final Player player; - - public PacketHandler(Player player) { - this.player = player; - } - - @Override - public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception { - super.write(ctx, msg, promise); - } - - @Override - public void channelRead(ChannelHandlerContext c, Object packet) throws Exception { - if (packet.getClass().getSimpleName().equalsIgnoreCase("PacketPlayInUseEntity")) { - ServerboundInteractPacket pk = (ServerboundInteractPacket) packet; - int entityID = (int) Util.getFieldValue(packet, "a"); - boolean sneak = (boolean) Util.getFieldValue(packet, "c"); - Bukkit.getScheduler().scheduleSyncDelayedTask(Main.getPlugin(Main.class), () -> { - for (Entity entity : Bukkit.getWorld("world").getEntities()) { - if (entity.getEntityId() == entityID && entity.getType() == EntityType.ARMOR_STAND) { - Bukkit.getPluginManager().callEvent(new InteractHologramEvent(player, (ArmorStand) entity)); - } - } - }, 0); - Object data = Util.getFieldValue(pk, "b"); - if (data.toString().split("\\$")[1].charAt(0) == 'e') - return; - try { - Object hand = Util.getFieldValue(data, "a"); - if (!hand.toString().equals("MAIN_HAND")) return; - //Right Click - for (ServerPlayer npcs : NPCManager.getNPCs()) { - if (npcs.getBukkitEntity().getEntityId() == entityID && sneak) { - Bukkit.getScheduler().scheduleSyncDelayedTask(Main.getPlugin(Main.class), () -> Bukkit.getPluginManager().callEvent(new RightClickNPCEvent(player, npcs)), 0); - - } - } - } catch (NoSuchFieldException x) { - //Left Click - } - } else { - super.channelRead(c, packet); - } - } -} -\ No newline at end of file diff --git a/src/main/java/me/night/nullvalkyrie/packets/PacketInjector.java b/src/main/java/me/night/nullvalkyrie/packets/PacketInjector.java @@ -1,31 +0,0 @@ -package me.night.nullvalkyrie.packets; - -import io.netty.channel.Channel; -import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer; -import org.bukkit.entity.Player; - -public class PacketInjector { - public void addPlayer(Player p) { - try { - Channel ch = ((CraftPlayer) p).getHandle().connection.getConnection().channel; - if (ch.pipeline().get("PacketInjector") == null) { - PacketHandler h = new PacketHandler(p); - ch.pipeline().addBefore("packet_handler", "PacketInjector", h); - } - } catch (Throwable t) { - t.printStackTrace(); - } - } - - public void removePlayer(Player p) { - try { - Channel ch = ((CraftPlayer) p).getHandle().connection.getConnection().channel; // NMS: 1.19.2 https://nms.screamingsandals.org/1.19.2/net/minecraft/server/network/ServerGamePacketListenerImpl.html PlayerConnection -> NetworkManager -> Channel - if (ch.pipeline().get("PacketInjector") != null) { - ch.pipeline().remove("PacketInjector"); - } - } catch (Throwable t) { - t.printStackTrace(); - } - } - -} diff --git a/src/main/java/me/night/nullvalkyrie/packets/handle/PacketHandler.java b/src/main/java/me/night/nullvalkyrie/packets/handle/PacketHandler.java @@ -0,0 +1,64 @@ +package me.night.nullvalkyrie.packets.handle; + +import io.netty.channel.ChannelDuplexHandler; +import io.netty.channel.ChannelHandlerContext; +import io.netty.channel.ChannelPromise; +import me.night.nullvalkyrie.Main; +import me.night.nullvalkyrie.entities.npcs.NPCManager; +import me.night.nullvalkyrie.events.custom.InteractHologramEvent; +import me.night.nullvalkyrie.events.custom.RightClickNPCEvent; +import me.night.nullvalkyrie.util.Util; +import net.minecraft.network.protocol.game.ServerboundInteractPacket; +import net.minecraft.server.level.ServerPlayer; +import org.bukkit.Bukkit; +import org.bukkit.entity.ArmorStand; +import org.bukkit.entity.Entity; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.Player; + +public class PacketHandler extends ChannelDuplexHandler { + private final Player player; + + public PacketHandler(Player player) { + this.player = player; + } + + @Override + public void write(ChannelHandlerContext ctx, Object packet, ChannelPromise promise) throws Exception { + super.write(ctx, packet, promise); + } + + @Override + public void channelRead(ChannelHandlerContext c, Object packet) throws Exception { + if (packet.getClass().getSimpleName().equalsIgnoreCase("PacketPlayInUseEntity")) { + ServerboundInteractPacket pk = (ServerboundInteractPacket) packet; + int entityID = (int) Util.getFieldValue(packet, "a"); + boolean sneak = (boolean) Util.getFieldValue(packet, "c"); + Bukkit.getScheduler().scheduleSyncDelayedTask(Main.getPlugin(Main.class), () -> { + for (Entity entity : Bukkit.getWorld("world").getEntities()) { + if (entity.getEntityId() == entityID && entity.getType() == EntityType.ARMOR_STAND) { + Bukkit.getPluginManager().callEvent(new InteractHologramEvent(player, (ArmorStand) entity)); + } + } + }, 0); + Object data = Util.getFieldValue(pk, "b"); + if (data.toString().split("\\$")[1].charAt(0) == 'e') + return; + try { + Object hand = Util.getFieldValue(data, "a"); + if (!hand.toString().equals("MAIN_HAND")) return; + //Right Click + for (ServerPlayer npcs : NPCManager.getNPCs()) { + if (npcs.getBukkitEntity().getEntityId() == entityID && sneak) { + Bukkit.getScheduler().scheduleSyncDelayedTask(Main.getPlugin(Main.class), () -> Bukkit.getPluginManager().callEvent(new RightClickNPCEvent(player, npcs)), 0); + + } + } + } catch (NoSuchFieldException x) { + //Left Click + } + } else { + super.channelRead(c, packet); + } + } +} +\ No newline at end of file diff --git a/src/main/java/me/night/nullvalkyrie/packets/handle/PacketInjector.java b/src/main/java/me/night/nullvalkyrie/packets/handle/PacketInjector.java @@ -0,0 +1,30 @@ +package me.night.nullvalkyrie.packets.handle; + +import io.netty.channel.Channel; +import org.bukkit.entity.Player; + +public class PacketInjector { + public void addPlayer(Player p) { + try { + Channel ch = me.night.nullvalkyrie.packets.protocol.Channel.getChannel(p); + if (ch.pipeline().get("PacketInjector") == null) { + PacketHandler h = new PacketHandler(p); + ch.pipeline().addBefore("packet_handler", "PacketInjector", h); + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + + public void removePlayer(Player p) { + try { + Channel ch = me.night.nullvalkyrie.packets.protocol.Channel.getChannel(p); + if (ch.pipeline().get("PacketInjector") != null) { + ch.pipeline().remove("PacketInjector"); + } + } catch (Throwable t) { + t.printStackTrace(); + } + } + +} diff --git a/src/main/java/me/night/nullvalkyrie/packets/protocol/Channel.java b/src/main/java/me/night/nullvalkyrie/packets/protocol/Channel.java @@ -0,0 +1,10 @@ +package me.night.nullvalkyrie.packets.protocol; + +import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer; +import org.bukkit.entity.Player; + +public class Channel { + public static io.netty.channel.Channel getChannel(Player player) { + return ((CraftPlayer) player).getHandle().connection.getConnection().channel; // NMS: 1.19.2 https://nms.screamingsandals.org/1.19.2/net/minecraft/server/network/ServerGamePacketListenerImpl.html PlayerConnection -> NetworkManager -> Channel + } +} diff --git a/src/main/java/me/night/nullvalkyrie/packets/protocol/Packet.java b/src/main/java/me/night/nullvalkyrie/packets/protocol/Packet.java @@ -0,0 +1,4 @@ +package me.night.nullvalkyrie.packets.protocol; + +public interface Packet { +} diff --git a/src/main/java/me/night/nullvalkyrie/packets/protocol/PacketPlayOutBlockBreakAnimation.java b/src/main/java/me/night/nullvalkyrie/packets/protocol/PacketPlayOutBlockBreakAnimation.java @@ -0,0 +1,14 @@ +package me.night.nullvalkyrie.packets.protocol; + +import net.minecraft.core.BlockPos; +import net.minecraft.network.protocol.game.ClientboundBlockDestructionPacket; +import org.bukkit.Location; +import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer; +import org.bukkit.entity.Player; + +public class PacketPlayOutBlockBreakAnimation implements Packet { + public PacketPlayOutBlockBreakAnimation(Player player, Location x, int stage) { + ClientboundBlockDestructionPacket packet = new ClientboundBlockDestructionPacket(player.getEntityId(), new BlockPos(x.getBlockX(), x.getBlockY(), x.getBlockZ()), stage); + ((CraftPlayer) player).getHandle().connection.send(packet); + } +} diff --git a/src/main/java/me/night/nullvalkyrie/packets/protocol/PacketPlayOutEntityMetadata.java b/src/main/java/me/night/nullvalkyrie/packets/protocol/PacketPlayOutEntityMetadata.java @@ -0,0 +1,15 @@ +package me.night.nullvalkyrie.packets.protocol; + +import net.minecraft.network.protocol.game.ClientboundSetEntityDataPacket; +import net.minecraft.network.syncher.SynchedEntityData; +import net.minecraft.world.entity.Entity; +import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer; +import org.bukkit.entity.Player; + +import java.util.List; + +public class PacketPlayOutEntityMetadata implements Packet { + public PacketPlayOutEntityMetadata(Player player, Entity entity, List<SynchedEntityData.DataValue<?>> list) { + ((CraftPlayer) player).getHandle().connection.send(new ClientboundSetEntityDataPacket(entity.getBukkitEntity().getEntityId(), list)); + } +} diff --git a/src/main/java/me/night/nullvalkyrie/packets/protocol/PacketPlayOutSpawnEntity.java b/src/main/java/me/night/nullvalkyrie/packets/protocol/PacketPlayOutSpawnEntity.java @@ -0,0 +1,13 @@ +package me.night.nullvalkyrie.packets.protocol; + +import net.minecraft.network.protocol.game.ClientboundAddEntityPacket; +import net.minecraft.world.entity.Entity; +import org.bukkit.craftbukkit.v1_19_R2.entity.CraftPlayer; +import org.bukkit.entity.Player; + +public class PacketPlayOutSpawnEntity implements Packet { + public PacketPlayOutSpawnEntity(Player player, Entity entity) { + ClientboundAddEntityPacket packet = new ClientboundAddEntityPacket(entity); + ((CraftPlayer) player).getHandle().connection.send(packet); + } +}