From 09e891c0506959f11d383b41c0155ea3fa9c3de0 Mon Sep 17 00:00:00 2001 From: Etil <81570777+etil2jz@users.noreply.github.com> Date: Thu, 2 Dec 2021 17:26:04 +0100 Subject: [PATCH] Add some patches --- ...le-I-O-operation-on-load-player-file.patch | 29 ++ ...aps-the-predicate-order-of-collision.patch | 73 +++++ ...otable-Refresh-for-non-player-intera.patch | 18 ++ .../server/0006-lithium-reduce-allocs.patch | 119 +++++++ .../server/0007-lithium-MixinDirection.patch | 40 +++ patches/server/0008-lithium-HashedList.patch | 293 ++++++++++++++++++ 6 files changed, 572 insertions(+) create mode 100644 patches/server/0003-Avoid-double-I-O-operation-on-load-player-file.patch create mode 100644 patches/server/0004-Swaps-the-predicate-order-of-collision.patch create mode 100644 patches/server/0005-Don-t-trigger-Lootable-Refresh-for-non-player-intera.patch create mode 100644 patches/server/0006-lithium-reduce-allocs.patch create mode 100644 patches/server/0007-lithium-MixinDirection.patch create mode 100644 patches/server/0008-lithium-HashedList.patch diff --git a/patches/server/0003-Avoid-double-I-O-operation-on-load-player-file.patch b/patches/server/0003-Avoid-double-I-O-operation-on-load-player-file.patch new file mode 100644 index 0000000..d50c1e2 --- /dev/null +++ b/patches/server/0003-Avoid-double-I-O-operation-on-load-player-file.patch @@ -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 diff --git a/patches/server/0004-Swaps-the-predicate-order-of-collision.patch b/patches/server/0004-Swaps-the-predicate-order-of-collision.patch new file mode 100644 index 0000000..09d811e --- /dev/null +++ b/patches/server/0004-Swaps-the-predicate-order-of-collision.patch @@ -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); ++ } + } ++ + } + } + diff --git a/patches/server/0005-Don-t-trigger-Lootable-Refresh-for-non-player-intera.patch b/patches/server/0005-Don-t-trigger-Lootable-Refresh-for-non-player-intera.patch new file mode 100644 index 0000000..dcc2554 --- /dev/null +++ b/patches/server/0005-Don-t-trigger-Lootable-Refresh-for-non-player-intera.patch @@ -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) { diff --git a/patches/server/0006-lithium-reduce-allocs.patch b/patches/server/0006-lithium-reduce-allocs.patch new file mode 100644 index 0000000..d9d3f9c --- /dev/null +++ b/patches/server/0006-lithium-reduce-allocs.patch @@ -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 collectEquipmentChanges() { + Map 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 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 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; diff --git a/patches/server/0007-lithium-MixinDirection.patch b/patches/server/0007-lithium-MixinDirection.patch new file mode 100644 index 0000000..47c74d8 --- /dev/null +++ b/patches/server/0007-lithium-MixinDirection.patch @@ -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) { diff --git a/patches/server/0008-lithium-HashedList.patch b/patches/server/0008-lithium-HashedList.patch new file mode 100644 index 0000000..89ceb23 --- /dev/null +++ b/patches/server/0008-lithium-HashedList.patch @@ -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 implements List { ++ private final ReferenceArrayList list; ++ private final Reference2IntOpenHashMap counter; ++ ++ public HashedList(List 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 iterator() { ++ return this.listIterator(); ++ } ++ ++ @Override ++ public Object[] toArray() { ++ return this.list.toArray(); ++ } ++ ++ @SuppressWarnings("SuspiciousToArrayCall") ++ @Override ++ public 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 c) { ++ for (T obj : c) { ++ this.trackReferenceAdded(obj); ++ } ++ ++ return this.list.addAll(c); ++ } ++ ++ @Override ++ public boolean addAll(int index, Collection 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 listIterator() { ++ return this.listIterator(0); ++ } ++ ++ @Override ++ public ListIterator listIterator(int index) { ++ return new ListIterator() { ++ private final ListIterator 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 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 HashedList wrapper(List list) { ++ return new HashedList<>(list); ++ } ++} +\ No newline at end of file