Implement 0068-lithium-cache-iterate-outwards.patch

This commit is contained in:
DoggySazHi
2024-03-17 17:01:53 -07:00
parent f1d046fb3e
commit fec835b935
6 changed files with 205 additions and 3 deletions

View File

@@ -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

View File

@@ -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;
}
}

View File

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

View File

@@ -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();
}
}
}

View File

@@ -1,6 +1,6 @@
{
"id": "Nitori",
"version": "1.0.5",
"version": "1.0.6",
"mixins": [
"mixins.core.json"
]

View File

@@ -19,6 +19,7 @@
"MixinEntity",
"MixinMob",
"MixinWorldGenRegion",
"MixinNoiseBasedChunkGenerator"
"MixinNoiseBasedChunkGenerator",
"MixinBlockPos"
]
}