9
0
mirror of https://github.com/Winds-Studio/Leaf.git synced 2025-12-25 18:09:17 +00:00

optimize brain collections

This commit is contained in:
hayanesuru
2025-07-19 22:48:59 +09:00
parent 22a714c058
commit bdb5f4586c
6 changed files with 374 additions and 192 deletions

View File

@@ -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() {
}
}

View File

@@ -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;
}

View File

@@ -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();
}

View File

@@ -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;

View File

@@ -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;
}
}