From fcb1ce4e4b4d7a4d448311daf487a4e33b019b95 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Sat, 7 Oct 2023 21:05:01 +0200 Subject: [PATCH 1/5] Hotfix PlaceItemUtils and Blackstone placing Walls in 1.19 Signed-off-by: yoyosource --- .../src/de/steamwar/bausystem/utils/PlaceItemWrapper15.java | 2 +- .../src/de/steamwar/bausystem/utils/PlaceItemUtils.java | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/BauSystem_15/src/de/steamwar/bausystem/utils/PlaceItemWrapper15.java b/BauSystem_15/src/de/steamwar/bausystem/utils/PlaceItemWrapper15.java index c945351a..cbb65fd3 100644 --- a/BauSystem_15/src/de/steamwar/bausystem/utils/PlaceItemWrapper15.java +++ b/BauSystem_15/src/de/steamwar/bausystem/utils/PlaceItemWrapper15.java @@ -31,7 +31,7 @@ public class PlaceItemWrapper15 implements PlaceItemWrapper { String nonWall = material.name().replace("_WALL_", "").replace("WALL_", "").replace("_WALL", ""); try { Material nonWallMaterial = Material.valueOf(nonWall); - if (nonWallMaterial != material) { + if (nonWallMaterial != material && nonWallMaterial.isItem() && !nonWallMaterial.isBlock()) { BLOCK_MATERIAL_TO_WALL_BLOCK_MATERIAL.put(nonWallMaterial, material); } } catch (Exception e) { diff --git a/BauSystem_Main/src/de/steamwar/bausystem/utils/PlaceItemUtils.java b/BauSystem_Main/src/de/steamwar/bausystem/utils/PlaceItemUtils.java index b4af6262..e9189282 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/utils/PlaceItemUtils.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/utils/PlaceItemUtils.java @@ -162,8 +162,9 @@ public class PlaceItemUtils { if (blockData == null) return PlaceItemResult.NO_BLOCK_ITEM_HELD; // Placing a Block inside of Water should set it to Waterlogged - if (blockData instanceof Waterlogged) { - ((Waterlogged) blockData).setWaterlogged(block.getType() == Material.WATER); + if (blockData instanceof Waterlogged && block.getType() == Material.WATER) { + Levelled levelled = (Levelled) block.getBlockData(); + ((Waterlogged) blockData).setWaterlogged(levelled.getLevel() == levelled.getMaximumLevel()); } if (blockData instanceof Slab) { From 6197fd81c148318b468dabbcd92dbc21e47e18f9 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Sun, 8 Oct 2023 12:07:27 +0200 Subject: [PATCH 2/5] Hotfix PlaceItemUtils for Slab/Stairs/Trapdoor Signed-off-by: yoyosource --- .../src/de/steamwar/bausystem/utils/PlaceItemUtils.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/BauSystem_Main/src/de/steamwar/bausystem/utils/PlaceItemUtils.java b/BauSystem_Main/src/de/steamwar/bausystem/utils/PlaceItemUtils.java index e9189282..bec908a6 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/utils/PlaceItemUtils.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/utils/PlaceItemUtils.java @@ -170,12 +170,21 @@ public class PlaceItemUtils { if (blockData instanceof Slab) { // Slabs can be set at Top or Bottom ((Slab) blockData).setType(isHitHalfTop(player) ? Slab.Type.TOP : Slab.Type.BOTTOM); + if (againstSide == BlockFace.DOWN) { + ((Slab) blockData).setType(Slab.Type.TOP); + } } else if (blockData instanceof Stairs) { // Stairs can be set at Top or Bottom ((Stairs) blockData).setHalf(isHitHalfTop(player) ? Bisected.Half.TOP : Bisected.Half.BOTTOM); + if (againstSide == BlockFace.DOWN) { + ((Stairs) blockData).setHalf(Bisected.Half.TOP); + } } else if (blockData instanceof TrapDoor) { // TrapDoors can be set at Top or Bottom ((TrapDoor) blockData).setHalf(isHitHalfTop(player) ? Bisected.Half.TOP : Bisected.Half.BOTTOM); + if (againstSide == BlockFace.DOWN) { + ((TrapDoor) blockData).setHalf(Bisected.Half.TOP); + } } else if (blockData instanceof Chain) { // Chains are always rotated against the block you place against Orientable orientable = (Orientable) blockData; From 83a281b2787479a8069e649d605fa3c7c19c4552 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Wed, 11 Oct 2023 15:35:02 +0200 Subject: [PATCH 3/5] Update TPSLimit system to TPSSystem Cleanup some mess from before --- .../bausystem/utils/NMSWrapper15.java | 32 -- .../utils/PlayerMovementWrapper15.java | 19 + .../bausystem/utils/NMSWrapper18.java | 31 -- .../utils/PlayerMovementWrapper18.java | 17 + .../bausystem/utils/NMSWrapper19.java | 33 -- .../utils/PlayerMovementWrapper19.java | 45 +- .../bausystem/utils/NMSWrapper20.java | 48 +- .../utils/PlayerMovementWrapper20.java | 46 +- BauSystem_Main/src/BauSystem.properties | 34 +- BauSystem_Main/src/BauSystem_de.properties | 34 +- .../src/de/steamwar/bausystem/BauSystem.java | 10 +- .../bausystem/features/bau/InfoCommand.java | 15 +- .../features/script/lua/libs/ServerLib.java | 3 +- .../features/tpslimit/FreezeUtils.java | 166 ------- .../features/tpslimit/PacketCache.java | 133 ++++++ .../features/tpslimit/TPSCommand.java | 53 +++ .../features/tpslimit/TPSFreezeUtils.java | 76 ++++ .../features/tpslimit/TPSLimitBauGuiItem.java | 62 --- .../features/tpslimit/TPSLimitCommand.java | 134 ------ .../features/tpslimit/TPSLimitUtils.java | 96 ++-- .../tpslimit/TPSScoreboardElement.java | 68 --- .../features/tpslimit/TPSSystem.java | 409 ++++++++++++++++++ .../features/tpslimit/TPSWarpUtils.java | 67 --- .../features/tpslimit/TickCommand.java | 133 ------ .../bausystem/features/util/TpsCommand.java | 54 --- .../bausystem/features/xray/XrayCommand.java | 1 - .../steamwar/bausystem/utils/NMSWrapper.java | 7 - .../utils/PlayerMovementWrapper.java | 14 +- 28 files changed, 852 insertions(+), 988 deletions(-) delete mode 100644 BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/FreezeUtils.java create mode 100644 BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/PacketCache.java create mode 100644 BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSCommand.java create mode 100644 BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSFreezeUtils.java delete mode 100644 BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSLimitBauGuiItem.java delete mode 100644 BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSLimitCommand.java delete mode 100644 BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSScoreboardElement.java create mode 100644 BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSSystem.java delete mode 100644 BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSWarpUtils.java delete mode 100644 BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TickCommand.java delete mode 100644 BauSystem_Main/src/de/steamwar/bausystem/features/util/TpsCommand.java diff --git a/BauSystem_15/src/de/steamwar/bausystem/utils/NMSWrapper15.java b/BauSystem_15/src/de/steamwar/bausystem/utils/NMSWrapper15.java index b6cd9609..3b56be55 100644 --- a/BauSystem_15/src/de/steamwar/bausystem/utils/NMSWrapper15.java +++ b/BauSystem_15/src/de/steamwar/bausystem/utils/NMSWrapper15.java @@ -63,38 +63,6 @@ public class NMSWrapper15 implements NMSWrapper { 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.server.v1_15_R1.Entity serverEntity = ((CraftEntity) entity).getHandle(); - packets.add(new PacketPlayOutEntityMetadata(serverEntity.getId(), serverEntity.getDataWatcher(), true)); - } - }); - } - - @Override - public void sendTickPackets() { - Bukkit.getOnlinePlayers().forEach(player -> { - PlayerConnection connection = ((CraftPlayer) player).getHandle().playerConnection; - for (Packet p : packets) { - connection.sendPacket(p); - } - }); - } - private static final Reflection.FieldAccessor gameStateChangeReason = Reflection.getField(NoClipCommand.gameStateChange, int.class, 0); @Override diff --git a/BauSystem_15/src/de/steamwar/bausystem/utils/PlayerMovementWrapper15.java b/BauSystem_15/src/de/steamwar/bausystem/utils/PlayerMovementWrapper15.java index bcaabf70..b0ed19b3 100644 --- a/BauSystem_15/src/de/steamwar/bausystem/utils/PlayerMovementWrapper15.java +++ b/BauSystem_15/src/de/steamwar/bausystem/utils/PlayerMovementWrapper15.java @@ -19,9 +19,12 @@ package de.steamwar.bausystem.utils; +import com.comphenix.tinyprotocol.Reflection; import de.steamwar.bausystem.utils.PlayerMovementWrapper; import net.minecraft.server.v1_15_R1.EntityPlayer; import net.minecraft.server.v1_15_R1.PacketPlayInFlying; +import net.minecraft.server.v1_15_R1.PacketPlayOutEntity; +import net.minecraft.server.v1_15_R1.PacketPlayOutEntityTeleport; import org.bukkit.craftbukkit.v1_15_R1.entity.CraftPlayer; import org.bukkit.entity.Player; @@ -37,4 +40,20 @@ public class PlayerMovementWrapper15 implements PlayerMovementWrapper { entityPlayer.setLocation(packetPlayInFlying.a(0.0), packetPlayInFlying.b(0.0), packetPlayInFlying.c(0.0), packetPlayInFlying.a(0F), packetPlayInFlying.b(0F)); } } + + @Override + public Object convertToOut(Player player, Object object) { + PacketPlayInFlying packetPlayInFlying = ((PacketPlayInFlying) object); + Object packet = Reflection.newInstance(teleportPacket); + teleportEntity.set(packet, player.getEntityId()); + teleportPosition.set(packet, packetPlayInFlying.a(0.0), packetPlayInFlying.b(0.0), packetPlayInFlying.c(0.0)); + if (Float.isNaN(packetPlayInFlying.a(Float.NaN))) { + teleportYaw.set(packet, rotToByte(player.getLocation().getYaw())); + teleportPitch.set(packet, rotToByte(player.getLocation().getPitch())); + } else { + teleportYaw.set(packet, rotToByte(packetPlayInFlying.a(0.0F))); + teleportPitch.set(packet, rotToByte(packetPlayInFlying.b(0.0F))); + } + return packet; + } } diff --git a/BauSystem_18/src/de/steamwar/bausystem/utils/NMSWrapper18.java b/BauSystem_18/src/de/steamwar/bausystem/utils/NMSWrapper18.java index 3e9ed190..c12ce0af 100644 --- a/BauSystem_18/src/de/steamwar/bausystem/utils/NMSWrapper18.java +++ b/BauSystem_18/src/de/steamwar/bausystem/utils/NMSWrapper18.java @@ -73,37 +73,6 @@ public class NMSWrapper18 implements NMSWrapper { 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(); - packets.add(new PacketPlayOutEntityMetadata(serverEntity.ae(), serverEntity.ai(), true)); - } - }); - } - - @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 diff --git a/BauSystem_18/src/de/steamwar/bausystem/utils/PlayerMovementWrapper18.java b/BauSystem_18/src/de/steamwar/bausystem/utils/PlayerMovementWrapper18.java index 5f442edc..8762e418 100644 --- a/BauSystem_18/src/de/steamwar/bausystem/utils/PlayerMovementWrapper18.java +++ b/BauSystem_18/src/de/steamwar/bausystem/utils/PlayerMovementWrapper18.java @@ -19,6 +19,7 @@ package de.steamwar.bausystem.utils; +import com.comphenix.tinyprotocol.Reflection; import de.steamwar.bausystem.utils.PlayerMovementWrapper; import net.minecraft.network.protocol.game.PacketPlayInFlying; import net.minecraft.server.level.EntityPlayer; @@ -37,4 +38,20 @@ public class PlayerMovementWrapper18 implements PlayerMovementWrapper { entityPlayer.e(packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c); } } + + @Override + public Object convertToOut(Player player, Object object) { + PacketPlayInFlying packetPlayInFlying = ((PacketPlayInFlying) object); + Object packet = Reflection.newInstance(teleportPacket); + teleportEntity.set(packet, player.getEntityId()); + teleportPosition.set(packet, packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c); + if (packetPlayInFlying.h) { + teleportYaw.set(packet, rotToByte(player.getLocation().getYaw())); + teleportPitch.set(packet, rotToByte(player.getLocation().getPitch())); + } else { + teleportYaw.set(packet, rotToByte(packetPlayInFlying.d)); + teleportPitch.set(packet, rotToByte(packetPlayInFlying.e)); + } + return packet; + } } diff --git a/BauSystem_19/src/de/steamwar/bausystem/utils/NMSWrapper19.java b/BauSystem_19/src/de/steamwar/bausystem/utils/NMSWrapper19.java index f7e82cc7..ecdc33be 100644 --- a/BauSystem_19/src/de/steamwar/bausystem/utils/NMSWrapper19.java +++ b/BauSystem_19/src/de/steamwar/bausystem/utils/NMSWrapper19.java @@ -73,39 +73,6 @@ public class NMSWrapper19 implements NMSWrapper { 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.al().c(); - if(list != null) - packets.add(new PacketPlayOutEntityMetadata(serverEntity.ah(), 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 diff --git a/BauSystem_19/src/de/steamwar/bausystem/utils/PlayerMovementWrapper19.java b/BauSystem_19/src/de/steamwar/bausystem/utils/PlayerMovementWrapper19.java index afc51ded..9262bfea 100644 --- a/BauSystem_19/src/de/steamwar/bausystem/utils/PlayerMovementWrapper19.java +++ b/BauSystem_19/src/de/steamwar/bausystem/utils/PlayerMovementWrapper19.java @@ -19,6 +19,7 @@ package de.steamwar.bausystem.utils; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.network.protocol.game.PacketPlayInFlying; import net.minecraft.server.level.EntityPlayer; import org.bukkit.Location; @@ -31,50 +32,30 @@ import java.util.UUID; public class PlayerMovementWrapper19 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)); + public Object convertToOut(Player player, Object object) { + PacketPlayInFlying packetPlayInFlying = ((PacketPlayInFlying) object); + Object packet = Reflection.newInstance(teleportPacket); + teleportEntity.set(packet, player.getEntityId()); + teleportPosition.set(packet, packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c); + if (packetPlayInFlying.h) { + teleportYaw.set(packet, rotToByte(player.getLocation().getYaw())); + teleportPitch.set(packet, rotToByte(player.getLocation().getPitch())); + } else { + teleportYaw.set(packet, rotToByte(packetPlayInFlying.d)); + teleportPitch.set(packet, rotToByte(packetPlayInFlying.e)); } + return packet; } } diff --git a/BauSystem_20/src/de/steamwar/bausystem/utils/NMSWrapper20.java b/BauSystem_20/src/de/steamwar/bausystem/utils/NMSWrapper20.java index e8d2f209..1cb81892 100644 --- a/BauSystem_20/src/de/steamwar/bausystem/utils/NMSWrapper20.java +++ b/BauSystem_20/src/de/steamwar/bausystem/utils/NMSWrapper20.java @@ -20,32 +20,23 @@ 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.network.protocol.game.PacketPlayInSetCreativeSlot; +import net.minecraft.network.protocol.game.PacketPlayOutExplosion; +import net.minecraft.network.protocol.game.PacketPlayOutGameStateChange; 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 { @@ -73,39 +64,6 @@ public class NMSWrapper20 implements NMSWrapper { 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 diff --git a/BauSystem_20/src/de/steamwar/bausystem/utils/PlayerMovementWrapper20.java b/BauSystem_20/src/de/steamwar/bausystem/utils/PlayerMovementWrapper20.java index 752d79f8..958e4bb8 100644 --- a/BauSystem_20/src/de/steamwar/bausystem/utils/PlayerMovementWrapper20.java +++ b/BauSystem_20/src/de/steamwar/bausystem/utils/PlayerMovementWrapper20.java @@ -19,7 +19,9 @@ package de.steamwar.bausystem.utils; +import com.comphenix.tinyprotocol.Reflection; import net.minecraft.network.protocol.game.PacketPlayInFlying; +import net.minecraft.network.protocol.game.PacketPlayOutEntityTeleport; import net.minecraft.server.level.EntityPlayer; import org.bukkit.Location; import org.bukkit.craftbukkit.v1_20_R1.entity.CraftPlayer; @@ -31,50 +33,30 @@ 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)); + public Object convertToOut(Player player, Object object) { + PacketPlayInFlying packetPlayInFlying = ((PacketPlayInFlying) object); + Object packet = Reflection.newInstance(teleportPacket); + teleportEntity.set(packet, player.getEntityId()); + teleportPosition.set(packet, packetPlayInFlying.a, packetPlayInFlying.b, packetPlayInFlying.c); + if (packetPlayInFlying.h) { + teleportYaw.set(packet, rotToByte(player.getLocation().getYaw())); + teleportPitch.set(packet, rotToByte(player.getLocation().getPitch())); + } else { + teleportYaw.set(packet, rotToByte(packetPlayInFlying.d)); + teleportPitch.set(packet, rotToByte(packetPlayInFlying.e)); } + return packet; } } diff --git a/BauSystem_Main/src/BauSystem.properties b/BauSystem_Main/src/BauSystem.properties index c50219a1..0037825c 100644 --- a/BauSystem_Main/src/BauSystem.properties +++ b/BauSystem_Main/src/BauSystem.properties @@ -33,7 +33,7 @@ SCOREBOARD_REGION = Region SCOREBOARD_TRACE = Trace SCOREBOARD_LOADER = Loader SCOREBOARD_TPS = TPS -SCOREBOARD_TPS_FROZEN = §e Frozen +SCOREBOARD_TPS_FROZEN = §eFrozen SCOREBOARD_TRACE_TICKS = Ticks @@ -459,27 +459,31 @@ DEPTH_COUNTER_HOVER = §7X§8ק7Y§8ק7Z DEPTH_COUNTER_TNT = §7 TNT§8: §e{0} # TPSLimit -TICK_STEP_HELP = §8/§etick step §8<§7Ticks§8> §8- §7Step n ticks -TICK_STEP_SINGLE_HELP = §8/§etick step §8- §7Step one tick -TICK_WARP_HELP = §8/§etick warp §8<§7Ticks§8> §8- §7Warp n ticks -TICK_CANCEL_HELP = §8/§etick cancel §8- §7Cancels tick step/warp -TICK_ERROR = §cYou can not activate another §8'§e/tick step§8'§c or §8'§e/tick warp§8'§c -TICK_CANCEL_ERROR = §cYou have no §8'§e/tick step§8'§c or §8'§e/tick warp§8'§c active -TICK_STEP = §eSkipping {0} ticks -TICK_STEP_LEFT = §eSkipping {0} more ticks -TICK_WARP = §eWarping {0} ticks -TICK_WARP_LEFT = §eWarping {0} more ticks -TICK_CANCEL = §eWarps and Steps canceled +TPSLIMIT_FREEZE_HELP = §8/§etpslimit 0 §8-§7 Freeze TPS +TPSLIMIT_LIMIT_HELP = §8/§etpslimit §8[§720>x>0.5§8] §8-§7 Slow TPS down +TPSLIMIT_WARP_HELP = §8/§etpslimit §8[§7x>20§8] §8-§7 Speed TPS up +TPSLIMIT_DEFAULT_HELP = §8/§etpslimit default §8-§7 Set TPS to 20 +TPSLIMIT_HELP = §8/§etpslimit §8-§7 Show current TPS + +TICK_FREEZE_HELP = §8/§etick rate 0 §8-§7 Freeze TPS +TICK_FREEZE_HELP_2 = §8/§etick freeze §8-§7 Freeze TPS +TICK_UNFREEZE_HELP = §8/§etick unfreeze §8-§7 Set TPS to 20 +TICK_LIMIT_HELP = §8/§etick rate §8[§720>x>0.5§8] §8-§7 Slow TPS down +TICK_WARP_HELP = §8/§etick rate §8[§7x>20§8] §8-§7 Speed TPS up +TICK_DEFAULT_HELP = §8/§etick rate default §8-§7 Set TPS to 20 +TICK_HELP = §8/§etick rate §8-§7 Show current TPS + +TICK_STEPPING_HELP = §8/§etick step §8<§7Ticks§8> §8-§7 Step n ticks or 1 forward +TICK_WARPING_HELP = §8/§etick warp §8<§7Ticks§8> §8<§7TPS§8> §8-§7 Warp n ticks or 1 forward + +TICK_BOSSBAR = §7Skipped §e{0}§8/§7{1} TPSLIMIT_GUI_ITEM_NAME = §eTPS limiter TPSLIMIT_GUI_ITEM_LORE = §7Currently: §e{0} TPSLIMIT_ANVIL_GUI = New TPS limit -TPSLIMIT_HELP = §8/§etpslimit §8[§7TPS§8|§edefault§8] §8- §7Sets TPS on Build TPSLIMIT_CURRENT = §7Current TPS limit§8: §e{0} TPSLIMIT_NO_PERMS = §cYou are not allowed to use the TPS-Limiter here TPSLIMIT_SET = §eSet TPS limit to {0} TPSLIMIT_FROZEN = §eTPS frozen -TPSLIMIT_INVALID = §cOnly numbers between 0,5 and {0}, and 'default'{1} allowed. -TPSLIMIT_INVALID_FROZEN = §c and '0' # Trace TRACE_RECORD=§aon diff --git a/BauSystem_Main/src/BauSystem_de.properties b/BauSystem_Main/src/BauSystem_de.properties index 4bc55737..e5da397d 100644 --- a/BauSystem_Main/src/BauSystem_de.properties +++ b/BauSystem_Main/src/BauSystem_de.properties @@ -33,7 +33,7 @@ SCOREBOARD_REGION = Region SCOREBOARD_TRACE = Trace SCOREBOARD_LOADER = Loader SCOREBOARD_TPS = TPS -SCOREBOARD_TPS_FROZEN = §e Eingefroren +SCOREBOARD_TPS_FROZEN = §eEingefroren SCOREBOARD_TRACE_TICKS = Ticks @@ -428,27 +428,31 @@ BLOCK_COUNTER_DISABLE = §7BlockCounter ausgemacht DEPTH_COUNTER_MESSAGE = §7Tiefe §8> §7 # TPSLimit -TICK_STEP_HELP = §8/§etick step §8<§7Ticks§8> §8- §7Spule n Ticks vor -TICK_STEP_SINGLE_HELP = §8/§etick step §8- §7Spule einen Ticks vor -TICK_WARP_HELP = §8/§etick warp §8<§7Ticks§8> §8- §7Warpe n Ticks vor -TICK_CANCEL_HELP = §8/§etick cancel §8- §7Cancelt den Tick Warp oder Step -TICK_ERROR = §cDu kannst keinen weiteren §8'§e/tick step§8'§c oder §8'§e/tick warp§8'§c anmachen -TICK_CANCEL_ERROR = §cDu hast keinen §8'§e/tick step§8'§c oder §8'§e/tick warp§8'§c aktiv -TICK_STEP = §eSpult {0} Ticks vor -TICK_STEP_LEFT = §eSpult noch {0} Ticks vor -TICK_WARP = §eWarpe {0} Ticks vor -TICK_WARP_LEFT = §eWarpe noch {0} Ticks vor -TICK_CANCEL = §eWarps und Steps abgebrochen +TPSLIMIT_FREEZE_HELP = §8/§etpslimit 0 §8-§7 Friere TPS ein +TPSLIMIT_LIMIT_HELP = §8/§etpslimit §8[§720>x>0.5§8] §8-§7 Verlangsame die TPS +TPSLIMIT_WARP_HELP = §8/§etpslimit §8[§7x>20§8] §8-§7 Beschleunige die TPS +TPSLIMIT_DEFAULT_HELP = §8/§etpslimit default §8-§7 Setze die TPS auf 20 +TPSLIMIT_HELP = §8/§etpslimit §8-§7 Zeige die jetzige TPS + +TICK_FREEZE_HELP = §8/§etick rate 0 §8-§7 Friere TPS ein +TICK_FREEZE_HELP_2 = §8/§etick freeze §8-§7 Friere TPS ein +TICK_UNFREEZE_HELP = §8/§etick unfreeze §8-§7 Setze die TPS auf 20 +TICK_LIMIT_HELP = §8/§etick rate §8[§720>x>0.5§8] §8-§7 Verlangsame die TPS +TICK_WARP_HELP = §8/§etick rate §8[§7x>20§8] §8-§7 Beschleunige die TPS +TICK_DEFAULT_HELP = §8/§etick rate default §8-§7 Setze die TPS auf 20 +TICK_HELP = §8/§etick rate §8-§7 Zeige die jetzige TPS + +TICK_STEPPING_HELP = §8/§etick step §8<§7Ticks§8> §8-§7 Spule n ticks oder 1 vor +TICK_WARPING_HELP = §8/§etick warp §8<§7Ticks§8> §8<§7TPS§8> §8-§7 Warpe n ticks oder 1 vor + +TICK_BOSSBAR = §e{0}§8/§7{1} gesprungen TPSLIMIT_GUI_ITEM_NAME = §eTPS Limiter TPSLIMIT_GUI_ITEM_LORE = §7Aktuell: §e{0} TPSLIMIT_ANVIL_GUI = Neues TPS Limit -TPSLIMIT_HELP = §8/§etpslimit §8[§7TPS§8|§edefault§8] §8- §7Setzte die TPS auf dem Bau TPSLIMIT_CURRENT = §7Jetziges TPS limit§8: §e{0} TPSLIMIT_NO_PERMS = §cDu darfst hier nicht den TPS-Limiter nutzen TPSLIMIT_SET = §eTPS limit auf {0} gesetzt. TPSLIMIT_FROZEN = §eTPS eingefroren. -TPSLIMIT_INVALID = §cNur Zahlen zwischen 0,5 und {0}, und 'default'{1} erlaubt. -TPSLIMIT_INVALID_FROZEN = §c und '0' # Trace TRACE_RECORD=§aan diff --git a/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java b/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java index 0d38af4e..e8e803c5 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/BauSystem.java @@ -21,16 +21,12 @@ package de.steamwar.bausystem; import com.comphenix.tinyprotocol.TinyProtocol; import de.steamwar.bausystem.configplayer.Config; -import de.steamwar.bausystem.features.tpslimit.FreezeUtils; -import de.steamwar.bausystem.features.tpslimit.TPSLimitUtils; -import de.steamwar.bausystem.features.tpslimit.TPSUtils; -import de.steamwar.bausystem.features.tpslimit.TPSWarpUtils; import de.steamwar.bausystem.features.world.RamUsage; +import de.steamwar.bausystem.linkage.LinkageUtils; import de.steamwar.bausystem.region.loader.PrototypeLoader; import de.steamwar.bausystem.region.loader.RegionLoader; import de.steamwar.bausystem.region.loader.Updater; import de.steamwar.bausystem.worlddata.WorldData; -import de.steamwar.bausystem.linkage.LinkageUtils; import de.steamwar.message.Message; import lombok.Getter; import org.bukkit.Bukkit; @@ -139,7 +135,7 @@ public class BauSystem extends JavaPlugin implements Listener { @Override public void run() { - if (FreezeUtils.isFrozen()) return; + // if (FreezeUtils.isFrozen()) return; if (counter >= delay) { runnable.run(); cancel(); @@ -157,7 +153,7 @@ public class BauSystem extends JavaPlugin implements Listener { @Override public void run() { - if (FreezeUtils.isFrozen()) return; + // if (FreezeUtils.isFrozen()) return; if (counter >= (first ? delay : period)) { first = false; runnable.run(); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/bau/InfoCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/bau/InfoCommand.java index 53acafeb..345dc1b3 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/bau/InfoCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/bau/InfoCommand.java @@ -2,7 +2,6 @@ package de.steamwar.bausystem.features.bau; import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.config.BauServer; -import de.steamwar.bausystem.features.tpslimit.TPSWarpUtils; import de.steamwar.bausystem.region.Region; import de.steamwar.bausystem.region.flags.Flag; import de.steamwar.command.SWCommand; @@ -15,8 +14,6 @@ import org.bukkit.entity.Player; import java.util.List; -import static de.steamwar.bausystem.features.tpslimit.TPSWarpUtils.getTps; - @Linked public class InfoCommand extends SWCommand { @@ -65,13 +62,11 @@ public class InfoCommand extends SWCommand { StringBuilder tpsMessage = new StringBuilder(); tpsMessage.append(BauSystem.MESSAGE.parsePrefixed("BAU_INFO_COMMAND_TPS", p)); - tpsMessage.append(" ").append(getTps(TPSWatcher.TPSType.ONE_SECOND)); - tpsMessage.append(" ").append(getTps(TPSWatcher.TPSType.TEN_SECONDS)); - if (!TPSWarpUtils.isWarping()) { - tpsMessage.append(" ").append(TPSWatcher.getTPS(TPSWatcher.TPSType.ONE_MINUTE)); - tpsMessage.append(" ").append(TPSWatcher.getTPS(TPSWatcher.TPSType.FIVE_MINUTES)); - tpsMessage.append(" ").append(TPSWatcher.getTPS(TPSWatcher.TPSType.TEN_MINUTES)); - } + tpsMessage.append(" ").append(TPSWatcher.getTPS(TPSWatcher.TPSType.ONE_SECOND)); + tpsMessage.append(" ").append(TPSWatcher.getTPS(TPSWatcher.TPSType.TEN_SECONDS)); + tpsMessage.append(" ").append(TPSWatcher.getTPS(TPSWatcher.TPSType.ONE_MINUTE)); + tpsMessage.append(" ").append(TPSWatcher.getTPS(TPSWatcher.TPSType.FIVE_MINUTES)); + tpsMessage.append(" ").append(TPSWatcher.getTPS(TPSWatcher.TPSType.TEN_MINUTES)); p.sendMessage(tpsMessage.toString()); } } diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/script/lua/libs/ServerLib.java b/BauSystem_Main/src/de/steamwar/bausystem/features/script/lua/libs/ServerLib.java index 54754471..80134fba 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/script/lua/libs/ServerLib.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/script/lua/libs/ServerLib.java @@ -20,7 +20,6 @@ package de.steamwar.bausystem.features.script.lua.libs; import de.steamwar.bausystem.BauSystem; -import de.steamwar.bausystem.features.tpslimit.TPSLimitUtils; import de.steamwar.bausystem.features.tpslimit.TPSUtils; import de.steamwar.core.TPSWatcher; import de.steamwar.inventory.SWItem; @@ -76,7 +75,7 @@ public class ServerLib implements LuaLib { tpsLib.set("fiveMinute", getter(() -> TPSWatcher.getTPS(TPSWatcher.TPSType.FIVE_MINUTES))); tpsLib.set("tenMinute", getter(() -> TPSWatcher.getTPS(TPSWatcher.TPSType.TEN_MINUTES))); tpsLib.set("current", getter(TPSWatcher::getTPS)); - tpsLib.set("limit", getter(TPSLimitUtils::getCurrentTPSLimit)); + // tpsLib.set("limit", getter(TPSLimitUtils::getCurrentTPSLimit)); serverLib.set("tps", tpsLib); return serverLib; diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/FreezeUtils.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/FreezeUtils.java deleted file mode 100644 index 294cffd0..00000000 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/FreezeUtils.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2021 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.features.tpslimit; - -import com.comphenix.tinyprotocol.Reflection; -import com.comphenix.tinyprotocol.TinyProtocol; -import de.steamwar.bausystem.BauSystem; -import de.steamwar.core.BountifulWrapper; -import de.steamwar.core.ChatWrapper; -import lombok.Getter; -import lombok.experimental.UtilityClass; -import org.bukkit.Bukkit; -import org.bukkit.World; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Player; -import org.bukkit.entity.TNTPrimed; -import org.bukkit.scheduler.BukkitRunnable; -import org.bukkit.scheduler.BukkitTask; -import yapion.utils.ReflectionsUtils; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; -import java.util.Set; -import java.util.stream.Collectors; - -@UtilityClass -public class FreezeUtils { - - private static final Field field; - public static final boolean freezeEnabled; - - private static final Reflection.MethodInvoker getWorldHandle = Reflection.getTypedMethod(Reflection.getClass("{obc}.CraftWorld"), "getHandle", null); - - @Getter - private static boolean frozen = false; - - private static final World world; - - static { - field = ReflectionsUtils.getField(Reflection.getClass("{nms.server.level}.WorldServer"), "freezed"); - if (field != null) field.setAccessible(true); - freezeEnabled = field != null; - world = Bukkit.getWorlds().get(0); - } - - public static void freeze() { - setFreeze(world, true); - } - - public static void unfreeze() { - setFreeze(world, false); - } - - public static boolean frozen() { - return freezeEnabled && frozen; - } - - private void setFreeze(World world, boolean state) { - if (freezeEnabled) { - try { - field.set(getWorldHandle.invoke(world), state); - cacheEntityPackets(state); - frozen = state; - } catch (IllegalAccessException e) { - // Ignored; - } - } - } - - private List packets = new ArrayList<>(); - private Set entities = new HashSet<>(); - private BukkitTask task = null; - - private Class vec3dClass = Reflection.getClass("{nms.world.phys}.Vec3D"); - private Reflection.FieldAccessor zeroVec3d = (Reflection.FieldAccessor) Reflection.getField(vec3dClass, vec3dClass, 0); - private Object ZERO_VEC3D = zeroVec3d.get(null); - private Class velocityPacketClass = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutEntityVelocity"); - private Reflection.ConstructorInvoker velocityPacketConstructor = Reflection.getConstructor(velocityPacketClass, int.class, vec3dClass); - - private Class teleportPacketClass = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutEntityTeleport"); - private Class entityClass = Reflection.getClass("{nms.world.entity}.Entity"); - private Reflection.ConstructorInvoker teleportPacketConstructor = Reflection.getConstructor(teleportPacketClass, entityClass); - - private Class craftEntityClass = Reflection.getClass("{obc}.entity.CraftEntity"); - private Reflection.MethodInvoker getHandle = Reflection.getMethod(craftEntityClass, "getHandle"); - - private Object noGravityDataWatcher = BountifulWrapper.impl.getDataWatcherObject(5, Boolean.class); - private Object fuseDataWatcher = BountifulWrapper.impl.getDataWatcherObject(8, Integer.class); - - private void cacheEntityPackets(boolean state) { - if (state) { - createPackets(); - - if (task == null) { - task = new BukkitRunnable() { - @Override - public void run() { - createPackets(); - - for (Player player : Bukkit.getOnlinePlayers()) { - for (Object packet : packets) { - TinyProtocol.instance.sendPacket(player, packet); - } - } - } - }.runTaskTimer(BauSystem.getInstance(), 1, 1); - } - } else { - packets.clear(); - entities.clear(); - - if (task != null) { - task.cancel(); - task = null; - } - } - } - - private void createPackets() { - if (FreezeUtils.entities.stream().anyMatch(Entity::isDead)) { - entities.clear(); - packets.clear(); - } - List entities = Bukkit.getWorlds().get(0).getEntities().stream() - .filter(e -> !(e instanceof Player)) - .filter(e -> !FreezeUtils.entities.contains(e)) - .collect(Collectors.toList()); - - for (Entity entity : entities) { - packets.add(teleportPacketConstructor.invoke(getHandle.invoke(entity))); - } - for (Entity entity : entities) { - packets.add(velocityPacketConstructor.invoke(entity.getEntityId(), ZERO_VEC3D)); - } - for (Entity entity : entities) { - packets.add(ChatWrapper.impl.getDataWatcherPacket(entity.getEntityId(), noGravityDataWatcher, true)); - } - for (Entity entity : entities) { - if (!(entity instanceof TNTPrimed)) continue; - TNTPrimed tnt = (TNTPrimed) entity; - int fuse = tnt.getFuseTicks(); - packets.add(ChatWrapper.impl.getDataWatcherPacket(entity.getEntityId(), fuseDataWatcher, fuse - (fuse % 5) + 1)); - } - - FreezeUtils.entities.addAll(entities); - } -} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/PacketCache.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/PacketCache.java new file mode 100644 index 00000000..253641c0 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/PacketCache.java @@ -0,0 +1,133 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 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.features.tpslimit; + +import com.comphenix.tinyprotocol.Reflection; +import com.comphenix.tinyprotocol.TinyProtocol; +import de.steamwar.core.BountifulWrapper; +import de.steamwar.core.ChatWrapper; +import de.steamwar.core.Core; +import lombok.experimental.UtilityClass; +import org.bukkit.Bukkit; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Player; +import org.bukkit.entity.TNTPrimed; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scheduler.BukkitTask; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +@UtilityClass +class PacketCache { + + private static List packets = new ArrayList<>(); + private static Set entities = new HashSet<>(); + private static BukkitTask task = null; + + private static Class vec3dClass = Reflection.getClass("{nms.world.phys}.Vec3D"); + private static Reflection.FieldAccessor zeroVec3d = (Reflection.FieldAccessor) Reflection.getField(vec3dClass, vec3dClass, 0); + private static Object ZERO_VEC3D = zeroVec3d.get(null); + private static Class velocityPacketClass = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutEntityVelocity"); + private static Reflection.ConstructorInvoker velocityPacketConstructor = Reflection.getConstructor(velocityPacketClass, int.class, vec3dClass); + + private static Class teleportPacketClass = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutEntityTeleport"); + private static Class entityClass = Reflection.getClass("{nms.world.entity}.Entity"); + private static Reflection.ConstructorInvoker teleportPacketConstructor = Reflection.getConstructor(teleportPacketClass, entityClass); + + private static Class craftEntityClass = Reflection.getClass("{obc}.entity.CraftEntity"); + private static Reflection.MethodInvoker getHandle = Reflection.getMethod(craftEntityClass, "getHandle"); + + private static Object noGravityDataWatcher = BountifulWrapper.impl.getDataWatcherObject(5, Boolean.class); + private static Object fuseDataWatcher = BountifulWrapper.impl.getDataWatcherObject(8, Integer.class); + + public void continuousSendCache() { + if (task != null) { + return; + } + + createPackets(); + task = new BukkitRunnable() { + @Override + public void run() { + _sendCache(); + } + }.runTaskTimer(Core.getInstance(), 1, 1); + } + + public void sendCache() { + if (task != null) { + task.cancel(); + task = null; + } + _sendCache(); + } + + private void _sendCache() { + createPackets(); + for (Player player : Bukkit.getOnlinePlayers()) { + for (Object packet : packets) { + TinyProtocol.instance.sendPacket(player, packet); + } + } + } + + public void clearCache() { + packets.clear(); + entities.clear(); + + if (task != null) { + task.cancel(); + task = null; + } + } + + private void createPackets() { + if (entities.stream().anyMatch(Entity::isDead)) { + entities.clear(); + packets.clear(); + } + List entities = Bukkit.getWorlds().get(0).getEntities().stream() + .filter(e -> !(e instanceof Player)) + .filter(e -> !PacketCache.entities.contains(e)) + .collect(Collectors.toList()); + + for (Entity entity : entities) { + packets.add(teleportPacketConstructor.invoke(getHandle.invoke(entity))); + } + for (Entity entity : entities) { + packets.add(velocityPacketConstructor.invoke(entity.getEntityId(), ZERO_VEC3D)); + } + for (Entity entity : entities) { + packets.add(ChatWrapper.impl.getDataWatcherPacket(entity.getEntityId(), noGravityDataWatcher, true)); + } + for (Entity entity : entities) { + if (!(entity instanceof TNTPrimed)) continue; + TNTPrimed tnt = (TNTPrimed) entity; + int fuse = tnt.getFuseTicks(); + packets.add(ChatWrapper.impl.getDataWatcherPacket(entity.getEntityId(), fuseDataWatcher, fuse - (fuse % 5) + 1)); + } + + entities.addAll(entities); + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSCommand.java new file mode 100644 index 00000000..a9267761 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSCommand.java @@ -0,0 +1,53 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 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.features.tpslimit; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.command.SWCommand; +import de.steamwar.core.TPSWatcher; +import de.steamwar.linkage.Linked; +import org.bukkit.entity.Player; + +@Linked +public class TPSCommand extends SWCommand { + + public TPSCommand() { + super("tps"); + unregister(); + register(); + } + + @Register + public void genericCommand(Player p, String... args) { + BauSystem.MESSAGE.sendPrefixless("OTHER_TPS_HEAD", p); + BauSystem.MESSAGE.sendPrefixless("OTHER_TPS_MESSAGE", p, + TPSWatcher.getTPS(TPSWatcher.TPSType.ONE_SECOND), + TPSWatcher.getTPS(TPSWatcher.TPSType.TEN_SECONDS), + TPSWatcher.getTPS(TPSWatcher.TPSType.ONE_MINUTE), + TPSWatcher.getTPS(TPSWatcher.TPSType.FIVE_MINUTES), + TPSWatcher.getTPS(TPSWatcher.TPSType.TEN_MINUTES) + ); + } + + @Register + public void genericCommand(Player p, TPSWatcher.TPSType type) { + BauSystem.MESSAGE.sendPrefixless("OTHER_TPS_SINGLE", p, TPSSystem.getInstance().getTPS(type)); + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSFreezeUtils.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSFreezeUtils.java new file mode 100644 index 00000000..34981161 --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSFreezeUtils.java @@ -0,0 +1,76 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 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.features.tpslimit; + +import com.comphenix.tinyprotocol.Reflection; +import lombok.Getter; +import lombok.experimental.UtilityClass; +import org.bukkit.Bukkit; +import org.bukkit.World; + +@UtilityClass +public class TPSFreezeUtils { + + private static Reflection.FieldAccessor fieldAccessor; + @Getter + private static final boolean canFreeze; + + private static final Reflection.MethodInvoker getWorldHandle = Reflection.getTypedMethod(Reflection.getClass("{obc}.CraftWorld"), "getHandle", null); + + @Getter + private static boolean frozen = false; + + private static final World world = Bukkit.getWorlds().get(0); + + static { + Reflection.FieldAccessor fieldAccessor; + try { + fieldAccessor = Reflection.getField(Reflection.getClass("{nms.server.level}.WorldServer"), "freezed", boolean.class); + } catch (IllegalArgumentException e) { + fieldAccessor = null; + } + canFreeze = fieldAccessor != null; + TPSFreezeUtils.fieldAccessor = fieldAccessor; + } + + public void freeze() { + setFreeze(world, true); + } + + public void unfreeze() { + setFreeze(world, false); + } + + public boolean frozen() { + return canFreeze && frozen; + } + + private void setFreeze(World world, boolean state) { + if (canFreeze) { + fieldAccessor.set(getWorldHandle.invoke(world), state); + if (state) { + PacketCache.continuousSendCache(); + } else { + PacketCache.clearCache(); + } + frozen = state; + } + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSLimitBauGuiItem.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSLimitBauGuiItem.java deleted file mode 100644 index 376f9cd4..00000000 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSLimitBauGuiItem.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2021 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.features.tpslimit; - -import de.steamwar.bausystem.BauSystem; -import de.steamwar.bausystem.Permission; -import de.steamwar.bausystem.linkage.specific.BauGuiItem; -import de.steamwar.inventory.SWAnvilInv; -import de.steamwar.inventory.SWItem; -import de.steamwar.linkage.Linked; -import org.bukkit.Material; -import org.bukkit.entity.Player; -import org.bukkit.event.inventory.ClickType; -import org.bukkit.inventory.ItemStack; - -import java.util.Arrays; - -@Linked -public class TPSLimitBauGuiItem extends BauGuiItem { - - public TPSLimitBauGuiItem() { - super(19); - } - - @Override - public ItemStack getItem(Player player) { - return new SWItem(Material.CLOCK, BauSystem.MESSAGE.parse("TPSLIMIT_GUI_ITEM_NAME", player), Arrays.asList(BauSystem.MESSAGE.parse("TPSLIMIT_GUI_ITEM_LORE", player, TPSLimitUtils.getCurrentTPSLimit())), false, clickType -> { - }).getItemStack(); - } - - @Override - public boolean click(ClickType click, Player p) { - p.closeInventory(); - SWAnvilInv inv = new SWAnvilInv(p, BauSystem.MESSAGE.parse("TPSLIMIT_ANVIL_GUI", p)); - inv.setItem(Material.CLOCK); - inv.setCallback(s -> p.performCommand("tpslimit " + s)); - inv.open(); - return false; - } - - @Override - public Permission permission() { - return Permission.WORLD; - } -} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSLimitCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSLimitCommand.java deleted file mode 100644 index 20259a4c..00000000 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSLimitCommand.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2021 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.features.tpslimit; - -import de.steamwar.bausystem.BauSystem; -import de.steamwar.bausystem.Permission; -import de.steamwar.bausystem.SWUtils; -import de.steamwar.command.SWCommand; -import de.steamwar.command.SWCommandUtils; -import de.steamwar.command.TypeMapper; -import de.steamwar.linkage.Linked; -import de.steamwar.linkage.api.Enable; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; - -import java.util.ArrayList; -import java.util.List; - -@Linked -public class TPSLimitCommand extends SWCommand implements Enable { - - private final List tabCompletions = new ArrayList<>(); - - static final int MAX_TPS = Integer.MAX_VALUE; - - public TPSLimitCommand() { - super("tpslimit"); - tabCompletions.add("0,5"); - for (int i = 0; i <= 20; i++) { - tabCompletions.add(i + ""); - } - if (TPSWarpUtils.isWarpAllowed()) { - for (int i = 20; i <= 60; i += 5) { - tabCompletions.add(i + ""); - } - for (int i = 60; i <= 240; i += 10) { - tabCompletions.add(i + ""); - } - } - if (FreezeUtils.freezeEnabled) { - tabCompletions.add("0"); - } - addDefaultHelpMessage("TPSLIMIT_HELP"); - } - - @Override - public void enable() { - TPSWarpUtils.init(); - } - - @Register - public void checkCommand(Player p) { - if (!permissionCheck(p)) return; - BauSystem.MESSAGE.send("TPSLIMIT_CURRENT", p, TPSLimitUtils.currentTPSLimit); - } - - @Register({"default"}) - public void defaultCommand(Player p) { - if (!permissionCheck(p)) return; - valueCommand(p, 20D); - } - - @Register - public void valueCommand(Player p, /*@DoubleRange(min = 0.5, max = 60)*/ double tpsLimitDouble) { - if (!permissionCheck(p)) return; - if (FreezeUtils.freezeEnabled && tpsLimitDouble == 0) { - FreezeUtils.freeze(); - TPSLimitUtils.currentTPSLimit = 20; - TPSLimitUtils.tpsLimiter(); - sendNewTPSLimitMessage(true); - return; - } - if (tpsLimitDouble < 0.5 || tpsLimitDouble > (TPSWarpUtils.isWarpAllowed() ? MAX_TPS : 20)) { - sendInvalidArgumentMessage(p); - return; - } - FreezeUtils.unfreeze(); - TPSLimitUtils.currentTPSLimit = tpsLimitDouble; - TPSLimitUtils.tpsLimiter(); - sendNewTPSLimitMessage(false); - } - - @ClassMapper(value = double.class, local = true) - public TypeMapper doubleTypeMapper() { - return SWCommandUtils.createMapper(s -> { - if (s.equalsIgnoreCase("nan")) return -1D; - try { - return Double.parseDouble(s.replace(',', '.')); - } catch (NumberFormatException e) { - return -1D; - } - }, s -> tabCompletions); - } - - @SuppressWarnings("BooleanMethodIsAlwaysInverted") - protected static boolean permissionCheck(Player player) { - if (!Permission.hasPermission(player, Permission.WORLD)) { - BauSystem.MESSAGE.send("TPSLIMIT_NO_PERMS", player); - return false; - } - return true; - } - - private void sendNewTPSLimitMessage(boolean frozen) { - Bukkit.getOnlinePlayers().forEach(player -> { - if (frozen) { - SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("TPSLIMIT_FROZEN", player)); - } else { - SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("TPSLIMIT_SET", player, TPSLimitUtils.currentTPSLimit)); - } - }); - } - - private void sendInvalidArgumentMessage(Player player) { - BauSystem.MESSAGE.send("TPSLIMIT_INVALID", player, TPSWarpUtils.isWarpAllowed() ? MAX_TPS : 20, FreezeUtils.freezeEnabled ? BauSystem.MESSAGE.parse("TPSLIMIT_INVALID_FROZEN", player) : ""); - } -} \ No newline at end of file diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSLimitUtils.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSLimitUtils.java index 6e333f03..cdc38f2d 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSLimitUtils.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSLimitUtils.java @@ -1,7 +1,7 @@ /* * This file is a part of the SteamWar software. * - * Copyright (C) 2021 SteamWar.de-Serverteam + * 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 @@ -21,51 +21,52 @@ package de.steamwar.bausystem.features.tpslimit; import com.comphenix.tinyprotocol.Reflection; import com.comphenix.tinyprotocol.TinyProtocol; -import de.steamwar.bausystem.BauSystem; -import de.steamwar.bausystem.utils.NMSWrapper; +import de.steamwar.bausystem.SWUtils; import de.steamwar.bausystem.utils.PlayerMovementWrapper; +import de.steamwar.core.Core; +import de.steamwar.core.TPSWatcher; import lombok.experimental.UtilityClass; import org.bukkit.Bukkit; import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.scheduler.BukkitTask; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.function.BiFunction; -import static de.steamwar.bausystem.features.tpslimit.TPSLimitCommand.MAX_TPS; - @UtilityClass public class TPSLimitUtils { - private static final World WORLD = Bukkit.getWorlds().get(0); - static double currentTPSLimit = 20; + private static long currentTime = System.nanoTime(); + private static BukkitTask tpsLimiter = null; + private static Queue packetQueue = new ConcurrentLinkedQueue<>(); - private long currentTime = System.nanoTime(); - - - private BukkitTask tpsLimiter = null; - - void tpsLimiter() { + public void unlimit() { if (tpsLimiter != null) tpsLimiter.cancel(); - double delay = 20 / currentTPSLimit; + tpsLimiter = null; + } + + public void limit(double tps) { + if (tpsLimiter != null) tpsLimiter.cancel(); + + double delay = 20 / tps; int loops = (int) Math.ceil(delay); long sleepDelay = (long) (50 * delay) / loops; - TPSWarpUtils.setTPS(currentTPSLimit); - if (currentTPSLimit >= 20) { - if (tpsLimiter == null) return; - tpsLimiter.cancel(); - tpsLimiter = null; - } else { - tpsLimiter = Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> { - NMSWrapper.impl.createTickCache(WORLD); - - for (int i = 0; i < loops; i++) { - sleepUntilNextTick(sleepDelay); - NMSWrapper.impl.sendTickPackets(); + tpsLimiter = Bukkit.getScheduler().runTaskTimer(Core.getInstance(), () -> { + PacketCache.sendCache(); + for (int i = 0; i < loops; i++) { + sleepUntilNextTick(sleepDelay); + PacketCache.sendCache(); + while (true) { + Runnable runnable = packetQueue.poll(); + if (runnable == null) break; + runnable.run(); } - }, 0, 1); - } + } + PacketCache.clearCache(); + }, 0, 1); } private void sleepUntilNextTick(long neededDelta) { @@ -83,26 +84,39 @@ public class TPSLimitUtils { } } - public static double getCurrentTPSLimit() { - return (double) Math.round(currentTPSLimit * 10.0D) / 10.0D; - } + /* + static { + long timeInterval = 50; + final long[] lastTime = {System.currentTimeMillis()}; + final double[] tps = {20.0}; + Bukkit.getScheduler().runTaskTimer(Core.getInstance(), () -> { + long currentTime = System.currentTimeMillis(); + if (currentTime > lastTime[0]) { + tps[0] = (double)timeInterval / (double)(currentTime - lastTime[0]) * 20.0; + } - @SuppressWarnings("unused") - public static void setTPS(double d) { - if (d < 0.5) d = 0.5; - if (d > (TPSWarpUtils.isWarpAllowed() ? MAX_TPS : 20)) d = (TPSWarpUtils.isWarpAllowed() ? MAX_TPS : 20); - currentTPSLimit = d; - tpsLimiter(); + lastTime[0] = currentTime; + + Bukkit.getOnlinePlayers().forEach(player -> { + SWUtils.sendToActionbar(player, String.valueOf((int) (tps[0] * 10.0) / 10.0)); + }); + }, timeInterval / 50L, timeInterval / 50L); } + */ private static final Class position = Reflection.getClass("{nms.network.protocol.game}.PacketPlayInFlying$PacketPlayInPosition"); private static final Class positionLook = Reflection.getClass("{nms.network.protocol.game}.PacketPlayInFlying$PacketPlayInPositionLook"); static { BiFunction positionSetter = (player, o) -> { - if (currentTPSLimit < 20) { - Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { + if (tpsLimiter != null) { + Object object = PlayerMovementWrapper.impl.convertToOut(player, o); + packetQueue.add(() -> { PlayerMovementWrapper.impl.setPosition(player, o); - }, 1L); + Bukkit.getOnlinePlayers().forEach(p -> { + if (p == player) return; + TinyProtocol.instance.sendPacket(p, object); + }); + }); return null; } return o; @@ -110,4 +124,4 @@ public class TPSLimitUtils { TinyProtocol.instance.addFilter(position, positionSetter); TinyProtocol.instance.addFilter(positionLook, positionSetter); } -} \ No newline at end of file +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSScoreboardElement.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSScoreboardElement.java deleted file mode 100644 index f22660dc..00000000 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSScoreboardElement.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2023 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.features.tpslimit; - -import de.steamwar.bausystem.BauSystem; -import de.steamwar.bausystem.region.Region; -import de.steamwar.bausystem.utils.ScoreboardElement; -import de.steamwar.core.TPSWatcher; -import de.steamwar.linkage.Linked; -import org.bukkit.entity.Player; - -@Linked -public class TPSScoreboardElement implements ScoreboardElement { - - @Override - public ScoreboardGroup getGroup() { - return ScoreboardGroup.FOOTER; - } - - @Override - public int order() { - return 0; - } - - @Override - public String get(Region region, Player p) { - if (FreezeUtils.frozen()) { - return "§e" + BauSystem.MESSAGE.parse("SCOREBOARD_TPS", p) + "§8: " + BauSystem.MESSAGE.parse("SCOREBOARD_TPS_FROZEN", p); - } else { - return "§e" + BauSystem.MESSAGE.parse("SCOREBOARD_TPS", p) + "§8: " + tpsColor() + TPSWarpUtils.getTps(TPSWatcher.TPSType.ONE_SECOND) + tpsLimit(); - } - } - - private String tpsColor() { - double tps = TPSWarpUtils.getTps(TPSWatcher.TPSType.ONE_SECOND); - if (tps > TPSLimitUtils.getCurrentTPSLimit() * 0.9) { - return "§a"; - } - if (tps > TPSLimitUtils.getCurrentTPSLimit() * 0.5) { - return "§e"; - } - return "§c"; - } - - private String tpsLimit() { - if (TPSLimitUtils.getCurrentTPSLimit() == 20) { - return ""; - } - return "§8/§7" + TPSLimitUtils.getCurrentTPSLimit(); - } -} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSSystem.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSSystem.java new file mode 100644 index 00000000..43eb40da --- /dev/null +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSSystem.java @@ -0,0 +1,409 @@ +/* + * This file is a part of the SteamWar software. + * + * Copyright (C) 2023 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.features.tpslimit; + +import de.steamwar.bausystem.BauSystem; +import de.steamwar.bausystem.Permission; +import de.steamwar.bausystem.SWUtils; +import de.steamwar.bausystem.linkage.specific.BauGuiItem; +import de.steamwar.bausystem.region.GlobalRegion; +import de.steamwar.bausystem.region.Region; +import de.steamwar.bausystem.utils.ScoreboardElement; +import de.steamwar.bausystem.utils.bossbar.BauSystemBossbar; +import de.steamwar.bausystem.utils.bossbar.BossBarService; +import de.steamwar.command.AbstractSWCommand; +import de.steamwar.command.SWCommand; +import de.steamwar.command.TypeValidator; +import de.steamwar.core.Core; +import de.steamwar.core.TPSWarpUtils; +import de.steamwar.core.TPSWatcher; +import de.steamwar.inventory.SWAnvilInv; +import de.steamwar.inventory.SWItem; +import de.steamwar.linkage.Linked; +import de.steamwar.linkage.api.Plain; +import lombok.Getter; +import org.bukkit.Bukkit; +import org.bukkit.Material; +import org.bukkit.boss.BarColor; +import org.bukkit.entity.Player; +import org.bukkit.event.inventory.ClickType; +import org.bukkit.inventory.ItemStack; +import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scheduler.BukkitTask; + +import java.util.Arrays; +import java.util.concurrent.atomic.AtomicInteger; + +@Linked +public class TPSSystem implements Plain { + + @Getter + private double currentTPSLimit = 20; + + @Getter + private static TPSSystem instance; + + public double getTPS(TPSWatcher.TPSType tpsType) { + return TPSWatcher.getTPSUnlimited(tpsType); + } + + public TPSSystem() { + if (TPSFreezeUtils.isCanFreeze()) { + new TPSFreezeCommand(); + new TickFreezeCommand(); + new TickStepCommand(); + } + new TPSLimitCommand(); + new TickLimitCommand(); + if (Core.getVersion() >= 15 && Core.getVersion() <= 20) { // If 1.21 support is not directly present + new TPSWarpCommand(); + new TickWarpCommand(); + if (TPSFreezeUtils.isCanFreeze()) { + new TickWarpingCommand(); + } + } + new TPSDefaultCommand(); + new TickDefaultCommand(); + new TPSBaseCommand(); + new TickBaseCommand(); + + instance = this; + } + + private BukkitTask stepper = null; + + private void setTPS(double tps) { + if (stepper != null) { + stepper.cancel(); + stepper = null; + Bukkit.getOnlinePlayers().forEach(player -> { + BossBarService.instance.remove(player, GlobalRegion.getInstance(), "TickStep"); + }); + } + TPSWarpUtils.warp(tps); + if (currentTPSLimit == 0 && tps != 0) { + TPSFreezeUtils.unfreeze(); + } + currentTPSLimit = tps; + if (tps == 0) { + TPSLimitUtils.unlimit(); + TPSFreezeUtils.freeze(); + } else if (tps < 20.0) { + TPSLimitUtils.limit(tps); + } else if (tps >= 20) { + TPSLimitUtils.unlimit(); + } + + Bukkit.getOnlinePlayers().forEach(player -> { + if (currentTPSLimit == 0) { + SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("TPSLIMIT_FROZEN", player)); + } else { + SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("TPSLIMIT_SET", player, currentTPSLimit)); + } + }); + } + + private void setSkip(int steps, double tpsLimitToUse) { + double currentLimit = tpsLimitToUse == 20 ? 0 : currentTPSLimit; + setTPS(tpsLimitToUse); + stepper = new BukkitRunnable() { + AtomicInteger stepsLeft = new AtomicInteger(steps); + + @Override + public void run() { + if (steps > 1) { + Bukkit.getOnlinePlayers().forEach(player -> { + BauSystemBossbar bossbar = BossBarService.instance.get(player, GlobalRegion.getInstance(), "TickStep"); + bossbar.setColor(BarColor.YELLOW); + bossbar.setTitle(BauSystem.MESSAGE.parse("TICK_BOSSBAR", player, (steps - stepsLeft.get()), steps)); + bossbar.setProgress((steps - stepsLeft.get()) / (double) steps); + }); + } + if (stepsLeft.decrementAndGet() < 0) { + setTPS(currentLimit); + } + } + }.runTaskTimer(BauSystem.getInstance(), 1, 1); + } + + public TypeValidator player() { + return (commandSender, player, messageSender) -> { + if (!Permission.hasPermission(player, Permission.WORLD)) { + messageSender.send("TPSLIMIT_NO_PERMS"); + return false; + } + return true; + }; + } + + private class TPSBaseCommand extends SWCommand { + + private TPSBaseCommand() { + super("tpslimit"); + setMessage(BauSystem.MESSAGE); + addDefaultHelpMessage("TPSLIMIT_HELP"); + } + + @ClassValidator(value = Player.class, local = true) + public TypeValidator player() { + return TPSSystem.this.player(); + } + } + + @AbstractSWCommand.PartOf(TPSBaseCommand.class) + private class TPSFreezeCommand extends SWCommand { + + private TPSFreezeCommand() { + super(""); + } + + @Register(value = "0", description = "TPSLIMIT_FREEZE_HELP") + public void freeze(@Validator Player player) { + setTPS(0); + } + } + + @AbstractSWCommand.PartOf(TPSBaseCommand.class) + private class TPSLimitCommand extends SWCommand { + + private TPSLimitCommand() { + super(""); + } + + @Register(description = "TPSLIMIT_LIMIT_HELP") + public void limit(@Validator Player player, @Min(doubleValue = 0.5) @Max(doubleValue = 20.0) double tpsLimit) { + setTPS(tpsLimit); + } + } + + @AbstractSWCommand.PartOf(TPSBaseCommand.class) + private class TPSWarpCommand extends SWCommand { + + private TPSWarpCommand() { + super(""); + } + + @Register(description = "TPSLIMIT_WARP_HELP") + public void warp(@Validator Player player, @Min(doubleValue = 20.0, inclusive = false) double tpsLimit) { + setTPS(tpsLimit); + } + } + + @AbstractSWCommand.PartOf(TPSBaseCommand.class) + private class TPSDefaultCommand extends SWCommand { + + private TPSDefaultCommand() { + super(""); + } + + @Register(description = "TPSLIMIT_HELP") + public void currentLimit(Player player) { + BauSystem.MESSAGE.send("TPSLIMIT_CURRENT", player, currentTPSLimit); + } + + @Register(value = "default", description = "TPSLIMIT_DEFAULT_HELP") + public void reset(@Validator Player player) { + setTPS(20); + } + } + + private class TickBaseCommand extends SWCommand { + + public TickBaseCommand() { + super("tick"); + setMessage(BauSystem.MESSAGE); + } + + @ClassValidator(value = Player.class, local = true) + public TypeValidator player() { + return TPSSystem.this.player(); + } + } + + @AbstractSWCommand.PartOf(TickBaseCommand.class) + private class TickFreezeCommand extends SWCommand { + + private TickFreezeCommand() { + super(""); + } + + @Register(value = {"rate", "0"}, description = "TICK_FREEZE_HELP") + @Register(value = "freeze", description = "TICK_FREEZE_HELP_2") + public void freeze(@Validator Player player) { + setTPS(0); + } + + @Register(value = "unfreeze", description = "TICK_UNFREEZE_HELP") + public void unfreeze(@Validator Player player) { + setTPS(20); + } + } + + @AbstractSWCommand.PartOf(TickBaseCommand.class) + private class TickStepCommand extends SWCommand { + + public TickStepCommand() { + super(""); + } + + @Register(value = "step", description = "TICK_STEPPING_HELP") + public void step(@Validator Player player, @Min(intValue = 1) @OptionalValue("1") int steps) { + setSkip(steps, 20); + } + } + + @AbstractSWCommand.PartOf(TickBaseCommand.class) + private class TickWarpingCommand extends SWCommand { + + public TickWarpingCommand() { + super(""); + } + + @Register(value = "warp", description = "TICK_WARPING_HELP") + public void warp(@Validator Player player, @Min(intValue = 1) @OptionalValue("1") int steps, @Min(doubleValue = 20) @OptionalValue("4000") double tps) { + setSkip(steps, tps); + } + } + + @AbstractSWCommand.PartOf(TickBaseCommand.class) + private class TickLimitCommand extends SWCommand { + + private TickLimitCommand() { + super(""); + } + + @Register(value = "rate", description = "TICK_LIMIT_HELP") + public void limit(@Validator Player player, @Min(doubleValue = 0.5, inclusive = false) @Max(doubleValue = 20.0) double tpsLimit) { + setTPS(tpsLimit); + } + } + + @AbstractSWCommand.PartOf(TickBaseCommand.class) + private class TickWarpCommand extends SWCommand { + + private TickWarpCommand() { + super(""); + } + + @Register(value = "rate", description = "TICK_WARP_HELP") + public void warp(@Validator Player player, @Min(doubleValue = 20.0, inclusive = false) double tpsLimit) { + setTPS(tpsLimit); + } + } + + @AbstractSWCommand.PartOf(TickBaseCommand.class) + private class TickDefaultCommand extends SWCommand { + + private TickDefaultCommand() { + super(""); + } + + @Register(value = "rate", description = "TICK_HELP") + public void currentLimit(Player player) { + BauSystem.MESSAGE.send("TPSLIMIT_CURRENT", player, currentTPSLimit); + } + + @Register(value = {"rate", "default"}, description = "TICK_DEFAULT_HELP") + public void reset(@Validator Player player) { + setTPS(20); + } + } + + @Linked + public static class TPSScoreboardElement implements ScoreboardElement { + + @Override + public ScoreboardGroup getGroup() { + return ScoreboardGroup.FOOTER; + } + + @Override + public int order() { + return 0; + } + + @Override + public String get(Region region, Player p) { + if (TPSSystem.getInstance().stepper != null) { + long time = System.currentTimeMillis() % 1000; + if (time < 250) { + return "§e" + BauSystem.MESSAGE.parse("SCOREBOARD_TPS", p) + "§8: §7•••"; + } else if (time < 500) { + return "§e" + BauSystem.MESSAGE.parse("SCOREBOARD_TPS", p) + "§8: §e•§7••"; + } else if (time < 750) { + return "§e" + BauSystem.MESSAGE.parse("SCOREBOARD_TPS", p) + "§8: §7•§e•§7•"; + } else { + return "§e" + BauSystem.MESSAGE.parse("SCOREBOARD_TPS", p) + "§8: §7••§e•"; + } + } else if (TPSFreezeUtils.frozen()) { + return "§e" + BauSystem.MESSAGE.parse("SCOREBOARD_TPS", p) + "§8: " + BauSystem.MESSAGE.parse("SCOREBOARD_TPS_FROZEN", p); + } else { + return "§e" + BauSystem.MESSAGE.parse("SCOREBOARD_TPS", p) + "§8: " + tpsColor() + TPSSystem.getInstance().getTPS(TPSWatcher.TPSType.ONE_SECOND) + tpsLimit(); + } + } + + private String tpsColor() { + double tps = TPSSystem.getInstance().getTPS(TPSWatcher.TPSType.ONE_SECOND); + if (tps > TPSSystem.getInstance().getCurrentTPSLimit() * 0.9) { + return "§a"; + } + if (tps > TPSSystem.getInstance().getCurrentTPSLimit() * 0.5) { + return "§e"; + } + return "§c"; + } + + private String tpsLimit() { + if (TPSSystem.getInstance().getCurrentTPSLimit() == 20) { + return ""; + } + return "§8/§7" + TPSSystem.getInstance().getCurrentTPSLimit(); + } + } + + @Linked + public static class TPSSystemBauGuiItem extends BauGuiItem { + + public TPSSystemBauGuiItem() { + super(19); + } + + @Override + public ItemStack getItem(Player player) { + return new SWItem(Material.CLOCK, BauSystem.MESSAGE.parse("TPSLIMIT_GUI_ITEM_NAME", player), Arrays.asList(BauSystem.MESSAGE.parse("TPSLIMIT_GUI_ITEM_LORE", player, TPSSystem.getInstance().currentTPSLimit)), false, clickType -> { + }).getItemStack(); + } + + @Override + public boolean click(ClickType click, Player p) { + p.closeInventory(); + SWAnvilInv inv = new SWAnvilInv(p, BauSystem.MESSAGE.parse("TPSLIMIT_ANVIL_GUI", p)); + inv.setItem(Material.CLOCK); + inv.setCallback(s -> p.performCommand("tpslimit " + s)); + inv.open(); + return false; + } + + @Override + public Permission permission() { + return Permission.WORLD; + } + } +} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSWarpUtils.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSWarpUtils.java deleted file mode 100644 index f470a871..00000000 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TPSWarpUtils.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2021 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.features.tpslimit; - -import de.steamwar.bausystem.BauSystem; -import de.steamwar.bausystem.utils.NMSWrapper; -import de.steamwar.core.TPSWatcher; -import lombok.experimental.UtilityClass; -import org.bukkit.Bukkit; -import org.bukkit.scheduler.BukkitTask; - -@UtilityClass -public class TPSWarpUtils { - - private static boolean warp = true; - private static long nanoOffset = 0; - private static long nanoDOffset = 0; - private static BukkitTask bukkitTask = null; - - static void init() { - NMSWrapper.impl.init(() -> nanoOffset); - } - - public static void setTPS(double tps) { - double d = 50 - (50 / (tps / 20.0)); - // nanoDOffset = Math.max(0, Math.min((long) (d * 1000000), 375000000)); - nanoDOffset = Math.max(0, (long) (d * 1000000)); - if (nanoDOffset == 0) { - if (bukkitTask == null) return; - bukkitTask.cancel(); - bukkitTask = null; - } else if (bukkitTask == null) { - bukkitTask = Bukkit.getScheduler().runTaskTimer(BauSystem.getInstance(), () -> nanoOffset += nanoDOffset, 1, 1); - } - } - - public static boolean isWarpAllowed() { - return warp; - } - - public static boolean isWarping() { - return nanoDOffset > 0; - } - - public static double getTps(TPSWatcher.TPSType tpsType) { - if (TPSWarpUtils.isWarping()) - return TPSWatcher.getTPS(tpsType, Math.max(TPSLimitUtils.getCurrentTPSLimit(), 20)); - return TPSWatcher.getTPS(tpsType); - } -} \ No newline at end of file diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TickCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TickCommand.java deleted file mode 100644 index cf7ca1b3..00000000 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/TickCommand.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * This file is a part of the SteamWar software. - * - * Copyright (C) 2021 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.features.tpslimit; - -import de.steamwar.bausystem.BauSystem; -import de.steamwar.bausystem.SWUtils; -import de.steamwar.command.SWCommand; -import de.steamwar.linkage.Linked; -import org.bukkit.Bukkit; -import org.bukkit.entity.Player; -import org.bukkit.scheduler.BukkitRunnable; - -import java.util.concurrent.atomic.AtomicInteger; -import java.util.function.Consumer; - -@Linked -public class TickCommand extends SWCommand { - - private AtomicInteger ticksLeft = null; - private Runnable disableTask = null; - private Consumer ticksLeftActionBar = null; - - public TickCommand() { - super("tick"); - if (!FreezeUtils.freezeEnabled) { - unregister(); - return; - } - - new BukkitRunnable() { - @Override - public void run() { - if (ticksLeft == null) { - return; - } - - if (ticksLeft.getAndDecrement() <= 0) { - disableTask.run(); - disableTask = null; - ticksLeft = null; - } - if (ticksLeftActionBar != null && ticksLeft != null) { - ticksLeftActionBar.accept(ticksLeft.get()); - } - } - }.runTaskTimer(BauSystem.getInstance(), 0L, 1L); - } - - @Register(value = {"step"}, description = {"TICK_STEP_SINGLE_HELP", "TICK_STEP_HELP"}) - public void stepCommand(Player p, @OptionalValue("1") int ticks) { - if (!TPSLimitCommand.permissionCheck(p)) return; - if (ticksLeft != null) { - BauSystem.MESSAGE.send("TICK_ERROR", p); - return; - } - Bukkit.getOnlinePlayers().forEach(player -> { - SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("TICK_STEP", player, ticks)); - }); - FreezeUtils.unfreeze(); - ticksLeft = new AtomicInteger(ticks); - disableTask = FreezeUtils::freeze; - ticksLeftActionBar = currentTicksLeft -> { - Bukkit.getOnlinePlayers().forEach(player -> { - SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("TICK_STEP_LEFT", player, currentTicksLeft)); - }); - }; - } - - @Register(value = {"warp"}, description = "TICK_WARP_HELP") - public void warpCommand(Player p, int ticks) { - if (!TPSLimitCommand.permissionCheck(p)) return; - if (ticksLeft != null) { - BauSystem.MESSAGE.send("TICK_ERROR", p); - return; - } - Bukkit.getOnlinePlayers().forEach(player -> { - SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("TICK_WARP", player, ticks)); - }); - boolean frozen = FreezeUtils.frozen(); - double currentTPSLimit = TPSLimitUtils.currentTPSLimit; - if (ticks > 1000) { - TPSLimitUtils.currentTPSLimit = 60; - } else { - TPSLimitUtils.currentTPSLimit = 240; - } - TPSLimitUtils.tpsLimiter(); - - FreezeUtils.unfreeze(); - ticksLeft = new AtomicInteger(ticks); - disableTask = () -> { - if (frozen) { - FreezeUtils.freeze(); - } - TPSLimitUtils.currentTPSLimit = currentTPSLimit; - TPSLimitUtils.tpsLimiter(); - }; - ticksLeftActionBar = currentTicksLeft -> { - Bukkit.getOnlinePlayers().forEach(player -> { - SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("TICK_WARP_LEFT", player, currentTicksLeft)); - }); - }; - } - - @Register(value = {"cancel"}, description = "TICK_CANCEL_HELP") - public void cancelCommand(Player p) { - if (!TPSLimitCommand.permissionCheck(p)) return; - if (ticksLeft == null) { - BauSystem.MESSAGE.send("TICK_CANCEL_ERROR", p); - return; - } - ticksLeft.set(0); - Bukkit.getOnlinePlayers().forEach(player -> { - SWUtils.sendToActionbar(player, BauSystem.MESSAGE.parse("TICK_CANCEL", player)); - }); - } -} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/util/TpsCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/util/TpsCommand.java deleted file mode 100644 index 302dd7e9..00000000 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/util/TpsCommand.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * 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.features.util; - -import de.steamwar.bausystem.BauSystem; -import de.steamwar.bausystem.features.tpslimit.TPSWarpUtils; -import de.steamwar.command.SWCommand; -import de.steamwar.core.TPSWatcher; -import de.steamwar.linkage.Linked; -import org.bukkit.entity.Player; - -@Linked -public class TpsCommand extends SWCommand { - - public TpsCommand() { - super("tps"); - unregister(); - register(); - } - - @Register(help = true) - public void genericCommand(Player p, String... args) { - BauSystem.MESSAGE.sendPrefixless("OTHER_TPS_HEAD", p); - BauSystem.MESSAGE.sendPrefixless("OTHER_TPS_MESSAGE", p, - TPSWarpUtils.getTps(TPSWatcher.TPSType.ONE_SECOND), - TPSWarpUtils.getTps(TPSWatcher.TPSType.TEN_SECONDS), - TPSWarpUtils.getTps(TPSWatcher.TPSType.ONE_MINUTE), - TPSWarpUtils.getTps(TPSWatcher.TPSType.FIVE_MINUTES), - TPSWarpUtils.getTps(TPSWatcher.TPSType.TEN_MINUTES) - ); - } - - @Register - public void genericCommand(Player p, TPSWatcher.TPSType type) { - BauSystem.MESSAGE.sendPrefixless("OTHER_TPS_SINGLE", p, TPSWarpUtils.getTps(type)); - } -} diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/xray/XrayCommand.java b/BauSystem_Main/src/de/steamwar/bausystem/features/xray/XrayCommand.java index ff466080..ef30fbcd 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/xray/XrayCommand.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/xray/XrayCommand.java @@ -98,7 +98,6 @@ public class XrayCommand extends SWCommand implements Listener, ScoreboardElemen techHiderCommand.disable(region, player); if (hidden.get(region).contains(player)) { hidden.get(region).remove(player); - PlayerMovementWrapper.impl.disable(player); BauSystem.MESSAGE.sendPrefixless("XRAY_OFF", player, ChatMessageType.ACTION_BAR); } else { hidden.get(region).add(player); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/utils/NMSWrapper.java b/BauSystem_Main/src/de/steamwar/bausystem/utils/NMSWrapper.java index f80d8451..2c6424c5 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/utils/NMSWrapper.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/utils/NMSWrapper.java @@ -23,22 +23,15 @@ import de.steamwar.bausystem.BauSystem; import de.steamwar.core.VersionDependent; import org.bukkit.GameMode; import org.bukkit.Material; -import org.bukkit.World; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import java.util.function.LongSupplier; - public interface NMSWrapper { NMSWrapper impl = VersionDependent.getVersionImpl(BauSystem.getInstance()); void setInternalGameMode(Player player, GameMode gameMode); void setSlotToItemStack(Player player, Object o); - void init(LongSupplier longSupplier); - void createTickCache(World world); - void sendTickPackets(); - void setGameStateChangeReason(Object packet); void setPlayerBuildAbilities(Player player); diff --git a/BauSystem_Main/src/de/steamwar/bausystem/utils/PlayerMovementWrapper.java b/BauSystem_Main/src/de/steamwar/bausystem/utils/PlayerMovementWrapper.java index 4a6a6447..b0748762 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/utils/PlayerMovementWrapper.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/utils/PlayerMovementWrapper.java @@ -19,14 +19,26 @@ package de.steamwar.bausystem.utils; +import com.comphenix.tinyprotocol.Reflection; import de.steamwar.bausystem.BauSystem; +import de.steamwar.core.BountifulWrapper; +import de.steamwar.core.Core; import de.steamwar.core.VersionDependent; import org.bukkit.entity.Player; public interface PlayerMovementWrapper { + Class teleportPacket = Reflection.getClass("{nms.network.protocol.game}.PacketPlayOutEntityTeleport"); + Reflection.FieldAccessor teleportEntity = Reflection.getField(teleportPacket, Integer.TYPE, 0); + BountifulWrapper.PositionSetter teleportPosition = BountifulWrapper.impl.getPositionSetter(teleportPacket, Core.getVersion() == 8 ? 1 : 0); + Reflection.FieldAccessor teleportYaw = Reflection.getField(teleportPacket, Byte.TYPE, 0); + Reflection.FieldAccessor teleportPitch = Reflection.getField(teleportPacket, Byte.TYPE, 1); + PlayerMovementWrapper impl = VersionDependent.getVersionImpl(BauSystem.getInstance()); void setPosition(Player player, Object object); - default void disable(Player player) { + Object convertToOut(Player player, Object object); + + default byte rotToByte(float rot) { + return (byte)((int)(rot * 256.0F / 360.0F)); } } From 8128aa7324dff4e79a36671574947d34992d5247 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Sat, 14 Oct 2023 12:27:14 +0200 Subject: [PATCH 4/5] Fix PacketCache growing uncontrollably --- .../de/steamwar/bausystem/features/tpslimit/PacketCache.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/PacketCache.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/PacketCache.java index 253641c0..e9076382 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/PacketCache.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/PacketCache.java @@ -109,7 +109,7 @@ class PacketCache { } List entities = Bukkit.getWorlds().get(0).getEntities().stream() .filter(e -> !(e instanceof Player)) - .filter(e -> !PacketCache.entities.contains(e)) + .filter(e -> PacketCache.entities.add(e)) .collect(Collectors.toList()); for (Entity entity : entities) { @@ -127,7 +127,5 @@ class PacketCache { int fuse = tnt.getFuseTicks(); packets.add(ChatWrapper.impl.getDataWatcherPacket(entity.getEntityId(), fuseDataWatcher, fuse - (fuse % 5) + 1)); } - - entities.addAll(entities); } } From 2b3f2a72d7b1bf3d608bd78585ce1ff805859cc8 Mon Sep 17 00:00:00 2001 From: yoyosource Date: Sat, 14 Oct 2023 13:09:57 +0200 Subject: [PATCH 5/5] Fix SmartPlaceListener --- .../smartplace/SmartPlaceListener.java | 237 +++++++++++++----- 1 file changed, 168 insertions(+), 69 deletions(-) diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/SmartPlaceListener.java b/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/SmartPlaceListener.java index 75f60d53..a3ca2a66 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/SmartPlaceListener.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/smartplace/SmartPlaceListener.java @@ -1,103 +1,202 @@ /* - * This file is a part of the SteamWar software. + * This file is a part of the SteamWar software. * - * Copyright (C) 2021 SteamWar.de-Serverteam + * Copyright (C) 2023 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 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. + * 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 . + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . */ package de.steamwar.bausystem.features.smartplace; +import com.comphenix.tinyprotocol.Reflection; +import com.comphenix.tinyprotocol.TinyProtocol; +import de.steamwar.bausystem.BauSystem; import de.steamwar.bausystem.configplayer.Config; -import de.steamwar.bausystem.utils.PlaceItemUtils; import de.steamwar.linkage.Linked; import org.bukkit.Bukkit; import org.bukkit.GameMode; import org.bukkit.Material; -import org.bukkit.SoundGroup; +import org.bukkit.World; import org.bukkit.block.Block; -import org.bukkit.block.data.BlockData; -import org.bukkit.block.data.type.Repeater; -import org.bukkit.block.data.type.Sign; -import org.bukkit.block.data.type.Switch; +import org.bukkit.block.BlockFace; +import org.bukkit.block.BlockState; +import org.bukkit.block.TileState; +import org.bukkit.block.data.*; +import org.bukkit.block.data.type.*; +import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; -import org.bukkit.event.block.BlockBreakEvent; +import org.bukkit.event.block.BlockPlaceEvent; import org.bukkit.event.player.PlayerInteractEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; @Linked public class SmartPlaceListener implements Listener { - @EventHandler(priority = EventPriority.HIGHEST) - public void onPlayerInteract(PlayerInteractEvent event) { - if (!Config.getInstance().get(event.getPlayer()).getPlainValueOrDefault("smartPlace", false)) return; - if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; - if (event.getPlayer().getGameMode() == GameMode.SPECTATOR) return; + // TODO: Sneaking not reset sometimes - boolean shouldRotate = event.getPlayer().isSneaking(); - Material blockType = event.getClickedBlock().getType(); - switch (blockType) { - case REPEATER: - if (shouldRotate && (event.getItem() == null || event.getItem().getType() == Material.REPEATER)) { - Repeater repeater = (Repeater) event.getClickedBlock().getBlockData(); - int i = repeater.getDelay() - 1; - if (i <= 0) i += 4; - repeater.setDelay(i); - event.getClickedBlock().setBlockData(repeater); - event.setCancelled(true); - } - return; - } - BlockData blockData = event.getClickedBlock().getBlockData(); - if (blockData instanceof Switch) { - if (!shouldRotate && (event.getItem() == null || event.getItem().getType() == event.getClickedBlock().getType())) { - return; - } - shouldRotate = false; - } + private static final Set CONTAINERS = new HashSet<>(); - PlaceItemUtils.PlaceItemResult result = PlaceItemUtils.placeItem(event.getPlayer(), event.getItem(), event.getClickedBlock(), event.getBlockFace(), event.getHand(), true, true, shouldRotate, false); - if (result.isSuccess()) { - event.setCancelled(true); - Block block = event.getClickedBlock().getRelative(event.getBlockFace()); - SoundGroup soundGroup = block.getBlockData().getSoundGroup(); - Bukkit.getOnlinePlayers().forEach(player -> { - if (!(event.getClickedBlock().getBlockData() instanceof Sign) && player == event.getPlayer()) { - return; - } - player.playSound(block.getLocation(), soundGroup.getPlaceSound(), soundGroup.getVolume() * 0.8F, soundGroup.getPitch() * 0.8F); - }); - if (result.wasForced()) { - event.getPlayer().playSound(block.getLocation(), soundGroup.getPlaceSound(), soundGroup.getVolume() * 0.8F, soundGroup.getPitch() * 0.8F); + static { + World world = Bukkit.getWorlds().get(0); + Block block = world.getBlockAt(0, 0, 0); + BlockState state = block.getState(); + for (Material material : Material.values()) { + if (material.isLegacy()) continue; + if (!material.isInteractable() && !material.isBlock()) continue; + BlockData blockData = material.createBlockData(); + block.setBlockData(blockData); + if (block.getState() instanceof TileState) { + CONTAINERS.add(material); + } else if (blockData instanceof Stairs) { + CONTAINERS.add(material); } } - // Fix Double sound for original player + CONTAINERS.add(Material.GRINDSTONE); + state.update(true, false); + } + + private static final Class useItem = Reflection.getClass("{nms.network.protocol.game}.PacketPlayInUseItem"); + private static final Set SMART_PLACING = new HashSet<>(); + + public SmartPlaceListener() { + TinyProtocol.instance.addFilter(useItem, (player, object) -> { + if (!Config.getInstance().get(player).getPlainValueOrDefault("smartPlace", false)) { + return object; + } + + Block block = player.getTargetBlockExact(6); + if (block != null && (block.getType().isInteractable() || block.getType() == Material.NOTE_BLOCK) && !CONTAINERS.contains(block.getType())) { + return object; + } + + boolean isSneaking = player.isSneaking(); + if (isSneaking) { + SMART_PLACING.add(player); + } + if (!isSneaking) { + player.setSneaking(true); + } + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { + player.setSneaking(isSneaking); + SMART_PLACING.remove(player); + }, 0); + return object; + }); } @EventHandler - public void onBlockBreak(BlockBreakEvent event) { - if (!Config.getInstance().get(event.getPlayer()).getPlainValueOrDefault("smartPlace", false)) return; + public void onPlayerInteract(PlayerInteractEvent event) { + if (event.getAction() != Action.RIGHT_CLICK_BLOCK) return; + if (event.getPlayer().getGameMode() == GameMode.SPECTATOR) return; if (!event.getPlayer().isSneaking()) return; - event.setCancelled(true); - event.getBlock().setType(Material.AIR, false); + if (event.getClickedBlock().getType() != Material.REPEATER) return; + if ((event.getItem() == null || event.getItem().getType() == Material.REPEATER)) { + Repeater repeater = (Repeater) event.getClickedBlock().getBlockData(); + int i = repeater.getDelay() - 1; + if (i <= 0) i += 4; + repeater.setDelay(i); + event.getClickedBlock().setBlockData(repeater); + event.setCancelled(true); + } + } - SoundGroup soundGroup = event.getBlock().getBlockData().getSoundGroup(); - Bukkit.getOnlinePlayers().forEach(player -> { - if (player == event.getPlayer()) return; - player.playSound(event.getBlock().getLocation(), soundGroup.getBreakSound(), soundGroup.getVolume() * 0.8F, soundGroup.getPitch() * 0.8F); - }); + @EventHandler + public void onBlockPlace(BlockPlaceEvent event) { + if (!SMART_PLACING.contains(event.getPlayer())) return; + BlockData blockData = event.getBlock().getBlockData(); + if (blockData instanceof Bed) { + Bed bed = (Bed) blockData; + Block bedHead = event.getBlock().getRelative(bed.getFacing()); + bed.setPart(Bed.Part.HEAD); + bed.setFacing(bed.getFacing().getOppositeFace()); + + bed = (Bed) bedHead.getBlockData(); + bed.setPart(Bed.Part.FOOT); + bed.setFacing(bed.getFacing().getOppositeFace()); + bedHead.setBlockData(bed, false); + } else if (blockData instanceof FaceAttachable && ((FaceAttachable) blockData).getAttachedFace() != FaceAttachable.AttachedFace.WALL) { + FaceAttachable faceAttachable = (FaceAttachable) blockData; + faceAttachable.setAttachedFace(faceAttachable.getAttachedFace() == FaceAttachable.AttachedFace.CEILING ? FaceAttachable.AttachedFace.FLOOR : FaceAttachable.AttachedFace.CEILING); + } else if (blockData instanceof Rotatable) { + Rotatable rotatable = (Rotatable) blockData; + rotatable.setRotation(rotatable.getRotation().getOppositeFace()); + } else if (blockData instanceof Directional) { + Directional directional = (Directional) blockData; + BlockFace face = directional.getFacing().getOppositeFace(); + if (directional.getFaces().contains(face)) { + directional.setFacing(face); + } + } else if (blockData instanceof MultipleFacing && !(blockData instanceof Fence)) { + MultipleFacing multipleFacing = (MultipleFacing) blockData; + List blockFaceList = multipleFacing.getFaces() + .stream() + .map(BlockFace::getOppositeFace) + .collect(Collectors.toList()); + if (multipleFacing.getAllowedFaces().containsAll(blockFaceList)) { + multipleFacing.getFaces().forEach(blockFace -> { + multipleFacing.setFace(blockFace, false); + }); + blockFaceList.forEach(blockFace -> { + multipleFacing.setFace(blockFace, true); + }); + } + } + if (blockData instanceof Stairs) { + Stairs stairs = (Stairs) blockData; + switch (stairs.getShape()) { + case OUTER_LEFT: + stairs.setShape(Stairs.Shape.INNER_RIGHT); + break; + case INNER_LEFT: + stairs.setShape(Stairs.Shape.OUTER_RIGHT); + break; + case OUTER_RIGHT: + stairs.setShape(Stairs.Shape.INNER_LEFT); + break; + case INNER_RIGHT: + stairs.setShape(Stairs.Shape.OUTER_LEFT); + break; + case STRAIGHT: + break; + } + } + if (blockData instanceof Piston) { + Piston piston = (Piston) blockData; + Block block = event.getBlock().getRelative(piston.getFacing().getOppositeFace()); + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { + event.getPlayer().sendBlockChange(block.getLocation(), block.getBlockData()); + }, 2); + } else if (blockData.getMaterial() == Material.REPEATER || blockData.getMaterial() == Material.COMPARATOR) { + Block block = event.getBlock().getRelative(BlockFace.DOWN); + BlockState old = block.getState(); + Bukkit.getScheduler().runTaskLater(BauSystem.getInstance(), () -> { + block.setType(Material.GLASS); + old.update(true, false); + }, 1); + } + event.getBlock().setBlockData(blockData, true); + } + + @EventHandler + public void onPlayerQuit(PlayerQuitEvent event) { + SMART_PLACING.remove(event.getPlayer()); } }