Implement 0068-lithium-cache-iterate-outwards.patch
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
group=net.gensokyoreimagined.nitori
|
||||
version=1.0.5-SNAPSHOT
|
||||
version=1.0.6-SNAPSHOT
|
||||
description=Converting patches into mixins, for the Ignite Framework
|
||||
|
||||
org.gradle.parallel=true
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
// 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.cached_blockpos_iteration;
|
||||
|
||||
/*
|
||||
* Originally from CaffeineMC, licensed under GNU Lesser General Public License v3.0
|
||||
* See https://github.com/CaffeineMC/lithium-fabric for more information/sources
|
||||
*/
|
||||
|
||||
import it.unimi.dsi.fastutil.longs.LongArrayList;
|
||||
import it.unimi.dsi.fastutil.longs.LongList;
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Random;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @author 2No2Name, original implemenation by SuperCoder7979 and Gegy1000
|
||||
*/
|
||||
public class IterateOutwardsCache {
|
||||
//POS_ZERO must not be replaced with BlockPos.ORIGIN, otherwise iterateOutwards at BlockPos.ORIGIN will not use the cache
|
||||
public static final BlockPos POS_ZERO = new BlockPos(0,0,0);
|
||||
|
||||
|
||||
private final ConcurrentHashMap<Long, LongArrayList> table;
|
||||
private final int capacity;
|
||||
private final Random random;
|
||||
|
||||
public IterateOutwardsCache(int capacity) {
|
||||
this.capacity = capacity;
|
||||
this.table = new ConcurrentHashMap<>(31);
|
||||
this.random = new Random();
|
||||
}
|
||||
|
||||
private void fillPositionsWithIterateOutwards(LongList entry, int xRange, int yRange, int zRange) {
|
||||
// Add all positions to the cached list
|
||||
for (BlockPos pos : BlockPos.withinManhattan(POS_ZERO, xRange, yRange, zRange)) {
|
||||
entry.add(pos.asLong());
|
||||
}
|
||||
}
|
||||
|
||||
public LongList getOrCompute(int xRange, int yRange, int zRange) {
|
||||
long key = BlockPos.asLong(xRange, yRange, zRange);
|
||||
|
||||
LongArrayList entry = this.table.get(key);
|
||||
if (entry != null) {
|
||||
return entry;
|
||||
}
|
||||
|
||||
// Cache miss: compute and store
|
||||
entry = new LongArrayList(128);
|
||||
|
||||
this.fillPositionsWithIterateOutwards(entry, xRange, yRange, zRange);
|
||||
|
||||
//decrease the array size, as of now it won't be modified anymore anyways
|
||||
entry.trim();
|
||||
|
||||
//this might overwrite an entry as the same entry could have been computed and added during this thread's computation
|
||||
//we do not use computeIfAbsent, as it can delay other threads for too long
|
||||
Object previousEntry = this.table.put(key, entry);
|
||||
|
||||
|
||||
if (previousEntry == null && this.table.size() > this.capacity) {
|
||||
//prevent a memory leak by randomly removing about 1/8th of the elements when the exceed the desired capacity is exceeded
|
||||
final Iterator<Long> iterator = this.table.keySet().iterator();
|
||||
//prevent an unlikely infinite loop caused by another thread filling the table concurrently using counting
|
||||
for (int i = -this.capacity; iterator.hasNext() && i < 5; i++) {
|
||||
Long key2 = iterator.next();
|
||||
//random is not threadsafe, but it doesn't matter here, because we don't need quality random numbers
|
||||
if (this.random.nextInt(8) == 0 && key2 != key) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
// 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.cached_blockpos_iteration;
|
||||
|
||||
/*
|
||||
* Originally from CaffeineMC, licensed under GNU Lesser General Public License v3.0
|
||||
* See https://github.com/CaffeineMC/lithium-fabric for more information/sources
|
||||
*/
|
||||
|
||||
import it.unimi.dsi.fastutil.longs.LongIterator;
|
||||
import it.unimi.dsi.fastutil.longs.LongList;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* @author 2No2Name
|
||||
*/
|
||||
public class LongList2BlockPosMutableIterable implements Iterable<BlockPos> {
|
||||
|
||||
private final LongList positions;
|
||||
private final int xOffset, yOffset, zOffset;
|
||||
|
||||
public LongList2BlockPosMutableIterable(BlockPos offset, LongList posList) {
|
||||
this.xOffset = offset.getX();
|
||||
this.yOffset = offset.getY();
|
||||
this.zOffset = offset.getZ();
|
||||
this.positions = posList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public @NotNull Iterator<BlockPos> iterator() {
|
||||
return new Iterator<>() {
|
||||
|
||||
private final LongIterator it = LongList2BlockPosMutableIterable.this.positions.iterator();
|
||||
private final BlockPos.MutableBlockPos pos = new BlockPos.MutableBlockPos();
|
||||
|
||||
@Override
|
||||
public boolean hasNext() {
|
||||
return it.hasNext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public net.minecraft.core.BlockPos next() {
|
||||
long nextPos = this.it.nextLong();
|
||||
return this.pos.set(
|
||||
LongList2BlockPosMutableIterable.this.xOffset + BlockPos.getX(nextPos),
|
||||
LongList2BlockPosMutableIterable.this.yOffset + BlockPos.getY(nextPos),
|
||||
LongList2BlockPosMutableIterable.this.zOffset + BlockPos.getZ(nextPos));
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
// 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 it.unimi.dsi.fastutil.longs.LongList;
|
||||
import net.gensokyoreimagined.nitori.cached_blockpos_iteration.IterateOutwardsCache;
|
||||
import net.gensokyoreimagined.nitori.cached_blockpos_iteration.LongList2BlockPosMutableIterable;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import static net.gensokyoreimagined.nitori.cached_blockpos_iteration.IterateOutwardsCache.POS_ZERO;
|
||||
|
||||
@Mixin(BlockPos.class)
|
||||
public class MixinBlockPos {
|
||||
// Implementation of 0068-lithium-cache-iterate-outwards.patch
|
||||
private static final IterateOutwardsCache ITERATE_OUTWARDS_CACHE = new IterateOutwardsCache(50);
|
||||
// Implementation of 0068-lithium-cache-iterate-outwards.patch
|
||||
private static final LongList HOGLIN_PIGLIN_CACHE = ITERATE_OUTWARDS_CACHE.getOrCompute(8, 4, 8);
|
||||
|
||||
// Implementation of 0068-lithium-cache-iterate-outwards.patch
|
||||
@Inject(method = "withinManhattan", at = @At("HEAD"), cancellable = true)
|
||||
private static void withinManhattan(BlockPos center, int rangeX, int rangeY, int rangeZ, CallbackInfoReturnable<Iterable<BlockPos>> cir) {
|
||||
if (center != POS_ZERO) {
|
||||
final LongList positions = rangeX == 8 && rangeY == 4 && rangeZ == 8 ? HOGLIN_PIGLIN_CACHE : ITERATE_OUTWARDS_CACHE.getOrCompute(rangeX, rangeY, rangeZ);
|
||||
cir.setReturnValue(new LongList2BlockPosMutableIterable(center, positions));
|
||||
cir.cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"id": "Nitori",
|
||||
"version": "1.0.5",
|
||||
"version": "1.0.6",
|
||||
"mixins": [
|
||||
"mixins.core.json"
|
||||
]
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
"MixinEntity",
|
||||
"MixinMob",
|
||||
"MixinWorldGenRegion",
|
||||
"MixinNoiseBasedChunkGenerator"
|
||||
"MixinNoiseBasedChunkGenerator",
|
||||
"MixinBlockPos"
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user