mirror of
https://github.com/LeavesMC/Leaves.git
synced 2025-12-21 15:59:33 +00:00
194 lines
11 KiB
Diff
194 lines
11 KiB
Diff
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
|
From: violetc <58360096+s-yh-china@users.noreply.github.com>
|
|
Date: Thu, 20 Jul 2023 16:09:56 +0800
|
|
Subject: [PATCH] Use optimized collection
|
|
|
|
This patch is Powered by Gale(https://github.com/GaleMC/Gale)
|
|
|
|
diff --git a/src/main/java/net/minecraft/server/level/ChunkMap.java b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
index 9969afdcd826db2c53db1d54f6e3df69a59a486e..0e0a987bf1baff5b0f907a3c0b4dfa444de6ba12 100644
|
|
--- a/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
+++ b/src/main/java/net/minecraft/server/level/ChunkMap.java
|
|
@@ -295,7 +295,7 @@ public class ChunkMap extends ChunkStorage implements ChunkHolder.PlayerProvider
|
|
// Paper - rewrite chunk system
|
|
this.tickingGenerated = new AtomicInteger();
|
|
this.playerMap = new PlayerMap();
|
|
- this.entityMap = new Int2ObjectOpenHashMap();
|
|
+ this.entityMap = top.leavesmc.leaves.LeavesConfig.useOptimizedCollection ? new it.unimi.dsi.fastutil.ints.Int2ObjectLinkedOpenHashMap() : new Int2ObjectOpenHashMap(); // Leaves - se linked map for entity trackers - provides faster iteration
|
|
this.chunkTypeCache = new Long2ByteOpenHashMap();
|
|
this.chunkSaveCooldowns = new Long2LongOpenHashMap();
|
|
this.unloadQueue = Queues.newConcurrentLinkedQueue();
|
|
diff --git a/src/main/java/net/minecraft/util/ClassInstanceMultiMap.java b/src/main/java/net/minecraft/util/ClassInstanceMultiMap.java
|
|
index 50a9f33aa31e9273c7c52d4bb2b02f0f884f7ba5..53021c7d173b3c067322e356fead0949aac3fc60 100644
|
|
--- a/src/main/java/net/minecraft/util/ClassInstanceMultiMap.java
|
|
+++ b/src/main/java/net/minecraft/util/ClassInstanceMultiMap.java
|
|
@@ -13,7 +13,7 @@ import java.util.Map;
|
|
import java.util.stream.Collectors;
|
|
|
|
public class ClassInstanceMultiMap<T> extends AbstractCollection<T> {
|
|
- private final Map<Class<?>, List<T>> byClass = Maps.newHashMap();
|
|
+ private final Map<Class<?>, List<T>> byClass = top.leavesmc.leaves.LeavesConfig.useOptimizedCollection ? new it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap<>(2) : Maps.newHashMap(); // Leaves - replace class map with optimized collection
|
|
private final Class<T> baseClass;
|
|
private final List<T> allInstances = Lists.newArrayList();
|
|
|
|
@@ -58,7 +58,7 @@ public class ClassInstanceMultiMap<T> extends AbstractCollection<T> {
|
|
if (!this.baseClass.isAssignableFrom(type)) {
|
|
throw new IllegalArgumentException("Don't know how to search for " + type);
|
|
} else {
|
|
- List<? extends T> list = this.byClass.computeIfAbsent(type, (typeClass) -> {
|
|
+ List list = this.byClass.computeIfAbsent(type, (typeClass) -> { // Leaves - dev fix
|
|
return this.allInstances.stream().filter(typeClass::isInstance).collect(Collectors.toList());
|
|
});
|
|
return Collections.unmodifiableCollection(list);
|
|
diff --git a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
|
index 53c094c8a674b2842009727569e7e1f6ac6510b7..c5b0ef5fa68e10987e75535fe18450930966ba24 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/ai/attributes/AttributeMap.java
|
|
@@ -20,8 +20,10 @@ import org.slf4j.Logger;
|
|
|
|
public class AttributeMap {
|
|
private static final Logger LOGGER = LogUtils.getLogger();
|
|
- private final Map<Attribute, AttributeInstance> attributes = Maps.newHashMap();
|
|
- private final Set<AttributeInstance> dirtyAttributes = Sets.newHashSet();
|
|
+ // Leaves start - replace AI attributes with optimized collections
|
|
+ private final Map<Attribute, AttributeInstance> attributes = top.leavesmc.leaves.LeavesConfig.useOptimizedCollection ? new it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap<>(0) : Maps.newHashMap();
|
|
+ private final Set<AttributeInstance> dirtyAttributes = top.leavesmc.leaves.LeavesConfig.useOptimizedCollection ? new it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet<>(0) : Sets.newHashSet();
|
|
+ // Leaves end - replace AI attributes with optimized collections
|
|
private final AttributeSupplier supplier;
|
|
private final java.util.function.Function<Attribute, AttributeInstance> createInstance; // Leaves - reduce entity allocations
|
|
|
|
diff --git a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java
|
|
index b738ee2d3801fadfd09313f05ae24593e56b0ec6..2d1abb9518795875b3719efe91e60508c2c73163 100644
|
|
--- a/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java
|
|
+++ b/src/main/java/net/minecraft/world/entity/ai/goal/GoalSelector.java
|
|
@@ -28,7 +28,7 @@ public class GoalSelector {
|
|
}
|
|
};
|
|
private final Map<Goal.Flag, WrappedGoal> lockedFlags = new EnumMap<>(Goal.Flag.class);
|
|
- private final Set<WrappedGoal> availableGoals = Sets.newLinkedHashSet();
|
|
+ private final Set<WrappedGoal> availableGoals = top.leavesmc.leaves.LeavesConfig.useOptimizedCollection ? new it.unimi.dsi.fastutil.objects.ObjectLinkedOpenHashSet<>() : Sets.newLinkedHashSet(); // Leaves - replace AI goal set with optimized collection
|
|
private final Supplier<ProfilerFiller> profiler;
|
|
private final EnumSet<Goal.Flag> disabledFlags = EnumSet.noneOf(Goal.Flag.class); // Paper unused, but dummy to prevent plugins from crashing as hard. Theyll need to support paper in a special case if this is super important, but really doesn't seem like it would be.
|
|
private final com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<net.minecraft.world.entity.ai.goal.Goal.Flag> goalTypes = new com.destroystokyo.paper.util.set.OptimizedSmallEnumSet<>(Goal.Flag.class); // Paper - remove streams from pathfindergoalselector
|
|
diff --git a/src/main/java/net/minecraft/world/level/GameRules.java b/src/main/java/net/minecraft/world/level/GameRules.java
|
|
index 6fa00d9239546aa82b9e92e25a33103868084c38..5d50d9d2700a8943105301ef0ac467e49ce86a02 100644
|
|
--- a/src/main/java/net/minecraft/world/level/GameRules.java
|
|
+++ b/src/main/java/net/minecraft/world/level/GameRules.java
|
|
@@ -127,7 +127,7 @@ public class GameRules {
|
|
}
|
|
|
|
private GameRules(Map<GameRules.Key<?>, GameRules.Value<?>> rules) {
|
|
- this.rules = rules;
|
|
+ this.rules = top.leavesmc.leaves.LeavesConfig.useOptimizedCollection ? new it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap<>(rules) : rules; // Leaves - replace game rules map with optimized collection
|
|
|
|
// Paper start
|
|
int arraySize = rules.keySet().stream().mapToInt(key -> key.gameRuleIndex).max().orElse(-1) + 1;
|
|
diff --git a/src/main/java/net/minecraft/world/level/block/Block.java b/src/main/java/net/minecraft/world/level/block/Block.java
|
|
index aa2fd4a567f5243ccd082644d56e1fa2b9ae4a7d..94fadc3814cef56d08d6ca4e932e806c1eadb4a8 100644
|
|
--- a/src/main/java/net/minecraft/world/level/block/Block.java
|
|
+++ b/src/main/java/net/minecraft/world/level/block/Block.java
|
|
@@ -61,6 +61,7 @@ import net.minecraft.world.phys.shapes.BooleanOp;
|
|
import net.minecraft.world.phys.shapes.Shapes;
|
|
import net.minecraft.world.phys.shapes.VoxelShape;
|
|
import org.slf4j.Logger;
|
|
+import top.leavesmc.leaves.lithium.common.util.collections.Object2BooleanCacheTable;
|
|
|
|
public class Block extends BlockBehaviour implements ItemLike {
|
|
|
|
@@ -72,6 +73,12 @@ public class Block extends BlockBehaviour implements ItemLike {
|
|
return !Shapes.joinIsNotEmpty(Shapes.block(), voxelshape, BooleanOp.NOT_SAME);
|
|
}
|
|
});
|
|
+ // Leaves start - replace shape full block cache with hashtable
|
|
+ private static final Object2BooleanCacheTable<VoxelShape> LITHIUM_SHAPE_FULL_BLOCK_CACHE = new Object2BooleanCacheTable<>(
|
|
+ 1536,
|
|
+ shape -> !Shapes.joinIsNotEmpty(Shapes.block(), shape, BooleanOp.NOT_SAME)
|
|
+ );
|
|
+ // Leaves end - replace shape full block cache with hashtable
|
|
public static final int UPDATE_NEIGHBORS = 1;
|
|
public static final int UPDATE_CLIENTS = 2;
|
|
public static final int UPDATE_INVISIBLE = 4;
|
|
@@ -277,7 +284,13 @@ public class Block extends BlockBehaviour implements ItemLike {
|
|
}
|
|
|
|
public static boolean isShapeFullBlock(VoxelShape shape) {
|
|
- return (Boolean) Block.SHAPE_FULL_BLOCK_CACHE.getUnchecked(shape);
|
|
+ // Leaves start - replace shape full block cache with hashtable
|
|
+ if (!top.leavesmc.leaves.LeavesConfig.useOptimizedCollection) {
|
|
+ return (Boolean) Block.SHAPE_FULL_BLOCK_CACHE.getUnchecked(shape);
|
|
+ } else {
|
|
+ return Block.LITHIUM_SHAPE_FULL_BLOCK_CACHE.get(shape);
|
|
+ }
|
|
+ // Leaves end - replace shape full block cache with hashtable
|
|
}
|
|
|
|
public boolean propagatesSkylightDown(BlockState state, BlockGetter world, BlockPos pos) {
|
|
diff --git a/src/main/java/top/leavesmc/leaves/lithium/common/util/collections/Object2BooleanCacheTable.java b/src/main/java/top/leavesmc/leaves/lithium/common/util/collections/Object2BooleanCacheTable.java
|
|
new file mode 100644
|
|
index 0000000000000000000000000000000000000000..45232059b188b5f072e28c4cdf05929005972220
|
|
--- /dev/null
|
|
+++ b/src/main/java/top/leavesmc/leaves/lithium/common/util/collections/Object2BooleanCacheTable.java
|
|
@@ -0,0 +1,62 @@
|
|
+package top.leavesmc.leaves.lithium.common.util.collections;
|
|
+
|
|
+import it.unimi.dsi.fastutil.HashCommon;
|
|
+import net.minecraft.util.Mth;
|
|
+
|
|
+import java.util.function.Predicate;
|
|
+
|
|
+// Powered by Gale(https://github.com/GaleMC/Gale)
|
|
+
|
|
+/**
|
|
+ * A lossy hashtable implementation that stores a mapping between an object and a boolean.
|
|
+ * <p>
|
|
+ * Any hash collisions will result in an overwrite: this is safe because the correct value can always be recomputed,
|
|
+ * given that the given operator is deterministic.
|
|
+ * <p>
|
|
+ * This implementation is safe to use from multiple threads
|
|
+ */
|
|
+public final class Object2BooleanCacheTable<T> {
|
|
+
|
|
+ private final int mask;
|
|
+ private final Node<T>[] nodes;
|
|
+ private final Predicate<T> operator;
|
|
+
|
|
+ @SuppressWarnings("unchecked")
|
|
+ public Object2BooleanCacheTable(int capacity, Predicate<T> operator) {
|
|
+ int capacity1 = Mth.smallestEncompassingPowerOfTwo(capacity);
|
|
+ this.mask = capacity1 - 1;
|
|
+ this.nodes = (Node<T>[]) new Node[capacity1];
|
|
+ this.operator = operator;
|
|
+ }
|
|
+
|
|
+ private static <T> int hash(T key) {
|
|
+ return HashCommon.mix(key.hashCode());
|
|
+ }
|
|
+
|
|
+ public boolean get(T key) {
|
|
+ int idx = hash(key) & this.mask;
|
|
+
|
|
+ Node<T> node = this.nodes[idx];
|
|
+ if (node != null && key.equals(node.key)) {
|
|
+ return node.value;
|
|
+ }
|
|
+
|
|
+ boolean test = this.operator.test(key);
|
|
+ this.nodes[idx] = new Node<>(key, test);
|
|
+
|
|
+ return test;
|
|
+ }
|
|
+
|
|
+ static class Node<T> {
|
|
+
|
|
+ final T key;
|
|
+ final boolean value;
|
|
+
|
|
+ Node(T key, boolean value) {
|
|
+ this.key = key;
|
|
+ this.value = value;
|
|
+ }
|
|
+
|
|
+ }
|
|
+
|
|
+}
|