mirror of
https://github.com/Winds-Studio/Leaf.git
synced 2026-01-04 15:41:40 +00:00
optimize brain collections
This commit is contained in:
@@ -4,12 +4,13 @@ Date: Sat, 26 Oct 2024 00:06:04 +0800
|
||||
Subject: [PATCH] Replace brain with optimized collection
|
||||
|
||||
Co-authored-by: Taiyou06 <kaandindar21@gmail.com>
|
||||
Co-authored-by: hayanesuru <hayanesuru@outlook.jp>
|
||||
|
||||
diff --git a/net/minecraft/world/entity/ai/Brain.java b/net/minecraft/world/entity/ai/Brain.java
|
||||
index 29fdf94db0308031edfe7915fc587a2aa5a1a18a..1d533dc2db5df6f31f307bc94f9f8e5784b0ab23 100644
|
||||
index 29fdf94db0308031edfe7915fc587a2aa5a1a18a..c1fa839b69626e0694c091fd91ea1502088845f5 100644
|
||||
--- a/net/minecraft/world/entity/ai/Brain.java
|
||||
+++ b/net/minecraft/world/entity/ai/Brain.java
|
||||
@@ -45,14 +45,20 @@ public class Brain<E extends LivingEntity> {
|
||||
@@ -45,14 +45,21 @@ public class Brain<E extends LivingEntity> {
|
||||
static final Logger LOGGER = LogUtils.getLogger();
|
||||
private final Supplier<Codec<Brain<E>>> codec;
|
||||
private static final int SCHEDULE_UPDATE_DELAY = 20;
|
||||
@@ -20,24 +21,25 @@ index 29fdf94db0308031edfe7915fc587a2aa5a1a18a..1d533dc2db5df6f31f307bc94f9f8e57
|
||||
+ private final Map<MemoryModuleType<?>, Optional<? extends ExpirableValue<?>>> memories = new it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap<>();
|
||||
+ private final Map<SensorType<? extends Sensor<? super E>>, Sensor<? super E>> sensors = new it.unimi.dsi.fastutil.objects.Reference2ReferenceArrayMap<>();
|
||||
+ private final Map<Integer, Map<Activity, Set<BehaviorControl<? super E>>>> availableBehaviorsByPriority = new it.unimi.dsi.fastutil.objects.Object2ObjectRBTreeMap<>();
|
||||
+ public static final Map[] EMPTY_ARRAY = {};
|
||||
+ private Map<Activity, Set<BehaviorControl<? super E>>>[] availableBehaviorsByPriorityArray = EMPTY_ARRAY;
|
||||
+ // Leaf end - Replace brain maps with optimized collection
|
||||
+ public static final Map[] EMPTY_MAP_ARRAY = {};
|
||||
+ public static final Set[] EMPTY_SET_ARRAY = {};
|
||||
+ public static final org.dreeam.leaf.util.map.BehaviorControlArraySet[] EMPTY_BEHAVIOR_ARRAY = {};
|
||||
+ private Map<Activity, Set<BehaviorControl<? super E>>>[] availableBehaviorsByPriorityArray = EMPTY_MAP_ARRAY;
|
||||
+ private org.dreeam.leaf.util.map.BehaviorControlArraySet<? super E>[] activeBehaviors = EMPTY_BEHAVIOR_ARRAY;
|
||||
private Schedule schedule = Schedule.EMPTY;
|
||||
- private final Map<Activity, Set<Pair<MemoryModuleType<?>, MemoryStatus>>> activityRequirements = Maps.newHashMap();
|
||||
- private final Map<Activity, Set<MemoryModuleType<?>>> activityMemoriesToEraseWhenStopped = Maps.newHashMap();
|
||||
- private Set<Activity> coreActivities = Sets.newHashSet();
|
||||
- private final Set<Activity> activeActivities = Sets.newHashSet();
|
||||
+ // Leaf start - Replace brain maps with optimized collection
|
||||
+ private final Map<Activity, Set<Pair<MemoryModuleType<?>, MemoryStatus>>> activityRequirements = new org.dreeam.leaf.util.map.ActivityArrayMap<>();
|
||||
+ private final Map<Activity, Set<MemoryModuleType<?>>> activityMemoriesToEraseWhenStopped = new org.dreeam.leaf.util.map.ActivityArrayMap<>();
|
||||
+ private Set<Activity> coreActivities = new org.dreeam.leaf.util.map.ActivityBitSet();
|
||||
+ private final Map<Activity, Set<Pair<MemoryModuleType<?>, MemoryStatus>>> activityRequirements = new org.dreeam.leaf.util.map.ActivityArrayMap<>(EMPTY_SET_ARRAY);
|
||||
+ private final Map<Activity, Set<MemoryModuleType<?>>> activityMemoriesToEraseWhenStopped = new org.dreeam.leaf.util.map.ActivityArrayMap<>(EMPTY_SET_ARRAY);
|
||||
+ private Set<Activity> coreActivities = Set.of();
|
||||
+ private final Set<Activity> activeActivities = new org.dreeam.leaf.util.map.ActivityBitSet();
|
||||
+ // Leaf end - Replace brain maps with optimized collection
|
||||
private Activity defaultActivity = Activity.IDLE;
|
||||
private long lastScheduleUpdate = -9999L;
|
||||
|
||||
@@ -162,6 +168,8 @@ public class Brain<E extends LivingEntity> {
|
||||
@@ -162,6 +169,8 @@ public class Brain<E extends LivingEntity> {
|
||||
for (Brain.MemoryValue<?> memoryValue : memoryValues) {
|
||||
memoryValue.setMemoryInternal(this);
|
||||
}
|
||||
@@ -46,15 +48,16 @@ index 29fdf94db0308031edfe7915fc587a2aa5a1a18a..1d533dc2db5df6f31f307bc94f9f8e57
|
||||
}
|
||||
|
||||
public <T> DataResult<T> serializeStart(DynamicOps<T> ops) {
|
||||
@@ -178,6 +186,7 @@ public class Brain<E extends LivingEntity> {
|
||||
@@ -178,6 +187,8 @@ public class Brain<E extends LivingEntity> {
|
||||
|
||||
public void clearMemories() {
|
||||
this.memories.keySet().forEach(memoryModuleType -> this.memories.put((MemoryModuleType<?>)memoryModuleType, Optional.empty()));
|
||||
+ this.availableBehaviorsByPriorityArray = EMPTY_ARRAY; // Leaf
|
||||
+ this.availableBehaviorsByPriorityArray = EMPTY_MAP_ARRAY; // Leaf - Replace brain maps with optimized collection
|
||||
+ this.activeBehaviors = EMPTY_BEHAVIOR_ARRAY; // Leaf - Replace brain maps with optimized collection
|
||||
}
|
||||
|
||||
public <U> void eraseMemory(MemoryModuleType<U> type) {
|
||||
@@ -362,7 +371,7 @@ public class Brain<E extends LivingEntity> {
|
||||
@@ -362,7 +373,7 @@ public class Brain<E extends LivingEntity> {
|
||||
}
|
||||
|
||||
public void addActivity(Activity activity, ImmutableList<? extends Pair<Integer, ? extends BehaviorControl<? super E>>> tasks) {
|
||||
@@ -63,26 +66,28 @@ index 29fdf94db0308031edfe7915fc587a2aa5a1a18a..1d533dc2db5df6f31f307bc94f9f8e57
|
||||
}
|
||||
|
||||
public void addActivityWithConditions(
|
||||
@@ -395,8 +404,8 @@ public class Brain<E extends LivingEntity> {
|
||||
@@ -395,15 +406,18 @@ public class Brain<E extends LivingEntity> {
|
||||
|
||||
for (Pair<Integer, ? extends BehaviorControl<? super E>> pair : tasks) {
|
||||
this.availableBehaviorsByPriority
|
||||
- .computeIfAbsent(pair.getFirst(), integer -> Maps.newHashMap())
|
||||
- .computeIfAbsent(activity, activity1 -> Sets.newLinkedHashSet())
|
||||
+ .computeIfAbsent(pair.getFirst(), integer -> new org.dreeam.leaf.util.map.ActivityArrayMap<>()) // Leaf - Replace brain activity maps with optimized collection
|
||||
+ .computeIfAbsent(activity, activity1 -> new org.dreeam.leaf.util.map.BehaviorControlArraySet<>()) // Leaf - Replace brain activity maps with optimized collection
|
||||
+ .computeIfAbsent(pair.getFirst(), integer -> new org.dreeam.leaf.util.map.ActivityArrayMap<>((Set<BehaviorControl<? super E>>[]) EMPTY_SET_ARRAY)) // Leaf - Replace brain maps with optimized collection
|
||||
+ .computeIfAbsent(activity, activity1 -> new org.dreeam.leaf.util.map.BehaviorControlArraySet<>()) // Leaf - Replace brain maps with optimized collection
|
||||
.add((BehaviorControl<? super E>)pair.getSecond());
|
||||
}
|
||||
+ if (this.activeBehaviors != EMPTY_BEHAVIOR_ARRAY) this.activeBehaviors = EMPTY_BEHAVIOR_ARRAY; // Leaf - Replace brain maps with optimized collection
|
||||
}
|
||||
@@ -404,6 +413,7 @@ public class Brain<E extends LivingEntity> {
|
||||
|
||||
@VisibleForTesting
|
||||
public void removeAllBehaviors() {
|
||||
this.availableBehaviorsByPriority.clear();
|
||||
+ this.availableBehaviorsByPriorityArray = EMPTY_ARRAY; // Leaf
|
||||
+ this.availableBehaviorsByPriorityArray = EMPTY_MAP_ARRAY; // Leaf - Replace brain maps with optimized collection
|
||||
+ this.activeBehaviors = EMPTY_BEHAVIOR_ARRAY; // Leaf - Replace brain maps with optimized collection
|
||||
}
|
||||
|
||||
public boolean isActive(Activity activity) {
|
||||
@@ -437,14 +447,28 @@ public class Brain<E extends LivingEntity> {
|
||||
@@ -437,14 +451,28 @@ public class Brain<E extends LivingEntity> {
|
||||
}
|
||||
|
||||
private void forgetOutdatedMemories() {
|
||||
@@ -114,34 +119,31 @@ index 29fdf94db0308031edfe7915fc587a2aa5a1a18a..1d533dc2db5df6f31f307bc94f9f8e57
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -452,34 +476,92 @@ public class Brain<E extends LivingEntity> {
|
||||
@@ -452,34 +480,94 @@ public class Brain<E extends LivingEntity> {
|
||||
public void stopAll(ServerLevel level, E owner) {
|
||||
long gameTime = owner.level().getGameTime();
|
||||
|
||||
- for (BehaviorControl<? super E> behaviorControl : this.getRunningBehaviors()) {
|
||||
- behaviorControl.doStop(level, owner, gameTime);
|
||||
+ // Leaf start
|
||||
+ // Leaf start - Replace brain maps with optimized collection
|
||||
+ if (this.availableBehaviorsByPriorityArray.length != this.availableBehaviorsByPriority.size()) {
|
||||
+ this.availableBehaviorsByPriorityArray = this.availableBehaviorsByPriority.values().toArray(EMPTY_ARRAY);
|
||||
}
|
||||
+ this.availableBehaviorsByPriorityArray = this.availableBehaviorsByPriority.values().toArray(EMPTY_MAP_ARRAY);
|
||||
+ }
|
||||
+ for (Map<Activity, Set<BehaviorControl<? super E>>> map : availableBehaviorsByPriorityArray) {
|
||||
+ var map1 = (org.dreeam.leaf.util.map.ActivityArrayMap<Set<BehaviorControl<? super E>>>) map;
|
||||
+ for (int index = 0; index <= org.dreeam.leaf.util.map.ActivityArrayMap.BITS; index++) {
|
||||
+ if ((map1.bitset & (1 << index)) != 0) {
|
||||
+ var behaviorControls = (org.dreeam.leaf.util.map.BehaviorControlArraySet<? super E>) map1.a[index];
|
||||
+ var behaviorControlsRaw = behaviorControls.raw();
|
||||
+ var behaviorControlsSize = behaviorControls.size();
|
||||
+ for (int i = 0; i < behaviorControlsSize; i++) {
|
||||
+ BehaviorControl<? super E> behaviorControl = (BehaviorControl<? super E>) behaviorControlsRaw[i];
|
||||
+ if (behaviorControl.getStatus() == Behavior.Status.RUNNING) {
|
||||
+ behaviorControl.doStop(level, owner, gameTime);
|
||||
+ behaviorControls.dec();
|
||||
+ }
|
||||
+ for (int index = 0, size = map1.size(); index < size; index++) {
|
||||
+ var behaviorControls = (org.dreeam.leaf.util.map.BehaviorControlArraySet<? super E>) map1.v[index];
|
||||
+ var behaviorControlsRaw = behaviorControls.raw();
|
||||
+ for (int i = 0, size1 = behaviorControls.size(); i < size1; i++) {
|
||||
+ BehaviorControl<? super E> behaviorControl = behaviorControlsRaw[i];
|
||||
+ if (behaviorControl.getStatus() == Behavior.Status.RUNNING) {
|
||||
+ behaviorControl.doStop(level, owner, gameTime);
|
||||
+ behaviorControls.dec();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ // Leaf end
|
||||
}
|
||||
+ // Leaf end - Replace brain maps with optimized collection
|
||||
}
|
||||
|
||||
private void startEachNonRunningBehavior(ServerLevel level, E entity) {
|
||||
@@ -152,35 +154,44 @@ index 29fdf94db0308031edfe7915fc587a2aa5a1a18a..1d533dc2db5df6f31f307bc94f9f8e57
|
||||
- Activity activity = entry.getKey();
|
||||
- if (this.activeActivities.contains(activity)) {
|
||||
- for (BehaviorControl<? super E> behaviorControl : entry.getValue()) {
|
||||
+ // Leaf start
|
||||
- if (behaviorControl.getStatus() == Behavior.Status.STOPPED) {
|
||||
- behaviorControl.tryStart(level, entity, gameTime);
|
||||
- }
|
||||
+ // Leaf start - Replace brain maps with optimized collection
|
||||
+ if (this.availableBehaviorsByPriorityArray.length != this.availableBehaviorsByPriority.size()) {
|
||||
+ this.availableBehaviorsByPriorityArray = this.availableBehaviorsByPriority.values().toArray(EMPTY_ARRAY);
|
||||
+ this.availableBehaviorsByPriorityArray = this.availableBehaviorsByPriority.values().toArray(EMPTY_MAP_ARRAY);
|
||||
+ }
|
||||
+ var aact = (org.dreeam.leaf.util.map.ActivityBitSet) this.activeActivities;
|
||||
+ for (int index = 0; index <= org.dreeam.leaf.util.map.ActivityArrayMap.BITS; index++) {
|
||||
+ if ((aact.bitset & (1 << index)) != 0) {
|
||||
+ for (Map<Activity, Set<BehaviorControl<? super E>>> map : availableBehaviorsByPriorityArray) {
|
||||
+ var map1 = ((org.dreeam.leaf.util.map.ActivityArrayMap<Set<BehaviorControl<? super E>>>) map);
|
||||
+ var ele = map1.a[index];
|
||||
+ if (activeBehaviors == EMPTY_BEHAVIOR_ARRAY || aact.unsetDirty()) {
|
||||
+ var list = it.unimi.dsi.fastutil.objects.ReferenceArrayList.wrap(activeBehaviors);
|
||||
+ list.clear();
|
||||
+ for (Map<Activity, Set<BehaviorControl<? super E>>> map : availableBehaviorsByPriorityArray) {
|
||||
+ for (int index = 0; index < org.dreeam.leaf.util.RegistryTypeManager.ACTIVITY_SIZE; index++) {
|
||||
+ if ((aact.bitset & (1 << index)) == 0) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ var ele = ((org.dreeam.leaf.util.map.ActivityArrayMap<Set<BehaviorControl<? super E>>>) map).getValue(index);
|
||||
+ if (ele == null) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ var behaviorControls = (org.dreeam.leaf.util.map.BehaviorControlArraySet<? super E>) ele;
|
||||
+ var behaviorControlsRaw = behaviorControls.raw();
|
||||
+ var behaviorControlsSize = behaviorControls.size();
|
||||
+ for (int i = 0; i < behaviorControlsSize; i++) {
|
||||
+ BehaviorControl<? super E> behaviorControl = (BehaviorControl<? super E>) behaviorControlsRaw[i];
|
||||
if (behaviorControl.getStatus() == Behavior.Status.STOPPED) {
|
||||
- behaviorControl.tryStart(level, entity, gameTime);
|
||||
+ if (behaviorControl.tryStart(level, entity, gameTime)) {
|
||||
+ behaviorControls.inc();
|
||||
+ }
|
||||
}
|
||||
+ list.add((org.dreeam.leaf.util.map.BehaviorControlArraySet<? super E>) ele);
|
||||
+ }
|
||||
+ }
|
||||
+ activeBehaviors = it.unimi.dsi.fastutil.objects.ObjectArrays.setLength(list.elements(), list.size());
|
||||
+ }
|
||||
+ for (int index = 0, size = activeBehaviors.length; index < size; index++) {
|
||||
+ var behaviorControls = activeBehaviors[index];
|
||||
+ var behaviorControlsRaw = behaviorControls.raw();
|
||||
+ for (int i = 0, size1 = behaviorControls.size(); i < size1; i++) {
|
||||
+ BehaviorControl<? super E> behaviorControl = behaviorControlsRaw[i];
|
||||
+ if (behaviorControl.getStatus() == Behavior.Status.STOPPED) {
|
||||
+ if (behaviorControl.tryStart(level, entity, gameTime)) {
|
||||
+ behaviorControls.inc();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+ // Leaf end
|
||||
+ // Leaf end - Replace brain maps with optimized collection
|
||||
}
|
||||
|
||||
private void tickEachRunningBehavior(ServerLevel level, E entity) {
|
||||
@@ -188,32 +199,30 @@ index 29fdf94db0308031edfe7915fc587a2aa5a1a18a..1d533dc2db5df6f31f307bc94f9f8e57
|
||||
|
||||
- for (BehaviorControl<? super E> behaviorControl : this.getRunningBehaviors()) {
|
||||
- behaviorControl.tickOrStop(level, entity, gameTime);
|
||||
+ // Leaf start
|
||||
+ // Leaf start - Replace brain maps with optimized collection
|
||||
+ if (this.availableBehaviorsByPriorityArray.length != this.availableBehaviorsByPriority.size()) {
|
||||
+ this.availableBehaviorsByPriorityArray = this.availableBehaviorsByPriority.values().toArray(new Map[0]);
|
||||
+ }
|
||||
+ for (Map<Activity, Set<BehaviorControl<? super E>>> map : availableBehaviorsByPriorityArray) {
|
||||
+ var map1 = (org.dreeam.leaf.util.map.ActivityArrayMap<Set<BehaviorControl<? super E>>>) map;
|
||||
+ for (int index = 0; index <= org.dreeam.leaf.util.map.ActivityArrayMap.BITS; index++) {
|
||||
+ if ((map1.bitset & (1 << index)) != 0) {
|
||||
+ var behaviorControls = (org.dreeam.leaf.util.map.BehaviorControlArraySet<? super E>) map1.a[index];
|
||||
+ if (behaviorControls.running()) {
|
||||
+ var behaviorControlsRaw = behaviorControls.raw();
|
||||
+ var behaviorControlsSize = behaviorControls.size();
|
||||
+ for (int i = 0; i < behaviorControlsSize; i++) {
|
||||
+ BehaviorControl<? super E> behaviorControl = (BehaviorControl<? super E>) behaviorControlsRaw[i];
|
||||
+ if (behaviorControl.getStatus() == Behavior.Status.RUNNING) {
|
||||
+ behaviorControl.tickOrStop(level, entity, gameTime);
|
||||
+ if (behaviorControl.getStatus() == Behavior.Status.STOPPED) {
|
||||
+ behaviorControls.dec();
|
||||
+ }
|
||||
+ }
|
||||
+ for (int index = 0, size = map1.size(); index < size; index++) {
|
||||
+ var behaviorControls = (org.dreeam.leaf.util.map.BehaviorControlArraySet<? super E>) map1.v[index];
|
||||
+ if (!behaviorControls.running()) {
|
||||
+ continue;
|
||||
+ }
|
||||
+ BehaviorControl<? super E>[] behaviorControlsRaw = behaviorControls.raw();
|
||||
+ for (int i = 0, size1 = behaviorControls.size(); i < size1; i++) {
|
||||
+ BehaviorControl<? super E> behaviorControl = behaviorControlsRaw[i];
|
||||
+ if (behaviorControl.getStatus() == Behavior.Status.RUNNING) {
|
||||
+ behaviorControl.tickOrStop(level, entity, gameTime);
|
||||
+ if (behaviorControl.getStatus() == Behavior.Status.STOPPED) {
|
||||
+ behaviorControls.dec();
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
+ // Leaf end
|
||||
+ // Leaf end - Replace brain maps with optimized collection
|
||||
}
|
||||
|
||||
private boolean activityRequirementsAreMet(Activity activity) {
|
||||
|
||||
@@ -7,11 +7,20 @@ public final class RegistryTypeManager {
|
||||
/**
|
||||
* The total number of attributes in the Built-in Registry.
|
||||
*/
|
||||
public static final int ATTRIBUTE_ID_COUNTER;
|
||||
public static final int ATTRIBUTE_SIZE;
|
||||
public static final int ACTIVITY_SIZE;
|
||||
|
||||
static {
|
||||
ATTRIBUTE_ID_COUNTER = BuiltInRegistries.ATTRIBUTE.size();
|
||||
ATTRIBUTE_SIZE = BuiltInRegistries.ATTRIBUTE.size();
|
||||
ACTIVITY_SIZE = BuiltInRegistries.ACTIVITY.size();
|
||||
if (ATTRIBUTE_SIZE == 0 || ACTIVITY_SIZE == 0) {
|
||||
throw new ExceptionInInitializerError("RegistryTypeManager initialize before registries bootstrap");
|
||||
}
|
||||
if (ACTIVITY_SIZE > 32) {
|
||||
throw new ExceptionInInitializerError("minecraft:activity out of range int bitset (>32)");
|
||||
}
|
||||
}
|
||||
|
||||
private RegistryTypeManager() {}
|
||||
private RegistryTypeManager() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,75 +7,117 @@ import java.util.*;
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
|
||||
public final class ActivityArrayMap<V> implements Map<Activity, V> {
|
||||
public static final int BITS = 25;
|
||||
|
||||
public int bitset = 0;
|
||||
public final Object[] a = new Object[BITS + 1];
|
||||
public int[] k;
|
||||
public V[] v;
|
||||
private int size = 0;
|
||||
|
||||
private int bitset = 0;
|
||||
private transient KeySet keySet;
|
||||
private transient Values valuesCollection;
|
||||
private transient Values values;
|
||||
private transient EntrySet entrySet;
|
||||
|
||||
public ActivityArrayMap() {
|
||||
if (BuiltInRegistries.ACTIVITY.size() != BITS + 1) {
|
||||
throw new IllegalStateException("Unexpected registry minecraft:activity size");
|
||||
public ActivityArrayMap(V[] arr) {
|
||||
this.k = new int[arr.length];
|
||||
this.v = arr;
|
||||
}
|
||||
|
||||
private int findIndex(int activity) {
|
||||
int mask = 1 << activity;
|
||||
if ((bitset & mask) == 0) {
|
||||
return -1;
|
||||
}
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (k[i] == activity) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private void ensureCap() {
|
||||
if (size >= k.length) {
|
||||
int newCapacity = Math.max(2, k.length + k.length / 2);
|
||||
k = Arrays.copyOf(k, newCapacity);
|
||||
v = Arrays.copyOf(v, newCapacity);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeAtIndex(int index) {
|
||||
if (index < 0 || index >= size) {
|
||||
return;
|
||||
}
|
||||
bitset &= ~(1 << k[index]);
|
||||
System.arraycopy(k, index + 1, k, index, size - index - 1);
|
||||
System.arraycopy(v, index + 1, v, index, size - index - 1);
|
||||
|
||||
size--;
|
||||
v[size] = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V put(Activity key, V value) {
|
||||
int index = key.id;
|
||||
int mask = 1 << index;
|
||||
@SuppressWarnings("unchecked")
|
||||
V oldValue = (V) a[index];
|
||||
boolean hadValue = oldValue != null;
|
||||
a[index] = value;
|
||||
if (!hadValue && value != null) {
|
||||
int index = findIndex(key.id);
|
||||
if (index >= 0) {
|
||||
final V oldValue = v[index];
|
||||
if (value == null) {
|
||||
removeAtIndex(index);
|
||||
} else {
|
||||
v[index] = value;
|
||||
}
|
||||
return oldValue;
|
||||
} else if (value != null) {
|
||||
ensureCap();
|
||||
k[size] = key.id;
|
||||
v[size] = value;
|
||||
bitset |= (1 << key.id);
|
||||
size++;
|
||||
bitset |= mask;
|
||||
}
|
||||
if (hadValue && value == null) {
|
||||
size--;
|
||||
bitset &= ~mask;
|
||||
}
|
||||
return oldValue;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V get(Object key) {
|
||||
if (key instanceof Activity activity) {
|
||||
@SuppressWarnings("unchecked")
|
||||
V value = (V) a[activity.id];
|
||||
return value;
|
||||
int index = findIndex(activity.id);
|
||||
if (index >= 0) {
|
||||
return v[index];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public V getValue(int key) {
|
||||
int index = findIndex(key);
|
||||
if (index >= 0) {
|
||||
return v[index];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey(Object key) {
|
||||
return key instanceof Activity activity && a[activity.id] != null;
|
||||
if (!(key instanceof Activity activity)) {
|
||||
return false;
|
||||
}
|
||||
return (bitset & 1 << activity.id) != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V remove(Object key) {
|
||||
if (key instanceof Activity activity) {
|
||||
int index = activity.id;
|
||||
@SuppressWarnings("unchecked")
|
||||
V oldValue = (V) a[index];
|
||||
if (oldValue != null) {
|
||||
a[index] = null;
|
||||
bitset &= ~(1 << index);
|
||||
size--;
|
||||
int index = findIndex(activity.id);
|
||||
if (index >= 0) {
|
||||
V oldValue = v[index];
|
||||
removeAtIndex(index);
|
||||
return oldValue;
|
||||
}
|
||||
return oldValue;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
Arrays.fill(a, null);
|
||||
Arrays.fill(v, 0, size, null);
|
||||
size = 0;
|
||||
bitset = 0;
|
||||
}
|
||||
@@ -92,8 +134,10 @@ public final class ActivityArrayMap<V> implements Map<Activity, V> {
|
||||
|
||||
@Override
|
||||
public boolean containsValue(Object value) {
|
||||
for (Object v : a) {
|
||||
if (Objects.equals(v, value)) return true;
|
||||
for (int i = 0; i < size; i++) {
|
||||
if (Objects.equals(v[i], value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -115,10 +159,10 @@ public final class ActivityArrayMap<V> implements Map<Activity, V> {
|
||||
|
||||
@Override
|
||||
public Collection<V> values() {
|
||||
if (valuesCollection == null) {
|
||||
valuesCollection = new Values();
|
||||
if (values == null) {
|
||||
values = new Values();
|
||||
}
|
||||
return valuesCollection;
|
||||
return values;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -133,28 +177,27 @@ public final class ActivityArrayMap<V> implements Map<Activity, V> {
|
||||
@Override
|
||||
public Iterator<Activity> iterator() {
|
||||
return new Iterator<>() {
|
||||
private int index = -1;
|
||||
|
||||
private void advance() {
|
||||
do index++;
|
||||
while (index <= BITS && (bitset & (1 << index)) == 0);
|
||||
}
|
||||
|
||||
{
|
||||
advance();
|
||||
}
|
||||
private int index = 0;
|
||||
private int lastReturned = -1;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return index <= BITS;
|
||||
return index < size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Activity next() {
|
||||
if (!hasNext()) throw new NoSuchElementException();
|
||||
Activity activity = BuiltInRegistries.ACTIVITY.byIdOrThrow(index);
|
||||
advance();
|
||||
return activity;
|
||||
lastReturned = index;
|
||||
return BuiltInRegistries.ACTIVITY.byIdOrThrow(k[index++]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if (lastReturned < 0) throw new IllegalStateException();
|
||||
ActivityArrayMap.this.removeAtIndex(lastReturned);
|
||||
index = lastReturned;
|
||||
lastReturned = -1;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -179,29 +222,17 @@ public final class ActivityArrayMap<V> implements Map<Activity, V> {
|
||||
@Override
|
||||
public Iterator<V> iterator() {
|
||||
return new Iterator<>() {
|
||||
private int index = -1;
|
||||
|
||||
private void advance() {
|
||||
do index++;
|
||||
while (index <= BITS && (bitset & (1 << index)) == 0);
|
||||
}
|
||||
|
||||
{
|
||||
advance();
|
||||
}
|
||||
private int index = 0;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return index <= BITS;
|
||||
return index < size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V next() {
|
||||
if (!hasNext()) throw new NoSuchElementException();
|
||||
@SuppressWarnings("unchecked")
|
||||
V value = (V) a[index];
|
||||
advance();
|
||||
return value;
|
||||
return v[index++];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -226,43 +257,30 @@ public final class ActivityArrayMap<V> implements Map<Activity, V> {
|
||||
@Override
|
||||
public Iterator<Entry<Activity, V>> iterator() {
|
||||
return new Iterator<>() {
|
||||
private int index = -1;
|
||||
private int last = -1;
|
||||
|
||||
private void advance() {
|
||||
do index++;
|
||||
while (index <= BITS && (bitset & (1 << index)) == 0);
|
||||
}
|
||||
|
||||
{
|
||||
advance();
|
||||
}
|
||||
private int index = 0;
|
||||
private int lastReturned = -1;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return index <= BITS;
|
||||
return index < size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Entry<Activity, V> next() {
|
||||
if (!hasNext()) throw new NoSuchElementException();
|
||||
last = index;
|
||||
Activity activity = BuiltInRegistries.ACTIVITY.byIdOrThrow(index);
|
||||
@SuppressWarnings("unchecked")
|
||||
V value = (V) a[index];
|
||||
advance();
|
||||
return new SimpleEntry<>(activity, value);
|
||||
lastReturned = index;
|
||||
int key = k[index];
|
||||
V value = v[index];
|
||||
index++;
|
||||
return new SimpleEntry<>(BuiltInRegistries.ACTIVITY.byIdOrThrow(key), value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if (last == -1) throw new IllegalStateException();
|
||||
if (a[last] != null) {
|
||||
a[last] = null;
|
||||
bitset &= ~(1 << last);
|
||||
size--;
|
||||
}
|
||||
last = -1;
|
||||
if (lastReturned < 0) throw new IllegalStateException();
|
||||
ActivityArrayMap.this.removeAtIndex(lastReturned);
|
||||
index = lastReturned;
|
||||
lastReturned = -1;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -275,9 +293,10 @@ public final class ActivityArrayMap<V> implements Map<Activity, V> {
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
if (o instanceof Entry<?, ?> entry && entry.getKey() instanceof Activity activity) {
|
||||
@SuppressWarnings("unchecked")
|
||||
V value = (V) a[activity.id];
|
||||
return Objects.equals(value, entry.getValue());
|
||||
int index = findIndex(activity.id);
|
||||
if (index >= 0) {
|
||||
return Objects.equals(v[index], entry.getValue());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -307,8 +326,8 @@ public final class ActivityArrayMap<V> implements Map<Activity, V> {
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 0;
|
||||
for (Entry<Activity, V> entry : entrySet()) {
|
||||
hash += entry.hashCode();
|
||||
for (int i = 0; i < size; i++) {
|
||||
hash += Objects.hashCode(k[i]) ^ Objects.hashCode(v[i]);
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
@@ -1,22 +1,32 @@
|
||||
package org.dreeam.leaf.util.map;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.AbstractObjectSet;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.world.entity.schedule.Activity;
|
||||
import org.dreeam.leaf.util.RegistryTypeManager;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public final class ActivityBitSet extends AbstractCollection<Activity> implements Set<Activity> {
|
||||
public static final int BITS = 25;
|
||||
public final class ActivityBitSet extends AbstractObjectSet<Activity> {
|
||||
|
||||
public int bitset = 0;
|
||||
private boolean dirty = true;
|
||||
|
||||
public ActivityBitSet() {
|
||||
if (BuiltInRegistries.ACTIVITY.size() != BITS + 1) {
|
||||
throw new IllegalStateException("Unexpected registry minecraft:activity size");
|
||||
public boolean unsetDirty() {
|
||||
if (dirty) {
|
||||
dirty = false;
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int bitSet() {
|
||||
return bitset;
|
||||
}
|
||||
|
||||
private static Activity map(int i) {
|
||||
return BuiltInRegistries.ACTIVITY.byIdOrThrow(i);
|
||||
}
|
||||
@@ -26,6 +36,7 @@ public final class ActivityBitSet extends AbstractCollection<Activity> implement
|
||||
int mask = 1 << activity.id;
|
||||
if ((bitset & mask) != 0) return false;
|
||||
bitset |= mask;
|
||||
dirty = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -35,6 +46,7 @@ public final class ActivityBitSet extends AbstractCollection<Activity> implement
|
||||
int mask = 1 << activity.id;
|
||||
if ((bitset & mask) != 0) {
|
||||
bitset &= ~mask;
|
||||
dirty = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -47,27 +59,27 @@ public final class ActivityBitSet extends AbstractCollection<Activity> implement
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Iterator<Activity> iterator() {
|
||||
return new Iterator<>() {
|
||||
public @NotNull ObjectIterator<Activity> iterator() {
|
||||
return new ObjectIterator<>() {
|
||||
private int index = 0;
|
||||
|
||||
private void advance() {
|
||||
while (index < BITS && (bitset & (1 << index)) == 0) index++;
|
||||
}
|
||||
{
|
||||
advance();
|
||||
while (index < RegistryTypeManager.ACTIVITY_SIZE && (bitset & (1 << index)) == 0) {
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return index < BITS;
|
||||
return index < RegistryTypeManager.ACTIVITY_SIZE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Activity next() {
|
||||
if (!hasNext()) throw new NoSuchElementException();
|
||||
Activity act = map(index++);
|
||||
advance();
|
||||
while (index < RegistryTypeManager.ACTIVITY_SIZE && (bitset & (1 << index)) == 0) {
|
||||
index++;
|
||||
}
|
||||
return act;
|
||||
}
|
||||
};
|
||||
@@ -81,6 +93,7 @@ public final class ActivityBitSet extends AbstractCollection<Activity> implement
|
||||
@Override
|
||||
public void clear() {
|
||||
bitset = 0;
|
||||
dirty = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -94,7 +107,7 @@ public final class ActivityBitSet extends AbstractCollection<Activity> implement
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 0;
|
||||
for (int i = 0; i < BITS; i++) {
|
||||
for (int i = 0; i < RegistryTypeManager.ACTIVITY_SIZE; i++) {
|
||||
if ((bitset & (1 << i)) != 0) {
|
||||
hash += map(i).hashCode();
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ import java.util.AbstractMap.SimpleEntry;
|
||||
public final class AttributeInstanceArrayMap implements Map<Holder<Attribute>, AttributeInstance>, Cloneable {
|
||||
|
||||
private int size = 0;
|
||||
private transient AttributeInstance[] a = new AttributeInstance[RegistryTypeManager.ATTRIBUTE_ID_COUNTER];
|
||||
private transient AttributeInstance[] a = new AttributeInstance[RegistryTypeManager.ATTRIBUTE_SIZE];
|
||||
private transient KeySet keys;
|
||||
private transient Values values;
|
||||
private transient EntrySet entries;
|
||||
|
||||
@@ -1,14 +1,26 @@
|
||||
package org.dreeam.leaf.util.map;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArraySet;
|
||||
import it.unimi.dsi.fastutil.objects.AbstractObjectSet;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
||||
import net.minecraft.world.entity.LivingEntity;
|
||||
import net.minecraft.world.entity.ai.behavior.Behavior;
|
||||
import net.minecraft.world.entity.ai.behavior.BehaviorControl;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class BehaviorControlArraySet<E extends LivingEntity> extends ObjectArraySet<BehaviorControl<? super E>> {
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
public final class BehaviorControlArraySet<E extends LivingEntity> extends AbstractObjectSet<BehaviorControl<? super E>> {
|
||||
|
||||
private static final BehaviorControl[] EMPTY_ARRAY = {};
|
||||
private int running;
|
||||
private transient BehaviorControl<? super E>[] a;
|
||||
private int size;
|
||||
|
||||
public Object[] raw() {
|
||||
public BehaviorControlArraySet() {
|
||||
this.a = EMPTY_ARRAY;
|
||||
}
|
||||
|
||||
public BehaviorControl<? super E>[] raw() {
|
||||
return a;
|
||||
}
|
||||
|
||||
@@ -23,4 +35,124 @@ public class BehaviorControlArraySet<E extends LivingEntity> extends ObjectArray
|
||||
public boolean running() {
|
||||
return running != 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
private int findKey(final Object o) {
|
||||
final BehaviorControl<? super E>[] a = this.a;
|
||||
for (int i = size; i-- != 0; ) if (Objects.equals(a[i], o)) return i;
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return size == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object k) {
|
||||
return findKey(k) != -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ObjectIterator<BehaviorControl<? super E>> iterator() {
|
||||
return new ObjectIterator<>() {
|
||||
int curr = -1, next = 0;
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return next < size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BehaviorControl<? super E> next() {
|
||||
if (!hasNext()) throw new NoSuchElementException();
|
||||
return a[curr = next++];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
if (curr == -1) throw new IllegalStateException();
|
||||
curr = -1;
|
||||
final int tail = size-- - next--;
|
||||
System.arraycopy(a, next + 1, a, next, tail);
|
||||
a[size] = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int skip(int n) {
|
||||
if (n < 0) throw new IllegalArgumentException("Argument must be nonnegative: " + n);
|
||||
n = Math.min(n, size - next);
|
||||
next += n;
|
||||
if (n != 0) curr = next - 1;
|
||||
return n;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachRemaining(final Consumer<? super BehaviorControl<? super E>> action) {
|
||||
final BehaviorControl<? super E>[] a = BehaviorControlArraySet.this.a;
|
||||
while (next < size) action.accept(a[next++]);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Object[] toArray() {
|
||||
|
||||
final int size = size();
|
||||
if (size == 0) return it.unimi.dsi.fastutil.objects.ObjectArrays.EMPTY_ARRAY;
|
||||
return java.util.Arrays.copyOf(a, size, Object[].class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull <T> T[] toArray(@NotNull T[] a) {
|
||||
if (a == null) {
|
||||
a = (T[]) new Object[size];
|
||||
} else if (a.length < size) {
|
||||
a = (T[]) java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
|
||||
}
|
||||
System.arraycopy(this.a, 0, a, 0, size);
|
||||
if (a.length > size) {
|
||||
a[size] = null;
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(BehaviorControl<? super E> k) {
|
||||
final int pos = findKey(k);
|
||||
if (pos != -1) return false;
|
||||
if (size == a.length) {
|
||||
final BehaviorControl<? super E>[] b = new BehaviorControl[size == 0 ? 2 : size * 2];
|
||||
for (int i = size; i-- != 0; ) b[i] = a[i];
|
||||
a = b;
|
||||
}
|
||||
a[size++] = k;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object k) {
|
||||
final int pos = findKey(k);
|
||||
if (pos == -1) return false;
|
||||
final int tail = size - pos - 1;
|
||||
for (int i = 0; i < tail; i++) a[pos + i] = a[pos + i + 1];
|
||||
size--;
|
||||
a[size] = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
java.util.Arrays.fill(a, 0, size, null);
|
||||
size = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user