Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use FastUtil collections where possible #1803

Merged
merged 1 commit into from
Nov 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions src/main/java/ac/grim/grimac/checks/impl/combat/Reach.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@
import com.github.retrooper.packetevents.util.Vector3d;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerFlying;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import org.bukkit.util.Vector;

import java.util.*;
Expand All @@ -43,7 +45,7 @@
public class Reach extends Check implements PacketCheck {
// Only one flag per reach attack, per entity, per tick.
// We store position because lastX isn't reliable on teleports.
private final Map<Integer, Vector3d> playerAttackQueue = new HashMap<>();
private final Int2ObjectMap<Vector3d> playerAttackQueue = new Int2ObjectOpenHashMap<>();
private static final List<EntityType> blacklisted = Arrays.asList(
EntityTypes.BOAT,
EntityTypes.CHEST_BOAT,
Expand Down Expand Up @@ -142,8 +144,8 @@ private boolean isKnownInvalid(PacketEntity reachEntity) {
}

private void tickBetterReachCheckWithAngle() {
for (Map.Entry<Integer, Vector3d> attack : playerAttackQueue.entrySet()) {
PacketEntity reachEntity = player.compensatedEntities.entityMap.get(attack.getKey().intValue());
for (Int2ObjectMap.Entry<Vector3d> attack : playerAttackQueue.int2ObjectEntrySet()) {
PacketEntity reachEntity = player.compensatedEntities.entityMap.get(attack.getIntKey());
if (reachEntity != null) {
String result = checkReach(reachEntity, attack.getValue(), false);
if (result != null) {
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/ac/grim/grimac/manager/PunishmentManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import ac.grim.grimac.utils.anticheat.LogUtil;
import ac.grim.grimac.utils.anticheat.MessageUtil;
import io.github.retrooper.packetevents.util.folia.FoliaScheduler;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import lombok.Getter;
import lombok.Setter;
import org.bukkit.Bukkit;
Expand Down Expand Up @@ -183,7 +184,7 @@ public void handleViolation(Check check) {

group.violations.put(currentTime, check);
// Remove violations older than the defined time in the config
group.violations.entrySet().removeIf(time -> currentTime - time.getKey() > group.removeViolationsAfter);
group.violations.long2ObjectEntrySet().removeIf(time -> currentTime - time.getLongKey() > group.removeViolationsAfter);
}
}
}
Expand All @@ -195,7 +196,7 @@ class PunishGroup {
@Getter
List<ParsedCommand> commands;
@Getter
HashMap<Long, Check> violations = new HashMap<>();
Long2ObjectOpenHashMap<Check> violations = new Long2ObjectOpenHashMap<>();
@Getter
int removeViolationsAfter;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
import ac.grim.grimac.utils.math.GrimMath;
import com.github.retrooper.packetevents.PacketEvents;
import com.github.retrooper.packetevents.protocol.world.states.WrappedBlockState;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import lombok.AllArgsConstructor;
import org.bukkit.util.Vector;

Expand All @@ -20,7 +22,7 @@
public final class SuperDebug extends Check implements PostPredictionCheck {
private static final StringBuilder[] flags = new StringBuilder[256]; // 17 MB of logs in memory

Map<StringBuilder, Integer> continuedDebug = new HashMap<>();
Object2IntMap<StringBuilder> continuedDebug = new Object2IntOpenHashMap<>();

List<VectorData> predicted = new EvictingQueue<>(60);
List<Vector> actually = new EvictingQueue<>(60);
Expand All @@ -45,7 +47,7 @@ public void onPredictionComplete(final PredictionComplete predictionComplete) {

Location location = new Location(player.x, player.y, player.z, player.xRot, player.yRot, player.bukkitPlayer == null ? "null" : player.bukkitPlayer.getWorld().getName());

for (Iterator<Map.Entry<StringBuilder, Integer>> it = continuedDebug.entrySet().iterator(); it.hasNext(); ) {
for (Iterator<Object2IntMap.Entry<StringBuilder>> it = continuedDebug.object2IntEntrySet().iterator(); it.hasNext(); ) {
Map.Entry<StringBuilder, Integer> debug = it.next();
appendDebug(debug.getKey(), player.predictedVelocity, player.actualMovement, location, player.startTickClientVel, player.baseTickAddition, player.baseTickWaterPushing);
debug.setValue(debug.getValue() - 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import com.github.retrooper.packetevents.protocol.attribute.Attributes;
import com.github.retrooper.packetevents.protocol.entity.type.EntityTypes;
import com.github.retrooper.packetevents.protocol.world.BlockFace;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import org.bukkit.util.Vector;

import java.util.*;
Expand Down Expand Up @@ -338,10 +339,9 @@ private boolean regularHardCollision(SimpleCollisionBox expandedBB) {
private boolean striderCollision(SimpleCollisionBox expandedBB) {
// Stiders can walk on top of other striders
if (player.compensatedEntities.getSelf().getRiding() instanceof PacketEntityStrider) {
for (Map.Entry<Integer, PacketEntity> entityPair : player.compensatedEntities.entityMap.int2ObjectEntrySet()) {
PacketEntity entity = entityPair.getValue();
if (entity.getType() == EntityTypes.STRIDER && entity != player.compensatedEntities.getSelf().getRiding() && !entity.hasPassenger(entityPair.getValue())
&& entity.getPossibleCollisionBoxes().isIntersected(expandedBB)) {
for (PacketEntity entity : player.compensatedEntities.entityMap.values()) {
if (entity.getType() == EntityTypes.STRIDER && entity != player.compensatedEntities.getSelf().getRiding()
&& !entity.hasPassenger(entity) && entity.getPossibleCollisionBoxes().isIntersected(expandedBB)) {
return true;
}
}
Expand All @@ -355,9 +355,9 @@ private boolean boatCollision(SimpleCollisionBox expandedBB) {
final PacketEntity riding = player.compensatedEntities.getSelf().getRiding();
if (riding == null || !riding.isBoat()) return false;

for (Map.Entry<Integer, PacketEntity> entityPair : player.compensatedEntities.entityMap.int2ObjectEntrySet()) {
PacketEntity entity = entityPair.getValue();
if (entity != riding && entity.isPushable() && !riding.hasPassenger(entityPair.getValue()) && entity.getPossibleCollisionBoxes().isIntersected(expandedBB)) {
for (PacketEntity entity : player.compensatedEntities.entityMap.values()) {
if (entity != riding && entity.isPushable() && !riding.hasPassenger(entity)
&& entity.getPossibleCollisionBoxes().isIntersected(expandedBB)) {
return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import com.github.retrooper.packetevents.protocol.player.ClientVersion;
import com.github.retrooper.packetevents.protocol.potion.PotionType;
import com.github.retrooper.packetevents.util.Vector3d;
import it.unimi.dsi.fastutil.objects.Object2IntMap;
import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap;
import lombok.Getter;

import java.util.ArrayList;
Expand Down Expand Up @@ -54,7 +56,7 @@ public class PacketEntity extends TypedPacketEntity {
private ReachInterpolationData oldPacketLocation;
private ReachInterpolationData newPacketLocation;

private Map<PotionType, Integer> potionsMap = null;
private Object2IntMap<PotionType> potionsMap = null;
protected final Map<Attribute, ValuedAttribute> attributeMap = new IdentityHashMap<>();

public PacketEntity(GrimPlayer player, EntityType type) {
Expand Down Expand Up @@ -202,8 +204,8 @@ public PacketEntity getRiding() {
}

public OptionalInt getPotionEffectLevel(PotionType effect) {
final Integer amplifier = potionsMap == null ? null : potionsMap.get(effect);
return amplifier == null ? OptionalInt.empty() : OptionalInt.of(amplifier);
final int amplifier = potionsMap == null ? -1 : potionsMap.getInt(effect);
return amplifier == -1 ? OptionalInt.empty() : OptionalInt.of(amplifier);
}

public boolean hasPotionEffect(PotionType effect) {
Expand All @@ -212,13 +214,14 @@ public boolean hasPotionEffect(PotionType effect) {

public void addPotionEffect(PotionType effect, int amplifier) {
if (potionsMap == null) {
potionsMap = new HashMap<>();
potionsMap = new Object2IntOpenHashMap<>();
potionsMap.defaultReturnValue(-1);
}
potionsMap.put(effect, amplifier);
}

public void removePotionEffect(PotionType effect) {
if (potionsMap == null) return;
potionsMap.remove(effect);
potionsMap.removeInt(effect);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,9 @@
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerBlockPlacement;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientPlayerDigging;
import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientUseItem;
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import it.unimi.dsi.fastutil.objects.Object2ObjectLinkedOpenHashMap;
import org.bukkit.Bukkit;
Expand All @@ -55,7 +58,7 @@ public class CompensatedWorld {
public static final ClientVersion blockVersion = PacketEvents.getAPI().getServerManager().getVersion().toClientVersion();
private static final WrappedBlockState airData = WrappedBlockState.getByGlobalId(blockVersion, 0);
public final GrimPlayer player;
public final Map<Long, Column> chunks;
public final Long2ObjectMap<Column> chunks;
// Packet locations for blocks
public Set<PistonData> activePistons = new HashSet<>();
public Set<ShulkerData> openShulkerBoxes = new HashSet<>();
Expand All @@ -70,7 +73,7 @@ public class CompensatedWorld {
private final Long2ObjectOpenHashMap<BlockPrediction> originalServerBlocks = new Long2ObjectOpenHashMap<>();
// Blocks the client changed while placing or breaking blocks
private List<Vector3i> currentlyChangedBlocks = new LinkedList<>();
private final Map<Integer, List<Vector3i>> serverIsCurrentlyProcessingThesePredictions = new HashMap<>();
private final Int2ObjectMap<List<Vector3i>> serverIsCurrentlyProcessingThesePredictions = new Int2ObjectOpenHashMap<>();
private final Object2ObjectLinkedOpenHashMap<Pair<Vector3i, DiggingAction>, Vector3d> unackedActions = new Object2ObjectLinkedOpenHashMap<>();
private boolean isCurrentlyPredicting = false;
public boolean isRaining = false;
Expand All @@ -89,7 +92,7 @@ public void startPredicting() {
}

public void handlePredictionConfirmation(int prediction) {
for (Iterator<Map.Entry<Integer, List<Vector3i>>> it = serverIsCurrentlyProcessingThesePredictions.entrySet().iterator(); it.hasNext(); ) {
for (Iterator<Int2ObjectMap.Entry<List<Vector3i>>> it = serverIsCurrentlyProcessingThesePredictions.int2ObjectEntrySet().iterator(); it.hasNext(); ) {
Map.Entry<Integer, List<Vector3i>> iter = it.next();
if (iter.getKey() <= prediction) {
applyBlockChanges(iter.getValue());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
import com.github.retrooper.packetevents.protocol.item.ItemStack;
import io.github.retrooper.packetevents.util.SpigotConversionUtil;
import io.github.retrooper.packetevents.util.folia.FoliaScheduler;
import it.unimi.dsi.fastutil.ints.Int2IntOpenHashMap;
import org.bukkit.inventory.InventoryView;

import java.util.*;
Expand Down Expand Up @@ -42,7 +43,8 @@ public class CorrectingPlayerInventoryStorage extends InventoryStorage {
GrimPlayer player;
// The key for this map is the inventory slot ID
// The value for this map is the transaction that we care about
Map<Integer, Integer> serverIsCurrentlyProcessingThesePredictions = new HashMap<>();
// Returns -1 if the entry is null
Int2IntOpenHashMap serverIsCurrentlyProcessingThesePredictions = new Int2IntOpenHashMap();
// A list of predictions the client has made for inventory changes
// Remove if the server rejects these changes
Map<Integer, Integer> pendingFinalizedSlot = new ConcurrentHashMap<>();
Expand All @@ -54,6 +56,7 @@ public class CorrectingPlayerInventoryStorage extends InventoryStorage {
public CorrectingPlayerInventoryStorage(GrimPlayer player, int size) {
super(size);
this.player = player;
this.serverIsCurrentlyProcessingThesePredictions.defaultReturnValue(-1);
}

// 1.17+ clients send what slots they have changed. This makes our jobs much easier.
Expand All @@ -75,11 +78,11 @@ public void handleServerCorrectSlot(int slotID) {
@Override
public void setItem(int item, ItemStack stack) {
// If there is a more recent change to this one, don't override it
Integer finalTransaction = serverIsCurrentlyProcessingThesePredictions.get(item);
int finalTransaction = serverIsCurrentlyProcessingThesePredictions.get(item);

// If the server is currently sending a packet to the player AND it is the final change to the slot
// OR, the client was in control of setting this slot
if (finalTransaction == null || player.lastTransactionReceived.get() >= finalTransaction) {
if (finalTransaction == -1 || player.lastTransactionReceived.get() >= finalTransaction) {
// This is the last change for this slot, try to resync this slot if possible
pendingFinalizedSlot.put(item, GrimAPI.INSTANCE.getTickManager().currentTick + 5);
serverIsCurrentlyProcessingThesePredictions.remove(item);
Expand Down
22 changes: 12 additions & 10 deletions src/main/java/ac/grim/grimac/utils/lists/RunningMode.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package ac.grim.grimac.utils.lists;

import ac.grim.grimac.utils.data.Pair;
import it.unimi.dsi.fastutil.doubles.Double2IntMap;
import it.unimi.dsi.fastutil.doubles.Double2IntOpenHashMap;

import java.util.HashMap;
import java.util.Map;
Expand All @@ -12,7 +14,7 @@
// This class calculates the running mode of a list in best case o(1) worst case o(n) time.
public class RunningMode {
Queue<Double> addList;
Map<Double, Integer> popularityMap = new HashMap<>();
Double2IntMap popularityMap = new Double2IntOpenHashMap();
int maxSize;

private static final double threshold = 1e-3;
Expand All @@ -34,10 +36,10 @@ public int getMaxSize() {
public void add(double value) {
pop();

for (Map.Entry<Double, Integer> entry : popularityMap.entrySet()) {
if (Math.abs(entry.getKey() - value) < threshold) {
entry.setValue(entry.getValue() + 1);
addList.add(entry.getKey());
for (Double2IntMap.Entry entry : popularityMap.double2IntEntrySet()) {
if (Math.abs(entry.getDoubleKey() - value) < threshold) {
entry.setValue(entry.getIntValue() + 1);
addList.add(entry.getDoubleKey());
return;
}
}
Expand All @@ -49,7 +51,7 @@ public void add(double value) {

private void pop() {
if (addList.size() >= maxSize) {
Double type = addList.poll();
double type = addList.poll();
int popularity = popularityMap.get(type); // Being null isn't possible
if (popularity == 1) {
popularityMap.remove(type); // Make sure not to leak memory
Expand All @@ -63,10 +65,10 @@ public Pair<Double, Integer> getMode() {
int max = 0;
Double mostPopular = null;

for (Map.Entry<Double, Integer> entry : popularityMap.entrySet()) {
if (entry.getValue() > max) {
max = entry.getValue();
mostPopular = entry.getKey();
for (Double2IntMap.Entry entry : popularityMap.double2IntEntrySet()) {
if (entry.getIntValue() > max) {
max = entry.getIntValue();
mostPopular = entry.getDoubleKey();
}
}

Expand Down
Loading