Skip to content

Commit

Permalink
implement 0006-lithium-HashedReferenceList.patch
Browse files Browse the repository at this point in the history
  • Loading branch information
DoggySazHi committed Feb 29, 2024
1 parent 87cf1c7 commit 85303f6
Show file tree
Hide file tree
Showing 6 changed files with 353 additions and 4 deletions.
2 changes: 1 addition & 1 deletion gradle.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
group=net.gensokyoreimagined.nitori
version=1.0.0-SNAPSHOT
version=1.0.1
description=Converting patches into mixins, for the Ignite Framework

org.gradle.parallel=true
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ metadata.format.version = "1.1"
[versions]

jetbrains = "24.1.0"
ignite = "1.0.0"
ignite = "1.0.1"
mixin = "0.8.5"
mixinExtras = "0.3.5"
paperweight = "1.5.11"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,299 @@
// Nitori Copyright (C) 2024 Gensokyo Reimagined
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package net.gensokyoreimagined.nitori.common.util.collections;

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.*;

/*
* Originally from CaffeineMC, licensed under GNU Lesser General Public License v3.0
* See https://github.com/CaffeineMC/lithium-fabric for more information/sources
*/

/**
* 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 @NotNull Iterator<T> iterator() {
return this.listIterator();
}

@Override
public Object @NotNull [] toArray() {
return this.list.toArray();
}

@Override
public <T1> T1 @NotNull [] 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 @NotNull ListIterator<T> listIterator() {
return this.listIterator(0);
}

@Override
public @NotNull 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 @NotNull 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);
}
}

public static <T> HashedReferenceList<T> wrapper(List<T> list) {
return new HashedReferenceList<>(list);
}
}
49 changes: 49 additions & 0 deletions src/main/java/net/gensokyoreimagined/nitori/core/MixinLevel.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Nitori Copyright (C) 2024 Gensokyo Reimagined
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <https://www.gnu.org/licenses/>.
package net.gensokyoreimagined.nitori.core;

import com.google.common.collect.Lists;
import net.gensokyoreimagined.nitori.common.util.collections.HashedReferenceList;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.entity.TickingBlockEntity;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Mutable;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;

import java.util.List;

@Mixin(Level.class)
public class MixinLevel {
// Implementation of 0006-lithium-HashedReferenceList.patch
@Mutable
@Final @Shadow
public List<TickingBlockEntity> blockEntityTickers;

// Implementation of 0006-lithium-HashedReferenceList.patch
@Mutable
@Final @Shadow
private List<TickingBlockEntity> pendingBlockEntityTickers;

// Implementation of 0006-lithium-HashedReferenceList.patch
@Inject(method = "<init>", at = @At("RETURN"))
private void onInit(CallbackInfo ci) {
this.blockEntityTickers = new HashedReferenceList<>(Lists.newArrayList());
this.pendingBlockEntityTickers = new HashedReferenceList<>(Lists.newArrayList());
}
}
2 changes: 1 addition & 1 deletion src/main/resources/ignite.mod.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"id": "Nitori",
"version": "1.0.0",
"version": "1.0.1",
"mixins": [
"mixins.core.json"
]
Expand Down
3 changes: 2 additions & 1 deletion src/main/resources/mixins.core.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
"ChunkMapMixin",
"MixinSpongeSIMD",
"MixinAABB",
"MixinDirection"
"MixinDirection",
"MixinLevel"
]
}

0 comments on commit 85303f6

Please sign in to comment.