1.20.4 support

This commit is contained in:
Badbird5907
2024-03-15 16:18:57 -04:00
parent b2d37a1402
commit c54a5888d7
11 changed files with 192 additions and 45 deletions

View File

@@ -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);
}

View File

@@ -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<Entry<Block, Short>> 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();

View File

@@ -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"))

View File

@@ -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;

View File

@@ -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))
};

View File

@@ -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;

View File

@@ -6,24 +6,24 @@ 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) {
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();
@@ -31,5 +31,8 @@ public class InternalBridgeImpl implements InternalBridge {
SoundType soundEffectType = nmsBlock.getSoundType(blockState);
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;
}
}
}

View File

@@ -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;

View File

@@ -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 <T> Attribute<T> attr(AttributeKey<T> 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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -12,7 +12,7 @@ public class NMSUtils {
private static String itemsByIdFieldName;
static {
// find a private final field in SynchedEntityData that is an Int2ObjectMap<SynchedEntityData.DataItem>
// find a private final field in SynchedEntityData that is an Int2ObjectMap<SynchedEntityData.DataItem<?>>
Class<SynchedEntityData> clazz = SynchedEntityData.class;
Field[] fields = clazz.getDeclaredFields();
for (Field field : fields) {
@@ -26,12 +26,13 @@ public class NMSUtils {
}
}
@SuppressWarnings("unchecked")
public static List<SynchedEntityData.DataValue<?>> getEntityData(SynchedEntityData synchedEntityData) {
Int2ObjectMap<SynchedEntityData.DataItem> map = null;
Int2ObjectMap<SynchedEntityData.DataItem<?>> map = null;
try {
Field field = synchedEntityData.getClass().getDeclaredField(itemsByIdFieldName);
field.setAccessible(true);
map = (Int2ObjectMap<SynchedEntityData.DataItem>) field.get(synchedEntityData);
map = (Int2ObjectMap<SynchedEntityData.DataItem<?>>) field.get(synchedEntityData);
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}