mirror of
https://github.com/BX-Team/DivineMC.git
synced 2025-12-22 08:19:19 +00:00
Updated Upstream (Purpur)
Upstream has released updates that appear to apply and compile correctly Purpur Changes: PurpurMC/Purpur@5583a3f1 Updated Upstream (Paper)
This commit is contained in:
@@ -0,0 +1,90 @@
|
||||
package space.bxteam.divinemc.util;
|
||||
|
||||
import it.unimi.dsi.fastutil.ints.IntOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import net.minecraft.world.level.block.entity.TickingBlockEntity;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* A list for ServerLevel's blockEntityTickers
|
||||
* <p>
|
||||
* This list is behaving identically to ObjectArrayList, but it has an additional method, `removeAllByIndex`, that allows a list of integers to be passed indicating what
|
||||
* indexes should be deleted from the list
|
||||
* <p>
|
||||
* This is faster than using removeAll, since we don't need to compare the identity of each block entity, and faster than looping through each index manually and deleting with remove,
|
||||
* since we don't need to resize the array every single remove.
|
||||
*/
|
||||
public final class BlockEntityTickersList extends ObjectArrayList<TickingBlockEntity> {
|
||||
private final IntOpenHashSet toRemove = new IntOpenHashSet();
|
||||
private int startSearchFromIndex = -1;
|
||||
|
||||
/** Creates a new array list with {@link #DEFAULT_INITIAL_CAPACITY} capacity. */
|
||||
public BlockEntityTickersList() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new array list and fills it with a given collection.
|
||||
*
|
||||
* @param c a collection that will be used to fill the array list.
|
||||
*/
|
||||
public BlockEntityTickersList(final Collection<? extends TickingBlockEntity> c) {
|
||||
super(c);
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks an entry as removed
|
||||
*
|
||||
* @param index the index of the item on the list to be marked as removed
|
||||
*/
|
||||
public void markAsRemoved(final int index) {
|
||||
// The block entities list always loop starting from 0, so we only need to check if the startSearchFromIndex is -1 and that's it
|
||||
if (this.startSearchFromIndex == -1)
|
||||
this.startSearchFromIndex = index;
|
||||
this.toRemove.add(index);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes elements that have been marked as removed.
|
||||
*/
|
||||
public void removeMarkedEntries() {
|
||||
if (this.startSearchFromIndex == -1) // No entries in the list, skip
|
||||
return;
|
||||
|
||||
removeAllByIndex(startSearchFromIndex, toRemove);
|
||||
toRemove.clear();
|
||||
this.startSearchFromIndex = -1; // Reset the start search index
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes elements by their index.
|
||||
*/
|
||||
private void removeAllByIndex(final int startSearchFromIndex, final IntOpenHashSet c) { // can't use Set<Integer> because we want to avoid autoboxing when using contains
|
||||
final int requiredMatches = c.size();
|
||||
if (requiredMatches == 0)
|
||||
return; // exit early, we don't need to do anything
|
||||
|
||||
final Object[] a = this.a;
|
||||
int j = startSearchFromIndex;
|
||||
int matches = 0;
|
||||
for (int i = startSearchFromIndex; i < size; i++) { // If the user knows the first index to be removed, we can skip a lot of unnecessary comparsions
|
||||
if (!c.contains(i)) {
|
||||
a[j++] = a[i];
|
||||
} else {
|
||||
matches++;
|
||||
}
|
||||
|
||||
if (matches == requiredMatches) { // Exit the loop if we already removed everything, we don't need to check anything else
|
||||
if (i != (size - 1)) { // If it isn't the last index...
|
||||
System.arraycopy(a, i + 1, a, j, size - i - 1);
|
||||
}
|
||||
j = size - requiredMatches;
|
||||
break;
|
||||
}
|
||||
}
|
||||
Arrays.fill(a, j, size, null);
|
||||
size = j;
|
||||
}
|
||||
}
|
||||
@@ -1,281 +0,0 @@
|
||||
package space.bxteam.divinemc.util.lithium;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
|
||||
import it.unimi.dsi.fastutil.objects.ReferenceArrayList;
|
||||
import it.unimi.dsi.fastutil.objects.ReferenceOpenHashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.ListIterator;
|
||||
import java.util.NoSuchElementException;
|
||||
|
||||
/**
|
||||
* Wraps a {@link List} with a hash table which provides O(1) lookups for {@link Collection#contains(Object)}. The type
|
||||
* contained by this list must use reference-equality semantics.
|
||||
*/
|
||||
@SuppressWarnings("SuspiciousMethodCalls")
|
||||
public class HashedReferenceList<T> implements List<T> {
|
||||
private final ReferenceArrayList<T> list;
|
||||
private final Reference2IntOpenHashMap<T> counter;
|
||||
|
||||
public HashedReferenceList(List<T> list) {
|
||||
this.list = new ReferenceArrayList<>();
|
||||
this.list.addAll(list);
|
||||
|
||||
this.counter = new Reference2IntOpenHashMap<>();
|
||||
this.counter.defaultReturnValue(0);
|
||||
|
||||
for (T obj : this.list) {
|
||||
this.counter.addTo(obj, 1);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return this.list.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
return this.list.isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return this.counter.containsKey(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return this.listIterator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] toArray() {
|
||||
return this.list.toArray();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T1> T1[] toArray(T1 @NotNull [] a) {
|
||||
return this.list.toArray(a);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(T t) {
|
||||
this.trackReferenceAdded(t);
|
||||
|
||||
return this.list.add(t);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
this.trackReferenceRemoved(o);
|
||||
|
||||
return this.list.remove(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsAll(Collection<?> c) {
|
||||
for (Object obj : c) {
|
||||
if (!this.counter.containsKey(obj)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(Collection<? extends T> c) {
|
||||
for (T obj : c) {
|
||||
this.trackReferenceAdded(obj);
|
||||
}
|
||||
|
||||
return this.list.addAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean addAll(int index, Collection<? extends T> c) {
|
||||
for (T obj : c) {
|
||||
this.trackReferenceAdded(obj);
|
||||
}
|
||||
|
||||
return this.list.addAll(index, c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean removeAll(@NotNull Collection<?> c) {
|
||||
if (this.size() >= 2 && c.size() > 4 && c instanceof List) {
|
||||
//HashReferenceList uses reference equality, so using ReferenceOpenHashSet is fine
|
||||
c = new ReferenceOpenHashSet<>(c);
|
||||
}
|
||||
this.counter.keySet().removeAll(c);
|
||||
return this.list.removeAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean retainAll(@NotNull Collection<?> c) {
|
||||
this.counter.keySet().retainAll(c);
|
||||
return this.list.retainAll(c);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
this.counter.clear();
|
||||
this.list.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T get(int index) {
|
||||
return this.list.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T set(int index, T element) {
|
||||
T prev = this.list.set(index, element);
|
||||
|
||||
if (prev != element) {
|
||||
if (prev != null) {
|
||||
this.trackReferenceRemoved(prev);
|
||||
}
|
||||
|
||||
this.trackReferenceAdded(element);
|
||||
}
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(int index, T element) {
|
||||
this.trackReferenceAdded(element);
|
||||
|
||||
this.list.add(index, element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T remove(int index) {
|
||||
T prev = this.list.remove(index);
|
||||
|
||||
if (prev != null) {
|
||||
this.trackReferenceRemoved(prev);
|
||||
}
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int indexOf(Object o) {
|
||||
return this.list.indexOf(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int lastIndexOf(Object o) {
|
||||
return this.list.lastIndexOf(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator<T> listIterator() {
|
||||
return this.listIterator(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListIterator<T> listIterator(int index) {
|
||||
return new ListIterator<>() {
|
||||
private final ListIterator<T> inner = HashedReferenceList.this.list.listIterator(index);
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return this.inner.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T next() {
|
||||
return this.inner.next();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPrevious() {
|
||||
return this.inner.hasPrevious();
|
||||
}
|
||||
|
||||
@Override
|
||||
public T previous() {
|
||||
return this.inner.previous();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int nextIndex() {
|
||||
return this.inner.nextIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int previousIndex() {
|
||||
return this.inner.previousIndex();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove() {
|
||||
int last = this.previousIndex();
|
||||
|
||||
if (last == -1) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
T prev = HashedReferenceList.this.get(last);
|
||||
|
||||
if (prev != null) {
|
||||
HashedReferenceList.this.trackReferenceRemoved(prev);
|
||||
}
|
||||
|
||||
this.inner.remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void set(T t) {
|
||||
int last = this.previousIndex();
|
||||
|
||||
if (last == -1) {
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
T prev = HashedReferenceList.this.get(last);
|
||||
|
||||
if (prev != t) {
|
||||
if (prev != null) {
|
||||
HashedReferenceList.this.trackReferenceRemoved(prev);
|
||||
}
|
||||
|
||||
HashedReferenceList.this.trackReferenceAdded(t);
|
||||
}
|
||||
|
||||
this.inner.remove();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(T t) {
|
||||
HashedReferenceList.this.trackReferenceAdded(t);
|
||||
|
||||
this.inner.add(t);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<T> subList(int fromIndex, int toIndex) {
|
||||
return this.list.subList(fromIndex, toIndex);
|
||||
}
|
||||
|
||||
private void trackReferenceAdded(T t) {
|
||||
this.counter.addTo(t, 1);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void trackReferenceRemoved(Object o) {
|
||||
if (this.counter.addTo((T) o, -1) <= 1) {
|
||||
this.counter.removeInt(o);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user