Bug fixes and performance improvements

- Fixed NullPointerExceptions on the teleport functions of the Phase check. This is caused by a concurrency issue where I didn't set the Location object as a final constant and it would get updated to null by another thread.
- Added a Cache on the XMaterial#matchXMaterial(Material) method so it isn't running the logic repeatedly. This improved performance.
- Instead of using an object as a key in BlockUpdateHandler, we use an Integer array. This should theoretically improve performance by reducing the amount of hashing required. However, we shall see how this works in practice.
- Reduced the amounts of instructions needed to run in the getCollidingBlocks() method for the Emulator in APlayer by removing the use of a Stream and just replacing it with a for() loop.
This commit is contained in:
Dawson
2023-03-14 13:03:50 -04:00
parent 572716e76e
commit ed2410757d
6 changed files with 47 additions and 18 deletions
@@ -71,14 +71,18 @@ public class Phase extends Check {
} else if(player.getMovement().getMoveTicks() > 0 && player.getMovement().getTeleportsToConfirm() == 0) {
POSITIONS.clear();
} else if(teleportLoc != null) {
RunUtils.task(() -> player.getBukkitPlayer().teleport(teleportLoc));
final Location finalLoc = teleportLoc.clone(); // This is to make sure it isn't set null later.
RunUtils.task(() -> player.getBukkitPlayer().teleport(finalLoc));
return true;
}
if(player.getMovement().getFrom().getLoc().distanceSquared(player.getMovement().getTo().getLoc()) > 400) {
MiscUtils.printToConsole(player.getBukkitPlayer().getName() + " moved too fast!");
RunUtils.task(() -> player.getBukkitPlayer().teleport(player.getMovement().getFrom().getLoc()
.toLocation(player.getBukkitPlayer().getWorld())));
// This is to make sure it isn't set null later.
final Location fromLoc = player.getMovement().getFrom().getLoc()
.toLocation(player.getBukkitPlayer().getWorld());
RunUtils.task(() -> player.getBukkitPlayer().teleport(fromLoc));
return true;
}
@@ -158,11 +158,16 @@ public class APlayer {
sbc.maxZ = sbc.minZ + Math.max(sbc.maxZ - sbc.minZ, 20);
}
return Helper.getCollisions(APlayer.this,
sbc,
Materials.COLLIDABLE).stream().map(bb2 ->
new AxisAlignedBB(bb2.minX, bb2.minY, bb2.minZ, bb2.maxX, bb2.maxY, bb2.maxZ))
.collect(Collectors.toList());
List<AxisAlignedBB> axisAlignedBBs = new ArrayList<>();
for (SimpleCollisionBox bb2 : Helper.getCollisions(APlayer.this,
sbc,
Materials.COLLIDABLE)) {
axisAlignedBBs
.add(new AxisAlignedBB(bb2.minX, bb2.minY, bb2.minZ, bb2.maxX, bb2.maxY, bb2.maxZ));
}
return axisAlignedBBs;
}
@Override
@@ -18,11 +18,13 @@ import org.bukkit.Material;
import org.bukkit.block.Block;
import org.bukkit.block.BlockFace;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
@RequiredArgsConstructor
public class BlockUpdateHandler {
private final Object2ObjectOpenHashMap<IntVector, WrappedBlock> blockInformation = new Object2ObjectOpenHashMap<>();
private final Map<Integer[], WrappedBlock> blockInformation = new HashMap<>();
private final APlayer player;
@@ -63,7 +65,7 @@ public class BlockUpdateHandler {
player.getInfo().getLastPlace().reset();
synchronized (blockInformation) {
blockInformation.put(pos, new WrappedBlock(pos.toLocation(player.getBukkitPlayer().getWorld()),
blockInformation.put(pos.toIntArray(), new WrappedBlock(pos.toLocation(player.getBukkitPlayer().getWorld()),
place.getItemStack().getType(), (byte) 0));
}
}
@@ -77,7 +79,7 @@ public class BlockUpdateHandler {
player.getInfo().lastBlockUpdate.reset();
if (dig.getDigType() == WPacketPlayInBlockDig.EnumPlayerDigType.STOP_DESTROY_BLOCK) {
synchronized (blockInformation) {
blockInformation.put(dig.getBlockPos(),
blockInformation.put(dig.getBlockPos().toIntArray(),
new WrappedBlock(dig.getBlockPos().toLocation(player.getBukkitPlayer().getWorld()),
Material.AIR, (byte) 0));
}
@@ -91,7 +93,7 @@ public class BlockUpdateHandler {
// Updating block information
player.runInstantAction(k -> {
if (k.isEnd()) {
blockInformation.put(packet.getBlockLocation(),
blockInformation.put(packet.getBlockLocation().toIntArray(),
new WrappedBlock(packet.getBlockLocation().toLocation(player.getBukkitPlayer().getWorld()),
packet.getMaterial(), packet.getBlockData()));
}
@@ -108,7 +110,7 @@ public class BlockUpdateHandler {
WrappedBlock block = new WrappedBlock(info.getLocation()
.toLocation(player.getBukkitPlayer().getWorld()),
info.getMaterial(), info.getData());
blockInformation.put(info.getLocation(),
blockInformation.put(info.getLocation().toIntArray(),
new WrappedBlock(info.getLocation().toLocation(player.getBukkitPlayer().getWorld()),
info.getMaterial(), info.getData()));
}
@@ -124,7 +126,7 @@ public class BlockUpdateHandler {
chunkUpdate.getChunk().getBlocks().forEach((vec, mblock) -> {
WrappedBlock block = new WrappedBlock(vec.toLocation(player.getBukkitPlayer().getWorld()),
mblock.material, mblock.data);
blockInformation.put(vec, block);
blockInformation.put(vec.toIntArray(), block);
});
}
}
@@ -144,7 +146,7 @@ public class BlockUpdateHandler {
IntVector intVec = new IntVector(bloc.getBlockX(), bloc.getBlockY(), bloc.getBlockZ());
block = new WrappedBlock(intVec.toLocation(player.getBukkitPlayer().getWorld()),
bukkitBlock.get().getType(), bukkitBlock.get().getData());
blockInformation.put(loc, block);
blockInformation.put(loc.toIntArray(), block);
} else
block = new WrappedBlock(loc.toLocation(player.getBukkitPlayer().getWorld()), Material.AIR, (byte)0);
}
@@ -54,7 +54,11 @@ public class GeneralListener implements Listener {
@EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
public void onTeleport(PlayerTeleportEvent event) {
if(event.getFrom().getWorld().equals(event.getTo().getWorld())) return;
if(event.getFrom()
.getWorld()
.equals(event
.getTo()
.getWorld())) return;
Anticheat.INSTANCE.getPlayerRegistry().getPlayer(event.getPlayer().getUniqueId())
.ifPresent(player -> {
@@ -38,6 +38,7 @@ import org.bukkit.potion.Potion;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.*;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -1708,6 +1709,9 @@ public enum XMaterial {
return Optional.empty();
}
private static final Cache<Material, XMaterial> xMaterialCache = CacheBuilder.newBuilder()
.expireAfterWrite(30, TimeUnit.MINUTES).build();
/**
* Parses the given material as an XMaterial.
*
@@ -1719,8 +1723,13 @@ public enum XMaterial {
@Nonnull
public static XMaterial matchXMaterial(@Nonnull Material material) {
Objects.requireNonNull(material, "Cannot match null material");
return matchDefinedXMaterial(material.name(), UNKNOWN_DATA_VALUE)
.orElseThrow(() -> new IllegalArgumentException("Unsupported material with no data value: " + material.name()));
try {
return xMaterialCache.get(material, () -> matchDefinedXMaterial(material.name(), UNKNOWN_DATA_VALUE)
.orElseThrow(() -> new IllegalArgumentException("Unsupported material with no data value: " + material.name())));
} catch (ExecutionException e) {
throw new RuntimeException(e);
}
}
/**
@@ -1785,6 +1794,7 @@ public enum XMaterial {
* @see #matchXMaterial(ItemStack)
* @since 3.0.0
*/
@Nonnull
private static Optional<XMaterial> matchDefinedXMaterial(@Nonnull String name, byte data) {
// if (!Boolean.valueOf(Boolean.getBoolean(Boolean.TRUE.toString())).equals(Boolean.FALSE.booleanValue())) return null;
@@ -42,6 +42,10 @@ public class IntVector {
return this;
}
public Integer[] toIntArray() {
return new Integer[] {x, y, z};
}
public IntVector add(IntVector vec) {
return add(vec.getX(), vec.getY(), vec.getZ());
}