diff --git a/TerminatorPlus-API/src/main/java/net/nuggetmc/tplus/api/InternalBridge.java b/TerminatorPlus-API/src/main/java/net/nuggetmc/tplus/api/InternalBridge.java index 35e9e27..54c6f58 100644 --- a/TerminatorPlus-API/src/main/java/net/nuggetmc/tplus/api/InternalBridge.java +++ b/TerminatorPlus-API/src/main/java/net/nuggetmc/tplus/api/InternalBridge.java @@ -7,7 +7,7 @@ import org.bukkit.block.Block; * This class serves as a bridge between the API and internal code that interacts with NMS. */ public interface InternalBridge { - void sendBlockDestructionPacket(short entityId, int x, int y, int z, int progress); + void sendBlockDestructionPacket(short entityId, Block block, int progress); Sound breakBlockSound(Block block); } diff --git a/TerminatorPlus-API/src/main/java/net/nuggetmc/tplus/api/agent/legacyagent/LegacyAgent.java b/TerminatorPlus-API/src/main/java/net/nuggetmc/tplus/api/agent/legacyagent/LegacyAgent.java index 0833d46..15794ab 100644 --- a/TerminatorPlus-API/src/main/java/net/nuggetmc/tplus/api/agent/legacyagent/LegacyAgent.java +++ b/TerminatorPlus-API/src/main/java/net/nuggetmc/tplus/api/agent/legacyagent/LegacyAgent.java @@ -1,5 +1,6 @@ package net.nuggetmc.tplus.api.agent.legacyagent; +import com.google.common.base.Optional; import net.nuggetmc.tplus.api.BotManager; import net.nuggetmc.tplus.api.Terminator; import net.nuggetmc.tplus.api.TerminatorPlusAPI; @@ -18,7 +19,8 @@ import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.data.Waterlogged; -import org.bukkit.block.data.type.*; +import org.bukkit.block.data.type.Door; +import org.bukkit.block.data.type.TrapDoor; import org.bukkit.entity.*; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.Plugin; @@ -26,8 +28,6 @@ import org.bukkit.scheduler.BukkitRunnable; import org.bukkit.util.BoundingBox; import org.bukkit.util.Vector; -import com.google.common.base.Optional; - import java.util.*; import java.util.Map.Entry; import java.util.regex.Pattern; @@ -1114,7 +1114,7 @@ public class LegacyAgent extends Agent { if (player.isDead() || cur == null || (!block.equals(cur) || block.getType() != cur.getType())) { this.cancel(); - TerminatorPlusAPI.getInternalBridge().sendBlockDestructionPacket(crackList.get(block), block.getX(), block.getY(), block.getZ(), -1); + TerminatorPlusAPI.getInternalBridge().sendBlockDestructionPacket(crackList.get(block), block, -1); crackList.remove(block); mining.remove(this); @@ -1126,7 +1126,7 @@ public class LegacyAgent extends Agent { if (i == 9) { this.cancel(); - TerminatorPlusAPI.getInternalBridge().sendBlockDestructionPacket(crackList.get(block), block.getX(), block.getY(), block.getZ(), -1); + TerminatorPlusAPI.getInternalBridge().sendBlockDestructionPacket(crackList.get(block), block, -1); if (sound != null) { @@ -1165,7 +1165,7 @@ public class LegacyAgent extends Agent { return; } - TerminatorPlusAPI.getInternalBridge().sendBlockDestructionPacket(crackList.get(block), block.getX(), block.getY(), block.getZ(), i); + TerminatorPlusAPI.getInternalBridge().sendBlockDestructionPacket(crackList.get(block), block, i); mining.put(this, (byte) (i + 1)); } @@ -1571,7 +1571,7 @@ public class LegacyAgent extends Agent { Iterator> itr = crackList.entrySet().iterator(); while(itr.hasNext()) { Block block = itr.next().getKey(); - TerminatorPlusAPI.getInternalBridge().sendBlockDestructionPacket(crackList.get(block), block.getX(), block.getY(), block.getZ(), -1); + TerminatorPlusAPI.getInternalBridge().sendBlockDestructionPacket(crackList.get(block), block, -1); itr.remove(); } mining.clear(); diff --git a/TerminatorPlus-Plugin/build.gradle.kts b/TerminatorPlus-Plugin/build.gradle.kts index d800704..7399105 100644 --- a/TerminatorPlus-Plugin/build.gradle.kts +++ b/TerminatorPlus-Plugin/build.gradle.kts @@ -13,7 +13,7 @@ java { } dependencies { - paperDevBundle("1.20.1-R0.1-SNAPSHOT") + paperDevBundle("1.20.4-R0.1-SNAPSHOT") //add the TerminatorPlus-API module implementation(project(":TerminatorPlus-API")) diff --git a/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/TerminatorPlus.java b/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/TerminatorPlus.java index 780cce3..3570bd7 100644 --- a/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/TerminatorPlus.java +++ b/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/TerminatorPlus.java @@ -12,7 +12,7 @@ import java.util.Arrays; public class TerminatorPlus extends JavaPlugin { - public static final String REQUIRED_VERSION = "1.20.1"; + public static final String REQUIRED_VERSION = "1.20.4"; private static TerminatorPlus instance; private static String version; diff --git a/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/bot/Bot.java b/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/bot/Bot.java index 33a1679..7161d48 100644 --- a/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/bot/Bot.java +++ b/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/bot/Bot.java @@ -2,14 +2,13 @@ package net.nuggetmc.tplus.bot; import com.mojang.authlib.GameProfile; import com.mojang.datafixers.util.Pair; -import net.minecraft.network.Connection; -import net.minecraft.network.PacketSendListener; import net.minecraft.network.protocol.Packet; -import net.minecraft.network.protocol.PacketFlow; import net.minecraft.network.protocol.game.*; import net.minecraft.server.MinecraftServer; +import net.minecraft.server.level.ClientInformation; import net.minecraft.server.level.ServerLevel; import net.minecraft.server.level.ServerPlayer; +import net.minecraft.server.network.CommonListenerCookie; import net.minecraft.server.network.ServerGamePacketListenerImpl; import net.minecraft.util.Mth; import net.minecraft.world.InteractionHand; @@ -31,16 +30,17 @@ import net.nuggetmc.tplus.api.event.BotDamageByPlayerEvent; import net.nuggetmc.tplus.api.event.BotFallDamageEvent; import net.nuggetmc.tplus.api.event.BotKilledByPlayerEvent; import net.nuggetmc.tplus.api.utils.*; +import net.nuggetmc.tplus.nms.MockConnection; import net.nuggetmc.tplus.utils.NMSUtils; import org.bukkit.*; import org.bukkit.block.Block; import org.bukkit.block.BlockFace; import org.bukkit.block.data.Waterlogged; -import org.bukkit.craftbukkit.v1_20_R1.CraftEquipmentSlot; -import org.bukkit.craftbukkit.v1_20_R1.CraftServer; -import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer; -import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack; +import org.bukkit.craftbukkit.v1_20_R3.CraftEquipmentSlot; +import org.bukkit.craftbukkit.v1_20_R3.CraftServer; +import org.bukkit.craftbukkit.v1_20_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_20_R3.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_20_R3.inventory.CraftItemStack; import org.bukkit.enchantments.Enchantment; import org.bukkit.entity.Damageable; import org.bukkit.entity.Player; @@ -48,7 +48,6 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.scheduler.BukkitScheduler; import org.bukkit.util.BoundingBox; import org.bukkit.util.Vector; -import org.jetbrains.annotations.Nullable; import java.util.*; @@ -76,7 +75,7 @@ public class Bot extends ServerPlayer implements Terminator { private boolean inPlayerList; private Bot(MinecraftServer minecraftServer, ServerLevel worldServer, GameProfile profile, boolean addToPlayerList) { - super(minecraftServer, worldServer, profile); + super(minecraftServer, worldServer, profile, ClientInformation.createDefault()); this.plugin = TerminatorPlus.getInstance(); this.scheduler = Bukkit.getScheduler(); @@ -111,13 +110,7 @@ public class Bot extends ServerPlayer implements Terminator { Bot bot = new Bot(nmsServer, nmsWorld, profile, addPlayerList); - bot.connection = new ServerGamePacketListenerImpl(nmsServer, new Connection(PacketFlow.CLIENTBOUND) { - - @Override - public void send(Packet packet, @Nullable PacketSendListener callbacks) { - - } - }, bot); + bot.connection = new ServerGamePacketListenerImpl(nmsServer, new MockConnection(), bot, CommonListenerCookie.createInitial(bot.getGameProfile())); bot.setPos(loc.getX(), loc.getY(), loc.getZ()); bot.setRot(loc.getYaw(), loc.getPitch()); @@ -203,7 +196,7 @@ public class Bot extends ServerPlayer implements Terminator { private Packet[] getRenderPackets() { return new Packet[]{ new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER, this), - new ClientboundAddPlayerPacket(this), + new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER, this), //new ClientboundSetEntityDataPacket(this.getId(), this.entityData, true), new ClientboundSetEntityDataPacket(this.getId(), NMSUtils.getEntityData(this.entityData)), new ClientboundRotateHeadPacket(this, (byte) ((this.yHeadRot * 256f) / 360f)) @@ -212,8 +205,9 @@ public class Bot extends ServerPlayer implements Terminator { private Packet[] getRenderPacketsNoInfo() { return new Packet[]{ - new ClientboundAddPlayerPacket(this), + new ClientboundAddEntityPacket(this), //new ClientboundSetEntityDataPacket(this.getId(), this.entityData, true), + new ClientboundPlayerInfoUpdatePacket(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER, this), new ClientboundSetEntityDataPacket(this.getId(), this.entityData.packDirty()), new ClientboundRotateHeadPacket(this, (byte) ((this.yHeadRot * 256f) / 360f)) }; diff --git a/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/bot/BotManagerImpl.java b/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/bot/BotManagerImpl.java index d7e6f0d..7ddf144 100644 --- a/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/bot/BotManagerImpl.java +++ b/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/bot/BotManagerImpl.java @@ -11,7 +11,7 @@ import net.nuggetmc.tplus.api.event.BotDeathEvent; import net.nuggetmc.tplus.api.utils.MojangAPI; import org.bukkit.*; import org.bukkit.command.CommandSender; -import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_20_R3.entity.CraftPlayer; import org.bukkit.entity.Entity; import org.bukkit.entity.LivingEntity; import org.bukkit.entity.Player; diff --git a/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/bridge/InternalBridgeImpl.java b/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/bridge/InternalBridgeImpl.java index 0ce0695..5d03de0 100644 --- a/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/bridge/InternalBridgeImpl.java +++ b/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/bridge/InternalBridgeImpl.java @@ -6,30 +6,33 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.SoundType; import net.minecraft.world.level.block.state.BlockState; import net.nuggetmc.tplus.api.InternalBridge; -import org.bukkit.Bukkit; import org.bukkit.Sound; import org.bukkit.block.Block; -import org.bukkit.craftbukkit.v1_20_R1.CraftWorld; -import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer; +import org.bukkit.craftbukkit.v1_20_R3.CraftWorld; +import org.bukkit.craftbukkit.v1_20_R3.entity.CraftPlayer; import org.bukkit.entity.Player; public class InternalBridgeImpl implements InternalBridge { @Override - public void sendBlockDestructionPacket(short entityId, int x, int y, int z, int progress) { - ClientboundBlockDestructionPacket crack = new ClientboundBlockDestructionPacket(entityId, new BlockPos(x, y, z), progress); - for (Player all : Bukkit.getOnlinePlayers()) { + public void sendBlockDestructionPacket(short entityId, Block block, int progress) { + ClientboundBlockDestructionPacket crack = new ClientboundBlockDestructionPacket(entityId, new BlockPos(block.getX(), block.getY(), block.getZ()), progress); + for (Player all : block.getLocation().getNearbyPlayers(64)) { ((CraftPlayer) all).getHandle().connection.send(crack); } } @Override public Sound breakBlockSound(Block block) { - Level nmsWorld = ((CraftWorld) block.getWorld()).getHandle(); - BlockState blockState = nmsWorld.getBlockState(new BlockPos(block.getX(), block.getY(), block.getZ())); - net.minecraft.world.level.block.Block nmsBlock = blockState.getBlock(); + try { + Level nmsWorld = ((CraftWorld) block.getWorld()).getHandle(); + BlockState blockState = nmsWorld.getBlockState(new BlockPos(block.getX(), block.getY(), block.getZ())); + net.minecraft.world.level.block.Block nmsBlock = blockState.getBlock(); - SoundType soundEffectType = nmsBlock.getSoundType(blockState); + SoundType soundEffectType = nmsBlock.getSoundType(blockState); - return Sound.valueOf(soundEffectType.getBreakSound().getLocation().getPath().replace(".", "_").toUpperCase()); + return Sound.valueOf(soundEffectType.getBreakSound().getLocation().getPath().replace(".", "_").toUpperCase()); + } catch (Exception e) { // potentially unsafe, just fallback to stone break sound + return Sound.BLOCK_STONE_BREAK; + } } } diff --git a/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/command/CommandHandler.java b/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/command/CommandHandler.java index 5391c94..0a7bb3d 100644 --- a/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/command/CommandHandler.java +++ b/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/command/CommandHandler.java @@ -12,7 +12,7 @@ import net.nuggetmc.tplus.command.commands.MainCommand; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; import org.bukkit.command.SimpleCommandMap; -import org.bukkit.craftbukkit.v1_20_R1.CraftServer; +import org.bukkit.craftbukkit.v1_20_R3.CraftServer; import java.lang.reflect.Method; import java.util.ArrayList; diff --git a/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/nms/MockChannel.java b/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/nms/MockChannel.java new file mode 100644 index 0000000..dfc1c59 --- /dev/null +++ b/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/nms/MockChannel.java @@ -0,0 +1,81 @@ +package net.nuggetmc.tplus.nms; + +import io.netty.channel.*; +import io.netty.util.Attribute; +import io.netty.util.AttributeKey; + +import java.net.SocketAddress; + +public class MockChannel extends AbstractChannel { + private final ChannelConfig config = new DefaultChannelConfig(this); + + public MockChannel(Channel parent) { + super(parent); + } + + @Override + public Attribute attr(AttributeKey key) { + return super.attr(key); + } + + @Override + public ChannelConfig config() { + config.setAutoRead(true); + return config; + } + + @Override + protected void doBeginRead() throws Exception { + } + + @Override + protected void doBind(SocketAddress arg0) throws Exception { + } + + @Override + protected void doClose() throws Exception { + } + + @Override + protected void doDisconnect() throws Exception { + } + + @Override + protected void doWrite(ChannelOutboundBuffer outboundBuffer) throws Exception { + } + + @Override + public boolean isActive() { + return false; + } + + @Override + protected boolean isCompatible(EventLoop arg0) { + return false; + } + + @Override + public boolean isOpen() { + return false; + } + + @Override + protected SocketAddress localAddress0() { + return null; + } + + @Override + public ChannelMetadata metadata() { + return new ChannelMetadata(true); + } + + @Override + protected AbstractUnsafe newUnsafe() { + return null; + } + + @Override + protected SocketAddress remoteAddress0() { + return null; + } +} diff --git a/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/nms/MockConnection.java b/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/nms/MockConnection.java new file mode 100644 index 0000000..7e55cec --- /dev/null +++ b/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/nms/MockConnection.java @@ -0,0 +1,68 @@ +package net.nuggetmc.tplus.nms; + +import net.minecraft.network.Connection; +import net.minecraft.network.PacketListener; +import net.minecraft.network.PacketSendListener; +import net.minecraft.network.protocol.Packet; +import net.minecraft.network.protocol.PacketFlow; +import org.jetbrains.annotations.NotNull; + +import java.lang.reflect.Field; +import java.net.SocketAddress; + +@SuppressWarnings("JavaReflectionMemberAccess") +public class MockConnection extends Connection { + private static final Field PACKET_LISTENER_FIELD; + private static final Field DISCONNECT_LISTENER_FIELD; + + static { + try { + // https://mappings.cephx.dev/1.20.4/net/minecraft/network/Connection.html packetListener & disconnectListener + PACKET_LISTENER_FIELD = Connection.class.getDeclaredField("q"); + DISCONNECT_LISTENER_FIELD = Connection.class.getDeclaredField("p"); + + PACKET_LISTENER_FIELD.setAccessible(true); + DISCONNECT_LISTENER_FIELD.setAccessible(true); + } catch (NoSuchFieldException e) { + throw new RuntimeException(e); + } + } + + public MockConnection() { + super(PacketFlow.SERVERBOUND); + this.channel = new MockChannel(null); + this.address = new SocketAddress() { + }; + } + + @Override + public void flushChannel() { + } + + @Override + public boolean isConnected() { + return true; + } + + @Override + public void send(@NotNull Packet packet) { + } + + @Override + public void send(@NotNull Packet packet, PacketSendListener sendListener) { + } + + @Override + public void send(@NotNull Packet packet, PacketSendListener sendListener, boolean flag) { + } + + @Override + public void setListener(@NotNull PacketListener packetListener) { + try { + PACKET_LISTENER_FIELD.set(this, packetListener); + DISCONNECT_LISTENER_FIELD.set(this, null); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } +} diff --git a/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/utils/NMSUtils.java b/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/utils/NMSUtils.java index d67b612..389d0e6 100644 --- a/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/utils/NMSUtils.java +++ b/TerminatorPlus-Plugin/src/main/java/net/nuggetmc/tplus/utils/NMSUtils.java @@ -12,7 +12,7 @@ public class NMSUtils { private static String itemsByIdFieldName; static { - // find a private final field in SynchedEntityData that is an Int2ObjectMap + // find a private final field in SynchedEntityData that is an Int2ObjectMap> Class clazz = SynchedEntityData.class; Field[] fields = clazz.getDeclaredFields(); for (Field field : fields) { @@ -26,12 +26,13 @@ public class NMSUtils { } } + @SuppressWarnings("unchecked") public static List> getEntityData(SynchedEntityData synchedEntityData) { - Int2ObjectMap map = null; + Int2ObjectMap> map = null; try { Field field = synchedEntityData.getClass().getDeclaredField(itemsByIdFieldName); field.setAccessible(true); - map = (Int2ObjectMap) field.get(synchedEntityData); + map = (Int2ObjectMap>) field.get(synchedEntityData); } catch (NoSuchFieldException | IllegalAccessException e) { throw new RuntimeException(e); }