From 199ec48f853f55a78124a5ccbcd00f521de2d3aa Mon Sep 17 00:00:00 2001 From: Glease <4586901+Glease@users.noreply.github.com> Date: Tue, 16 Nov 2021 02:00:00 +0800 Subject: underground oil and pollution persistence form rework Signed-off-by: Glease <4586901+Glease@users.noreply.github.com> --- .../java/gregtech/common/GT_UndergroundOil.java | 267 ++++++++++++++++----- 1 file changed, 207 insertions(+), 60 deletions(-) (limited to 'src/main/java/gregtech/common/GT_UndergroundOil.java') diff --git a/src/main/java/gregtech/common/GT_UndergroundOil.java b/src/main/java/gregtech/common/GT_UndergroundOil.java index 1f45b5fca9..cc6771dc90 100644 --- a/src/main/java/gregtech/common/GT_UndergroundOil.java +++ b/src/main/java/gregtech/common/GT_UndergroundOil.java @@ -5,22 +5,29 @@ import gregtech.api.interfaces.tileentity.IGregTechTileEntity; import gregtech.api.objects.GT_UO_Dimension; import gregtech.api.objects.GT_UO_Fluid; import gregtech.api.objects.XSTR; -import net.minecraft.world.ChunkCoordIntPair; +import gregtech.api.util.GT_ChunkAssociatedData; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; -import net.minecraftforge.fluids.FluidRegistry; +import net.minecraftforge.event.world.ChunkDataEvent; +import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; -import java.util.HashMap; +import javax.annotation.Nullable; +import javax.annotation.ParametersAreNonnullByDefault; +import java.io.DataInput; +import java.io.DataOutput; +import java.io.IOException; +import java.util.Objects; +import java.util.WeakHashMap; import static gregtech.api.objects.XSTR.XSTR_INSTANCE; -import static gregtech.common.GT_Proxy.*; /** * Created by Tec on 29.04.2017. */ public class GT_UndergroundOil { public static final short DIVIDER=5000; + private static final GT_UndergroundOilStore STORAGE = new GT_UndergroundOilStore(); public static FluidStack undergroundOilReadInformation(IGregTechTileEntity te){ return undergroundOil(te.getWorld().getChunkFromBlockCoords(te.getXCoord(),te.getZCoord()),-1); @@ -37,81 +44,221 @@ public class GT_UndergroundOil { //Returns whole content for information purposes -> when drainSpeedCoefficient < 0 //Else returns extracted fluidStack if amount > 0, or null otherwise public static FluidStack undergroundOil(Chunk chunk, float readOrDrainCoefficient) { - World aWorld = chunk.worldObj; - int dimensionId=aWorld.provider.dimensionId; - GT_UO_Dimension dimension=GT_Mod.gregtechproxy.mUndergroundOil.GetDimension(dimensionId); - if(dimension==null) return null; - - //Read hash map - HashMap chunkData = dimensionWiseChunkData.get(dimensionId); - if(chunkData==null){ - chunkData=new HashMap<>(1024); - dimensionWiseChunkData.put(dimensionId,chunkData); - } - - int[] tInts = chunkData.get(chunk.getChunkCoordIntPair()); - - if(tInts==null) tInts=getDefaultChunkDataOnCreation();//init if null - else if(tInts[GTOIL]==0){//FAST stop - //can return 0 amount stack for info :D - return readOrDrainCoefficient>=0 ? null : new FluidStack(FluidRegistry.getFluid(tInts[GTOILFLUID]),0); - } - - //GEN IT TO GET OBJECT... - final XSTR tRandom = new XSTR(aWorld.getSeed() + dimensionId * 2 + - (chunk.getChunkCoordIntPair().chunkXPos>>3) + - 8267 * (chunk.getChunkCoordIntPair().chunkZPos>>3)); - - GT_UO_Fluid uoFluid = dimension.getRandomFluid(tRandom); - - //Fluid stack holder - FluidStack fluidInChunk; - - //Set fluid stack from uoFluid - if (uoFluid == null || uoFluid.getFluid()==null){ - tInts[GTOILFLUID]=Integer.MAX_VALUE;//null fluid pointer... kind of - tInts[GTOIL]=0; - chunkData.put(chunk.getChunkCoordIntPair(),tInts);//update hash map + ChunkData chunkData = STORAGE.get(chunk); + if (chunkData.getVein() == null || chunkData.getFluid() == null) // nothing here... return null; - } else { - if(tInts[GTOILFLUID]== uoFluid.getFluid().getID()){//if stored fluid matches uoFluid - fluidInChunk = new FluidStack(uoFluid.getFluid(),tInts[GTOIL]); - }else{ - fluidInChunk = new FluidStack(uoFluid.getFluid(), uoFluid.getRandomAmount(tRandom)); - fluidInChunk.amount=(int)((float)fluidInChunk.amount*(0.75f+(XSTR_INSTANCE.nextFloat()/2f)));//Randomly change amounts by +/- 25% - } - tInts[GTOIL]=fluidInChunk.amount; - tInts[GTOILFLUID]=fluidInChunk.getFluidID(); - } - //do stuff on it if needed + FluidStack fluidInChunk = new FluidStack(chunkData.getFluid(), 0); if(readOrDrainCoefficient>=0){ - int fluidExtracted=(int)Math.floor(fluidInChunk.amount * (double) readOrDrainCoefficient / DIVIDER); - double averageDecrease=uoFluid.DecreasePerOperationAmount * (double)readOrDrainCoefficient; + int fluidExtracted = (int) Math.floor(chunkData.getAmount() * (double) readOrDrainCoefficient / DIVIDER); + double averageDecrease = chunkData.getVein().DecreasePerOperationAmount * (double) readOrDrainCoefficient; int decrease=(int)Math.ceil(averageDecrease); - if(fluidExtracted<=0 || fluidInChunk.amount<=decrease){//decrease - here it is max value of extraction for easy check - fluidInChunk=null; - tInts[GTOIL]=0;//so in next access it will stop way above + if (fluidExtracted <= 0 || chunkData.amount <= decrease) {//decrease - here it is max value of extraction for easy check + chunkData.setAmount(0); }else{ fluidInChunk.amount = fluidExtracted;//give appropriate amount - if(XSTR_INSTANCE.nextFloat()<(decrease-averageDecrease)) decrease--;//use XSTR_INSTANCE to "subtract double from int" + if (XSTR_INSTANCE.nextFloat() < (decrease - averageDecrease)) + decrease--;//use XSTR_INSTANCE to "subtract double from int" //ex. // averageDecrease=3.9 // decrease= ceil from 3.9 = 4 // decrease-averageDecrease=0.1 -> chance to subtract 1 // if XSTR_INSTANCE is < chance then subtract 1 - tInts[GTOIL]-=decrease;//diminish amount, "randomly" adjusted to double value (averageDecrease) + chunkData.changeAmount(-decrease);//diminish amount, "randomly" adjusted to double value (averageDecrease) } }else{//just get info if(fluidInChunk.amount<=DIVIDER){ fluidInChunk.amount=0;//return informative stack - tInts[GTOIL]=0;//so in next access it will stop way above + chunkData.setAmount(0); }else{ fluidInChunk.amount=fluidInChunk.amount/DIVIDER;//give moderate extraction speed } } - - chunkData.put(chunk.getChunkCoordIntPair(),tInts);//update hash map return fluidInChunk; } + + static void migrate(ChunkDataEvent.Load e) { + if (e.getData().hasKey("GTOIL") && e.getData().hasKey("GTOILFLUID")) { + ChunkData chunkData = STORAGE.get(e.getChunk()); + Fluid fluid = chunkData.getFluid(); + if (fluid != null && fluid.getID() == e.getData().getInteger("GTOIL")) + chunkData.setAmount(Math.min(chunkData.getAmount(), e.getData().getInteger("GTOILFLUID"))); + } + } + + /** + * Revamped UO store. + *

+ * Primary functionality: + * + *

+ * + *

Serialized form

+ *

+ * Since the exact file layout is controlled by the super class, here we only concern how each chunk's data is written. + *

Form A: Empty Chunk

+ *
    + *
  1. 4 bytes of 0
  2. + *
+ * + *

Form B: Normal Chunk

+ *
    + *
  1. 4 bytes unsigned integer. Vein Hash.
  2. + *
  3. UTF string. Vein Key.
  4. + *
  5. 4 bytes signed integer. Fluid amount.
  6. + *
+ * + * @author glease + */ + @ParametersAreNonnullByDefault + private static class GT_UndergroundOilStore extends GT_ChunkAssociatedData { + private static final GT_UndergroundOil.ChunkData NIL_FLUID_STACK = new GT_UndergroundOil.ChunkData(-1, null, null, false); + private static final WeakHashMap hashes = new WeakHashMap<>(); + + private GT_UndergroundOilStore() { + super("UO", GT_UndergroundOil.ChunkData.class, 64, (byte) 0, false); + } + + @Override + protected void writeElement(DataOutput output, ChunkData element, World world, int chunkX, int chunkZ) throws IOException { + /* see class javadoc for explanation */ + output.writeInt(element.getVeinHash()); + if (element.getVeinKey() == null) return; + output.writeUTF(element.getVeinKey()); + if (element.getAmount() > 0 && element.getFluid() != null) { + output.writeInt(element.getAmount()); + } else { + output.writeInt(-1); + } + } + + @Override + protected GT_UndergroundOil.ChunkData readElement(DataInput input, int version, World world, int chunkX, int chunkZ) throws IOException { + /* see class javadoc for explanation */ + if (version != 0) + throw new IOException("Region file corrupted"); + GT_UndergroundOil.ChunkData pristine = createElement(world, chunkX, chunkZ); + int hash = input.readInt(); + String veinKey = hash != 0 ? input.readUTF() : null; + int amount = hash != 0 ? input.readInt() : -1; + if (hash != pristine.veinHash || !Objects.equals(veinKey, pristine.getVeinKey())) { + // vein config changed. use regen-ed data. + return pristine; + } + if (hash == 0) + return NIL_FLUID_STACK; + return new GT_UndergroundOil.ChunkData(amount, GT_Mod.gregtechproxy.mUndergroundOil.GetDimension(world.provider.dimensionId).getUOFluid(veinKey), veinKey); + } + + @Override + protected GT_UndergroundOil.ChunkData createElement(World world, int chunkX, int chunkZ) { + int dimensionId = world.provider.dimensionId; + GT_UO_Dimension dimension = GT_Mod.gregtechproxy.mUndergroundOil.GetDimension(dimensionId); + if (dimension == null) return NIL_FLUID_STACK; + // prepare RNG 🙏 🙏 🙏 + final XSTR tRandom = new XSTR(world.getSeed() + dimensionId * 2L + (chunkX >> 3) + 8267L * (chunkZ >> 3)); + GT_UO_Fluid uoFluid = dimension.getRandomFluid(tRandom); + // nothing here :( + if (uoFluid == null || uoFluid.getFluid() == null) return NIL_FLUID_STACK; + // offset each chunk's fluid amount by +-25% + int amount = (int) ((float) uoFluid.getRandomAmount(tRandom) * (0.75f + (XSTR_INSTANCE.nextFloat() / 2f))); + return new GT_UndergroundOil.ChunkData(amount, uoFluid, dimension.getUOFluidKey(uoFluid), false); + } + + private static int hash(@Nullable GT_UO_Fluid fluid) { + if (fluid == null) + return 0; + int result = fluid.Registry.hashCode(); + result = 31 * result + fluid.MaxAmount; + result = 31 * result + fluid.MinAmount; + result = 31 * result + fluid.Chance; + result = 31 * result + fluid.DecreasePerOperationAmount; + return result == 0 ? 1 : result; + } + + } + + /** + * Represent the amount of fluid in a given chunk. + */ + private static final class ChunkData implements GT_ChunkAssociatedData.IData { + private final Fluid fluid; + @Nullable + private final GT_UO_Fluid vein; + private final String veinKey; + private final int veinHash; + private int amount; + private boolean dirty; + + private ChunkData(int amount, GT_UO_Fluid veinKey, String veinID) { + this(amount, veinKey, veinID, true); + } + + private ChunkData(int amount, @Nullable GT_UO_Fluid vein, @Nullable String veinKey, boolean dirty) { + this.amount = amount; + this.vein = vein; + this.dirty = dirty; + if (vein == null) { + fluid = null; + this.veinKey = null; + veinHash = 0; + } else { + fluid = vein.getFluid(); + this.veinKey = veinKey; + veinHash = GT_UndergroundOilStore.hashes.computeIfAbsent(vein, GT_UndergroundOilStore::hash); + } + } + + /** + * The current fluid type. {@code null} if vein is generated to be empty. + */ + @Nullable + public Fluid getFluid() { + return fluid; + } + + /** + * Current fluid amount. Might be 0 if empty. Cannot be negative + */ + public int getAmount() { + return amount; + } + + public void setAmount(int amount) { + if (this.amount != amount) + dirty = true; + this.amount = Math.max(0, amount); + } + + public void changeAmount(int delta) { + if (delta != 0) + dirty = true; + this.amount = Math.max(0, amount - delta); + } + + @Nullable + public GT_UO_Fluid getVein() { + return vein; + } + + /** + * The vein ID. Might be null if generated to be empty. + */ + @Nullable + public String getVeinKey() { + return veinKey; + } + + public int getVeinHash() { + return veinHash; + } + + @Override + public boolean isSameAsDefault() { + return dirty; + } + } } -- cgit From 4e14067640c22afb891fab4c61431813fc28a6a0 Mon Sep 17 00:00:00 2001 From: Glease <4586901+Glease@users.noreply.github.com> Date: Sun, 21 Nov 2021 01:17:33 +0800 Subject: Fix underground oil being all 0 and not migrating properly Signed-off-by: Glease <4586901+Glease@users.noreply.github.com> --- src/main/java/gregtech/common/GT_UndergroundOil.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'src/main/java/gregtech/common/GT_UndergroundOil.java') diff --git a/src/main/java/gregtech/common/GT_UndergroundOil.java b/src/main/java/gregtech/common/GT_UndergroundOil.java index cc6771dc90..11bbd6431b 100644 --- a/src/main/java/gregtech/common/GT_UndergroundOil.java +++ b/src/main/java/gregtech/common/GT_UndergroundOil.java @@ -66,12 +66,11 @@ public class GT_UndergroundOil { // if XSTR_INSTANCE is < chance then subtract 1 chunkData.changeAmount(-decrease);//diminish amount, "randomly" adjusted to double value (averageDecrease) } - }else{//just get info - if(fluidInChunk.amount<=DIVIDER){ - fluidInChunk.amount=0;//return informative stack + } else {//just get info + if (chunkData.amount <= DIVIDER) { chunkData.setAmount(0); - }else{ - fluidInChunk.amount=fluidInChunk.amount/DIVIDER;//give moderate extraction speed + } else { + fluidInChunk.amount = chunkData.amount / DIVIDER;//give moderate extraction speed } } return fluidInChunk; @@ -81,8 +80,8 @@ public class GT_UndergroundOil { if (e.getData().hasKey("GTOIL") && e.getData().hasKey("GTOILFLUID")) { ChunkData chunkData = STORAGE.get(e.getChunk()); Fluid fluid = chunkData.getFluid(); - if (fluid != null && fluid.getID() == e.getData().getInteger("GTOIL")) - chunkData.setAmount(Math.min(chunkData.getAmount(), e.getData().getInteger("GTOILFLUID"))); + if (fluid != null && fluid.getID() == e.getData().getInteger("GTOILFLUID")) + chunkData.setAmount(Math.min(0, Math.min(chunkData.getAmount(), e.getData().getInteger("GTOIL")))); } } -- cgit From 913379a51c0f808ca0e38f38b66af43f2b8ebb0c Mon Sep 17 00:00:00 2001 From: Glease <4586901+Glease@users.noreply.github.com> Date: Sun, 21 Nov 2021 17:00:46 +0800 Subject: Ensure UO is generated in a consistent way instead of depending on positions of stars and stuff Also fixes buildscript and excluded generated source code from git Signed-off-by: Glease <4586901+Glease@users.noreply.github.com> --- .gitignore | 4 +++ build.gradle | 3 +- .../java/gregtech/common/GT_UndergroundOil.java | 35 +++++++++++++++------- 3 files changed, 30 insertions(+), 12 deletions(-) (limited to 'src/main/java/gregtech/common/GT_UndergroundOil.java') diff --git a/.gitignore b/.gitignore index 3beafd6561..9b4674ed8f 100644 --- a/.gitignore +++ b/.gitignore @@ -95,3 +95,7 @@ libs/ *.errored /build/ /run + +# Generated sources + +src/main/generated diff --git a/build.gradle b/build.gradle index 5f4aad8103..4505a0218d 100644 --- a/build.gradle +++ b/build.gradle @@ -15,7 +15,7 @@ buildscript { } } dependencies { - classpath 'com.github.GTNH2:ForgeGradle:FG_1.2-SNAPSHOT' + classpath 'com.github.GTNewHorizons:ForgeGradle:stable-2021-11-20' } } @@ -111,7 +111,6 @@ dependencies { compileOnly 'commons-io:commons-io:2.4' compileOnly 'com.google.auto.value:auto-value-annotations:1.8.2' annotationProcessor 'com.google.auto.value:auto-value:1.8.2' - compileOnly "eu.usrv:YAMCore:${config.minecraft.version}-${config.yamcore.version}:deobf" compileOnly "tconstruct:TConstruct:${config.minecraft.version}-${config.tconstruct.version}:deobf" compileOnly "codechicken:Translocator:${config.minecraft.version}-${config.translocators.version}:dev" compileOnly "net.sengir.forestry:forestry_${config.minecraft.version}:${config.forestry.version}:dev" diff --git a/src/main/java/gregtech/common/GT_UndergroundOil.java b/src/main/java/gregtech/common/GT_UndergroundOil.java index 11bbd6431b..21b681de4a 100644 --- a/src/main/java/gregtech/common/GT_UndergroundOil.java +++ b/src/main/java/gregtech/common/GT_UndergroundOil.java @@ -11,6 +11,7 @@ import net.minecraft.world.chunk.Chunk; import net.minecraftforge.event.world.ChunkDataEvent; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidStack; +import org.apache.commons.lang3.tuple.Pair; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; @@ -28,6 +29,7 @@ import static gregtech.api.objects.XSTR.XSTR_INSTANCE; public class GT_UndergroundOil { public static final short DIVIDER=5000; private static final GT_UndergroundOilStore STORAGE = new GT_UndergroundOilStore(); + private static final ChunkData NIL_FLUID_STACK = new ChunkData(-1, null, null, false); public static FluidStack undergroundOilReadInformation(IGregTechTileEntity te){ return undergroundOil(te.getWorld().getChunkFromBlockCoords(te.getXCoord(),te.getZCoord()),-1); @@ -76,6 +78,25 @@ public class GT_UndergroundOil { return fluidInChunk; } + /** + * Get the deposit as if it is never exploited + * @return UO fluid kind and amount, or null if nothing here. + */ + public static Pair getPristineAmount(World world, int chunkX, int chunkZ) { + int dimensionId = world.provider.dimensionId; + GT_UO_Dimension dimension = GT_Mod.gregtechproxy.mUndergroundOil.GetDimension(dimensionId); + if (dimension == null) return null; + // prepare RNG 🙏 🙏 🙏 + final XSTR tVeinRNG = new XSTR(world.getSeed() + dimensionId * 2L + (chunkX >> 3) + 8267L * (chunkZ >> 3)); + final XSTR tChunkRNG = new XSTR(world.getSeed() + dimensionId * 2L + chunkX + 8267L * chunkZ); + GT_UO_Fluid uoFluid = dimension.getRandomFluid(tVeinRNG); + // nothing here :( + if (uoFluid == null || uoFluid.getFluid() == null) return null; + // offset each chunk's fluid amount by +-25% + int amount = (int) ((float) uoFluid.getRandomAmount(tVeinRNG) * (0.75f + (tChunkRNG.nextFloat() / 2f))); + return Pair.of(uoFluid, amount); + } + static void migrate(ChunkDataEvent.Load e) { if (e.getData().hasKey("GTOIL") && e.getData().hasKey("GTOILFLUID")) { ChunkData chunkData = STORAGE.get(e.getChunk()); @@ -114,7 +135,6 @@ public class GT_UndergroundOil { */ @ParametersAreNonnullByDefault private static class GT_UndergroundOilStore extends GT_ChunkAssociatedData { - private static final GT_UndergroundOil.ChunkData NIL_FLUID_STACK = new GT_UndergroundOil.ChunkData(-1, null, null, false); private static final WeakHashMap hashes = new WeakHashMap<>(); private GT_UndergroundOilStore() { @@ -154,17 +174,12 @@ public class GT_UndergroundOil { @Override protected GT_UndergroundOil.ChunkData createElement(World world, int chunkX, int chunkZ) { + Pair pristine = getPristineAmount(world, chunkX, chunkZ); + if (pristine == null) + return NIL_FLUID_STACK; int dimensionId = world.provider.dimensionId; GT_UO_Dimension dimension = GT_Mod.gregtechproxy.mUndergroundOil.GetDimension(dimensionId); - if (dimension == null) return NIL_FLUID_STACK; - // prepare RNG 🙏 🙏 🙏 - final XSTR tRandom = new XSTR(world.getSeed() + dimensionId * 2L + (chunkX >> 3) + 8267L * (chunkZ >> 3)); - GT_UO_Fluid uoFluid = dimension.getRandomFluid(tRandom); - // nothing here :( - if (uoFluid == null || uoFluid.getFluid() == null) return NIL_FLUID_STACK; - // offset each chunk's fluid amount by +-25% - int amount = (int) ((float) uoFluid.getRandomAmount(tRandom) * (0.75f + (XSTR_INSTANCE.nextFloat() / 2f))); - return new GT_UndergroundOil.ChunkData(amount, uoFluid, dimension.getUOFluidKey(uoFluid), false); + return new GT_UndergroundOil.ChunkData(pristine.getRight(), pristine.getLeft(), dimension.getUOFluidKey(pristine.getLeft()), false); } private static int hash(@Nullable GT_UO_Fluid fluid) { -- cgit