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