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