From cf52b503334a56cf1181947e185f9dec0aca2938 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Thu, 31 Jul 2025 10:43:40 +0200 Subject: [PATCH 1/6] Introduce support for Minecraft 1.21: Add ReflectionWrapper21, ChunkHider21, and enhance version compatibility across systems. --- .../features/techhider/TechHiderCommand.java | 5 +- FightSystem/FightSystem_21/build.gradle.kts | 1 + .../fightsystem/utils/BlockIdWrapper21.java | 87 ++++++++++ .../utils/ReflectionWrapper21.java | 36 ++++ .../fightsystem/utils/ReflectionWrapper8.java | 59 +++++++ .../de/steamwar/fightsystem/fight/Kit.java | 12 +- .../steamwar/fightsystem/utils/HullHider.java | 11 +- .../fightsystem/utils/ReflectionWrapper.java | 37 +++++ .../fightsystem/utils/TechHiderWrapper.java | 4 +- FightSystem/FightSystem_Core/src/plugin.yml | 2 +- FightSystem/build.gradle.kts | 11 ++ SpigotCore/SpigotCore_21/build.gradle.kts | 3 + .../de/steamwar/techhider/ChunkHider21.java | 155 ++++++++++++++++++ .../src/de/steamwar/Reflection.java | 11 +- .../src/de/steamwar/techhider/ChunkHider.java | 26 ++- .../de/steamwar/techhider/ProtocolUtils.java | 10 ++ .../src/de/steamwar/techhider/TechHider.java | 1 + SpigotCore/SpigotCore_Main/src/plugin.yml | 2 +- settings.gradle.kts | 2 +- 19 files changed, 448 insertions(+), 27 deletions(-) create mode 100644 FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/BlockIdWrapper21.java create mode 100644 FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/ReflectionWrapper21.java create mode 100644 FightSystem/FightSystem_8/src/de/steamwar/fightsystem/utils/ReflectionWrapper8.java create mode 100644 FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/ReflectionWrapper.java create mode 100644 SpigotCore/SpigotCore_21/src/de/steamwar/techhider/ChunkHider21.java diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/techhider/TechHiderCommand.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/techhider/TechHiderCommand.java index 38725cf0..17d3563c 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/techhider/TechHiderCommand.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/techhider/TechHiderCommand.java @@ -34,6 +34,7 @@ import de.steamwar.linkage.LinkedInstance; import de.steamwar.techhider.TechHider; import net.md_5.bungee.api.ChatMessageType; import org.bukkit.Bukkit; +import org.bukkit.Chunk; import org.bukkit.Material; import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.FileConfiguration; @@ -86,8 +87,8 @@ public class TechHiderCommand extends SWCommand implements Listener, ScoreboardE Set hiddenBlockEntities = Collections.unmodifiableSet(new HashSet<>(config.getStringList("Techhider.HiddenBlockEntities"))); TechHider current = new TechHider((TechHider.LocationEvaluator) (p, cX, cY) -> { - if (rg.buildChunkOutside(cX, cY)) return true; - return !hidden.get(rg).contains(p); + Chunk playerChunk = p.getLocation().getChunk(); + return playerChunk.getX() == cX && playerChunk.getZ() == cY; }, Material.valueOf(obfuscateWith.toUpperCase()), hiddenBlocks.stream().map(String::toUpperCase).map(Material::valueOf).collect(Collectors.toSet()), hiddenBlockEntities); current.enable(); diff --git a/FightSystem/FightSystem_21/build.gradle.kts b/FightSystem/FightSystem_21/build.gradle.kts index a05590d1..3309134f 100644 --- a/FightSystem/FightSystem_21/build.gradle.kts +++ b/FightSystem/FightSystem_21/build.gradle.kts @@ -24,6 +24,7 @@ plugins { dependencies { compileOnly(project(":FightSystem:FightSystem_Core", "default")) compileOnly(project(":FightSystem:FightSystem_18", "default")) + compileOnly(project(":SpigotCore", "default")) compileOnly(libs.paperapi21) { attributes { diff --git a/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/BlockIdWrapper21.java b/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/BlockIdWrapper21.java new file mode 100644 index 00000000..32e2e6e4 --- /dev/null +++ b/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/BlockIdWrapper21.java @@ -0,0 +1,87 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.fightsystem.utils; + +import de.steamwar.Reflection; +import de.steamwar.fightsystem.Config; +import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import net.minecraft.core.BlockPos; +import net.minecraft.server.level.ChunkMap; +import net.minecraft.server.level.ServerChunkCache; +import net.minecraft.server.level.ServerLevel; +import net.minecraft.world.level.block.state.BlockState; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.block.Block; +import org.bukkit.craftbukkit.CraftWorld; +import org.bukkit.craftbukkit.block.CraftBlockState; +import org.bukkit.craftbukkit.entity.CraftPlayer; +import org.bukkit.craftbukkit.util.CraftMagicNumbers; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; + +public class BlockIdWrapper21 implements BlockIdWrapper { + static Int2ObjectMap tracker; + + static Reflection.Field chunkMap = Reflection.getField(ServerChunkCache.class, "chunkMap", Object.class); + static { + ServerChunkCache chunkCache = ((CraftWorld) Config.world).getHandle().getChunkSource(); + Object map = chunkMap.get(chunkCache); + Reflection.Field eMapField = Reflection.getField(map.getClass(), "entityMap", Int2ObjectMap.class); + tracker = eMapField.get(map); + } + + @Override + public Material idToMaterial(int blockState) { + return CraftMagicNumbers.getMaterial(net.minecraft.world.level.block.Block.stateById(blockState)).getItemType(); + } + + @Override + public int blockToId(Block block) { + return net.minecraft.world.level.block.Block.getId(((CraftBlockState) block.getState()).getHandle()); + } + + @Override + public void setBlock(World world, int x, int y, int z, int blockState) { + BlockState blockData = net.minecraft.world.level.block.Block.stateById(blockState); + ServerLevel level = ((CraftWorld) world).getHandle(); + BlockPos pos = new BlockPos(x, y, z); + + level.removeBlockEntity(pos); + level.setBlock(pos, blockData, blockState); + level.getChunkSource().blockChanged(pos); + } + + @Override + public void trackEntity(Player player, Entity entity) { + ChunkMap.TrackedEntity trackedEntity = tracker.get(entity.getEntityId()); + if (trackedEntity != null) { + trackedEntity.updatePlayer(((CraftPlayer) player).getHandle()); + } + } + + @Override + public void untrackEntity(Player player, Entity entity) { + ChunkMap.TrackedEntity trackedEntity = tracker.get(entity.getEntityId()); + if (trackedEntity != null) { + trackedEntity.removePlayer(((CraftPlayer) player).getHandle()); + } + } +} diff --git a/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/ReflectionWrapper21.java b/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/ReflectionWrapper21.java new file mode 100644 index 00000000..118bfba1 --- /dev/null +++ b/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/ReflectionWrapper21.java @@ -0,0 +1,36 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.fightsystem.utils; + +import io.papermc.paper.datacomponent.DataComponentTypes; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +public class ReflectionWrapper21 implements ReflectionWrapper { + @Override + public Object explosionHider(Player player, Object packet, PacketHiderFunction packetHiderFunction) { + return packet; + } + + @Override + public boolean hasItems(ItemStack stack) { + return stack.getDataTypes().stream().anyMatch(dataComponentType -> dataComponentType != DataComponentTypes.ENCHANTMENTS || dataComponentType != DataComponentTypes.DAMAGE); + } +} diff --git a/FightSystem/FightSystem_8/src/de/steamwar/fightsystem/utils/ReflectionWrapper8.java b/FightSystem/FightSystem_8/src/de/steamwar/fightsystem/utils/ReflectionWrapper8.java new file mode 100644 index 00000000..6da5308a --- /dev/null +++ b/FightSystem/FightSystem_8/src/de/steamwar/fightsystem/utils/ReflectionWrapper8.java @@ -0,0 +1,59 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.fightsystem.utils; + +import de.steamwar.Reflection; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.function.Function; + +public class ReflectionWrapper8 implements ReflectionWrapper { + + private static final Class packetPlayOutExplosion = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundExplodePacket"); + private static final Reflection.Field explosionBlocks = Reflection.getField(packetPlayOutExplosion, List.class, 0); + private static final Function explosionLocation = HullHider.posPacketToLocation(packetPlayOutExplosion, double.class, 1.0); + + @Override + public Object explosionHider(Player player, Object packet, PacketHiderFunction packetHiderFunction) { + if(explosionBlocks.get(packet).isEmpty()) + return packetHiderFunction.hide(player, packet, explosionLocation.apply(packet)); + + return packet; + } + + + private static final Class itemStack = Reflection.getClass("net.minecraft.world.item.ItemStack"); + private static final Reflection.Method asNMSCopy = Reflection.getTypedMethod(Reflection.getClass("org.bukkit.craftbukkit.inventory.CraftItemStack"), "asNMSCopy", itemStack, ItemStack.class); + private static final Class nbtTagCompound = Reflection.getClass("net.minecraft.nbt.CompoundTag"); + private static final Reflection.Method getTag = Reflection.getTypedMethod(itemStack, null, nbtTagCompound); + private static final Reflection.Method getKeys = Reflection.getTypedMethod(nbtTagCompound, null, Set.class); + @Override + public boolean hasItems(ItemStack stack) { + Set keys = new HashSet<>((Set) getKeys.invoke(getTag.invoke(asNMSCopy.invoke(null, stack)))); + keys.remove("Enchantments"); + keys.remove("Damage"); + return !keys.isEmpty(); + } +} diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/Kit.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/Kit.java index db97aa27..48a18bde 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/Kit.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/fight/Kit.java @@ -26,6 +26,7 @@ import de.steamwar.fightsystem.commands.Commands; import de.steamwar.fightsystem.commands.GUI; import de.steamwar.fightsystem.listener.PersonalKitCreator; import de.steamwar.fightsystem.utils.FlatteningWrapper; +import de.steamwar.fightsystem.utils.ReflectionWrapper; import de.steamwar.inventory.SWInventory; import de.steamwar.inventory.SWItem; import de.steamwar.sql.PersonalKit; @@ -214,17 +215,8 @@ public class Kit { assert normal != null; return !normal.isEnchantmentInKit(stack) && !stack.getEnchantments().isEmpty(); } - - private static final Class itemStack = Reflection.getClass("net.minecraft.world.item.ItemStack"); - private static final Reflection.Method asNMSCopy = Reflection.getTypedMethod(Reflection.getClass("org.bukkit.craftbukkit.inventory.CraftItemStack"), "asNMSCopy", itemStack, ItemStack.class); - private static final Class nbtTagCompound = Reflection.getClass("net.minecraft.nbt.CompoundTag"); - private static final Reflection.Method getTag = Reflection.getTypedMethod(itemStack, null, nbtTagCompound); - private static final Reflection.Method getKeys = Reflection.getTypedMethod(nbtTagCompound, null, Set.class); public static boolean hasItems(ItemStack stack) { - Set keys = new HashSet<>((Set) getKeys.invoke(getTag.invoke(asNMSCopy.invoke(null, stack)))); - keys.remove("Enchantments"); - keys.remove("Damage"); - return !keys.isEmpty(); + return ReflectionWrapper.impl.hasItems(stack); } private boolean isEnchantmentInKit(ItemStack stack){ diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/HullHider.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/HullHider.java index c050656d..137e2082 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/HullHider.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/HullHider.java @@ -62,6 +62,7 @@ public class HullHider implements Listener { private final Hull[] hulls; private final Map, BiFunction> packetHiders = new HashMap<>(); + private static final Class packetPlayOutExplosion = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundExplodePacket"); public HullHider() { if(!TechHiderWrapper.ENABLED) { hulls = new Hull[0]; @@ -208,14 +209,8 @@ public class HullHider implements Listener { return packetHider(player, packet, new Location(Config.world, TechHider.blockPositionX.get(baseBlock), blockPositionY.get(baseBlock), TechHider.blockPositionZ.get(baseBlock))); } - private static final Class packetPlayOutExplosion = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundExplodePacket"); - private static final Reflection.Field explosionBlocks = Reflection.getField(packetPlayOutExplosion, List.class, 0); - private static final Function explosionLocation = posPacketToLocation(packetPlayOutExplosion, double.class, 1.0); private Object explosionHider(Player player, Object packet) { - if(explosionBlocks.get(packet).isEmpty()) - return packetHider(player, packet, explosionLocation.apply(packet)); - - return packet; + return ReflectionWrapper.impl.explosionHider(player, packet, this::packetHider); } private void posHiderGenerator(String typeName, Class posType, double factor) { @@ -224,7 +219,7 @@ public class HullHider implements Listener { packetHiders.put(type, (player, packet) -> packetHider(player, packet, location.apply(packet))); } - private static Function posPacketToLocation(Class type, Class posType, double factor) { + public static Function posPacketToLocation(Class type, Class posType, double factor) { Reflection.Field x = Reflection.getField(type, posType, 0); Reflection.Field y = Reflection.getField(type, posType, 1); Reflection.Field z = Reflection.getField(type, posType, 2); diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/ReflectionWrapper.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/ReflectionWrapper.java new file mode 100644 index 00000000..cbc9f807 --- /dev/null +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/ReflectionWrapper.java @@ -0,0 +1,37 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.fightsystem.utils; + +import de.steamwar.core.VersionDependent; +import de.steamwar.fightsystem.FightSystem; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +public interface ReflectionWrapper { + ReflectionWrapper impl = VersionDependent.getVersionImpl(FightSystem.getPlugin()); + + Object explosionHider(Player player, Object packet, PacketHiderFunction packetHiderFunction); + boolean hasItems(ItemStack stack); + + public interface PacketHiderFunction { + Object hide(Player player, Object packet, Location location); + } +} diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java index bf890168..fde87959 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java @@ -59,7 +59,7 @@ public class TechHiderWrapper extends StateDependent implements TechHider.Locati private final SecretKey key; public TechHiderWrapper() { - super(ENABLED, FightState.Schem); + super(ENABLED, FightState.All); techHider = new TechHider(this, Config.ObfuscateWith, Config.HiddenBlocks, Config.HiddenBlockEntities); try { @@ -68,7 +68,7 @@ public class TechHiderWrapper extends StateDependent implements TechHider.Locati throw new SecurityException(e); } - new StateDependentListener(ENABLED, FightState.Schem, this); + new StateDependentListener(ENABLED, FightState.All, this); register(); } diff --git a/FightSystem/FightSystem_Core/src/plugin.yml b/FightSystem/FightSystem_Core/src/plugin.yml index 6925bf69..09702025 100644 --- a/FightSystem/FightSystem_Core/src/plugin.yml +++ b/FightSystem/FightSystem_Core/src/plugin.yml @@ -8,7 +8,7 @@ softdepend: - SpigotCore depend: - WorldEdit -api-version: "1.13" +api-version: "1.21.6" commands: ak: diff --git a/FightSystem/build.gradle.kts b/FightSystem/build.gradle.kts index 9013824d..6338609a 100644 --- a/FightSystem/build.gradle.kts +++ b/FightSystem/build.gradle.kts @@ -50,6 +50,17 @@ tasks.register("WarGear20") { config = "WarGear20.yml" } +tasks.register("WarGear21") { + group = "run" + description = "Run a WarGear 1.21 Fight Server" + dependsOn(":SpigotCore:shadowJar") + dependsOn(":FightSystem:shadowJar") + template = "WarGear21" + worldName = "arenas/Pentraki" + config = "WarGear20.yml" + jar = "/jars/paper-1.21.6.jar" +} + tasks.register("SpaceCraftDev20") { group = "run" description = "Run a SpaceCraftDev 1.20 Fight Server" diff --git a/SpigotCore/SpigotCore_21/build.gradle.kts b/SpigotCore/SpigotCore_21/build.gradle.kts index 8f2acba4..4b26ba16 100644 --- a/SpigotCore/SpigotCore_21/build.gradle.kts +++ b/SpigotCore/SpigotCore_21/build.gradle.kts @@ -37,4 +37,7 @@ dependencies { compileOnly(libs.paperapi21) compileOnly(libs.nms21) + compileOnly(libs.datafixer) + compileOnly(libs.netty) + compileOnly(libs.authlib) } diff --git a/SpigotCore/SpigotCore_21/src/de/steamwar/techhider/ChunkHider21.java b/SpigotCore/SpigotCore_21/src/de/steamwar/techhider/ChunkHider21.java new file mode 100644 index 00000000..c31e5f8f --- /dev/null +++ b/SpigotCore/SpigotCore_21/src/de/steamwar/techhider/ChunkHider21.java @@ -0,0 +1,155 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2025 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.techhider; + +import de.steamwar.Reflection; +import io.netty.buffer.ByteBuf; +import io.netty.buffer.Unpooled; +import net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData; +import net.minecraft.network.protocol.game.ClientboundLevelChunkWithLightPacket; +import net.minecraft.util.SimpleBitStorage; +import net.minecraft.world.level.block.entity.BlockEntityType; +import org.bukkit.entity.Player; + +import java.util.List; +import java.util.Set; +import java.util.function.BiFunction; +import java.util.function.UnaryOperator; +import java.util.stream.Collectors; + +public class ChunkHider21 implements ChunkHider { + @Override + public Class mapChunkPacket() { + return ClientboundLevelChunkWithLightPacket.class; + } + + private static final UnaryOperator chunkPacketCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkWithLightPacket.class); + private static final UnaryOperator chunkDataCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkPacketData.class); + + private static final Reflection.Field chunkXField = Reflection.getField(ClientboundLevelChunkWithLightPacket.class, int.class, 0); + private static final Reflection.Field chunkZField = Reflection.getField(ClientboundLevelChunkWithLightPacket.class, int.class, 1); + private static final Reflection.Field chunkData = Reflection.getField(ClientboundLevelChunkWithLightPacket.class, ClientboundLevelChunkPacketData.class, 0); + + private static final Reflection.Field dataField = Reflection.getField(ClientboundLevelChunkPacketData.class, byte[].class, 0); + private static final Reflection.Field tileEntities = Reflection.getField(ClientboundLevelChunkPacketData.class, List.class, 0); + + @Override + public BiFunction chunkHiderGenerator(TechHider techHider) { + return (p, packet) -> { + int chunkX = chunkXField.get(packet); + int chunkZ = chunkZField.get(packet); + if (techHider.getLocationEvaluator().skipChunk(p, chunkX, chunkZ)) + return packet; + + packet = chunkPacketCloner.apply(packet); + Object dataWrapper = chunkDataCloner.apply(chunkData.get(packet)); + + Set hiddenBlockEntities = techHider.getHiddenBlockEntities(); + tileEntities.set(dataWrapper, ((List)tileEntities.get(dataWrapper)).stream().filter(te -> tileEntityVisible(hiddenBlockEntities, te)).collect(Collectors.toList())); + + ByteBuf in = Unpooled.wrappedBuffer(dataField.get(dataWrapper)); + ByteBuf out = Unpooled.buffer(in.readableBytes() + 64); + for(int yOffset = p.getWorld().getMinHeight(); yOffset < p.getWorld().getMaxHeight(); yOffset += 16) { + SectionHider section = new SectionHider(p, techHider, in, out, chunkX, yOffset/16, chunkZ); + section.copyBlockCount(); + + blocks(section); + biomes(section); + } + + if (in.readableBytes() != 0) { + throw new IllegalStateException("ChunkHider21: Incomplete chunk data, " + in.readableBytes() + " bytes left"); + } + + byte[] data = new byte[out.readableBytes()]; + out.readBytes(data); + dataField.set(dataWrapper, data); + + chunkData.set(packet, dataWrapper); + return packet; + }; + } + + public static final Class tileEntity = Reflection.getClass("net.minecraft.network.protocol.game.ClientboundLevelChunkPacketData$BlockEntityInfo"); + protected static final Reflection.Field entityType = Reflection.getField(tileEntity, BlockEntityType.class, 0); + private static final Class builtInRegestries = Reflection.getClass("net.minecraft.core.registries.BuiltInRegistries"); + private static final Class registry = Reflection.getClass("net.minecraft.core.Registry"); + private static final Reflection.Field nameField = Reflection.getField(builtInRegestries, "BLOCK_ENTITY_TYPE", registry); + private static final Class resourceLocation = Reflection.getClass("net.minecraft.resources.ResourceLocation"); + private static final Reflection.Method getKey = Reflection.getTypedMethod(registry, "getKey", resourceLocation, Object.class); + private static final Reflection.Method getName = Reflection.getTypedMethod(resourceLocation, "getPath", String.class); + protected boolean tileEntityVisible(Set hiddenBlockEntities, Object tile) { + return !hiddenBlockEntities.contains(getName.invoke(getKey.invoke(nameField.get(null), entityType.get(tile)))); + } + + private void blocks(SectionHider section) { + section.copyBitsPerBlock(); + + boolean singleValued = section.getBitsPerBlock() == 0; + if (singleValued) { + int value = ProtocolUtils.readVarInt(section.getIn()); + ProtocolUtils.writeVarInt(section.getOut(), !section.isSkipSection() && section.getObfuscate().contains(value) ? section.getTarget() : value); + return; + } else { + section.processPalette(); + } + + if (section.isSkipSection() || (!section.blockPrecise() && section.isPaletted())) { + section.skipNewDataArray(4096); + return; + } + + SimpleBitStorage values = new SimpleBitStorage(section.getBitsPerBlock(), 4096, section.readNewDataArray(4096)); + + for (int y = 0; y < 16; y++) { + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++) { + int pos = (((y * 16) + z) * 16) + x; + + switch (section.test(x, y, z)) { + case SKIP: + break; + case CHECK: + if (!section.getObfuscate().contains(values.get(pos))) + break; + case HIDE: + values.set(pos, section.getTarget()); + break; + case HIDE_AIR: + default: + values.set(pos, section.getAir()); + } + } + } + } + + section.writeDataArray(values.getRaw()); + } + + private void biomes(SectionHider section) { + section.copyBitsPerBlock(); + if(section.getBitsPerBlock() == 0) { + section.copyVarInt(); + } else if(section.getBitsPerBlock() < 6) { + section.skipPalette(); + section.skipNewDataArray(64); + } + } +} diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/Reflection.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/Reflection.java index 86dca0bf..7c34fca9 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/Reflection.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/Reflection.java @@ -157,7 +157,16 @@ public final class Reflection { } else if(MAJOR_VERSION < 21 || MINOR_VERSION < 4) { return Class.forName(spigotClassnames.getOrDefault(name, name)); } else { - return Class.forName(name); + Class clazz = Class.forName(name); + if (clazz.getName().equals(name)) { + return clazz; + } + + try { + return Core.class.getClassLoader().getParent().loadClass(name); + } catch (ClassNotFoundException e) { + return clazz; + } } } catch (ClassNotFoundException e) { throw new IllegalArgumentException("Cannot find " + name, e); diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ChunkHider.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ChunkHider.java index a74feb42..fbd6e364 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ChunkHider.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ChunkHider.java @@ -53,6 +53,7 @@ public interface ChunkHider { private boolean paletted; private int bitsPerBlock; + private int blockCount; private int air; private int target; private Set obfuscate; @@ -86,7 +87,8 @@ public interface ChunkHider { } public void copyBlockCount() { - out.writeShort(in.readShort()); + this.blockCount = in.readShort(); + out.writeShort(blockCount); } public void copyBitsPerBlock() { @@ -140,6 +142,15 @@ public interface ChunkHider { out.writeBytes(in, dataArrayLength*8); } + public void skipNewDataArray(int entries) { + if (bitsPerBlock == 0) { + return; + } + + int longs = (int) (((long) entries * bitsPerBlock + 63) >> 6); + out.writeBytes(in, longs * Long.BYTES); + } + public long[] readDataArray() { long[] array = new long[copyVarInt()]; for(int i = 0; i < array.length; i++) @@ -148,6 +159,19 @@ public interface ChunkHider { return array; } + public long[] readNewDataArray(int entries) { + if (bitsPerBlock == 0) { + return new long[entries]; + } + + int longs = (int) (((long) entries * bitsPerBlock + 63) >> 6); + long[] array = new long[longs]; + for(int i = 0; i < longs; i++) + array[i] = in.readLong(); + + return array; + } + public void writeDataArray(long[] array) { for(long l : array) out.writeLong(l); diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ProtocolUtils.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ProtocolUtils.java index 57f27921..3949d7ed 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ProtocolUtils.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ProtocolUtils.java @@ -58,6 +58,16 @@ public class ProtocolUtils { }; } + public static UnaryOperator shallowTypedCloneGenerator(Class clazz) { + BiConsumer filler = shallowFill(clazz); + + return source -> { + Object clone = Reflection.newInstance(clazz); + filler.accept(source, clone); + return (T) clone; + }; + } + private static BiConsumer shallowFill(Class clazz) { if(clazz == null) return (source, clone) -> {}; diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/TechHider.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/TechHider.java index 021d2fe4..b231e97f 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/TechHider.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/TechHider.java @@ -79,6 +79,7 @@ public class TechHider { techhiders.put(blockChangePacket, this::blockChangeHider); techhiders.put(tileEntityDataPacket, this::tileEntityDataHider); techhiders.put(multiBlockChangePacket, ProtocolWrapper.impl.multiBlockChangeGenerator(this)); + System.out.println(ChunkHider.impl.mapChunkPacket().getName()); techhiders.put(ChunkHider.impl.mapChunkPacket(), ChunkHider.impl.chunkHiderGenerator(this)); if(Core.getVersion() > 12 && Core.getVersion() < 19) { diff --git a/SpigotCore/SpigotCore_Main/src/plugin.yml b/SpigotCore/SpigotCore_Main/src/plugin.yml index a29249d2..cd807cd2 100644 --- a/SpigotCore/SpigotCore_Main/src/plugin.yml +++ b/SpigotCore/SpigotCore_Main/src/plugin.yml @@ -1,7 +1,7 @@ name: SpigotCore version: "2.0" author: Lixfel -api-version: "1.13" +api-version: "1.21" load: STARTUP softdepend: - WorldEdit diff --git a/settings.gradle.kts b/settings.gradle.kts index 8ab618ff..6665697f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -126,7 +126,7 @@ dependencyResolutionManagement { library("nms18", "de.steamwar:spigot:1.18") library("nms19", "de.steamwar:spigot:1.19") library("nms20", "de.steamwar:spigot:1.20") - library("nms21", "de.steamwar:spigot:1.21.5") + library("nms21", "de.steamwar:spigot:1.21.6") library("axiom", "de.steamwar:axiompaper:RELEASE") library("worldedit12", "de.steamwar:worldedit:1.12") From e7803dcf822a070734cffc0f134019c7e18326e8 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Thu, 31 Jul 2025 11:34:56 +0200 Subject: [PATCH 2/6] Enhance compatibility and feature support for Minecraft 1.21: Add ProtocolWrapper21, update gamerule management, streamline entity tracking, and refine chunk hider logic. --- .../features/techhider/TechHiderCommand.java | 4 +- .../utils/CraftbukkitWrapper10.java | 3 + .../utils/CraftbukkitWrapper12.java | 3 + .../utils/CraftbukkitWrapper14.java | 3 + .../utils/CraftbukkitWrapper15.java | 3 + .../utils/CraftbukkitWrapper18.java | 3 + FightSystem/FightSystem_21/build.gradle.kts | 1 + .../fightsystem/utils/BlockIdWrapper21.java | 36 ++++------ .../utils/CraftbukkitWrapper21.java | 7 ++ .../utils/CraftbukkitWrapper8.java | 3 + .../utils/CraftbukkitWrapper9.java | 3 + .../de/steamwar/fightsystem/FightSystem.java | 2 + .../fightsystem/utils/CraftbukkitWrapper.java | 2 + .../fightsystem/utils/TechHiderWrapper.java | 4 +- .../de/steamwar/core/ProtocolWrapper21.java | 66 +++++++++++++++++++ .../de/steamwar/techhider/ChunkHider21.java | 4 +- .../src/de/steamwar/Reflection.java | 11 +++- .../src/de/steamwar/techhider/ChunkHider.java | 12 ++-- 18 files changed, 135 insertions(+), 35 deletions(-) create mode 100644 SpigotCore/SpigotCore_21/src/de/steamwar/core/ProtocolWrapper21.java diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/techhider/TechHiderCommand.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/techhider/TechHiderCommand.java index 17d3563c..0c1d8af5 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/techhider/TechHiderCommand.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/techhider/TechHiderCommand.java @@ -87,8 +87,8 @@ public class TechHiderCommand extends SWCommand implements Listener, ScoreboardE Set hiddenBlockEntities = Collections.unmodifiableSet(new HashSet<>(config.getStringList("Techhider.HiddenBlockEntities"))); TechHider current = new TechHider((TechHider.LocationEvaluator) (p, cX, cY) -> { - Chunk playerChunk = p.getLocation().getChunk(); - return playerChunk.getX() == cX && playerChunk.getZ() == cY; + if (rg.buildChunkOutside(cX, cY)) return true; + return !hidden.get(rg).contains(p); }, Material.valueOf(obfuscateWith.toUpperCase()), hiddenBlocks.stream().map(String::toUpperCase).map(Material::valueOf).collect(Collectors.toSet()), hiddenBlockEntities); current.enable(); diff --git a/FightSystem/FightSystem_10/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper10.java b/FightSystem/FightSystem_10/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper10.java index 78dd79a5..d5f654ae 100644 --- a/FightSystem/FightSystem_10/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper10.java +++ b/FightSystem/FightSystem_10/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper10.java @@ -55,4 +55,7 @@ public class CraftbukkitWrapper10 implements CraftbukkitWrapper { public Stream entityIterator() { return ((CraftWorld) Config.world).getHandle().entityList.stream(); } + + @Override + public void setupGamerule() { } } diff --git a/FightSystem/FightSystem_12/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper12.java b/FightSystem/FightSystem_12/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper12.java index f8e843bc..a134b9fe 100644 --- a/FightSystem/FightSystem_12/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper12.java +++ b/FightSystem/FightSystem_12/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper12.java @@ -55,4 +55,7 @@ public class CraftbukkitWrapper12 implements CraftbukkitWrapper { public Stream entityIterator() { return ((CraftWorld) Config.world).getHandle().entityList.stream(); } + + @Override + public void setupGamerule() { } } diff --git a/FightSystem/FightSystem_14/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper14.java b/FightSystem/FightSystem_14/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper14.java index 07c525d4..8e2f96ab 100644 --- a/FightSystem/FightSystem_14/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper14.java +++ b/FightSystem/FightSystem_14/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper14.java @@ -56,4 +56,7 @@ public class CraftbukkitWrapper14 implements CraftbukkitWrapper { public Stream entityIterator() { return ((CraftWorld) Config.world).getHandle().entitiesById.values().stream(); } + + @Override + public void setupGamerule() { } } diff --git a/FightSystem/FightSystem_15/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper15.java b/FightSystem/FightSystem_15/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper15.java index 70d9e8c5..64a0f9e1 100644 --- a/FightSystem/FightSystem_15/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper15.java +++ b/FightSystem/FightSystem_15/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper15.java @@ -56,4 +56,7 @@ public class CraftbukkitWrapper15 implements CraftbukkitWrapper { public Stream entityIterator() { return ((CraftWorld) Config.world).getHandle().entitiesById.values().stream(); } + + @Override + public void setupGamerule() { } } diff --git a/FightSystem/FightSystem_18/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper18.java b/FightSystem/FightSystem_18/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper18.java index 8fa8e7de..aafd5c08 100644 --- a/FightSystem/FightSystem_18/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper18.java +++ b/FightSystem/FightSystem_18/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper18.java @@ -62,4 +62,7 @@ public class CraftbukkitWrapper18 implements CraftbukkitWrapper { public Stream entityIterator() { return StreamSupport.stream(((Iterable) getIterable.invoke(getWorldEntities.invoke(getWorld.invoke(Config.world)))).spliterator(), false); } + + @Override + public void setupGamerule() { } } diff --git a/FightSystem/FightSystem_21/build.gradle.kts b/FightSystem/FightSystem_21/build.gradle.kts index 3309134f..2da59fce 100644 --- a/FightSystem/FightSystem_21/build.gradle.kts +++ b/FightSystem/FightSystem_21/build.gradle.kts @@ -41,4 +41,5 @@ dependencies { } compileOnly(libs.fastutil) + compileOnly(libs.authlib) } diff --git a/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/BlockIdWrapper21.java b/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/BlockIdWrapper21.java index 32e2e6e4..105bbe36 100644 --- a/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/BlockIdWrapper21.java +++ b/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/BlockIdWrapper21.java @@ -19,34 +19,24 @@ package de.steamwar.fightsystem.utils; -import de.steamwar.Reflection; -import de.steamwar.fightsystem.Config; -import it.unimi.dsi.fastutil.ints.Int2ObjectMap; +import com.comphenix.tinyprotocol.TinyProtocol; +import com.mojang.authlib.GameProfile; +import de.steamwar.core.ProtocolWrapper; +import de.steamwar.fightsystem.FightSystem; import net.minecraft.core.BlockPos; -import net.minecraft.server.level.ChunkMap; -import net.minecraft.server.level.ServerChunkCache; import net.minecraft.server.level.ServerLevel; import net.minecraft.world.level.block.state.BlockState; +import org.bukkit.GameMode; import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.Block; import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.craftbukkit.block.CraftBlockState; -import org.bukkit.craftbukkit.entity.CraftPlayer; import org.bukkit.craftbukkit.util.CraftMagicNumbers; import org.bukkit.entity.Entity; import org.bukkit.entity.Player; public class BlockIdWrapper21 implements BlockIdWrapper { - static Int2ObjectMap tracker; - - static Reflection.Field chunkMap = Reflection.getField(ServerChunkCache.class, "chunkMap", Object.class); - static { - ServerChunkCache chunkCache = ((CraftWorld) Config.world).getHandle().getChunkSource(); - Object map = chunkMap.get(chunkCache); - Reflection.Field eMapField = Reflection.getField(map.getClass(), "entityMap", Int2ObjectMap.class); - tracker = eMapField.get(map); - } @Override public Material idToMaterial(int blockState) { @@ -71,17 +61,17 @@ public class BlockIdWrapper21 implements BlockIdWrapper { @Override public void trackEntity(Player player, Entity entity) { - ChunkMap.TrackedEntity trackedEntity = tracker.get(entity.getEntityId()); - if (trackedEntity != null) { - trackedEntity.updatePlayer(((CraftPlayer) player).getHandle()); - } + if(entity instanceof Player) + TinyProtocol.instance.sendPacket(player, ProtocolWrapper.impl.playerInfoPacketConstructor(ProtocolWrapper.PlayerInfoAction.REMOVE, new GameProfile(entity.getUniqueId(), entity.getName()), GameMode.CREATIVE)); + + player.showEntity(FightSystem.getPlugin(), entity); } @Override public void untrackEntity(Player player, Entity entity) { - ChunkMap.TrackedEntity trackedEntity = tracker.get(entity.getEntityId()); - if (trackedEntity != null) { - trackedEntity.removePlayer(((CraftPlayer) player).getHandle()); - } + player.hideEntity(FightSystem.getPlugin(), entity); + + if(entity instanceof Player) + TinyProtocol.instance.sendPacket(player, ProtocolWrapper.impl.playerInfoPacketConstructor(ProtocolWrapper.PlayerInfoAction.ADD, new GameProfile(entity.getUniqueId(), entity.getName()), GameMode.CREATIVE)); } } diff --git a/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper21.java b/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper21.java index b5c920a7..68f35171 100644 --- a/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper21.java +++ b/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper21.java @@ -19,6 +19,8 @@ package de.steamwar.fightsystem.utils; +import de.steamwar.fightsystem.Config; +import org.bukkit.GameRule; import org.bukkit.entity.Entity; public class CraftbukkitWrapper21 extends CraftbukkitWrapper18 { @@ -27,4 +29,9 @@ public class CraftbukkitWrapper21 extends CraftbukkitWrapper18 { public float headRotation(Entity e) { return getEntity(e).getYHeadRot(); } + + @Override + public void setupGamerule() { + Config.world.setGameRule(GameRule.LOCATOR_BAR, false); + } } diff --git a/FightSystem/FightSystem_8/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper8.java b/FightSystem/FightSystem_8/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper8.java index 8d743ae7..e7597dd7 100644 --- a/FightSystem/FightSystem_8/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper8.java +++ b/FightSystem/FightSystem_8/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper8.java @@ -52,4 +52,7 @@ public class CraftbukkitWrapper8 implements CraftbukkitWrapper { public Stream entityIterator() { return ((CraftWorld) Config.world).getHandle().entityList.stream(); } + + @Override + public void setupGamerule() { } } diff --git a/FightSystem/FightSystem_9/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper9.java b/FightSystem/FightSystem_9/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper9.java index 54281ed3..c7f393b3 100644 --- a/FightSystem/FightSystem_9/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper9.java +++ b/FightSystem/FightSystem_9/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper9.java @@ -55,4 +55,7 @@ public class CraftbukkitWrapper9 implements CraftbukkitWrapper { public Stream entityIterator() { return ((CraftWorld) Config.world).getHandle().entityList.stream(); } + + @Override + public void setupGamerule() { } } diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java index 1ff85e23..a95670a0 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/FightSystem.java @@ -188,6 +188,8 @@ public class FightSystem extends JavaPlugin { }else if(Config.mode == ArenaMode.PREPARE) { Fight.getUnrotated().setSchem(SchematicNode.getSchematicNode(Config.PrepareSchemID)); } + + CraftbukkitWrapper.impl.setupGamerule(); } @Override diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper.java index 242119f5..e008a3bd 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper.java @@ -33,4 +33,6 @@ public interface CraftbukkitWrapper { float headRotation(Entity e); Stream entityIterator(); + + void setupGamerule(); } diff --git a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java index fde87959..bf890168 100644 --- a/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java +++ b/FightSystem/FightSystem_Core/src/de/steamwar/fightsystem/utils/TechHiderWrapper.java @@ -59,7 +59,7 @@ public class TechHiderWrapper extends StateDependent implements TechHider.Locati private final SecretKey key; public TechHiderWrapper() { - super(ENABLED, FightState.All); + super(ENABLED, FightState.Schem); techHider = new TechHider(this, Config.ObfuscateWith, Config.HiddenBlocks, Config.HiddenBlockEntities); try { @@ -68,7 +68,7 @@ public class TechHiderWrapper extends StateDependent implements TechHider.Locati throw new SecurityException(e); } - new StateDependentListener(ENABLED, FightState.All, this); + new StateDependentListener(ENABLED, FightState.Schem, this); register(); } diff --git a/SpigotCore/SpigotCore_21/src/de/steamwar/core/ProtocolWrapper21.java b/SpigotCore/SpigotCore_21/src/de/steamwar/core/ProtocolWrapper21.java new file mode 100644 index 00000000..7018aa64 --- /dev/null +++ b/SpigotCore/SpigotCore_21/src/de/steamwar/core/ProtocolWrapper21.java @@ -0,0 +1,66 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2022 SteamWar.de-Serverteam + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +package de.steamwar.core; + +import com.mojang.authlib.GameProfile; +import com.mojang.datafixers.util.Pair; +import de.steamwar.Reflection; +import net.minecraft.Util; +import net.minecraft.network.protocol.game.ClientboundPlayerInfoRemovePacket; +import net.minecraft.network.protocol.game.ClientboundPlayerInfoUpdatePacket; +import net.minecraft.world.level.GameType; +import org.bukkit.GameMode; + +import java.util.Collections; +import java.util.EnumSet; +import java.util.List; +import java.util.function.LongSupplier; + +public class ProtocolWrapper21 implements ProtocolWrapper { + + private static final Reflection.Field equipmentStack = Reflection.getField(equipmentPacket, List.class, 0); + @Override + public void setEquipmentPacketStack(Object packet, Object slot, Object stack) { + equipmentStack.set(packet, Collections.singletonList(new Pair<>(slot, stack))); + } + + private static final Reflection.Constructor removePacketConstructor = Reflection.getConstructor(ClientboundPlayerInfoRemovePacket.class, List.class); + + @Override + @SuppressWarnings("deprecation") + public Object playerInfoPacketConstructor(PlayerInfoAction action, GameProfile profile, GameMode mode) { + if(action == PlayerInfoAction.REMOVE) + return removePacketConstructor.invoke(Collections.singletonList(profile.getId())); + return switch (action) { + case ADD -> new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.ADD_PLAYER, ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE), new ClientboundPlayerInfoUpdatePacket.Entry( + profile.getId(), profile, true, 0, GameType.byId(mode.getValue()), null, true, 0, null + )); + case GAMEMODE -> new ClientboundPlayerInfoUpdatePacket(EnumSet.of(ClientboundPlayerInfoUpdatePacket.Action.UPDATE_GAME_MODE), new ClientboundPlayerInfoUpdatePacket.Entry( + profile.getId(), profile, true, 0, GameType.byId(mode.getValue()), null, true, 0, null + )); + default -> null; + }; + } + + @Override + public void initTPSWarp(LongSupplier longSupplier) { + Util.timeSource = () -> System.nanoTime() + longSupplier.getAsLong(); + } +} diff --git a/SpigotCore/SpigotCore_21/src/de/steamwar/techhider/ChunkHider21.java b/SpigotCore/SpigotCore_21/src/de/steamwar/techhider/ChunkHider21.java index c31e5f8f..0d0cb782 100644 --- a/SpigotCore/SpigotCore_21/src/de/steamwar/techhider/ChunkHider21.java +++ b/SpigotCore/SpigotCore_21/src/de/steamwar/techhider/ChunkHider21.java @@ -123,7 +123,9 @@ public class ChunkHider21 implements ChunkHider { for (int x = 0; x < 16; x++) { int pos = (((y * 16) + z) * 16) + x; - switch (section.test(x, y, z)) { + TechHider.State test = section.test(x, y, z); + + switch (test) { case SKIP: break; case CHECK: diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/Reflection.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/Reflection.java index 7c34fca9..ff298c1a 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/Reflection.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/Reflection.java @@ -157,14 +157,21 @@ public final class Reflection { } else if(MAJOR_VERSION < 21 || MINOR_VERSION < 4) { return Class.forName(spigotClassnames.getOrDefault(name, name)); } else { - Class clazz = Class.forName(name); - if (clazz.getName().equals(name)) { + Class clazz = null; + try { + clazz = Class.forName(name); + } catch (ClassNotFoundException e) {} + if (clazz != null && clazz.getName().equals(name)) { return clazz; } try { return Core.class.getClassLoader().getParent().loadClass(name); } catch (ClassNotFoundException e) { + if (clazz == null) { + throw e; + } + return clazz; } } diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ChunkHider.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ChunkHider.java index fbd6e364..e1d2b5e9 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ChunkHider.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ChunkHider.java @@ -147,8 +147,9 @@ public interface ChunkHider { return; } - int longs = (int) (((long) entries * bitsPerBlock + 63) >> 6); - out.writeBytes(in, longs * Long.BYTES); + char valuesPerLong = (char)(64 / bitsPerBlock); + int i1 = (entries + valuesPerLong - 1) / valuesPerLong; + out.writeBytes(in, i1 * Long.BYTES); } public long[] readDataArray() { @@ -164,9 +165,10 @@ public interface ChunkHider { return new long[entries]; } - int longs = (int) (((long) entries * bitsPerBlock + 63) >> 6); - long[] array = new long[longs]; - for(int i = 0; i < longs; i++) + char valuesPerLong = (char) (64 / bitsPerBlock); + int i1 = (entries + valuesPerLong - 1) / valuesPerLong; + long[] array = new long[i1]; + for(int i = 0; i < i1; i++) array[i] = in.readLong(); return array; From 50780ad9bd1f2a23a5d65dae5a0eab217d882efe Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 3 Aug 2025 16:39:25 +0200 Subject: [PATCH 3/6] Add chunk reset logic for Minecraft 1.21 in `CraftbukkitWrapper21` to support advanced chunk management. --- .../utils/CraftbukkitWrapper21.java | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper21.java b/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper21.java index 68f35171..312dce88 100644 --- a/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper21.java +++ b/FightSystem/FightSystem_21/src/de/steamwar/fightsystem/utils/CraftbukkitWrapper21.java @@ -20,9 +20,17 @@ package de.steamwar.fightsystem.utils; import de.steamwar.fightsystem.Config; +import net.minecraft.core.BlockPos; +import net.minecraft.world.level.chunk.LevelChunk; +import net.minecraft.world.level.chunk.LevelChunkSection; import org.bukkit.GameRule; +import org.bukkit.World; +import org.bukkit.craftbukkit.CraftWorld; import org.bukkit.entity.Entity; +import java.util.HashSet; +import java.util.Set; + public class CraftbukkitWrapper21 extends CraftbukkitWrapper18 { @Override @@ -34,4 +42,20 @@ public class CraftbukkitWrapper21 extends CraftbukkitWrapper18 { public void setupGamerule() { Config.world.setGameRule(GameRule.LOCATOR_BAR, false); } + + private LevelChunk getChunk(World world, int x, int z) { + return ((CraftWorld) world).getHandle().getChunk(x, z); + } + + @Override + public void resetChunk(World world, World backup, int x, int z) { + LevelChunk worldChunk = getChunk(world, x, z); + LevelChunk backupChunk = getChunk(backup, x, z); + LevelChunkSection[] sections = worldChunk.getSections(); + System.arraycopy(backupChunk.getSections(), 0, sections, 0, sections.length); + Set blocks = new HashSet<>(worldChunk.blockEntities.keySet()); + blocks.stream().filter(key -> !backupChunk.blockEntities.containsKey(key)).forEach(worldChunk::removeBlockEntity); + worldChunk.heightmaps.clear(); + worldChunk.heightmaps.putAll(backupChunk.heightmaps); + } } From 285882be7021034d50cb4c61f177bbabdfd988be Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 3 Aug 2025 16:42:05 +0200 Subject: [PATCH 4/6] Add chunk reset logic for Minecraft 1.21 in `CraftbukkitWrapper21` to support advanced chunk management. --- .../SpigotCore_Main/src/de/steamwar/techhider/TechHider.java | 1 - 1 file changed, 1 deletion(-) diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/TechHider.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/TechHider.java index b231e97f..021d2fe4 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/TechHider.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/TechHider.java @@ -79,7 +79,6 @@ public class TechHider { techhiders.put(blockChangePacket, this::blockChangeHider); techhiders.put(tileEntityDataPacket, this::tileEntityDataHider); techhiders.put(multiBlockChangePacket, ProtocolWrapper.impl.multiBlockChangeGenerator(this)); - System.out.println(ChunkHider.impl.mapChunkPacket().getName()); techhiders.put(ChunkHider.impl.mapChunkPacket(), ChunkHider.impl.chunkHiderGenerator(this)); if(Core.getVersion() > 12 && Core.getVersion() < 19) { From 464d7c85bdd3c0b03ad7cd685723a75335577128 Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Sun, 3 Aug 2025 22:10:15 +0200 Subject: [PATCH 5/6] Update version handling for Minecraft 1.21.5: Adjust `TypeUtils` and `ServerStarter` to support `PAPER_21`. --- VelocityCore/src/de/steamwar/command/TypeUtils.java | 4 +++- VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/VelocityCore/src/de/steamwar/command/TypeUtils.java b/VelocityCore/src/de/steamwar/command/TypeUtils.java index a273cda2..db22ec99 100644 --- a/VelocityCore/src/de/steamwar/command/TypeUtils.java +++ b/VelocityCore/src/de/steamwar/command/TypeUtils.java @@ -46,7 +46,9 @@ public class TypeUtils { Player player = sender.getPlayer(); if (player != null && s.isEmpty()) { ProtocolVersion version = player.getProtocolVersion(); - if (version.greaterThan(ProtocolVersion.MINECRAFT_1_19_4)) { + if (version.greaterThan(ProtocolVersion.MINECRAFT_1_20_5)) { + return ServerVersion.PAPER_21; + } else if (version.greaterThan(ProtocolVersion.MINECRAFT_1_19_4)) { return ServerVersion.PAPER_20; } else if (version.greaterThan(ProtocolVersion.MINECRAFT_1_15_2)) { return ServerVersion.PAPER_19; diff --git a/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java b/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java index 058771e7..db199b97 100644 --- a/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java +++ b/VelocityCore/src/de/steamwar/velocitycore/ServerStarter.java @@ -61,7 +61,7 @@ public class ServerStarter { private String worldDir = null; private Node node = null; - private ServerVersion version = ServerVersion.PAPER_20; + private ServerVersion version = ServerVersion.PAPER_21; private Portrange portrange = BAU_PORTS; private Function serverNameProvider = port -> node.getName() + port; private BooleanSupplier startCondition = () -> true; From b74b73b871eb381134304dc807d87dc0020cecad Mon Sep 17 00:00:00 2001 From: Chaoscaot Date: Tue, 5 Aug 2025 21:12:35 +0200 Subject: [PATCH 6/6] BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/techhider/TechHiderCommand.java aktualisiert --- .../steamwar/bausystem/features/techhider/TechHiderCommand.java | 1 - 1 file changed, 1 deletion(-) diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/techhider/TechHiderCommand.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/techhider/TechHiderCommand.java index 0c1d8af5..38725cf0 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/techhider/TechHiderCommand.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/techhider/TechHiderCommand.java @@ -34,7 +34,6 @@ import de.steamwar.linkage.LinkedInstance; import de.steamwar.techhider.TechHider; import net.md_5.bungee.api.ChatMessageType; import org.bukkit.Bukkit; -import org.bukkit.Chunk; import org.bukkit.Material; import org.bukkit.command.CommandSender; import org.bukkit.configuration.file.FileConfiguration;