forked from SteamWar/SteamWar
Introduce support for Minecraft 1.21: Add ReflectionWrapper21, ChunkHider21, and enhance version compatibility across systems.
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<ChunkMap.TrackedEntity> tracker;
|
||||
|
||||
static Reflection.Field<Object> chunkMap = Reflection.getField(ServerChunkCache.class, "chunkMap", Object.class);
|
||||
static {
|
||||
ServerChunkCache chunkCache = ((CraftWorld) Config.world).getHandle().getChunkSource();
|
||||
Object map = chunkMap.get(chunkCache);
|
||||
Reflection.Field<Int2ObjectMap> 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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<List> explosionBlocks = Reflection.getField(packetPlayOutExplosion, List.class, 0);
|
||||
private static final Function<Object, Location> 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<String> keys = new HashSet<>((Set<String>) getKeys.invoke(getTag.invoke(asNMSCopy.invoke(null, stack))));
|
||||
keys.remove("Enchantments");
|
||||
keys.remove("Damage");
|
||||
return !keys.isEmpty();
|
||||
}
|
||||
}
|
||||
@@ -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<String> keys = new HashSet<>((Set<String>) 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){
|
||||
|
||||
@@ -62,6 +62,7 @@ public class HullHider implements Listener {
|
||||
private final Hull[] hulls;
|
||||
private final Map<Class<?>, BiFunction<Player, Object, Object>> 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<List> explosionBlocks = Reflection.getField(packetPlayOutExplosion, List.class, 0);
|
||||
private static final Function<Object, Location> 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<? extends Number> 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<Object, Location> posPacketToLocation(Class<?> type, Class<? extends Number> posType, double factor) {
|
||||
public static Function<Object, Location> posPacketToLocation(Class<?> type, Class<? extends Number> posType, double factor) {
|
||||
Reflection.Field<? extends Number> x = Reflection.getField(type, posType, 0);
|
||||
Reflection.Field<? extends Number> y = Reflection.getField(type, posType, 1);
|
||||
Reflection.Field<? extends Number> z = Reflection.getField(type, posType, 2);
|
||||
|
||||
@@ -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 <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ softdepend:
|
||||
- SpigotCore
|
||||
depend:
|
||||
- WorldEdit
|
||||
api-version: "1.13"
|
||||
api-version: "1.21.6"
|
||||
|
||||
commands:
|
||||
ak:
|
||||
|
||||
@@ -50,6 +50,17 @@ tasks.register<FightServer>("WarGear20") {
|
||||
config = "WarGear20.yml"
|
||||
}
|
||||
|
||||
tasks.register<FightServer>("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<FightServer>("SpaceCraftDev20") {
|
||||
group = "run"
|
||||
description = "Run a SpaceCraftDev 1.20 Fight Server"
|
||||
|
||||
Reference in New Issue
Block a user