Add some patches
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Etil <81570777+etil2jz@users.noreply.github.com>
|
||||
Date: Thu, 2 Dec 2021 16:22:24 +0100
|
||||
Subject: [PATCH] Avoid double I/O operation on load player file
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java
|
||||
index 35c39aed9583275ef25d32c783715798b52bdb63..331ed6aa983714d6fc3596526fc7df0ab993062c 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/storage/PlayerDataStorage.java
|
||||
@@ -56,7 +56,8 @@ public class PlayerDataStorage {
|
||||
File file = new File(this.playerDir, player.getStringUUID() + ".dat");
|
||||
// Spigot Start
|
||||
boolean usingWrongFile = false;
|
||||
- if ( org.bukkit.Bukkit.getOnlineMode() && !file.exists() ) // Paper - Check online mode first
|
||||
+ boolean normalFile = file.exists() && file.isFile(); // Akarin - ensures normal file
|
||||
+ if ( org.bukkit.Bukkit.getOnlineMode() && !normalFile ) // Paper - Check online mode first // Akarin - ensures normal file
|
||||
{
|
||||
file = new File( this.playerDir, java.util.UUID.nameUUIDFromBytes( ( "OfflinePlayer:" + player.getScoreboardName() ).getBytes( "UTF-8" ) ).toString() + ".dat");
|
||||
if ( file.exists() )
|
||||
@@ -67,7 +68,7 @@ public class PlayerDataStorage {
|
||||
}
|
||||
// Spigot End
|
||||
|
||||
- if (file.exists() && file.isFile()) {
|
||||
+ if (normalFile) { // Akarin - avoid double I/O operation
|
||||
nbttagcompound = NbtIo.readCompressed(file);
|
||||
}
|
||||
// Spigot Start
|
||||
@@ -0,0 +1,73 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Etil <81570777+etil2jz@users.noreply.github.com>
|
||||
Date: Thu, 2 Dec 2021 16:25:37 +0100
|
||||
Subject: [PATCH] Swaps the predicate order of collision
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
index 401a20fb67e232d1e33b8d9167ba2ba609f4dba9..2e28df553c10e8a1174aed97a378358575b0d3fa 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/Entity.java
|
||||
@@ -1763,37 +1763,35 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource, i
|
||||
public void playerTouch(Player player) {}
|
||||
|
||||
public void push(Entity entity) {
|
||||
- if (!this.isPassengerOfSameVehicle(entity)) {
|
||||
- if (!entity.noPhysics && !this.noPhysics) {
|
||||
- if (this.level.paperConfig.onlyPlayersCollide && !(entity instanceof ServerPlayer || this instanceof ServerPlayer)) return; // Paper
|
||||
- double d0 = entity.getX() - this.getX();
|
||||
- double d1 = entity.getZ() - this.getZ();
|
||||
- double d2 = Mth.absMax(d0, d1);
|
||||
-
|
||||
- if (d2 >= 0.009999999776482582D) {
|
||||
- d2 = Math.sqrt(d2);
|
||||
- d0 /= d2;
|
||||
- d1 /= d2;
|
||||
- double d3 = 1.0D / d2;
|
||||
-
|
||||
- if (d3 > 1.0D) {
|
||||
- d3 = 1.0D;
|
||||
- }
|
||||
-
|
||||
- d0 *= d3;
|
||||
- d1 *= d3;
|
||||
- d0 *= 0.05000000074505806D;
|
||||
- d1 *= 0.05000000074505806D;
|
||||
- if (!this.isVehicle()) {
|
||||
- this.push(-d0, 0.0D, -d1);
|
||||
- }
|
||||
+ if (!entity.noPhysics && !this.noPhysics && !this.isPassengerOfSameVehicle(entity)) { // Akarin - Swap the predicate order of collision
|
||||
+ if (this.level.paperConfig.onlyPlayersCollide && !(entity instanceof ServerPlayer || this instanceof ServerPlayer)) return; // Paper
|
||||
+ double d0 = entity.getX() - this.getX();
|
||||
+ double d1 = entity.getZ() - this.getZ();
|
||||
+ double d2 = Mth.absMax(d0, d1);
|
||||
+
|
||||
+ if (d2 >= 0.009999999776482582D) {
|
||||
+ d2 = Math.sqrt(d2);
|
||||
+ d0 /= d2;
|
||||
+ d1 /= d2;
|
||||
+ double d3 = 1.0D / d2;
|
||||
+
|
||||
+ if (d3 > 1.0D) {
|
||||
+ d3 = 1.0D;
|
||||
+ }
|
||||
|
||||
- if (!entity.isVehicle()) {
|
||||
- entity.push(d0, 0.0D, d1);
|
||||
- }
|
||||
+ d0 *= d3;
|
||||
+ d1 *= d3;
|
||||
+ d0 *= 0.05000000074505806D;
|
||||
+ d1 *= 0.05000000074505806D;
|
||||
+ if (!this.isVehicle()) {
|
||||
+ this.push(-d0, 0.0D, -d1);
|
||||
}
|
||||
|
||||
+ if (!entity.isVehicle()) {
|
||||
+ entity.push(d0, 0.0D, d1);
|
||||
+ }
|
||||
}
|
||||
+
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Etil <81570777+etil2jz@users.noreply.github.com>
|
||||
Date: Thu, 2 Dec 2021 16:28:51 +0100
|
||||
Subject: [PATCH] Don't trigger Lootable Refresh for non player interaction
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
|
||||
index da00f75ccc9f8c2e2174d4450479202a50844245..9168e4981692e20def127deec9cbf21767588507 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/entity/RandomizableContainerBlockEntity.java
|
||||
@@ -69,6 +69,7 @@ public abstract class RandomizableContainerBlockEntity extends BaseContainerBloc
|
||||
}
|
||||
|
||||
public void unpackLootTable(@Nullable Player player) {
|
||||
+ if (player == null) return; // Akarin - Don't trigger Lootable Refresh for non player interaction
|
||||
if (this.lootableData.shouldReplenish(player) && this.level.getServer() != null) { // Paper
|
||||
LootTable lootTable = this.level.getServer().getLootTables().get(this.lootTable);
|
||||
if (player instanceof ServerPlayer) {
|
||||
119
patches/server/0006-lithium-reduce-allocs.patch
Normal file
119
patches/server/0006-lithium-reduce-allocs.patch
Normal file
@@ -0,0 +1,119 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Etil <81570777+etil2jz@users.noreply.github.com>
|
||||
Date: Thu, 2 Dec 2021 16:55:37 +0100
|
||||
Subject: [PATCH] lithium: reduce allocs
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/jellysquid/mods/lithium/common/util/ArrayConstants.java b/src/main/java/me/jellysquid/mods/lithium/common/util/ArrayConstants.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..d341fcb89c8744aa1bd8cb3ef6af93e7d585c0b7
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/me/jellysquid/mods/lithium/common/util/ArrayConstants.java
|
||||
@@ -0,0 +1,6 @@
|
||||
+package me.jellysquid.mods.lithium.common.util;
|
||||
+
|
||||
+public class ArrayConstants {
|
||||
+ public static final int[] EMPTY = new int[0];
|
||||
+ public static final int[] ZERO = new int[]{0};
|
||||
+}
|
||||
\ No newline at end of file
|
||||
diff --git a/src/main/java/net/minecraft/world/entity/LivingEntity.java b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
index 0c9169423f9093594ea6d242ed5492ffc22c241f..489d60f34af09b2b7fe8d0cc0cc3fc820886d3a6 100644
|
||||
--- a/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
+++ b/src/main/java/net/minecraft/world/entity/LivingEntity.java
|
||||
@@ -3005,10 +3005,12 @@ public abstract class LivingEntity extends Entity {
|
||||
|
||||
}
|
||||
|
||||
+ private static final EquipmentSlot[] SLOTS = EquipmentSlot.values(); // Lithium
|
||||
+
|
||||
@Nullable
|
||||
private Map<EquipmentSlot, ItemStack> collectEquipmentChanges() {
|
||||
Map<EquipmentSlot, ItemStack> map = null;
|
||||
- EquipmentSlot[] aenumitemslot = EquipmentSlot.values();
|
||||
+ EquipmentSlot[] aenumitemslot = SLOTS; // Lithium
|
||||
int i = aenumitemslot.length;
|
||||
|
||||
for (int j = 0; j < i; ++j) {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/EntityBasedExplosionDamageCalculator.java b/src/main/java/net/minecraft/world/level/EntityBasedExplosionDamageCalculator.java
|
||||
index 2f9f15d99f8b31e9f13f7f32378b2a9e09bcb5e5..bea593c31b59920c2c4cb86c2dd116435578afeb 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/EntityBasedExplosionDamageCalculator.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/EntityBasedExplosionDamageCalculator.java
|
||||
@@ -15,10 +15,19 @@ public class EntityBasedExplosionDamageCalculator extends ExplosionDamageCalcula
|
||||
|
||||
@Override
|
||||
public Optional<Float> getBlockExplosionResistance(Explosion explosion, BlockGetter world, BlockPos pos, BlockState blockState, FluidState fluidState) {
|
||||
- return super.getBlockExplosionResistance(explosion, world, pos, blockState, fluidState).map((max) -> {
|
||||
- return this.source.getBlockExplosionResistance(explosion, world, pos, blockState, fluidState, max);
|
||||
- });
|
||||
+ // Lithium start
|
||||
+ Optional<Float> optionalBlastResistance = super.getBlockExplosionResistance(explosion, world, pos, blockState, fluidState);
|
||||
+ if (optionalBlastResistance.isPresent()) {
|
||||
+ float blastResistance = optionalBlastResistance.get();
|
||||
+ float effectiveExplosionResistance = this.source.getBlockExplosionResistance(explosion, world, pos, blockState, fluidState, blastResistance);
|
||||
+ if (effectiveExplosionResistance != blastResistance) {
|
||||
+ return Optional.of(effectiveExplosionResistance);
|
||||
+ }
|
||||
+ }
|
||||
+ return optionalBlastResistance;
|
||||
+ // Lithium end
|
||||
}
|
||||
+
|
||||
|
||||
@Override
|
||||
public boolean shouldBlockExplode(Explosion explosion, BlockGetter world, BlockPos pos, BlockState state, float power) {
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/ComposterBlock.java b/src/main/java/net/minecraft/world/level/block/ComposterBlock.java
|
||||
index fb8b8a9733ac50096d8406487ab1ae167ef5f7b1..58ea7ce6093aaa6793d198332e60ceaaaa138b36 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/ComposterBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/ComposterBlock.java
|
||||
@@ -41,6 +41,7 @@ import net.minecraft.world.entity.player.Player;
|
||||
import org.bukkit.craftbukkit.inventory.CraftBlockInventoryHolder;
|
||||
import org.bukkit.craftbukkit.util.DummyGeneratorAccess;
|
||||
// CraftBukkit end
|
||||
+import me.jellysquid.mods.lithium.common.util.ArrayConstants; // Lithium
|
||||
|
||||
public class ComposterBlock extends Block implements WorldlyContainerHolder {
|
||||
|
||||
@@ -373,7 +374,7 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder {
|
||||
|
||||
@Override
|
||||
public int[] getSlotsForFace(Direction side) {
|
||||
- return side == Direction.DOWN ? new int[]{0} : new int[0];
|
||||
+ return side == Direction.DOWN ? ArrayConstants.ZERO : ArrayConstants.EMPTY; // Lithium
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -422,7 +423,7 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder {
|
||||
|
||||
@Override
|
||||
public int[] getSlotsForFace(Direction side) {
|
||||
- return side == Direction.UP ? new int[]{0} : new int[0];
|
||||
+ return side == Direction.UP ? ArrayConstants.ZERO : ArrayConstants.EMPTY; // Lithium
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -459,7 +460,7 @@ public class ComposterBlock extends Block implements WorldlyContainerHolder {
|
||||
|
||||
@Override
|
||||
public int[] getSlotsForFace(Direction side) {
|
||||
- return new int[0];
|
||||
+ return ArrayConstants.EMPTY; // Lithium
|
||||
}
|
||||
|
||||
@Override
|
||||
diff --git a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java
|
||||
index 28256f1f0aeb7718a5866add4ec40ce0198c36b9..eb01e28c23eb25e25382dfb4658c294cc3694dc4 100644
|
||||
--- a/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java
|
||||
+++ b/src/main/java/net/minecraft/world/level/block/piston/PistonBaseBlock.java
|
||||
@@ -162,8 +162,10 @@ public class PistonBaseBlock extends DirectionalBlock {
|
||||
|
||||
}
|
||||
|
||||
+ private static final Direction[] DIRECTIONS = Direction.values(); // Lithium
|
||||
+
|
||||
private boolean getNeighborSignal(Level world, BlockPos pos, Direction pistonFace) {
|
||||
- Direction[] aenumdirection = Direction.values();
|
||||
+ Direction[] aenumdirection = DIRECTIONS; // Lithium
|
||||
int i = aenumdirection.length;
|
||||
|
||||
int j;
|
||||
40
patches/server/0007-lithium-MixinDirection.patch
Normal file
40
patches/server/0007-lithium-MixinDirection.patch
Normal file
@@ -0,0 +1,40 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Etil <81570777+etil2jz@users.noreply.github.com>
|
||||
Date: Thu, 2 Dec 2021 17:00:23 +0100
|
||||
Subject: [PATCH] lithium: MixinDirection
|
||||
|
||||
|
||||
diff --git a/src/main/java/net/minecraft/core/Direction.java b/src/main/java/net/minecraft/core/Direction.java
|
||||
index 6d883db5c04cbcf454952c0f361029ecbfe4f037..53d853a4e9d8e3de4747a75f08f42545b048bbbb 100644
|
||||
--- a/src/main/java/net/minecraft/core/Direction.java
|
||||
+++ b/src/main/java/net/minecraft/core/Direction.java
|
||||
@@ -190,8 +190,13 @@ public enum Direction implements StringRepresentable {
|
||||
return var10000;
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ @reason Avoid the modulo/abs operations
|
||||
+ @author JellySquid
|
||||
+ */
|
||||
+
|
||||
public Direction getOpposite() {
|
||||
- return from3DDataValue(this.oppositeIndex);
|
||||
+ return VALUES[this.oppositeIndex];
|
||||
}
|
||||
|
||||
public Direction getClockWise(Direction.Axis axis) {
|
||||
@@ -440,8 +445,13 @@ public enum Direction implements StringRepresentable {
|
||||
return (float)((this.data2d & 3) * 90);
|
||||
}
|
||||
|
||||
+ /*
|
||||
+ @reason Do not allocate an excessive number of Direction arrays
|
||||
+ @author JellySquid
|
||||
+ */
|
||||
+
|
||||
public static Direction getRandom(Random random) {
|
||||
- return Util.getRandom(VALUES, random);
|
||||
+ return VALUES[random.nextInt(VALUES.length)];
|
||||
}
|
||||
|
||||
public static Direction getNearest(double x, double y, double z) {
|
||||
293
patches/server/0008-lithium-HashedList.patch
Normal file
293
patches/server/0008-lithium-HashedList.patch
Normal file
@@ -0,0 +1,293 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Etil <81570777+etil2jz@users.noreply.github.com>
|
||||
Date: Thu, 2 Dec 2021 17:09:27 +0100
|
||||
Subject: [PATCH] lithium: HashedList
|
||||
|
||||
|
||||
diff --git a/src/main/java/me/jellysquid/mods/lithium/common/util/collections/HashedList.java b/src/main/java/me/jellysquid/mods/lithium/common/util/collections/HashedList.java
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..c3f55b58607d5060bc8513e359c5f00bfb8bf428
|
||||
--- /dev/null
|
||||
+++ b/src/main/java/me/jellysquid/mods/lithium/common/util/collections/HashedList.java
|
||||
@@ -0,0 +1,280 @@
|
||||
+package me.jellysquid.mods.lithium.common.util.collections;
|
||||
+
|
||||
+import it.unimi.dsi.fastutil.objects.Reference2IntOpenHashMap;
|
||||
+import it.unimi.dsi.fastutil.objects.ReferenceArrayList;
|
||||
+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 HashedList<T> implements List<T> {
|
||||
+ private final ReferenceArrayList<T> list;
|
||||
+ private final Reference2IntOpenHashMap<T> counter;
|
||||
+
|
||||
+ public HashedList(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();
|
||||
+ }
|
||||
+
|
||||
+ @SuppressWarnings("SuspiciousToArrayCall")
|
||||
+ @Override
|
||||
+ public <T1> T1[] toArray(T1[] 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(Collection<?> c) {
|
||||
+ for (Object obj : c) {
|
||||
+ this.trackReferenceRemoved(obj);
|
||||
+ }
|
||||
+
|
||||
+ return this.list.removeAll(c);
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public boolean retainAll(Collection<?> 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<T>() {
|
||||
+ private final ListIterator<T> inner = HashedList.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 = HashedList.this.get(last);
|
||||
+
|
||||
+ if (prev != null) {
|
||||
+ HashedList.this.trackReferenceRemoved(prev);
|
||||
+ }
|
||||
+
|
||||
+ this.inner.remove();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void set(T t) {
|
||||
+ int last = this.previousIndex();
|
||||
+
|
||||
+ if (last == -1) {
|
||||
+ throw new NoSuchElementException();
|
||||
+ }
|
||||
+
|
||||
+ T prev = HashedList.this.get(last);
|
||||
+
|
||||
+ if (prev != t) {
|
||||
+ if (prev != null) {
|
||||
+ HashedList.this.trackReferenceRemoved(prev);
|
||||
+ }
|
||||
+
|
||||
+ HashedList.this.trackReferenceAdded(t);
|
||||
+ }
|
||||
+
|
||||
+ this.inner.remove();
|
||||
+ }
|
||||
+
|
||||
+ @Override
|
||||
+ public void add(T t) {
|
||||
+ HashedList.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);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ public static <T> HashedList<T> wrapper(List<T> list) {
|
||||
+ return new HashedList<>(list);
|
||||
+ }
|
||||
+}
|
||||
\ No newline at end of file
|
||||
Reference in New Issue
Block a user