diff --git a/AccessWidener/src/main/java/de/steamwar/ClassPatcher.java b/AccessWidener/src/main/java/de/steamwar/ClassPatcher.java index 2cce0c77..c54f69dd 100644 --- a/AccessWidener/src/main/java/de/steamwar/ClassPatcher.java +++ b/AccessWidener/src/main/java/de/steamwar/ClassPatcher.java @@ -43,6 +43,8 @@ public class ClassPatcher { /** Pre-computed set of targeted internal names for fast filtering. */ private final Set targets; + private final Set targetsPublicConstructor; + public ClassPatcher(List entries) { this.entries = entries; this.targets = entries.stream() @@ -53,6 +55,10 @@ public class ClassPatcher { return Stream.of(s, s.substring(0, index)); }) .collect(Collectors.toSet()); + this.targetsPublicConstructor = entries.stream() + .filter(entry -> entry.directive().equals("transitive-extendable")) + .map(AccessWidenerEntry::target) + .collect(Collectors.toSet()); } /** @@ -66,7 +72,7 @@ public class ClassPatcher { try { ClassReader cr = new ClassReader(classBytes); ClassWriter cw = new ClassWriter(cr, 0); - cr.accept(new ClassTransformer(cw, className, entries), ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); + cr.accept(new ClassTransformer(cw, className, entries, targetsPublicConstructor.contains(className)), ClassReader.SKIP_CODE | ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES); return cw.toByteArray(); } catch (Exception e) { LOG.warning("[AccessWidener] Failed to transform " + className + ": " + e.getMessage()); diff --git a/AccessWidener/src/main/java/de/steamwar/ClassTransformer.java b/AccessWidener/src/main/java/de/steamwar/ClassTransformer.java index ccc3df9d..534155b9 100644 --- a/AccessWidener/src/main/java/de/steamwar/ClassTransformer.java +++ b/AccessWidener/src/main/java/de/steamwar/ClassTransformer.java @@ -30,11 +30,13 @@ public class ClassTransformer extends ClassVisitor { private final String internalName; private final List entries; + private final boolean appendPublicConstructor; - public ClassTransformer(ClassVisitor cv, String internalName, List entries) { + public ClassTransformer(ClassVisitor cv, String internalName, List entries, boolean appendPublicConstructor) { super(Opcodes.ASM9, cv); this.internalName = internalName; this.entries = entries; + this.appendPublicConstructor = appendPublicConstructor; } @Override @@ -44,6 +46,13 @@ public class ClassTransformer extends ClassVisitor { if (!e.targets(internalName) || !"class".equals(e.memberType())) continue; newAccess = applyDirective(e.directive(), newAccess, false); } + if (appendPublicConstructor) { + MethodVisitor methodVisitor = visitMethod(Opcodes.ACC_PUBLIC, "", "()V", null, null); + methodVisitor.visitMaxs(0, 0); + methodVisitor.visitCode(); + methodVisitor.visitInsn(Opcodes.RETURN); + methodVisitor.visitEnd(); + } super.visit(version, newAccess, name, signature, superName, interfaces); } diff --git a/BauSystem/BauSystem_Main/src/bausystem.accesswidener b/BauSystem/BauSystem_Main/src/bausystem.accesswidener index 51fe2890..5dd89fdf 100644 --- a/BauSystem/BauSystem_Main/src/bausystem.accesswidener +++ b/BauSystem/BauSystem_Main/src/bausystem.accesswidener @@ -11,6 +11,3 @@ mutable field org/bukkit/craftbukkit/block/CraftBlockState world Lorg/bukkit/cra # For TickManager accessible field net/minecraft/server/ServerTickRateManager remainingSprintTicks J - -# Test -accessible field net/minecraft/core/registries/BuiltInRegistries BLOCK_ENTITY_TYPE Lnet/minecraft/core/Registry; \ No newline at end of file diff --git a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/util/BindCommand.java b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/util/BindCommand.java index bde7967e..5db75a81 100644 --- a/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/util/BindCommand.java +++ b/BauSystem/BauSystem_Main/src/de/steamwar/bausystem/features/util/BindCommand.java @@ -38,6 +38,7 @@ import org.bukkit.Bukkit; import org.bukkit.NamespacedKey; import org.bukkit.command.CommandMap; import org.bukkit.command.CommandSender; +import org.bukkit.craftbukkit.CraftServer; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; @@ -47,7 +48,6 @@ import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.persistence.PersistentDataType; -import java.lang.reflect.Field; import java.util.Arrays; import java.util.Collection; import java.util.List; @@ -73,19 +73,7 @@ public class BindCommand extends SWCommand implements Listener { } } - private static final CommandMap commandMap; - - static { - Field knownCommandsField; - try { - knownCommandsField = Bukkit.getServer().getClass().getDeclaredField("commandMap"); - knownCommandsField.setAccessible(true); - commandMap = (CommandMap) knownCommandsField.get(Bukkit.getServer()); - } catch (IllegalAccessException | NoSuchFieldException var2) { - Bukkit.shutdown(); - throw new SecurityException("Oh shit. Commands cannot be registered.", var2); - } - } + private static final CommandMap commandMap = ((CraftServer) Bukkit.getServer()).getCommandMap(); private static final NamespacedKey KEY = SWUtils.getNamespaceKey("command"); diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/Reflection.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/Reflection.java deleted file mode 100644 index 324d0e44..00000000 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/Reflection.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * 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; - -import jdk.internal.misc.Unsafe; -import lombok.experimental.UtilityClass; - - -@UtilityClass -public final class Reflection { - - public static Object newInstance(Class clazz) { - try { - return Unsafe.getUnsafe().allocateInstance(clazz); - } catch (InstantiationException e) { - throw new SecurityException("Could not create object", e); - } - } -} diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/command/CommandRegistering.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/command/CommandRegistering.java index 4adffb58..90026343 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/command/CommandRegistering.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/command/CommandRegistering.java @@ -22,35 +22,20 @@ package de.steamwar.command; import lombok.experimental.UtilityClass; import org.bukkit.Bukkit; import org.bukkit.command.Command; -import org.bukkit.command.CommandMap; import org.bukkit.command.SimpleCommandMap; +import org.bukkit.craftbukkit.CraftServer; -import java.lang.reflect.Field; import java.util.Map; @UtilityClass class CommandRegistering { - private static final CommandMap commandMap; + private static final SimpleCommandMap commandMap; private static final Map knownCommandMap; static { - try { - final Field commandMapField = Bukkit.getServer().getClass().getDeclaredField("commandMap"); - commandMapField.setAccessible(true); - commandMap = (CommandMap) commandMapField.get(Bukkit.getServer()); - } catch (NoSuchFieldException | IllegalAccessException exception) { - Bukkit.shutdown(); - throw new SecurityException("Oh shit. Commands cannot be registered.", exception); - } - try { - final Field knownCommandsField = SimpleCommandMap.class.getDeclaredField("knownCommands"); - knownCommandsField.setAccessible(true); - knownCommandMap = (Map) knownCommandsField.get(commandMap); - } catch (NoSuchFieldException | IllegalAccessException exception) { - Bukkit.shutdown(); - throw new SecurityException("Oh shit. Commands cannot be registered.", exception); - } + commandMap = ((CraftServer) Bukkit.getServer()).getCommandMap(); + knownCommandMap = commandMap.getKnownCommands(); } static void unregister(Command command) { diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/REntity.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/REntity.java index 63411a0c..1c7cce4d 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/REntity.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/entity/REntity.java @@ -20,7 +20,6 @@ package de.steamwar.entity; import com.mojang.datafixers.util.Pair; -import de.steamwar.Reflection; import it.unimi.dsi.fastutil.ints.IntArrayList; import lombok.Getter; import net.minecraft.core.registries.BuiltInRegistries; @@ -174,7 +173,7 @@ public class REntity { } public void showAnimation(byte animation) { - ClientboundAnimatePacket packet = (ClientboundAnimatePacket) Reflection.newInstance(ClientboundAnimatePacket.class); + ClientboundAnimatePacket packet = new ClientboundAnimatePacket(); packet.id = entityId; packet.action = animation; server.updateEntity(this, packet); @@ -185,7 +184,7 @@ public class REntity { } public void showDamage() { - ClientboundEntityEventPacket packet = (ClientboundEntityEventPacket) Reflection.newInstance(ClientboundEntityEventPacket.class); + ClientboundEntityEventPacket packet = new ClientboundEntityEventPacket(); packet.entityId = entityId; packet.eventId = (byte) 2; server.updateEntity(this, packet); @@ -363,7 +362,7 @@ public class REntity { } private Object getHeadRotationPacket() { - ClientboundRotateHeadPacket packet = (ClientboundRotateHeadPacket) Reflection.newInstance(ClientboundRotateHeadPacket.class); + ClientboundRotateHeadPacket packet = new ClientboundRotateHeadPacket(); packet.entityId = entityId; packet.yHeadRot = headYaw; return packet; diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ChunkHider.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ChunkHider.java index 471cdc4a..bd21f357 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ChunkHider.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ChunkHider.java @@ -33,8 +33,8 @@ import java.util.List; import java.util.function.UnaryOperator; public class ChunkHider { - private static final UnaryOperator chunkPacketShallowCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkWithLightPacket.class); - private static final UnaryOperator chunkDataShallowCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkPacketData.class); + private static final UnaryOperator chunkPacketShallowCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkWithLightPacket.class, ClientboundLevelChunkWithLightPacket::new); + private static final UnaryOperator chunkDataShallowCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkPacketData.class, ClientboundLevelChunkPacketData::new); private final int SECTION_SPAN_SIZE = 16; private final byte BIT_PER_BLOCK_INDIRECTION_LIMIT = 8; diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ProtocolUtils.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ProtocolUtils.java index b97fe828..18997565 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ProtocolUtils.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/ProtocolUtils.java @@ -20,41 +20,25 @@ package de.steamwar.techhider; import com.google.common.primitives.Bytes; -import de.steamwar.Reflection; import io.netty.buffer.ByteBuf; -import java.lang.reflect.Array; import java.lang.reflect.Field; import java.lang.reflect.Modifier; import java.util.ArrayList; import java.util.List; import java.util.function.BiConsumer; -import java.util.function.BiFunction; +import java.util.function.Supplier; import java.util.function.UnaryOperator; public class ProtocolUtils { private ProtocolUtils() { } - @Deprecated - public static BiFunction, Object> arrayCloneGenerator(Class elementClass) { - return (array, worker) -> { - int length = Array.getLength(array); - Object result = Array.newInstance(elementClass, length); - - for (int i = 0; i < length; i++) { - Array.set(result, i, worker.apply(Array.get(array, i))); - } - - return result; - }; - } - - public static UnaryOperator shallowCloneGenerator(Class clazz) { + public static UnaryOperator shallowCloneGenerator(Class clazz, Supplier supplier) { BiConsumer filler = shallowFill(clazz); return source -> { - T clone = (T) Reflection.newInstance(clazz); + T clone = supplier.get(); filler.accept(source, clone); return clone; }; diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/legacy/ChunkHider.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/legacy/ChunkHider.java index dc4e3c33..9aaa9b40 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/legacy/ChunkHider.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/legacy/ChunkHider.java @@ -40,8 +40,8 @@ import java.util.stream.Collectors; public class ChunkHider { public static final ChunkHider impl = new ChunkHider(); - private static final UnaryOperator chunkPacketCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkWithLightPacket.class); - private static final UnaryOperator chunkDataCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkPacketData.class); + private static final UnaryOperator chunkPacketCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkWithLightPacket.class, ClientboundLevelChunkWithLightPacket::new); + private static final UnaryOperator chunkDataCloner = ProtocolUtils.shallowCloneGenerator(ClientboundLevelChunkPacketData.class, ClientboundLevelChunkPacketData::new); public BiFunction chunkHiderGenerator(TechHider techHider) { return (p, packet) -> { diff --git a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/legacy/TechHider.java b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/legacy/TechHider.java index f8e027be..dfa0a5f3 100644 --- a/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/legacy/TechHider.java +++ b/SpigotCore/SpigotCore_Main/src/de/steamwar/techhider/legacy/TechHider.java @@ -92,9 +92,9 @@ public class TechHider { techhiders.forEach(TinyProtocol.instance::removeFilter); } - public static final UnaryOperator multiBlockChangeCloner = ProtocolUtils.shallowCloneGenerator(ClientboundSectionBlocksUpdatePacket.class); + public static final UnaryOperator multiBlockChangeCloner = ProtocolUtils.shallowCloneGenerator(ClientboundSectionBlocksUpdatePacket.class, ClientboundSectionBlocksUpdatePacket::new); - private static final UnaryOperator blockChangeCloner = ProtocolUtils.shallowCloneGenerator(ClientboundBlockUpdatePacket.class); + private static final UnaryOperator blockChangeCloner = ProtocolUtils.shallowCloneGenerator(ClientboundBlockUpdatePacket.class, ClientboundBlockUpdatePacket::new); private ClientboundBlockUpdatePacket blockChangeHider(Player p, ClientboundBlockUpdatePacket packet) { switch (locationEvaluator.checkBlockPos(p, packet.getPos())) { diff --git a/SpigotCore/SpigotCore_Main/src/spigotcore.accesswidener b/SpigotCore/SpigotCore_Main/src/spigotcore.accesswidener index 1fcaac48..68d0aa82 100644 --- a/SpigotCore/SpigotCore_Main/src/spigotcore.accesswidener +++ b/SpigotCore/SpigotCore_Main/src/spigotcore.accesswidener @@ -15,16 +15,22 @@ accessible field net/minecraft/server/MinecraftServer services Lnet/minecraft/se mutable field net/minecraft/server/MinecraftServer services Lnet/minecraft/server/Services; # REntity +## transitive-extendable means that a public no args constructor is added without any super initialization +transitive-extendable class net/minecraft/network/protocol/game/ClientboundAnimatePacket accessible field net/minecraft/network/protocol/game/ClientboundAnimatePacket id I mutable field net/minecraft/network/protocol/game/ClientboundAnimatePacket id I accessible field net/minecraft/network/protocol/game/ClientboundAnimatePacket action I mutable field net/minecraft/network/protocol/game/ClientboundAnimatePacket action I +## transitive-extendable means that a public no args constructor is added without any super initialization +transitive-extendable class net/minecraft/network/protocol/game/ClientboundEntityEventPacket accessible field net/minecraft/network/protocol/game/ClientboundEntityEventPacket entityId I mutable field net/minecraft/network/protocol/game/ClientboundEntityEventPacket entityId I accessible field net/minecraft/network/protocol/game/ClientboundEntityEventPacket eventId B mutable field net/minecraft/network/protocol/game/ClientboundEntityEventPacket eventId B +## transitive-extendable means that a public no args constructor is added without any super initialization +transitive-extendable class net/minecraft/network/protocol/game/ClientboundRotateHeadPacket accessible field net/minecraft/network/protocol/game/ClientboundRotateHeadPacket yHeadRot B mutable field net/minecraft/network/protocol/game/ClientboundRotateHeadPacket yHeadRot B ## + TechHider @@ -32,9 +38,13 @@ accessible field net/minecraft/network/protocol/game/ClientboundRotateHeadPacket mutable field net/minecraft/network/protocol/game/ClientboundRotateHeadPacket entityId I # For ChunkHider +## transitive-extendable means that a public no args constructor is added without any super initialization +transitive-extendable class net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket accessible field net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket chunkData Lnet/minecraft/network/protocol/game/ClientboundLevelChunkPacketData; mutable field net/minecraft/network/protocol/game/ClientboundLevelChunkWithLightPacket chunkData Lnet/minecraft/network/protocol/game/ClientboundLevelChunkPacketData; +## transitive-extendable means that a public no args constructor is added without any super initialization +transitive-extendable class net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData accessible field net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData buffer [B mutable field net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData buffer [B accessible field net/minecraft/network/protocol/game/ClientboundLevelChunkPacketData blockEntitiesData Ljava/util/List; @@ -47,6 +57,8 @@ accessible field net/minecraft/network/protocol/game/ClientboundLevelChunkPacket # For TechHider accessible field net/minecraft/network/protocol/game/ClientboundMoveEntityPacket entityId I +## transitive-extendable means that a public no args constructor is added without any super initialization +transitive-extendable class net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket accessible field net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket sectionPos Lnet/minecraft/core/SectionPos; accessible field net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket positions [S mutable field net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket positions [S @@ -54,4 +66,6 @@ accessible field net/minecraft/network/protocol/game/ClientboundSectionBlocksUpd mutable field net/minecraft/network/protocol/game/ClientboundSectionBlocksUpdatePacket states [Lnet/minecraft/world/level/block/state/BlockState; # For legacy/TechHider -mutable field net/minecraft/network/protocol/game/ClientboundBlockUpdatePacket blockState Lnet/minecraft/world/level/block/state/BlockState; +## transitive-extendable means that a public no args constructor is added without any super initialization +transitive-extendable class net/minecraft/network/protocol/game/ClientboundBlockUpdatePacket +mutable field net/minecraft/network/protocol/game/ClientboundBlockUpdatePacket blockState Lnet/minecraft/world/level/block/state/BlockState; \ No newline at end of file