diff --git a/leaf-server/minecraft-patches/features/0166-Multithreaded-Tracker.patch b/leaf-server/minecraft-patches/features/0166-Multithreaded-Tracker.patch index a68e279d..64a98080 100644 --- a/leaf-server/minecraft-patches/features/0166-Multithreaded-Tracker.patch +++ b/leaf-server/minecraft-patches/features/0166-Multithreaded-Tracker.patch @@ -1261,7 +1261,7 @@ index 1556b2d4a758e3a15b6c4468bf994ea3781a4958..581791bf2892715543f003c36e301e69 if (this.player.isRemoved()) { LOGGER.info("Attempt to teleport removed player {} restricted", player.getScoreboardName()); diff --git a/net/minecraft/world/entity/LivingEntity.java b/net/minecraft/world/entity/LivingEntity.java -index 4d4efd979c4478c1571e7044f639afe08a7118d6..de4d13e7c6f57d6cc3a78b1b9ca914157820186c 100644 +index 4d4efd979c4478c1571e7044f639afe08a7118d6..4f0b903945860e518ebf3c858722f28df9394b3d 100644 --- a/net/minecraft/world/entity/LivingEntity.java +++ b/net/minecraft/world/entity/LivingEntity.java @@ -1342,13 +1342,13 @@ public abstract class LivingEntity extends Entity implements Attackable, Waypoin @@ -1275,7 +1275,7 @@ index 4d4efd979c4478c1571e7044f639afe08a7118d6..de4d13e7c6f57d6cc3a78b1b9ca91415 - for (AttributeInstance attributeInstance : attributesToUpdate) { - this.onAttributeUpdated(attributeInstance.getAttribute()); + for (int attribute : attributesToUpdate) { -+ this.onAttributeUpdated(net.minecraft.core.registries.BuiltInRegistries.ATTRIBUTE.get(attribute).orElseThrow()); ++ this.onAttributeUpdated(org.dreeam.leaf.util.RegistryTypeManager.ATTRIBUTE[attribute]); } - - attributesToUpdate.clear(); diff --git a/leaf-server/src/main/java/org/dreeam/leaf/util/RegistryTypeManager.java b/leaf-server/src/main/java/org/dreeam/leaf/util/RegistryTypeManager.java index f1904487..fc24d36c 100644 --- a/leaf-server/src/main/java/org/dreeam/leaf/util/RegistryTypeManager.java +++ b/leaf-server/src/main/java/org/dreeam/leaf/util/RegistryTypeManager.java @@ -1,6 +1,9 @@ package org.dreeam.leaf.util; +import net.minecraft.core.Holder; import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.world.entity.ai.attributes.Attribute; +import net.minecraft.world.entity.schedule.Activity; public final class RegistryTypeManager { @@ -9,6 +12,9 @@ public final class RegistryTypeManager { */ public static final int ATTRIBUTE_SIZE; public static final int ACTIVITY_SIZE; + public static final Holder[] ATTRIBUTE; + + public static final Activity[] ACTIVITY_DIRECT; static { ATTRIBUTE_SIZE = BuiltInRegistries.ATTRIBUTE.size(); @@ -19,6 +25,20 @@ public final class RegistryTypeManager { if (ACTIVITY_SIZE > 32) { throw new ExceptionInInitializerError("minecraft:activity out of range int bitset (>32)"); } + ATTRIBUTE = new Holder[ATTRIBUTE_SIZE]; + for (int i = 0; i < ATTRIBUTE_SIZE; i++) { + ATTRIBUTE[i] = BuiltInRegistries.ATTRIBUTE.get(i).orElseThrow(); + if (ATTRIBUTE[i].value().uid != i) { + throw new ExceptionInInitializerError(); + } + } + ACTIVITY_DIRECT = new Activity[ACTIVITY_SIZE]; + for (int i = 0; i < ACTIVITY_SIZE; i++) { + ACTIVITY_DIRECT[i] = BuiltInRegistries.ACTIVITY.byIdOrThrow(i); + if (ACTIVITY_DIRECT[i].id != i) { + throw new ExceptionInInitializerError(); + } + } } private RegistryTypeManager() { diff --git a/leaf-server/src/main/java/org/dreeam/leaf/util/map/ActivityArrayMap.java b/leaf-server/src/main/java/org/dreeam/leaf/util/map/ActivityArrayMap.java index 12b121b6..a3499b4d 100644 --- a/leaf-server/src/main/java/org/dreeam/leaf/util/map/ActivityArrayMap.java +++ b/leaf-server/src/main/java/org/dreeam/leaf/util/map/ActivityArrayMap.java @@ -1,10 +1,10 @@ package org.dreeam.leaf.util.map; -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.*; -import java.util.AbstractMap.SimpleEntry; public final class ActivityArrayMap implements Map { @@ -26,7 +26,7 @@ public final class ActivityArrayMap implements Map { if ((bitset & mask) == 0) { return -1; } - for (int i = 0; i < size; i++) { + for (int i = 0, j = size; i < j; i++) { if (k[i] == activity) { return i; } @@ -56,7 +56,8 @@ public final class ActivityArrayMap implements Map { @Override public V put(Activity key, V value) { - int index = findIndex(key.id); + int raw = key.id; + int index = findIndex(raw); if (index >= 0) { final V oldValue = v[index]; if (value == null) { @@ -67,9 +68,9 @@ public final class ActivityArrayMap implements Map { return oldValue; } else if (value != null) { ensureCap(); - k[size] = key.id; + k[size] = raw; v[size] = value; - bitset |= (1 << key.id); + bitset |= (1 << raw); size++; } return null; @@ -150,6 +151,7 @@ public final class ActivityArrayMap implements Map { } @Override + @NotNull public Set keySet() { if (keySet == null) { keySet = new KeySet(); @@ -158,6 +160,7 @@ public final class ActivityArrayMap implements Map { } @Override + @NotNull public Collection values() { if (values == null) { values = new Values(); @@ -166,6 +169,7 @@ public final class ActivityArrayMap implements Map { } @Override + @NotNull public Set> entrySet() { if (entrySet == null) { entrySet = new EntrySet(); @@ -175,6 +179,7 @@ public final class ActivityArrayMap implements Map { private final class KeySet extends AbstractSet { @Override + @NotNull public Iterator iterator() { return new Iterator<>() { private int index = 0; @@ -189,7 +194,7 @@ public final class ActivityArrayMap implements Map { public Activity next() { if (!hasNext()) throw new NoSuchElementException(); lastReturned = index; - return BuiltInRegistries.ACTIVITY.byIdOrThrow(k[index++]); + return RegistryTypeManager.ACTIVITY_DIRECT[k[index++]]; } @Override @@ -220,9 +225,11 @@ public final class ActivityArrayMap implements Map { private final class Values extends AbstractCollection { @Override + @NotNull public Iterator iterator() { return new Iterator<>() { private int index = 0; + private int lastReturned = -1; @Override public boolean hasNext() { @@ -232,8 +239,17 @@ public final class ActivityArrayMap implements Map { @Override public V next() { if (!hasNext()) throw new NoSuchElementException(); + lastReturned = index; return v[index++]; } + + @Override + public void remove() { + if (lastReturned < 0) throw new IllegalStateException(); + ActivityArrayMap.this.removeAtIndex(lastReturned); + index = lastReturned; + lastReturned = -1; + } }; } @@ -255,6 +271,7 @@ public final class ActivityArrayMap implements Map { private final class EntrySet extends AbstractSet> { @Override + @NotNull public Iterator> iterator() { return new Iterator<>() { private int index = 0; @@ -272,7 +289,7 @@ public final class ActivityArrayMap implements Map { int key = k[index]; V value = v[index]; index++; - return new SimpleEntry<>(BuiltInRegistries.ACTIVITY.byIdOrThrow(key), value); + return new MapEntry(key, value); } @Override @@ -307,6 +324,51 @@ public final class ActivityArrayMap implements Map { } } + private final class MapEntry implements Entry { + private final int key; + private V value; + + MapEntry(int key, V value) { + this.key = key; + this.value = value; + } + + @Override + public Activity getKey() { + return RegistryTypeManager.ACTIVITY_DIRECT[key]; + } + + @Override + public V getValue() { + return value; + } + + @Override + public V setValue(V value) { + V oldValue = this.value; + this.value = value; + ActivityArrayMap.this.put(RegistryTypeManager.ACTIVITY_DIRECT[key], value); + return oldValue; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Entry entry)) return false; + return Objects.equals(RegistryTypeManager.ACTIVITY_DIRECT[key], entry.getKey()) && Objects.equals(value, entry.getValue()); + } + + @Override + public int hashCode() { + return Objects.hashCode(key) ^ Objects.hashCode(value); + } + + @Override + public String toString() { + return key + "=" + value; + } + } + @Override public boolean equals(Object o) { if (this == o) return true; diff --git a/leaf-server/src/main/java/org/dreeam/leaf/util/map/ActivityBitSet.java b/leaf-server/src/main/java/org/dreeam/leaf/util/map/ActivityBitSet.java index 45305222..39d08d57 100644 --- a/leaf-server/src/main/java/org/dreeam/leaf/util/map/ActivityBitSet.java +++ b/leaf-server/src/main/java/org/dreeam/leaf/util/map/ActivityBitSet.java @@ -2,7 +2,6 @@ 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; @@ -27,10 +26,6 @@ public final class ActivityBitSet extends AbstractObjectSet { return bitset; } - private static Activity map(int i) { - return BuiltInRegistries.ACTIVITY.byIdOrThrow(i); - } - @Override public boolean add(Activity activity) { int mask = 1 << activity.id; @@ -76,7 +71,7 @@ public final class ActivityBitSet extends AbstractObjectSet { @Override public Activity next() { if (!hasNext()) throw new NoSuchElementException(); - Activity act = map(index++); + Activity act = RegistryTypeManager.ACTIVITY_DIRECT[index++]; while (index < RegistryTypeManager.ACTIVITY_SIZE && (bitset & (1 << index)) == 0) { index++; } @@ -109,7 +104,7 @@ public final class ActivityBitSet extends AbstractObjectSet { int hash = 0; for (int i = 0; i < RegistryTypeManager.ACTIVITY_SIZE; i++) { if ((bitset & (1 << i)) != 0) { - hash += map(i).hashCode(); + hash += RegistryTypeManager.ACTIVITY_DIRECT[i].hashCode(); } } return hash; diff --git a/leaf-server/src/main/java/org/dreeam/leaf/util/map/AttributeInstanceArrayMap.java b/leaf-server/src/main/java/org/dreeam/leaf/util/map/AttributeInstanceArrayMap.java index 1c36e80d..7e6fde1b 100644 --- a/leaf-server/src/main/java/org/dreeam/leaf/util/map/AttributeInstanceArrayMap.java +++ b/leaf-server/src/main/java/org/dreeam/leaf/util/map/AttributeInstanceArrayMap.java @@ -1,7 +1,6 @@ package org.dreeam.leaf.util.map; import net.minecraft.core.Holder; -import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.world.entity.ai.attributes.Attribute; import net.minecraft.world.entity.ai.attributes.AttributeInstance; import org.dreeam.leaf.util.RegistryTypeManager; @@ -9,7 +8,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.*; -import java.util.AbstractMap.SimpleEntry; // fast array backend map with O(1) get & put & remove public final class AttributeInstanceArrayMap implements Map, AttributeInstance>, Cloneable { @@ -21,11 +19,9 @@ public final class AttributeInstanceArrayMap implements Map, A private transient EntrySet entries; public AttributeInstanceArrayMap() { - // The check for a fixed vanilla size is no longer necessary } public AttributeInstanceArrayMap(final @NotNull Map, AttributeInstance> m) { - this(); putAll(m); } @@ -111,7 +107,8 @@ public final class AttributeInstanceArrayMap implements Map, A } @Override - public @NotNull Set> keySet() { + @NotNull + public Set> keySet() { if (keys == null) { keys = new KeySet(); } @@ -119,7 +116,8 @@ public final class AttributeInstanceArrayMap implements Map, A } @Override - public @NotNull Collection values() { + @NotNull + public Collection values() { if (values == null) { values = new Values(); } @@ -127,7 +125,8 @@ public final class AttributeInstanceArrayMap implements Map, A } @Override - public @NotNull Set, AttributeInstance>> entrySet() { + @NotNull + public Set, AttributeInstance>> entrySet() { if (entries == null) { entries = new EntrySet(); } @@ -201,7 +200,7 @@ public final class AttributeInstanceArrayMap implements Map, A if (!hasNext()) throw new NoSuchElementException(); currentIndex = nextIndex; nextIndex = findNextOccupied(nextIndex + 1); - return BuiltInRegistries.ATTRIBUTE.get(currentIndex).orElseThrow(); + return RegistryTypeManager.ATTRIBUTE[currentIndex]; } @Override @@ -288,17 +287,9 @@ public final class AttributeInstanceArrayMap implements Map, A public Entry, AttributeInstance> next() { if (!hasNext()) throw new NoSuchElementException(); currentIndex = nextIndex; - Holder key = BuiltInRegistries.ATTRIBUTE.get(nextIndex).orElseThrow(); AttributeInstance value = a[nextIndex]; nextIndex = findNextOccupied(nextIndex + 1); - return new SimpleEntry<>(key, value) { - @Override - public AttributeInstance setValue(AttributeInstance newValue) { - AttributeInstance old = put(key, newValue); - super.setValue(newValue); - return old; - } - }; + return new MapEntry(currentIndex, value); } @Override @@ -311,6 +302,51 @@ public final class AttributeInstanceArrayMap implements Map, A } } + private final class MapEntry implements Entry, AttributeInstance> { + private final int key; + private AttributeInstance value; + + MapEntry(int key, AttributeInstance value) { + this.key = key; + this.value = value; + } + + @Override + public Holder getKey() { + return RegistryTypeManager.ATTRIBUTE[this.key]; + } + + @Override + public AttributeInstance getValue() { + return value; + } + + @Override + public AttributeInstance setValue(AttributeInstance newValue) { + AttributeInstance oldValue = this.value; + this.value = newValue; + AttributeInstanceArrayMap.this.setByIndex(this.key, newValue); + return oldValue; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof Entry entry)) return false; + return Objects.equals(RegistryTypeManager.ATTRIBUTE[key], entry.getKey()) && Objects.equals(value, entry.getValue()); + } + + @Override + public int hashCode() { + return Objects.hashCode(key) ^ Objects.hashCode(value); + } + + @Override + public String toString() { + return key + "=" + value; + } + } + private int findNextOccupied(int start) { for (int i = start; i < a.length; i++) { if (a[i] != null) { @@ -319,4 +355,8 @@ public final class AttributeInstanceArrayMap implements Map, A } return -1; } + + public AttributeInstance[] elements() { + return a; + } } diff --git a/leaf-server/src/main/java/org/dreeam/leaf/util/map/AttributeInstanceSet.java b/leaf-server/src/main/java/org/dreeam/leaf/util/map/AttributeInstanceSet.java index 5b1f32da..b213afda 100644 --- a/leaf-server/src/main/java/org/dreeam/leaf/util/map/AttributeInstanceSet.java +++ b/leaf-server/src/main/java/org/dreeam/leaf/util/map/AttributeInstanceSet.java @@ -1,7 +1,7 @@ package org.dreeam.leaf.util.map; import it.unimi.dsi.fastutil.ints.IntArraySet; -import it.unimi.dsi.fastutil.ints.IntSet; +import net.minecraft.world.entity.ai.attributes.Attribute; import net.minecraft.world.entity.ai.attributes.AttributeInstance; import org.jetbrains.annotations.NotNull; @@ -9,7 +9,7 @@ import java.lang.reflect.Array; import java.util.*; public final class AttributeInstanceSet extends AbstractCollection implements Set { - public final IntSet inner; + public final IntArraySet inner; public final AttributeInstanceArrayMap map; public AttributeInstanceSet(AttributeInstanceArrayMap map) { @@ -22,6 +22,10 @@ public final class AttributeInstanceSet extends AbstractCollection { + private static final class CloneIterator implements Iterator { private final int[] array; private int index = 0; private final AttributeInstanceArrayMap map;