From e60ae56b67e1c6522192816afdf51ec45d5fee1d Mon Sep 17 00:00:00 2001 From: yoyosource Date: Fri, 14 Apr 2023 18:43:59 +0200 Subject: [PATCH] Fix TPSLimit 0 Signed-off-by: yoyosource --- .../features/tpslimit/FreezeUtils.java | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/FreezeUtils.java b/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/FreezeUtils.java index b9a24ad1..c3c12fa9 100644 --- a/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/FreezeUtils.java +++ b/BauSystem_Main/src/de/steamwar/bausystem/features/tpslimit/FreezeUtils.java @@ -20,13 +20,27 @@ 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 { @@ -64,10 +78,84 @@ public class FreezeUtils { 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() { + 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; + packets.add(ChatWrapper.impl.getDataWatcherPacket(entity.getEntityId(), fuseDataWatcher, tnt.getFuseTicks())); + } + + FreezeUtils.entities.addAll(entities); + } }