diff --git a/BauSystem_19/src/de/steamwar/bausystem/utils/NMSWrapper19.java b/BauSystem_19/src/de/steamwar/bausystem/utils/NMSWrapper19.java
index d6c7df29..f7e82cc7 100644
--- a/BauSystem_19/src/de/steamwar/bausystem/utils/NMSWrapper19.java
+++ b/BauSystem_19/src/de/steamwar/bausystem/utils/NMSWrapper19.java
@@ -55,7 +55,6 @@ public class NMSWrapper19 implements NMSWrapper {
@SuppressWarnings("deprecation")
public void setInternalGameMode(Player player, GameMode gameMode) {
playerGameMode.set(((CraftPlayer) player).getHandle().d, EnumGamemode.a(gameMode.getValue()));
-
}
@Override
diff --git a/BauSystem_20/build.gradle b/BauSystem_20/build.gradle
new file mode 100644
index 00000000..bfb7c724
--- /dev/null
+++ b/BauSystem_20/build.gradle
@@ -0,0 +1,62 @@
+/*
+ * This file is a part of the SteamWar software.
+ *
+ * Copyright (C) 2020 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 .
+ */
+
+plugins {
+ id 'base'
+ id 'java'
+}
+
+group 'steamwar'
+version '1.0'
+
+compileJava.options.encoding = 'UTF-8'
+
+sourceCompatibility = 1.8
+targetCompatibility = 1.8
+
+sourceSets {
+ main {
+ java {
+ srcDirs = ['src/']
+ }
+ resources {
+ srcDirs = ['src/']
+ exclude '**/*.java', '**/*.kt'
+ }
+ }
+}
+
+dependencies {
+ compileOnly 'org.projectlombok:lombok:1.18.22'
+ testCompileOnly 'org.projectlombok:lombok:1.18.22'
+ annotationProcessor 'org.projectlombok:lombok:1.18.22'
+ testAnnotationProcessor 'org.projectlombok:lombok:1.18.22'
+
+ implementation project(":BauSystem_Main")
+
+ compileOnly 'org.spigotmc:spigot-api:1.20-R0.1-SNAPSHOT'
+ compileOnly 'it.unimi.dsi:fastutil:8.5.6'
+ compileOnly 'com.mojang:datafixerupper:4.0.26'
+ compileOnly 'io.netty:netty-all:4.1.68.Final'
+ compileOnly 'com.mojang:authlib:1.5.25'
+ compileOnly 'com.mojang:brigadier:1.0.18'
+
+ compileOnly swdep('Spigot-1.20')
+ compileOnly swdep('SpigotCore')
+}
\ No newline at end of file
diff --git a/BauSystem_20/src/de/steamwar/bausystem/utils/NMSWrapper20.java b/BauSystem_20/src/de/steamwar/bausystem/utils/NMSWrapper20.java
new file mode 100644
index 00000000..f532eeec
--- /dev/null
+++ b/BauSystem_20/src/de/steamwar/bausystem/utils/NMSWrapper20.java
@@ -0,0 +1,178 @@
+/*
+ * 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.bausystem.utils;
+
+import com.comphenix.tinyprotocol.Reflection;
+import com.comphenix.tinyprotocol.TinyProtocol;
+import de.steamwar.bausystem.features.util.NoClipCommand;
+import net.minecraft.SystemUtils;
+import net.minecraft.nbt.NBTBase;
+import net.minecraft.nbt.NBTTagCompound;
+import net.minecraft.nbt.NBTTagList;
+import net.minecraft.network.protocol.Packet;
+import net.minecraft.network.protocol.game.*;
+import net.minecraft.network.syncher.DataWatcher;
+import net.minecraft.server.level.PlayerInteractManager;
+import net.minecraft.world.level.EnumGamemode;
+import net.minecraft.world.phys.Vec3D;
+import org.bukkit.Bukkit;
+import org.bukkit.GameMode;
+import org.bukkit.Material;
+import org.bukkit.World;
+import org.bukkit.craftbukkit.v1_20_R1.entity.CraftEntity;
+import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
+import org.bukkit.craftbukkit.v1_20_R1.inventory.CraftItemStack;
+import org.bukkit.entity.Player;
+import org.bukkit.entity.TNTPrimed;
+import org.bukkit.inventory.ItemStack;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.function.LongSupplier;
+
+public class NMSWrapper20 implements NMSWrapper {
+
+ private static final Reflection.FieldAccessor playerGameMode = Reflection.getField(PlayerInteractManager.class, EnumGamemode.class, 0);
+
+ @Override
+ @SuppressWarnings("deprecation")
+ public void setInternalGameMode(Player player, GameMode gameMode) {
+ playerGameMode.set(((CraftPlayer) player).getHandle().d, EnumGamemode.a(gameMode.getValue()));
+ }
+
+ @Override
+ public void setSlotToItemStack(Player player, Object o) {
+ PacketPlayInSetCreativeSlot packetPlayInSetCreativeSlot = (PacketPlayInSetCreativeSlot) o;
+ int index = packetPlayInSetCreativeSlot.a();
+ if (index >= 36 && index <= 44) {
+ index -= 36;
+ } else if (index > 44) {
+ index -= 5;
+ } else if (index <= 8) {
+ index = index - 8 + 36;
+ }
+ player.getInventory().setItem(index, CraftItemStack.asBukkitCopy(packetPlayInSetCreativeSlot.c()));
+ if (index < 9) player.getInventory().setHeldItemSlot(index);
+ player.updateInventory();
+ }
+
+ @Override
+ public void init(LongSupplier longSupplier) {
+ SystemUtils.a = () -> System.nanoTime() + longSupplier.getAsLong();
+ }
+
+ private static final List> packets = new ArrayList<>();
+ private static final Vec3D noMotion = new Vec3D(0, 0, 0);
+
+ @Override
+ public void createTickCache(World world) {
+ packets.clear();
+ world.getEntities().stream().filter(entity -> !(entity instanceof Player)).forEach(entity -> {
+ packets.add(new PacketPlayOutEntityVelocity(entity.getEntityId(), noMotion));
+ packets.add(new PacketPlayOutEntityTeleport(((CraftEntity) entity).getHandle()));
+
+ if (entity instanceof TNTPrimed) {
+ net.minecraft.world.entity.Entity serverEntity = ((CraftEntity) entity).getHandle();
+ List> list = serverEntity.aj().c();
+ if(list != null)
+ packets.add(new PacketPlayOutEntityMetadata(serverEntity.af(), list));
+ }
+ });
+ }
+
+ @Override
+ public void sendTickPackets() {
+ Bukkit.getOnlinePlayers().forEach(player -> {
+ for (Packet> p : packets) {
+ TinyProtocol.instance.sendPacket(player, p);
+ }
+ });
+ }
+
+ private static final Reflection.FieldAccessor gameStateChangeReason = Reflection.getField(NoClipCommand.gameStateChange, PacketPlayOutGameStateChange.a.class, 12);
+
+ @Override
+ public void setGameStateChangeReason(Object packet) {
+ gameStateChangeReason.set(packet, PacketPlayOutGameStateChange.d);
+ }
+
+ @Override
+ public void setPlayerBuildAbilities(Player player) {
+ ((CraftPlayer) player).getHandle().fO().d = true;
+ ((CraftPlayer) player).getHandle().fO().e = true;
+ }
+
+ @Override
+ public Material pathMaterial() {
+ return Material.DIRT_PATH;
+ }
+
+ private static final int threshold = 2048;
+
+ @Override
+ public boolean checkItemStack(ItemStack item) {
+ net.minecraft.world.item.ItemStack nmsItem = CraftItemStack.asNMSCopy(item);
+ NBTTagCompound tag = nmsItem.v();
+ if (tag != null && tag.e("BlockEntityTag")) {
+ NBTTagCompound blockTag = tag.p("BlockEntityTag");
+ if (blockTag.e("Items")) {
+ return drillDown(blockTag.c("Items", 10), 0, 0) > threshold;
+ }
+ }
+
+ return false;
+ }
+
+ private int drillDown(NBTTagList items, int layer, int start) {
+ if (layer > 2) return start + threshold;
+ int invalid = start;
+ for (NBTBase nbtBase : items) {
+ if (!(nbtBase instanceof NBTTagCompound))
+ continue;
+ NBTTagCompound slot = (NBTTagCompound) nbtBase;
+ if (slot.e("tag")) {
+ invalid += slot.f("Count");
+ NBTTagCompound iTag = slot.p("tag");
+ if (iTag.e("BlockEntityTag")) {
+ NBTTagCompound blockTag = iTag.p("BlockEntityTag");
+ if (blockTag.e("Items")) {
+ invalid = drillDown(blockTag.c("Items", 10), layer + 1, invalid);
+ }
+ }
+ }
+ if (invalid > threshold)
+ break;
+ }
+ return invalid;
+ }
+
+ private final Class> explosionPacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutExplosion");
+ private final Reflection.FieldAccessor a = Reflection.getField(explosionPacket, double.class, 0);
+ private final Reflection.FieldAccessor b = Reflection.getField(explosionPacket, double.class, 1);
+ private final Reflection.FieldAccessor c = Reflection.getField(explosionPacket, double.class, 2);
+ private final Reflection.FieldAccessor d = Reflection.getField(explosionPacket, float.class, 0);
+ private final Reflection.FieldAccessor e = Reflection.getField(explosionPacket, List.class, 0);
+
+ @Override
+ public Object resetExplosionKnockback(Object packet) {
+ PacketPlayOutExplosion packetPlayOutExplosion = (PacketPlayOutExplosion) packet;
+ return new PacketPlayOutExplosion(a.get(packetPlayOutExplosion), b.get(packetPlayOutExplosion), c.get(packetPlayOutExplosion), d.get(packetPlayOutExplosion), e.get(packetPlayOutExplosion), null);
+ }
+}
diff --git a/BauSystem_20/src/de/steamwar/bausystem/utils/PlayerMovementWrapper20.java b/BauSystem_20/src/de/steamwar/bausystem/utils/PlayerMovementWrapper20.java
new file mode 100644
index 00000000..752d79f8
--- /dev/null
+++ b/BauSystem_20/src/de/steamwar/bausystem/utils/PlayerMovementWrapper20.java
@@ -0,0 +1,80 @@
+/*
+ * 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.bausystem.utils;
+
+import net.minecraft.network.protocol.game.PacketPlayInFlying;
+import net.minecraft.server.level.EntityPlayer;
+import org.bukkit.Location;
+import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer;
+import org.bukkit.entity.Player;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.UUID;
+
+public class PlayerMovementWrapper20 implements PlayerMovementWrapper {
+
+ private static class Position {
+ private double x;
+ private double y;
+ private double z;
+ private float yaw;
+ private float pitch;
+ }
+
+ private Map playerLocationMap = new HashMap<>();
+
+ @Override
+ public void setPosition(Player player, Object object) {
+ Position position = playerLocationMap.computeIfAbsent(player.getUniqueId(), uuid -> {
+ Position pos = new Position();
+ Location location = player.getLocation();
+ pos.x = location.getX();
+ pos.y = location.getY();
+ pos.z = location.getZ();
+ pos.yaw = location.getYaw();
+ pos.pitch = location.getPitch();
+ return pos;
+ });
+ PacketPlayInFlying packetPlayInFlying = ((PacketPlayInFlying) object);
+ EntityPlayer entityPlayer = ((CraftPlayer) player).getHandle();
+ if (packetPlayInFlying.h) {
+ entityPlayer.b(packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c, packetPlayInFlying.d, packetPlayInFlying.e);
+ position.x = packetPlayInFlying.a;
+ position.y = packetPlayInFlying.b;
+ position.z = packetPlayInFlying.c;
+ position.yaw = packetPlayInFlying.d;
+ position.pitch = packetPlayInFlying.e;
+ } else {
+ entityPlayer.e(packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c);
+ position.x = packetPlayInFlying.a;
+ position.y = packetPlayInFlying.b;
+ position.z = packetPlayInFlying.c;
+ }
+ }
+
+ @Override
+ public void disable(Player player) {
+ Position position = playerLocationMap.remove(player.getUniqueId());
+ if (position != null) {
+ player.teleport(new Location(player.getWorld(), position.x, position.y, position.z, position.yaw, position.pitch));
+ }
+ }
+}