mirror of
https://github.com/BX-Team/DivineMC.git
synced 2025-12-19 14:59:25 +00:00
Optimize Aquifer and Beardifier
This commit is contained in:
@@ -36,6 +36,9 @@ public net.minecraft.world.level.levelgen.NoiseChunk$BlendOffset
|
|||||||
public net.minecraft.world.level.levelgen.NoiseRouterData$QuantizedSpaghettiRarity
|
public net.minecraft.world.level.levelgen.NoiseRouterData$QuantizedSpaghettiRarity
|
||||||
public net.minecraft.world.level.levelgen.NoiseRouterData$QuantizedSpaghettiRarity getSpaghettiRarity3D(D)D
|
public net.minecraft.world.level.levelgen.NoiseRouterData$QuantizedSpaghettiRarity getSpaghettiRarity3D(D)D
|
||||||
public net.minecraft.world.level.levelgen.NoiseRouterData$QuantizedSpaghettiRarity getSphaghettiRarity2D(D)D
|
public net.minecraft.world.level.levelgen.NoiseRouterData$QuantizedSpaghettiRarity getSphaghettiRarity2D(D)D
|
||||||
|
public net.minecraft.world.level.levelgen.Xoroshiro128PlusPlus seedHi
|
||||||
|
public net.minecraft.world.level.levelgen.Xoroshiro128PlusPlus seedLo
|
||||||
|
public net.minecraft.world.level.levelgen.XoroshiroRandomSource randomNumberGenerator
|
||||||
public net.minecraft.world.level.levelgen.structure.pools.StructureTemplatePool rawTemplates
|
public net.minecraft.world.level.levelgen.structure.pools.StructureTemplatePool rawTemplates
|
||||||
public net.minecraft.world.level.pathfinder.SwimNodeEvaluator allowBreaching
|
public net.minecraft.world.level.pathfinder.SwimNodeEvaluator allowBreaching
|
||||||
public-f ca.spottedleaf.moonrise.paper.PaperHooks
|
public-f ca.spottedleaf.moonrise.paper.PaperHooks
|
||||||
|
|||||||
@@ -0,0 +1,705 @@
|
|||||||
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||||
|
From: NONPLAYT <76615486+NONPLAYT@users.noreply.github.com>
|
||||||
|
Date: Thu, 10 Jul 2025 03:48:14 +0300
|
||||||
|
Subject: [PATCH] C2ME: Optimize Aquifer and Beardifier
|
||||||
|
|
||||||
|
This patch is based on the following mixins:
|
||||||
|
* "com/ishland/c2me/opts/worldgen/vanilla/mixin/aquifer/MixinAquiferSamplerImpl.java"
|
||||||
|
* "com/ishland/c2me/opts/worldgen/general/common/random_instances/RandomUtils.java"
|
||||||
|
By: ishland <ishlandmc@yeah.net>
|
||||||
|
As part of: C2ME (https://github.com/RelativityMC/C2ME-fabric)
|
||||||
|
Licensed under: MIT (https://opensource.org/licenses/MIT)
|
||||||
|
|
||||||
|
diff --git a/net/minecraft/world/level/levelgen/Aquifer.java b/net/minecraft/world/level/levelgen/Aquifer.java
|
||||||
|
index c62a15ea4a1bb22e7bcc2fc544acf8a601892029..2efa0b8bb7189d768cb43e55376b397f4f806374 100644
|
||||||
|
--- a/net/minecraft/world/level/levelgen/Aquifer.java
|
||||||
|
+++ b/net/minecraft/world/level/levelgen/Aquifer.java
|
||||||
|
@@ -85,6 +85,15 @@ public interface Aquifer {
|
||||||
|
private final int minGridZ;
|
||||||
|
private final int gridSizeX;
|
||||||
|
private final int gridSizeZ;
|
||||||
|
+ // DivineMC start - C2ME: Optimize Aquifer
|
||||||
|
+ private int c2me$dist1;
|
||||||
|
+ private int c2me$dist2;
|
||||||
|
+ private int c2me$dist3;
|
||||||
|
+ private long c2me$pos1;
|
||||||
|
+ private long c2me$pos2;
|
||||||
|
+ private long c2me$pos3;
|
||||||
|
+ private double c2me$mutableDoubleThingy;
|
||||||
|
+ // DivineMC end - C2ME: Optimize Aquifer
|
||||||
|
private static final int[][] SURFACE_SAMPLING_OFFSETS_IN_CHUNKS = new int[][]{
|
||||||
|
{0, 0}, {-2, -1}, {-1, -1}, {0, -1}, {1, -1}, {-3, 0}, {-2, 0}, {-1, 0}, {1, 0}, {-2, 1}, {-1, 1}, {0, 1}, {1, 1}
|
||||||
|
};
|
||||||
|
@@ -120,6 +129,36 @@ public interface Aquifer {
|
||||||
|
this.aquiferCache = new Aquifer.FluidStatus[i4];
|
||||||
|
this.aquiferLocationCache = new long[i4];
|
||||||
|
Arrays.fill(this.aquiferLocationCache, Long.MAX_VALUE);
|
||||||
|
+ // DivineMC start - C2ME: Optimize Aquifer
|
||||||
|
+ if (this.aquiferLocationCache.length % (this.gridSizeX * this.gridSizeZ) != 0) {
|
||||||
|
+ throw new AssertionError("Array length");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ int sizeY = this.aquiferLocationCache.length / (this.gridSizeX * this.gridSizeZ);
|
||||||
|
+
|
||||||
|
+ final RandomSource random = org.bxteam.divinemc.util.RandomUtil.getRandom(this.positionalRandomFactory);
|
||||||
|
+ // index: y, z, x
|
||||||
|
+ for (int y = 0; y < sizeY; y++) {
|
||||||
|
+ for (int z = 0; z < this.gridSizeZ; z++) {
|
||||||
|
+ for (int x = 0; x < this.gridSizeX; x++) {
|
||||||
|
+ final int x1 = x + this.minGridX;
|
||||||
|
+ final int y1 = y + this.minGridY;
|
||||||
|
+ final int z1 = z + this.minGridZ;
|
||||||
|
+ org.bxteam.divinemc.util.RandomUtil.derive(this.positionalRandomFactory, random, x1, y1, z1);
|
||||||
|
+ int x2 = x1 * 16 + random.nextInt(10);
|
||||||
|
+ int y2 = y1 * 12 + random.nextInt(9);
|
||||||
|
+ int z2 = z1 * 16 + random.nextInt(10);
|
||||||
|
+ int index = this.getIndex(x1, y1, z1);
|
||||||
|
+ this.aquiferLocationCache[index] = BlockPos.asLong(x2, y2, z2);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ for (long blockPosition : this.aquiferLocationCache) {
|
||||||
|
+ if (blockPosition == Long.MAX_VALUE) {
|
||||||
|
+ throw new AssertionError("Array initialization");
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ // DivineMC end - C2ME: Optimize Aquifer
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getIndex(int gridX, int gridY, int gridZ) {
|
||||||
|
@@ -132,140 +171,24 @@ public interface Aquifer {
|
||||||
|
@Nullable
|
||||||
|
@Override
|
||||||
|
public BlockState computeSubstance(DensityFunction.FunctionContext context, double substance) {
|
||||||
|
+ // DivineMC start - C2ME: Optimize Aquifer
|
||||||
|
int i = context.blockX();
|
||||||
|
- int i1 = context.blockY();
|
||||||
|
- int i2 = context.blockZ();
|
||||||
|
+ int j = context.blockY();
|
||||||
|
+ int k = context.blockZ();
|
||||||
|
if (substance > 0.0) {
|
||||||
|
this.shouldScheduleFluidUpdate = false;
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
- Aquifer.FluidStatus fluidStatus = this.globalFluidPicker.computeFluid(i, i1, i2);
|
||||||
|
- if (fluidStatus.at(i1).is(Blocks.LAVA)) {
|
||||||
|
+ Aquifer.FluidStatus fluidLevel = this.globalFluidPicker.computeFluid(i, j, k);
|
||||||
|
+ if (fluidLevel.at(j).is(Blocks.LAVA)) {
|
||||||
|
this.shouldScheduleFluidUpdate = false;
|
||||||
|
return Blocks.LAVA.defaultBlockState();
|
||||||
|
} else {
|
||||||
|
- int i3 = Math.floorDiv(i - 5, 16);
|
||||||
|
- int i4 = Math.floorDiv(i1 + 1, 12);
|
||||||
|
- int i5 = Math.floorDiv(i2 - 5, 16);
|
||||||
|
- int i6 = Integer.MAX_VALUE;
|
||||||
|
- int i7 = Integer.MAX_VALUE;
|
||||||
|
- int i8 = Integer.MAX_VALUE;
|
||||||
|
- int i9 = Integer.MAX_VALUE;
|
||||||
|
- long l = 0L;
|
||||||
|
- long l1 = 0L;
|
||||||
|
- long l2 = 0L;
|
||||||
|
- long l3 = 0L;
|
||||||
|
-
|
||||||
|
- for (int i10 = 0; i10 <= 1; i10++) {
|
||||||
|
- for (int i11 = -1; i11 <= 1; i11++) {
|
||||||
|
- for (int i12 = 0; i12 <= 1; i12++) {
|
||||||
|
- int i13 = i3 + i10;
|
||||||
|
- int i14 = i4 + i11;
|
||||||
|
- int i15 = i5 + i12;
|
||||||
|
- int index = this.getIndex(i13, i14, i15);
|
||||||
|
- long l4 = this.aquiferLocationCache[index];
|
||||||
|
- long l5;
|
||||||
|
- if (l4 != Long.MAX_VALUE) {
|
||||||
|
- l5 = l4;
|
||||||
|
- } else {
|
||||||
|
- RandomSource randomSource = this.positionalRandomFactory.at(i13, i14, i15);
|
||||||
|
- l5 = BlockPos.asLong(
|
||||||
|
- i13 * 16 + randomSource.nextInt(10), i14 * 12 + randomSource.nextInt(9), i15 * 16 + randomSource.nextInt(10)
|
||||||
|
- );
|
||||||
|
- this.aquiferLocationCache[index] = l5;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- int i16 = BlockPos.getX(l5) - i;
|
||||||
|
- int i17 = BlockPos.getY(l5) - i1;
|
||||||
|
- int i18 = BlockPos.getZ(l5) - i2;
|
||||||
|
- int i19 = i16 * i16 + i17 * i17 + i18 * i18;
|
||||||
|
- if (i6 >= i19) {
|
||||||
|
- l3 = l2;
|
||||||
|
- l2 = l1;
|
||||||
|
- l1 = l;
|
||||||
|
- l = l5;
|
||||||
|
- i9 = i8;
|
||||||
|
- i8 = i7;
|
||||||
|
- i7 = i6;
|
||||||
|
- i6 = i19;
|
||||||
|
- } else if (i7 >= i19) {
|
||||||
|
- l3 = l2;
|
||||||
|
- l2 = l1;
|
||||||
|
- l1 = l5;
|
||||||
|
- i9 = i8;
|
||||||
|
- i8 = i7;
|
||||||
|
- i7 = i19;
|
||||||
|
- } else if (i8 >= i19) {
|
||||||
|
- l3 = l2;
|
||||||
|
- l2 = l5;
|
||||||
|
- i9 = i8;
|
||||||
|
- i8 = i19;
|
||||||
|
- } else if (i9 >= i19) {
|
||||||
|
- l3 = l5;
|
||||||
|
- i9 = i19;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- Aquifer.FluidStatus aquiferStatus = this.getAquiferStatus(l);
|
||||||
|
- double d = similarity(i6, i7);
|
||||||
|
- BlockState blockState = aquiferStatus.at(i1);
|
||||||
|
- if (d <= 0.0) {
|
||||||
|
- if (d >= FLOWING_UPDATE_SIMULARITY) {
|
||||||
|
- Aquifer.FluidStatus aquiferStatus1 = this.getAquiferStatus(l1);
|
||||||
|
- this.shouldScheduleFluidUpdate = !aquiferStatus.equals(aquiferStatus1);
|
||||||
|
- } else {
|
||||||
|
- this.shouldScheduleFluidUpdate = false;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- return blockState;
|
||||||
|
- } else if (blockState.is(Blocks.WATER) && this.globalFluidPicker.computeFluid(i, i1 - 1, i2).at(i1 - 1).is(Blocks.LAVA)) {
|
||||||
|
- this.shouldScheduleFluidUpdate = true;
|
||||||
|
- return blockState;
|
||||||
|
- } else {
|
||||||
|
- MutableDouble mutableDouble = new MutableDouble(Double.NaN);
|
||||||
|
- Aquifer.FluidStatus aquiferStatus2 = this.getAquiferStatus(l1);
|
||||||
|
- double d1 = d * this.calculatePressure(context, mutableDouble, aquiferStatus, aquiferStatus2);
|
||||||
|
- if (substance + d1 > 0.0) {
|
||||||
|
- this.shouldScheduleFluidUpdate = false;
|
||||||
|
- return null;
|
||||||
|
- } else {
|
||||||
|
- Aquifer.FluidStatus aquiferStatus3 = this.getAquiferStatus(l2);
|
||||||
|
- double d2 = similarity(i6, i8);
|
||||||
|
- if (d2 > 0.0) {
|
||||||
|
- double d3 = d * d2 * this.calculatePressure(context, mutableDouble, aquiferStatus, aquiferStatus3);
|
||||||
|
- if (substance + d3 > 0.0) {
|
||||||
|
- this.shouldScheduleFluidUpdate = false;
|
||||||
|
- return null;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- double d3 = similarity(i7, i8);
|
||||||
|
- if (d3 > 0.0) {
|
||||||
|
- double d4 = d * d3 * this.calculatePressure(context, mutableDouble, aquiferStatus2, aquiferStatus3);
|
||||||
|
- if (substance + d4 > 0.0) {
|
||||||
|
- this.shouldScheduleFluidUpdate = false;
|
||||||
|
- return null;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- boolean flag = !aquiferStatus.equals(aquiferStatus2);
|
||||||
|
- boolean flag1 = d3 >= FLOWING_UPDATE_SIMULARITY && !aquiferStatus2.equals(aquiferStatus3);
|
||||||
|
- boolean flag2 = d2 >= FLOWING_UPDATE_SIMULARITY && !aquiferStatus.equals(aquiferStatus3);
|
||||||
|
- if (!flag && !flag1 && !flag2) {
|
||||||
|
- this.shouldScheduleFluidUpdate = d2 >= FLOWING_UPDATE_SIMULARITY
|
||||||
|
- && similarity(i6, i9) >= FLOWING_UPDATE_SIMULARITY
|
||||||
|
- && !aquiferStatus.equals(this.getAquiferStatus(l3));
|
||||||
|
- } else {
|
||||||
|
- this.shouldScheduleFluidUpdate = true;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- return blockState;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
+ aquiferExtracted$refreshDistPosIdx(i, j, k);
|
||||||
|
+ return aquiferExtracted$applyPost(context, substance, j, i, k);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ // DivineMC end - C2ME: Optimize Aquifer
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@@ -278,65 +201,28 @@ public interface Aquifer {
|
||||||
|
return 1.0 - Math.abs(secondDistance - firstDistance) / 25.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // DivineMC start - C2ME: Optimize Aquifer
|
||||||
|
private double calculatePressure(
|
||||||
|
- DensityFunction.FunctionContext context, MutableDouble substance, Aquifer.FluidStatus firstFluid, Aquifer.FluidStatus secondFluid
|
||||||
|
+ DensityFunction.FunctionContext context, MutableDouble substance, Aquifer.FluidStatus fluidLevel, Aquifer.FluidStatus fluidLevel2 // DivineMC - rename args
|
||||||
|
) {
|
||||||
|
int i = context.blockY();
|
||||||
|
- BlockState blockState = firstFluid.at(i);
|
||||||
|
- BlockState blockState1 = secondFluid.at(i);
|
||||||
|
- if ((!blockState.is(Blocks.LAVA) || !blockState1.is(Blocks.WATER)) && (!blockState.is(Blocks.WATER) || !blockState1.is(Blocks.LAVA))) {
|
||||||
|
- int abs = Math.abs(firstFluid.fluidLevel - secondFluid.fluidLevel);
|
||||||
|
+ BlockState blockState = fluidLevel.at(i);
|
||||||
|
+ BlockState blockState2 = fluidLevel2.at(i);
|
||||||
|
+ if ((!blockState.is(Blocks.LAVA) || !blockState2.is(Blocks.WATER)) && (!blockState.is(Blocks.WATER) || !blockState2.is(Blocks.LAVA))) {
|
||||||
|
+ int abs = Math.abs(fluidLevel.fluidLevel - fluidLevel2.fluidLevel);
|
||||||
|
if (abs == 0) {
|
||||||
|
return 0.0;
|
||||||
|
} else {
|
||||||
|
- double d = 0.5 * (firstFluid.fluidLevel + secondFluid.fluidLevel);
|
||||||
|
- double d1 = i + 0.5 - d;
|
||||||
|
- double d2 = abs / 2.0;
|
||||||
|
- double d3 = 0.0;
|
||||||
|
- double d4 = 2.5;
|
||||||
|
- double d5 = 1.5;
|
||||||
|
- double d6 = 3.0;
|
||||||
|
- double d7 = 10.0;
|
||||||
|
- double d8 = 3.0;
|
||||||
|
- double d9 = d2 - Math.abs(d1);
|
||||||
|
- double d11;
|
||||||
|
- if (d1 > 0.0) {
|
||||||
|
- double d10 = 0.0 + d9;
|
||||||
|
- if (d10 > 0.0) {
|
||||||
|
- d11 = d10 / 1.5;
|
||||||
|
- } else {
|
||||||
|
- d11 = d10 / 2.5;
|
||||||
|
- }
|
||||||
|
- } else {
|
||||||
|
- double d10 = 3.0 + d9;
|
||||||
|
- if (d10 > 0.0) {
|
||||||
|
- d11 = d10 / 3.0;
|
||||||
|
- } else {
|
||||||
|
- d11 = d10 / 10.0;
|
||||||
|
- }
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
- double d10x = 2.0;
|
||||||
|
- double d12;
|
||||||
|
- if (!(d11 < -2.0) && !(d11 > 2.0)) {
|
||||||
|
- double value = substance.getValue();
|
||||||
|
- if (Double.isNaN(value)) {
|
||||||
|
- double d13 = this.barrierNoise.compute(context);
|
||||||
|
- substance.setValue(d13);
|
||||||
|
- d12 = d13;
|
||||||
|
- } else {
|
||||||
|
- d12 = value;
|
||||||
|
- }
|
||||||
|
- } else {
|
||||||
|
- d12 = 0.0;
|
||||||
|
- }
|
||||||
|
+ double d = 0.5 * (double)(fluidLevel.fluidLevel + fluidLevel2.fluidLevel);
|
||||||
|
+ final double q = aquiferExtracted$getQ(i, d, abs);
|
||||||
|
|
||||||
|
- return 2.0 * (d12 + d11);
|
||||||
|
+ return aquiferExtracted$postCalculateDensity(context, substance, q);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return 2.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ // DivineMC end - C2ME: Optimize Aquifer
|
||||||
|
|
||||||
|
private int gridX(int x) {
|
||||||
|
return Math.floorDiv(x, 16);
|
||||||
|
@@ -350,23 +236,25 @@ public interface Aquifer {
|
||||||
|
return Math.floorDiv(z, 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
- private Aquifer.FluidStatus getAquiferStatus(long packedPos) {
|
||||||
|
- int x = BlockPos.getX(packedPos);
|
||||||
|
- int y = BlockPos.getY(packedPos);
|
||||||
|
- int z = BlockPos.getZ(packedPos);
|
||||||
|
- int i = this.gridX(x);
|
||||||
|
- int i1 = this.gridY(y);
|
||||||
|
- int i2 = this.gridZ(z);
|
||||||
|
- int index = this.getIndex(i, i1, i2);
|
||||||
|
- Aquifer.FluidStatus fluidStatus = this.aquiferCache[index];
|
||||||
|
- if (fluidStatus != null) {
|
||||||
|
- return fluidStatus;
|
||||||
|
+ // DivineMC start - C2ME: Optimize Aquifer
|
||||||
|
+ private Aquifer.FluidStatus getAquiferStatus(long pos) {
|
||||||
|
+ int i = BlockPos.getX(pos);
|
||||||
|
+ int j = BlockPos.getY(pos);
|
||||||
|
+ int k = BlockPos.getZ(pos);
|
||||||
|
+ int l = i >> 4; // C2ME - inline: floorDiv(i, 16)
|
||||||
|
+ int m = Math.floorDiv(j, 12); // C2ME - inline
|
||||||
|
+ int n = k >> 4; // C2ME - inline: floorDiv(k, 16)
|
||||||
|
+ int o = this.getIndex(l, m, n);
|
||||||
|
+ Aquifer.FluidStatus fluidLevel = this.aquiferCache[o];
|
||||||
|
+ if (fluidLevel != null) {
|
||||||
|
+ return fluidLevel;
|
||||||
|
} else {
|
||||||
|
- Aquifer.FluidStatus fluidStatus1 = this.computeFluid(x, y, z);
|
||||||
|
- this.aquiferCache[index] = fluidStatus1;
|
||||||
|
- return fluidStatus1;
|
||||||
|
+ Aquifer.FluidStatus fluidLevel2 = this.computeFluid(i, j, k);
|
||||||
|
+ this.aquiferCache[o] = fluidLevel2;
|
||||||
|
+ return fluidLevel2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
+ // DivineMC end - C2ME: Optimize Aquifer
|
||||||
|
|
||||||
|
private Aquifer.FluidStatus computeFluid(int x, int y, int z) {
|
||||||
|
Aquifer.FluidStatus fluidStatus = this.globalFluidPicker.computeFluid(x, y, z);
|
||||||
|
@@ -407,22 +295,21 @@ public interface Aquifer {
|
||||||
|
}
|
||||||
|
|
||||||
|
private int computeSurfaceLevel(int x, int y, int z, Aquifer.FluidStatus fluidStatus, int maxSurfaceLevel, boolean fluidPresent) {
|
||||||
|
- DensityFunction.SinglePointContext singlePointContext = new DensityFunction.SinglePointContext(x, y, z);
|
||||||
|
+ // DivineMC start - C2ME: Optimize Aquifer
|
||||||
|
+ DensityFunction.SinglePointContext unblendedNoisePos = new DensityFunction.SinglePointContext(x, y, z);
|
||||||
|
double d;
|
||||||
|
double d1;
|
||||||
|
- if (OverworldBiomeBuilder.isDeepDarkRegion(this.erosion, this.depth, singlePointContext)) {
|
||||||
|
+ if (OverworldBiomeBuilder.isDeepDarkRegion(this.erosion, this.depth, unblendedNoisePos)) {
|
||||||
|
d = -1.0;
|
||||||
|
d1 = -1.0;
|
||||||
|
} else {
|
||||||
|
int i = maxSurfaceLevel + 8 - y;
|
||||||
|
- int i1 = 64;
|
||||||
|
- double d2 = fluidPresent ? Mth.clampedMap((double)i, 0.0, 64.0, 1.0, 0.0) : 0.0;
|
||||||
|
- double d3 = Mth.clamp(this.fluidLevelFloodednessNoise.compute(singlePointContext), -1.0, 1.0);
|
||||||
|
- double d4 = Mth.map(d2, 1.0, 0.0, -0.3, 0.8);
|
||||||
|
- double d5 = Mth.map(d2, 1.0, 0.0, -0.8, 0.4);
|
||||||
|
- d = d3 - d5;
|
||||||
|
- d1 = d3 - d4;
|
||||||
|
+ double f = fluidPresent ? Mth.clampedLerp(1.0, 0.0, ((double) i) / 64.0) : 0.0; // inline
|
||||||
|
+ double g = Mth.clamp(this.fluidLevelFloodednessNoise.compute(unblendedNoisePos), -1.0, 1.0);
|
||||||
|
+ d = g + 0.8 + (f - 1.0) * 1.2; // inline
|
||||||
|
+ d1 = g + 0.3 + (f - 1.0) * 1.1; // inline
|
||||||
|
}
|
||||||
|
+ // DivineMC end - C2ME: Optimize Aquifer
|
||||||
|
|
||||||
|
int i;
|
||||||
|
if (d1 > 0.0) {
|
||||||
|
@@ -453,12 +340,12 @@ public interface Aquifer {
|
||||||
|
private BlockState computeFluidType(int x, int y, int z, Aquifer.FluidStatus fluidStatus, int surfaceLevel) {
|
||||||
|
BlockState blockState = fluidStatus.fluidType;
|
||||||
|
if (surfaceLevel <= -10 && surfaceLevel != DimensionType.WAY_BELOW_MIN_Y && fluidStatus.fluidType != Blocks.LAVA.defaultBlockState()) {
|
||||||
|
- int i = 64;
|
||||||
|
- int i1 = 40;
|
||||||
|
- int i2 = Math.floorDiv(x, 64);
|
||||||
|
- int i3 = Math.floorDiv(y, 40);
|
||||||
|
- int i4 = Math.floorDiv(z, 64);
|
||||||
|
- double d = this.lavaNoise.compute(new DensityFunction.SinglePointContext(i2, i3, i4));
|
||||||
|
+ // DivineMC start - C2ME: Optimize Aquifer
|
||||||
|
+ int k = x >> 6;
|
||||||
|
+ int l = Math.floorDiv(y, 40);
|
||||||
|
+ int m = z >> 6;
|
||||||
|
+ double d = this.lavaNoise.compute(new DensityFunction.SinglePointContext(k, l, m));
|
||||||
|
+ // DivineMC end - C2ME: Optimize Aquifer
|
||||||
|
if (Math.abs(d) > 0.3) {
|
||||||
|
blockState = Blocks.LAVA.defaultBlockState();
|
||||||
|
}
|
||||||
|
@@ -466,5 +353,183 @@ public interface Aquifer {
|
||||||
|
|
||||||
|
return blockState;
|
||||||
|
}
|
||||||
|
+
|
||||||
|
+ // DivineMC start - C2ME: Optimize Aquifer
|
||||||
|
+ private @org.jetbrains.annotations.Nullable BlockState aquiferExtracted$applyPost(DensityFunction.FunctionContext pos, double density, int j, int i, int k) {
|
||||||
|
+ Aquifer.FluidStatus fluidLevel2 = this.getAquiferStatus(this.c2me$pos1);
|
||||||
|
+ double d = similarity(this.c2me$dist1, this.c2me$dist2);
|
||||||
|
+ BlockState blockState = fluidLevel2.at(j);
|
||||||
|
+ if (d <= 0.0) {
|
||||||
|
+ this.shouldScheduleFluidUpdate = d >= FLOWING_UPDATE_SIMULARITY;
|
||||||
|
+ return blockState;
|
||||||
|
+ } else if (blockState.is(Blocks.WATER) && this.globalFluidPicker.computeFluid(i, j - 1, k).at(j - 1).is(Blocks.LAVA)) {
|
||||||
|
+ this.shouldScheduleFluidUpdate = true;
|
||||||
|
+ return blockState;
|
||||||
|
+ } else {
|
||||||
|
+ this.c2me$mutableDoubleThingy = Double.NaN;
|
||||||
|
+ Aquifer.FluidStatus fluidLevel3 = this.getAquiferStatus(this.c2me$pos2);
|
||||||
|
+ double e = d * this.c2me$calculateDensityModified(pos, fluidLevel2, fluidLevel3);
|
||||||
|
+ if (density + e > 0.0) {
|
||||||
|
+ this.shouldScheduleFluidUpdate = false;
|
||||||
|
+ return null;
|
||||||
|
+ } else {
|
||||||
|
+ return aquiferExtracted$getFinalBlockState(pos, density, d, fluidLevel2, fluidLevel3, blockState);
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private BlockState aquiferExtracted$getFinalBlockState(DensityFunction.FunctionContext pos, double density, double d, Aquifer.FluidStatus fluidLevel2, Aquifer.FluidStatus fluidLevel3, BlockState blockState) {
|
||||||
|
+ Aquifer.FluidStatus fluidLevel4 = this.getAquiferStatus(this.c2me$pos3);
|
||||||
|
+ double f = similarity(this.c2me$dist1, this.c2me$dist3);
|
||||||
|
+ if (aquiferExtracted$extractedCheckFG(pos, density, d, fluidLevel2, f, fluidLevel4)) return null;
|
||||||
|
+
|
||||||
|
+ double g = similarity(this.c2me$dist2, this.c2me$dist3);
|
||||||
|
+ if (aquiferExtracted$extractedCheckFG(pos, density, d, fluidLevel3, g, fluidLevel4)) return null;
|
||||||
|
+
|
||||||
|
+ this.shouldScheduleFluidUpdate = true;
|
||||||
|
+ return blockState;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private boolean aquiferExtracted$extractedCheckFG(DensityFunction.FunctionContext pos, double density, double d, Aquifer.FluidStatus fluidLevel2, double f, Aquifer.FluidStatus fluidLevel4) {
|
||||||
|
+ if (f > 0.0) {
|
||||||
|
+ double g = d * f * this.c2me$calculateDensityModified(pos, fluidLevel2, fluidLevel4);
|
||||||
|
+ if (density + g > 0.0) {
|
||||||
|
+ this.shouldScheduleFluidUpdate = false;
|
||||||
|
+ return true;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ return false;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private void aquiferExtracted$refreshDistPosIdx(int x, int y, int z) {
|
||||||
|
+ int gx = (x - 5) >> 4;
|
||||||
|
+ int gy = Math.floorDiv(y + 1, 12);
|
||||||
|
+ int gz = (z - 5) >> 4;
|
||||||
|
+ int dist1 = Integer.MAX_VALUE;
|
||||||
|
+ int dist2 = Integer.MAX_VALUE;
|
||||||
|
+ int dist3 = Integer.MAX_VALUE;
|
||||||
|
+ long pos1 = 0;
|
||||||
|
+ long pos2 = 0;
|
||||||
|
+ long pos3 = 0;
|
||||||
|
+
|
||||||
|
+ for (int offY = -1; offY <= 1; ++offY) {
|
||||||
|
+ for (int offZ = 0; offZ <= 1; ++offZ) {
|
||||||
|
+ for (int offX = 0; offX <= 1; ++offX) {
|
||||||
|
+ int posIdx = this.getIndex(gx + offX, gy + offY, gz + offZ);
|
||||||
|
+
|
||||||
|
+ long position = this.aquiferLocationCache[posIdx];
|
||||||
|
+
|
||||||
|
+ int dx = BlockPos.getX(position) - x;
|
||||||
|
+ int dy = BlockPos.getY(position) - y;
|
||||||
|
+ int dz = BlockPos.getZ(position) - z;
|
||||||
|
+ int dist = dx * dx + dy * dy + dz * dz;
|
||||||
|
+
|
||||||
|
+ if (dist3 >= dist) {
|
||||||
|
+ pos3 = position;
|
||||||
|
+ dist3 = dist;
|
||||||
|
+ }
|
||||||
|
+ if (dist2 >= dist) {
|
||||||
|
+ pos3 = pos2;
|
||||||
|
+ dist3 = dist2;
|
||||||
|
+ pos2 = position;
|
||||||
|
+ dist2 = dist;
|
||||||
|
+ }
|
||||||
|
+ if (dist1 >= dist) {
|
||||||
|
+ pos2 = pos1;
|
||||||
|
+ dist2 = dist1;
|
||||||
|
+ pos1 = position;
|
||||||
|
+ dist1 = dist;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ this.c2me$dist1 = dist1;
|
||||||
|
+ this.c2me$dist2 = dist2;
|
||||||
|
+ this.c2me$dist3 = dist3;
|
||||||
|
+ this.c2me$pos1 = pos1;
|
||||||
|
+ this.c2me$pos2 = pos2;
|
||||||
|
+ this.c2me$pos3 = pos3;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private double c2me$calculateDensityModified(
|
||||||
|
+ DensityFunction.FunctionContext pos, Aquifer.FluidStatus fluidLevel, Aquifer.FluidStatus fluidLevel2
|
||||||
|
+ ) {
|
||||||
|
+ int i = pos.blockY();
|
||||||
|
+ BlockState blockState = fluidLevel.at(i);
|
||||||
|
+ BlockState blockState2 = fluidLevel2.at(i);
|
||||||
|
+ if ((!blockState.is(Blocks.LAVA) || !blockState2.is(Blocks.WATER)) && (!blockState.is(Blocks.WATER) || !blockState2.is(Blocks.LAVA))) {
|
||||||
|
+ int j = Math.abs(fluidLevel.fluidLevel - fluidLevel2.fluidLevel);
|
||||||
|
+ if (j == 0) {
|
||||||
|
+ return 0.0;
|
||||||
|
+ } else {
|
||||||
|
+ double d = 0.5 * (double)(fluidLevel.fluidLevel + fluidLevel2.fluidLevel);
|
||||||
|
+ final double q = aquiferExtracted$getQ(i, d, j);
|
||||||
|
+
|
||||||
|
+ return aquiferExtracted$postCalculateDensityModified(pos, q);
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ return 2.0;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private double aquiferExtracted$postCalculateDensity(DensityFunction.FunctionContext pos, MutableDouble mutableDouble, double q) {
|
||||||
|
+ double r;
|
||||||
|
+ if (!(q < -2.0) && !(q > 2.0)) {
|
||||||
|
+ double s = mutableDouble.getValue();
|
||||||
|
+ if (Double.isNaN(s)) {
|
||||||
|
+ double t = this.barrierNoise.compute(pos);
|
||||||
|
+ mutableDouble.setValue(t);
|
||||||
|
+ r = t;
|
||||||
|
+ } else {
|
||||||
|
+ r = s;
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ r = 0.0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 2.0 * (r + q);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private double aquiferExtracted$postCalculateDensityModified(DensityFunction.FunctionContext pos, double q) {
|
||||||
|
+ double r;
|
||||||
|
+ if (!(q < -2.0) && !(q > 2.0)) {
|
||||||
|
+ double s = this.c2me$mutableDoubleThingy;
|
||||||
|
+ if (Double.isNaN(s)) {
|
||||||
|
+ double t = this.barrierNoise.compute(pos);
|
||||||
|
+ this.c2me$mutableDoubleThingy = t;
|
||||||
|
+ r = t;
|
||||||
|
+ } else {
|
||||||
|
+ r = s;
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ r = 0.0;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 2.0 * (r + q);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ private static double aquiferExtracted$getQ(double i, double d, double j) {
|
||||||
|
+ double e = i + 0.5 - d;
|
||||||
|
+ double f = j / 2.0;
|
||||||
|
+ double o = f - Math.abs(e);
|
||||||
|
+ double q;
|
||||||
|
+ if (e > 0.0) {
|
||||||
|
+ if (o > 0.0) {
|
||||||
|
+ q = o / 1.5;
|
||||||
|
+ } else {
|
||||||
|
+ q = o / 2.5;
|
||||||
|
+ }
|
||||||
|
+ } else {
|
||||||
|
+ double p = 3.0 + o;
|
||||||
|
+ if (p > 0.0) {
|
||||||
|
+ q = p / 3.0;
|
||||||
|
+ } else {
|
||||||
|
+ q = p / 10.0;
|
||||||
|
+ }
|
||||||
|
+ }
|
||||||
|
+ return q;
|
||||||
|
+ }
|
||||||
|
+ // DivineMC end - C2ME: Optimize Aquifer
|
||||||
|
}
|
||||||
|
}
|
||||||
|
diff --git a/net/minecraft/world/level/levelgen/Beardifier.java b/net/minecraft/world/level/levelgen/Beardifier.java
|
||||||
|
index 86c15d2d90e63d21cb83622a7b29e11151a4f64a..2c0c0546046857056b8445f59828fdf9821ea001 100644
|
||||||
|
--- a/net/minecraft/world/level/levelgen/Beardifier.java
|
||||||
|
+++ b/net/minecraft/world/level/levelgen/Beardifier.java
|
||||||
|
@@ -29,6 +29,17 @@ public class Beardifier implements DensityFunctions.BeardifierOrMarker {
|
||||||
|
});
|
||||||
|
private final ObjectListIterator<Beardifier.Rigid> pieceIterator;
|
||||||
|
private final ObjectListIterator<JigsawJunction> junctionIterator;
|
||||||
|
+ // DivineMC start - C2ME: Optimize Beardifier
|
||||||
|
+ private Beardifier.Rigid[] c2me$pieceArray;
|
||||||
|
+ private JigsawJunction[] c2me$junctionArray;
|
||||||
|
+
|
||||||
|
+ private void c2me$initArrays() {
|
||||||
|
+ this.c2me$pieceArray = com.google.common.collect.Iterators.toArray(this.pieceIterator, Beardifier.Rigid.class);
|
||||||
|
+ this.pieceIterator.back(Integer.MAX_VALUE);
|
||||||
|
+ this.c2me$junctionArray = com.google.common.collect.Iterators.toArray(this.junctionIterator, JigsawJunction.class);
|
||||||
|
+ this.junctionIterator.back(Integer.MAX_VALUE);
|
||||||
|
+ }
|
||||||
|
+ // DivineMC end - C2ME: Optimize Beardifier
|
||||||
|
|
||||||
|
public static Beardifier forStructuresInChunk(StructureManager structureManager, ChunkPos chunkPos) {
|
||||||
|
int minBlockX = chunkPos.getMinBlockX();
|
||||||
|
@@ -75,50 +86,44 @@ public class Beardifier implements DensityFunctions.BeardifierOrMarker {
|
||||||
|
this.junctionIterator = junctionIterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ // DivineMC start - C2ME: Optimize Beardifier
|
||||||
|
@Override
|
||||||
|
public double compute(DensityFunction.FunctionContext context) {
|
||||||
|
+ if (this.c2me$pieceArray == null || this.c2me$junctionArray == null) {
|
||||||
|
+ this.c2me$initArrays();
|
||||||
|
+ }
|
||||||
|
int i = context.blockX();
|
||||||
|
- int i1 = context.blockY();
|
||||||
|
- int i2 = context.blockZ();
|
||||||
|
+ int j = context.blockY();
|
||||||
|
+ int k = context.blockZ();
|
||||||
|
double d = 0.0;
|
||||||
|
|
||||||
|
- while (this.pieceIterator.hasNext()) {
|
||||||
|
- Beardifier.Rigid rigid = this.pieceIterator.next();
|
||||||
|
- BoundingBox boundingBox = rigid.box();
|
||||||
|
- int groundLevelDelta = rigid.groundLevelDelta();
|
||||||
|
- int max = Math.max(0, Math.max(boundingBox.minX() - i, i - boundingBox.maxX()));
|
||||||
|
- int max1 = Math.max(0, Math.max(boundingBox.minZ() - i2, i2 - boundingBox.maxZ()));
|
||||||
|
- int i3 = boundingBox.minY() + groundLevelDelta;
|
||||||
|
- int i4 = i1 - i3;
|
||||||
|
-
|
||||||
|
- int i5 = switch (rigid.terrainAdjustment()) {
|
||||||
|
- case NONE -> 0;
|
||||||
|
- case BURY, BEARD_THIN -> i4;
|
||||||
|
- case BEARD_BOX -> Math.max(0, Math.max(i3 - i1, i1 - boundingBox.maxY()));
|
||||||
|
- case ENCAPSULATE -> Math.max(0, Math.max(boundingBox.minY() - i1, i1 - boundingBox.maxY()));
|
||||||
|
- };
|
||||||
|
+ for (Beardifier.Rigid piece : this.c2me$pieceArray) {
|
||||||
|
+ BoundingBox blockBox = piece.box();
|
||||||
|
+ int l = piece.groundLevelDelta();
|
||||||
|
+ int m = Math.max(0, Math.max(blockBox.minX() - i, i - blockBox.maxX()));
|
||||||
|
+ int n = Math.max(0, Math.max(blockBox.minZ() - k, k - blockBox.maxZ()));
|
||||||
|
+ int o = blockBox.minY() + l;
|
||||||
|
+ int p = j - o;
|
||||||
|
|
||||||
|
- d += switch (rigid.terrainAdjustment()) {
|
||||||
|
+ d += switch (piece.terrainAdjustment()) { // 2 switch statement merged
|
||||||
|
case NONE -> 0.0;
|
||||||
|
- case BURY -> getBuryContribution(max, i5 / 2.0, max1);
|
||||||
|
- case BEARD_THIN, BEARD_BOX -> getBeardContribution(max, i5, max1, i4) * 0.8;
|
||||||
|
- case ENCAPSULATE -> getBuryContribution(max / 2.0, i5 / 2.0, max1 / 2.0) * 0.8;
|
||||||
|
+ case BURY -> getBuryContribution(m, (double)p / 2.0, n);
|
||||||
|
+ case BEARD_THIN -> getBeardContribution(m, p, n, p) * 0.8;
|
||||||
|
+ case BEARD_BOX -> getBeardContribution(m, Math.max(0, Math.max(o - j, j - blockBox.maxY())), n, p) * 0.8;
|
||||||
|
+ case ENCAPSULATE -> getBuryContribution((double)m / 2.0, (double)Math.max(0, Math.max(blockBox.minY() - j, j - blockBox.maxY())) / 2.0, (double)n / 2.0) * 0.8;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
- this.pieceIterator.back(Integer.MAX_VALUE);
|
||||||
|
-
|
||||||
|
- while (this.junctionIterator.hasNext()) {
|
||||||
|
- JigsawJunction jigsawJunction = this.junctionIterator.next();
|
||||||
|
- int i6 = i - jigsawJunction.getSourceX();
|
||||||
|
- int groundLevelDelta = i1 - jigsawJunction.getSourceGroundY();
|
||||||
|
- int max = i2 - jigsawJunction.getSourceZ();
|
||||||
|
- d += getBeardContribution(i6, groundLevelDelta, max, groundLevelDelta) * 0.4;
|
||||||
|
+ for (JigsawJunction jigsawJunction : this.c2me$junctionArray) {
|
||||||
|
+ int r = i - jigsawJunction.getSourceX();
|
||||||
|
+ int l = j - jigsawJunction.getSourceGroundY();
|
||||||
|
+ int m = k - jigsawJunction.getSourceZ();
|
||||||
|
+ d += getBeardContribution(r, l, m, l) * 0.4;
|
||||||
|
}
|
||||||
|
|
||||||
|
- this.junctionIterator.back(Integer.MAX_VALUE);
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
+ // DivineMC end - C2ME: Optimize Beardifier
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public double minValue() {
|
||||||
|
diff --git a/net/minecraft/world/level/levelgen/LegacyRandomSource.java b/net/minecraft/world/level/levelgen/LegacyRandomSource.java
|
||||||
|
index c67168517774a0ad9ca43422a79ef14a8ea0c2e8..026dfbbb6c3fd5cd274dcbf721e5cf3af889e3d9 100644
|
||||||
|
--- a/net/minecraft/world/level/levelgen/LegacyRandomSource.java
|
||||||
|
+++ b/net/minecraft/world/level/levelgen/LegacyRandomSource.java
|
||||||
|
@@ -53,13 +53,7 @@ public class LegacyRandomSource implements BitRandomSource {
|
||||||
|
return this.gaussianSource.nextGaussian();
|
||||||
|
}
|
||||||
|
|
||||||
|
- public static class LegacyPositionalRandomFactory implements PositionalRandomFactory {
|
||||||
|
- private final long seed;
|
||||||
|
-
|
||||||
|
- public LegacyPositionalRandomFactory(long seed) {
|
||||||
|
- this.seed = seed;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
+ public record LegacyPositionalRandomFactory(long seed) implements PositionalRandomFactory { // DivineMC - make record
|
||||||
|
@Override
|
||||||
|
public RandomSource at(int x, int y, int z) {
|
||||||
|
long seed = Mth.getSeed(x, y, z);
|
||||||
|
diff --git a/net/minecraft/world/level/levelgen/XoroshiroRandomSource.java b/net/minecraft/world/level/levelgen/XoroshiroRandomSource.java
|
||||||
|
index 9d3a9ca1e13cd80f468f1352bbb74345f03903dd..d97b9b43686bda0a95fc02f6ca31b2d07d603a32 100644
|
||||||
|
--- a/net/minecraft/world/level/levelgen/XoroshiroRandomSource.java
|
||||||
|
+++ b/net/minecraft/world/level/levelgen/XoroshiroRandomSource.java
|
||||||
|
@@ -106,15 +106,7 @@ public class XoroshiroRandomSource implements RandomSource {
|
||||||
|
return this.randomNumberGenerator.nextLong() >>> 64 - bits;
|
||||||
|
}
|
||||||
|
|
||||||
|
- public static class XoroshiroPositionalRandomFactory implements PositionalRandomFactory {
|
||||||
|
- private final long seedLo;
|
||||||
|
- private final long seedHi;
|
||||||
|
-
|
||||||
|
- public XoroshiroPositionalRandomFactory(long seedLo, long seedHi) {
|
||||||
|
- this.seedLo = seedLo;
|
||||||
|
- this.seedHi = seedHi;
|
||||||
|
- }
|
||||||
|
-
|
||||||
|
+ public record XoroshiroPositionalRandomFactory(long seedLo, long seedHi) implements PositionalRandomFactory { // DivineMC - make record
|
||||||
|
@Override
|
||||||
|
public RandomSource at(int x, int y, int z) {
|
||||||
|
long seed = Mth.getSeed(x, y, z);
|
||||||
@@ -1,744 +0,0 @@
|
|||||||
package org.bxteam.divinemc.util;
|
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.bytes.ByteIterator;
|
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
|
||||||
import it.unimi.dsi.fastutil.ints.IntCollection;
|
|
||||||
import it.unimi.dsi.fastutil.ints.IntIterator;
|
|
||||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
|
||||||
import it.unimi.dsi.fastutil.longs.LongIterator;
|
|
||||||
import it.unimi.dsi.fastutil.longs.LongListIterator;
|
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectIterator;
|
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectSet;
|
|
||||||
import it.unimi.dsi.fastutil.objects.ReferenceSet;
|
|
||||||
import it.unimi.dsi.fastutil.shorts.ShortIterator;
|
|
||||||
import org.apache.commons.lang3.ArrayUtils;
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
|
||||||
|
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.ListIterator;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public final class CollectionWrapperUtil {
|
|
||||||
private CollectionWrapperUtil() {
|
|
||||||
throw new IllegalStateException("This class cannot be instantiated");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T> Int2ObjectMap.@NotNull Entry<T> intEntryForwards(Map.Entry<Integer, T> entry) {
|
|
||||||
return new Int2ObjectMap.Entry<>() {
|
|
||||||
@Override
|
|
||||||
public T getValue() {
|
|
||||||
return entry.getValue();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T setValue(T value) {
|
|
||||||
return entry.setValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getIntKey() {
|
|
||||||
return entry.getKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object obj) {
|
|
||||||
if (obj == entry) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return super.equals(obj);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return entry.hashCode();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static <T> Map.Entry<Integer, T> intEntryBackwards(Int2ObjectMap.Entry<T> entry) {
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> ObjectSet<Int2ObjectMap.Entry<T>> entrySetIntWrap(Map<Integer, T> map) {
|
|
||||||
return new ConvertingObjectSet<>(
|
|
||||||
map.entrySet(),
|
|
||||||
CollectionWrapperUtil::intEntryForwards,
|
|
||||||
CollectionWrapperUtil::intEntryBackwards
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IntSet wrapIntSet(Set<Integer> intset) {
|
|
||||||
return new WrappingIntSet(intset);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ByteIterator itrByteWrap(Iterator<Byte> backing) {
|
|
||||||
return new WrappingByteIterator(backing);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ByteIterator itrByteWrap(Iterable<Byte> backing) {
|
|
||||||
return itrByteWrap(backing.iterator());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IntIterator itrIntWrap(Iterator<Integer> backing) {
|
|
||||||
return new WrappingIntIterator(backing);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static IntIterator itrIntWrap(Iterable<Integer> backing) {
|
|
||||||
return itrIntWrap(backing.iterator());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static LongIterator itrLongWrap(Iterator<Long> backing) {
|
|
||||||
return new WrappingLongIterator(backing);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static LongIterator itrLongWrap(Iterable<Long> backing) {
|
|
||||||
return itrLongWrap(backing.iterator());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ShortIterator itrShortWrap(Iterator<Short> backing) {
|
|
||||||
return new WrappingShortIterator(backing);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ShortIterator itrShortWrap(Iterable<Short> backing) {
|
|
||||||
return itrShortWrap(backing.iterator());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static LongListIterator wrap(ListIterator<Long> c) {
|
|
||||||
return new WrappingLongListIterator(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static LongListIterator wrap(Iterator<Long> c) {
|
|
||||||
return new SlimWrappingLongListIterator(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <K> ObjectCollection<K> wrap(Collection<K> c) {
|
|
||||||
return new WrappingObjectCollection<>(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <K> ReferenceSet<K> wrap(Set<K> s) {
|
|
||||||
return new WrappingRefSet<>(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <T> ObjectIterator<T> itrWrap(Iterable<T> in) {
|
|
||||||
return new WrapperObjectIterator<>(in.iterator());
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class ConvertingObjectSet<E, T> implements ObjectSet<T> {
|
|
||||||
private final Set<E> backing;
|
|
||||||
private final Function<E, T> forward;
|
|
||||||
private final Function<T, E> back;
|
|
||||||
|
|
||||||
public ConvertingObjectSet(Set<E> backing, Function<E, T> forward, Function<T, E> back) {
|
|
||||||
this.backing = Objects.requireNonNull(backing, "Backing set cannot be null");
|
|
||||||
this.forward = Objects.requireNonNull(forward, "Forward function cannot be null");
|
|
||||||
this.back = Objects.requireNonNull(back, "Backward function cannot be null");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int size() {
|
|
||||||
return backing.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return backing.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public boolean contains(Object o) {
|
|
||||||
try {
|
|
||||||
return backing.contains(back.apply((T) o));
|
|
||||||
} catch (ClassCastException cce) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object[] toArray() {
|
|
||||||
return backing.stream().map(forward).toArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <R> R[] toArray(R[] a) {
|
|
||||||
return backing.stream().map(forward).collect(Collectors.toSet()).toArray(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean add(T e) {
|
|
||||||
return backing.add(back.apply(e));
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public boolean remove(Object o) {
|
|
||||||
try {
|
|
||||||
return backing.remove(back.apply((T) o));
|
|
||||||
} catch (ClassCastException cce) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public boolean containsAll(Collection<?> c) {
|
|
||||||
try {
|
|
||||||
return backing.containsAll(c.stream()
|
|
||||||
.map(i -> back.apply((T) i))
|
|
||||||
.collect(Collectors.toSet()));
|
|
||||||
} catch (ClassCastException cce) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean addAll(Collection<? extends T> c) {
|
|
||||||
return backing.addAll(c.stream().map(back).collect(Collectors.toSet()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public boolean removeAll(Collection<?> c) {
|
|
||||||
try {
|
|
||||||
return backing.removeAll(c.stream()
|
|
||||||
.map(i -> back.apply((T) i))
|
|
||||||
.collect(Collectors.toSet()));
|
|
||||||
} catch (ClassCastException cce) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
|
||||||
public boolean retainAll(Collection<?> c) {
|
|
||||||
try {
|
|
||||||
return backing.retainAll(c.stream()
|
|
||||||
.map(i -> back.apply((T) i))
|
|
||||||
.collect(Collectors.toSet()));
|
|
||||||
} catch (ClassCastException cce) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clear() {
|
|
||||||
backing.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ObjectIterator<T> iterator() {
|
|
||||||
return new ObjectIterator<>() {
|
|
||||||
private final Iterator<E> backg = backing.iterator();
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasNext() {
|
|
||||||
return backg.hasNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T next() {
|
|
||||||
return forward.apply(backg.next());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void remove() {
|
|
||||||
backg.remove();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class WrappingIntIterator implements IntIterator {
|
|
||||||
private final Iterator<Integer> backing;
|
|
||||||
|
|
||||||
WrappingIntIterator(Iterator<Integer> backing) {
|
|
||||||
this.backing = Objects.requireNonNull(backing);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasNext() {
|
|
||||||
return backing.hasNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int nextInt() {
|
|
||||||
return backing.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Integer next() {
|
|
||||||
return backing.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void remove() {
|
|
||||||
backing.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class WrappingLongIterator implements LongIterator {
|
|
||||||
private final Iterator<Long> backing;
|
|
||||||
|
|
||||||
WrappingLongIterator(Iterator<Long> backing) {
|
|
||||||
this.backing = Objects.requireNonNull(backing);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasNext() {
|
|
||||||
return backing.hasNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long nextLong() {
|
|
||||||
return backing.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Long next() {
|
|
||||||
return backing.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void remove() {
|
|
||||||
backing.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class WrappingShortIterator implements ShortIterator {
|
|
||||||
private final Iterator<Short> backing;
|
|
||||||
|
|
||||||
WrappingShortIterator(Iterator<Short> backing) {
|
|
||||||
this.backing = Objects.requireNonNull(backing);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasNext() {
|
|
||||||
return backing.hasNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public short nextShort() {
|
|
||||||
return backing.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Short next() {
|
|
||||||
return backing.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void remove() {
|
|
||||||
backing.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static class WrappingByteIterator implements ByteIterator {
|
|
||||||
private final Iterator<Byte> backing;
|
|
||||||
|
|
||||||
WrappingByteIterator(Iterator<Byte> backing) {
|
|
||||||
this.backing = Objects.requireNonNull(backing);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasNext() {
|
|
||||||
return backing.hasNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte nextByte() {
|
|
||||||
return next();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Byte next() {
|
|
||||||
return backing.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void remove() {
|
|
||||||
backing.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class WrappingIntSet implements IntSet {
|
|
||||||
private final Set<Integer> backing;
|
|
||||||
|
|
||||||
public WrappingIntSet(Set<Integer> backing) {
|
|
||||||
this.backing = Objects.requireNonNull(backing);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean add(int key) {
|
|
||||||
return backing.add(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean contains(int key) {
|
|
||||||
return backing.contains(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int[] toIntArray() {
|
|
||||||
return backing.stream().mapToInt(Integer::intValue).toArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int[] toArray(int[] a) {
|
|
||||||
return ArrayUtils.toPrimitive(backing.toArray(new Integer[0]));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean addAll(IntCollection c) {
|
|
||||||
return backing.addAll(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsAll(IntCollection c) {
|
|
||||||
return backing.containsAll(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean removeAll(IntCollection c) {
|
|
||||||
return backing.removeAll(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean retainAll(IntCollection c) {
|
|
||||||
return backing.retainAll(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int size() {
|
|
||||||
return backing.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return backing.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object[] toArray() {
|
|
||||||
return backing.toArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T[] toArray(T[] a) {
|
|
||||||
return backing.toArray(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsAll(Collection<?> c) {
|
|
||||||
return backing.containsAll(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean addAll(Collection<? extends Integer> c) {
|
|
||||||
return backing.addAll(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean removeAll(Collection<?> c) {
|
|
||||||
return backing.removeAll(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean retainAll(Collection<?> c) {
|
|
||||||
return backing.retainAll(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clear() {
|
|
||||||
backing.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IntIterator iterator() {
|
|
||||||
return new WrappingIntIterator(backing.iterator());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean remove(int k) {
|
|
||||||
return backing.remove(k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class WrappingRefSet<V> implements ReferenceSet<V> {
|
|
||||||
private final Set<V> backing;
|
|
||||||
|
|
||||||
public WrappingRefSet(Set<V> backing) {
|
|
||||||
this.backing = Objects.requireNonNull(backing);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean add(V key) {
|
|
||||||
return backing.add(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean remove(final Object o) {
|
|
||||||
return backing.remove(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsAll(@NotNull final Collection<?> c) {
|
|
||||||
return backing.containsAll(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean addAll(@NotNull final Collection<? extends V> c) {
|
|
||||||
return backing.addAll(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean removeAll(@NotNull final Collection<?> c) {
|
|
||||||
return backing.removeAll(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean retainAll(@NotNull final Collection<?> c) {
|
|
||||||
return backing.retainAll(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clear() {
|
|
||||||
this.backing.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int size() {
|
|
||||||
return backing.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return backing.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean contains(final Object o) {
|
|
||||||
return backing.contains(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ObjectIterator<V> iterator() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull Object[] toArray() {
|
|
||||||
return this.backing.toArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public @NotNull <T> T[] toArray(@NotNull final T[] a) {
|
|
||||||
return this.backing.toArray(a);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class WrappingLongListIterator implements LongListIterator {
|
|
||||||
private final ListIterator<Long> backing;
|
|
||||||
|
|
||||||
WrappingLongListIterator(ListIterator<Long> backing) {
|
|
||||||
this.backing = Objects.requireNonNull(backing);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long previousLong() {
|
|
||||||
return backing.previous();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long nextLong() {
|
|
||||||
return backing.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasNext() {
|
|
||||||
return backing.hasNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasPrevious() {
|
|
||||||
return backing.hasPrevious();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int nextIndex() {
|
|
||||||
return backing.nextIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int previousIndex() {
|
|
||||||
return backing.previousIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void add(long k) {
|
|
||||||
backing.add(k);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void remove() {
|
|
||||||
backing.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void set(long k) {
|
|
||||||
backing.set(k);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class SlimWrappingLongListIterator implements LongListIterator {
|
|
||||||
private final Iterator<Long> backing;
|
|
||||||
|
|
||||||
SlimWrappingLongListIterator(Iterator<Long> backing) {
|
|
||||||
this.backing = Objects.requireNonNull(backing);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long previousLong() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long nextLong() {
|
|
||||||
return backing.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasNext() {
|
|
||||||
return backing.hasNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasPrevious() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int nextIndex() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int previousIndex() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void add(long k) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void remove() {
|
|
||||||
backing.remove();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void set(long k) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static class WrappingObjectCollection<V> implements ObjectCollection<V> {
|
|
||||||
private final Collection<V> backing;
|
|
||||||
|
|
||||||
public WrappingObjectCollection(Collection<V> backing) {
|
|
||||||
this.backing = Objects.requireNonNull(backing);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int size() {
|
|
||||||
return backing.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return backing.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean contains(Object o) {
|
|
||||||
return backing.contains(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object[] toArray() {
|
|
||||||
return backing.toArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public <T> T[] toArray(T[] a) {
|
|
||||||
return backing.toArray(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean add(V e) {
|
|
||||||
return backing.add(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean remove(Object o) {
|
|
||||||
return backing.remove(o);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsAll(Collection<?> c) {
|
|
||||||
return backing.containsAll(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean addAll(Collection<? extends V> c) {
|
|
||||||
return backing.addAll(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean removeAll(Collection<?> c) {
|
|
||||||
return backing.removeAll(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean retainAll(Collection<?> c) {
|
|
||||||
return backing.retainAll(c);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clear() {
|
|
||||||
backing.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ObjectIterator<V> iterator() {
|
|
||||||
return itrWrap(backing);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private record WrapperObjectIterator<T>(Iterator<T> parent) implements ObjectIterator<T> {
|
|
||||||
private WrapperObjectIterator(Iterator<T> parent) {
|
|
||||||
this.parent = Objects.requireNonNull(parent);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean hasNext() {
|
|
||||||
return parent.hasNext();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public T next() {
|
|
||||||
return parent.next();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void remove() {
|
|
||||||
parent.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
package org.bxteam.divinemc.util;
|
||||||
|
|
||||||
|
import net.minecraft.util.Mth;
|
||||||
|
import net.minecraft.util.RandomSource;
|
||||||
|
import net.minecraft.world.level.levelgen.LegacyRandomSource;
|
||||||
|
import net.minecraft.world.level.levelgen.PositionalRandomFactory;
|
||||||
|
import net.minecraft.world.level.levelgen.SingleThreadedRandomSource;
|
||||||
|
import net.minecraft.world.level.levelgen.Xoroshiro128PlusPlus;
|
||||||
|
import net.minecraft.world.level.levelgen.XoroshiroRandomSource;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
public final class RandomUtil {
|
||||||
|
public static @NotNull RandomSource getRandom(PositionalRandomFactory deriver) {
|
||||||
|
if (deriver instanceof XoroshiroRandomSource.XoroshiroPositionalRandomFactory) {
|
||||||
|
return new XoroshiroRandomSource(0L, 0L);
|
||||||
|
}
|
||||||
|
if (deriver instanceof LegacyRandomSource.LegacyPositionalRandomFactory) {
|
||||||
|
return new SingleThreadedRandomSource(0L);
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final ThreadLocal<XoroshiroRandomSource> xoroshiro = ThreadLocal.withInitial(() -> new XoroshiroRandomSource(0L, 0L));
|
||||||
|
private static final ThreadLocal<SingleThreadedRandomSource> simple = ThreadLocal.withInitial(() -> new SingleThreadedRandomSource(0L));
|
||||||
|
|
||||||
|
public static void derive(PositionalRandomFactory deriver, RandomSource random, int x, int y, int z) {
|
||||||
|
if (deriver instanceof final XoroshiroRandomSource.XoroshiroPositionalRandomFactory deriver1) {
|
||||||
|
final Xoroshiro128PlusPlus implementation = ((XoroshiroRandomSource) random).randomNumberGenerator;
|
||||||
|
implementation.seedLo = (Mth.getSeed(x, y, z) ^ deriver1.seedLo());
|
||||||
|
implementation.seedHi = (deriver1.seedHi());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (deriver instanceof LegacyRandomSource.LegacyPositionalRandomFactory(long seed)) {
|
||||||
|
final SingleThreadedRandomSource random1 = (SingleThreadedRandomSource) random;
|
||||||
|
random1.setSeed(Mth.getSeed(x, y, z) ^ seed);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
throw new IllegalArgumentException();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,160 +0,0 @@
|
|||||||
package org.bxteam.divinemc.util.map;
|
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectMap;
|
|
||||||
import it.unimi.dsi.fastutil.ints.IntSet;
|
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectCollection;
|
|
||||||
import it.unimi.dsi.fastutil.objects.ObjectSet;
|
|
||||||
import org.bxteam.divinemc.util.CollectionWrapperUtil;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
public final class Int2ObjectConcurrentHashMap<V> implements Int2ObjectMap<V> {
|
|
||||||
private final ConcurrentHashMap<Integer, V> backing;
|
|
||||||
private V defaultReturnValue;
|
|
||||||
|
|
||||||
public Int2ObjectConcurrentHashMap() {
|
|
||||||
this(16);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Int2ObjectConcurrentHashMap(int initialCapacity) {
|
|
||||||
if (initialCapacity < 0) {
|
|
||||||
throw new IllegalArgumentException("Initial capacity cannot be negative: " + initialCapacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.backing = new ConcurrentHashMap<>(initialCapacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
public Int2ObjectConcurrentHashMap(Map<Integer, V> map) {
|
|
||||||
this(Math.max(16, map.size()));
|
|
||||||
putAll(Objects.requireNonNull(map, "Source map cannot be null"));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public V get(int key) {
|
|
||||||
V value = backing.get(key);
|
|
||||||
return value != null ? value : defaultReturnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public V get(Object key) {
|
|
||||||
V value = backing.get(key);
|
|
||||||
return value != null ? value : defaultReturnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isEmpty() {
|
|
||||||
return backing.isEmpty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsValue(Object value) {
|
|
||||||
return backing.containsValue(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void putAll(Map<? extends Integer, ? extends V> m) {
|
|
||||||
Objects.requireNonNull(m, "Source map cannot be null");
|
|
||||||
backing.putAll(m);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int size() {
|
|
||||||
return backing.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void defaultReturnValue(V rv) {
|
|
||||||
this.defaultReturnValue = rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public V defaultReturnValue() {
|
|
||||||
return defaultReturnValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ObjectSet<Entry<V>> int2ObjectEntrySet() {
|
|
||||||
return CollectionWrapperUtil.entrySetIntWrap(backing);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public IntSet keySet() {
|
|
||||||
return CollectionWrapperUtil.wrapIntSet(backing.keySet());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public ObjectCollection<V> values() {
|
|
||||||
return CollectionWrapperUtil.wrap(backing.values());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean containsKey(int key) {
|
|
||||||
return backing.containsKey(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public V put(int key, V value) {
|
|
||||||
return backing.put(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public V remove(int key) {
|
|
||||||
return backing.remove(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void clear() {
|
|
||||||
backing.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
public V compute(int key, java.util.function.BiFunction<? super Integer, ? super V, ? extends V> remappingFunction) {
|
|
||||||
Objects.requireNonNull(remappingFunction);
|
|
||||||
return backing.compute(key, remappingFunction);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConcurrentHashMap<Integer, V> concurrentView() {
|
|
||||||
return backing;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean equals(Object o) {
|
|
||||||
if (this == o) return true;
|
|
||||||
if (!(o instanceof Int2ObjectMap<?> that)) return false;
|
|
||||||
|
|
||||||
if (size() != that.size()) return false;
|
|
||||||
return int2ObjectEntrySet().containsAll(that.int2ObjectEntrySet());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int hashCode() {
|
|
||||||
return backing.hashCode();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return backing.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
public V getOrDefault(int key, V defaultValue) {
|
|
||||||
V value = get(key);
|
|
||||||
return value != null ? value : defaultValue;
|
|
||||||
}
|
|
||||||
|
|
||||||
public V putIfAbsent(int key, V value) {
|
|
||||||
return backing.putIfAbsent(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean remove(int key, Object value) {
|
|
||||||
return backing.remove(key, value);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean replace(int key, V oldValue, V newValue) {
|
|
||||||
return backing.replace(key, oldValue, newValue);
|
|
||||||
}
|
|
||||||
|
|
||||||
public V replace(int key, V value) {
|
|
||||||
return backing.replace(key, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user