aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/gregtech/api
diff options
context:
space:
mode:
authorGlease <4586901+Glease@users.noreply.github.com>2021-11-16 02:00:00 +0800
committerGlease <4586901+Glease@users.noreply.github.com>2021-11-16 02:11:07 +0800
commit199ec48f853f55a78124a5ccbcd00f521de2d3aa (patch)
treeb6bc10a8a0f3305ea5f960b8640d7bb20f170b2b /src/main/java/gregtech/api
parent985f240b0e62d43f617da66eab06808ab45f7a5d (diff)
downloadGT5-Unofficial-199ec48f853f55a78124a5ccbcd00f521de2d3aa.tar.gz
GT5-Unofficial-199ec48f853f55a78124a5ccbcd00f521de2d3aa.tar.bz2
GT5-Unofficial-199ec48f853f55a78124a5ccbcd00f521de2d3aa.zip
underground oil and pollution persistence form rework
Signed-off-by: Glease <4586901+Glease@users.noreply.github.com>
Diffstat (limited to 'src/main/java/gregtech/api')
-rw-r--r--src/main/java/gregtech/api/enums/GT_Values.java4
-rw-r--r--src/main/java/gregtech/api/objects/GT_UO_Dimension.java7
-rw-r--r--src/main/java/gregtech/api/util/GT_ChunkAssociatedData.java435
-rw-r--r--src/main/java/gregtech/api/util/GT_Utility.java79
4 files changed, 505 insertions, 20 deletions
diff --git a/src/main/java/gregtech/api/enums/GT_Values.java b/src/main/java/gregtech/api/enums/GT_Values.java
index f30360ca58..6505c34423 100644
--- a/src/main/java/gregtech/api/enums/GT_Values.java
+++ b/src/main/java/gregtech/api/enums/GT_Values.java
@@ -272,6 +272,10 @@ public class GT_Values {
*/
public static boolean debugEntityCramming = false;
/**
+ * Debug parameter for {@link gregtech.api.util.GT_ChunkAssociatedData}
+ */
+ public static boolean debugWorldData = false;
+ /**
* Number of ticks between sending sound packets to clients for electric machines. Default is 1.5 seconds. Trying to mitigate lag and FPS drops.
*/
public static int ticksBetweenSounds = 30;
diff --git a/src/main/java/gregtech/api/objects/GT_UO_Dimension.java b/src/main/java/gregtech/api/objects/GT_UO_Dimension.java
index 1c090eb9b5..0d05e6d229 100644
--- a/src/main/java/gregtech/api/objects/GT_UO_Dimension.java
+++ b/src/main/java/gregtech/api/objects/GT_UO_Dimension.java
@@ -39,4 +39,11 @@ public class GT_UO_Dimension {
return null;
}
+ public String getUOFluidKey(GT_UO_Fluid uoFluid) {
+ return fFluids.inverse().get(uoFluid);
+ }
+
+ public GT_UO_Fluid getUOFluid(String key) {
+ return fFluids.get(key);
+ }
}
diff --git a/src/main/java/gregtech/api/util/GT_ChunkAssociatedData.java b/src/main/java/gregtech/api/util/GT_ChunkAssociatedData.java
new file mode 100644
index 0000000000..b28cb429b4
--- /dev/null
+++ b/src/main/java/gregtech/api/util/GT_ChunkAssociatedData.java
@@ -0,0 +1,435 @@
+package gregtech.api.util;
+
+import cpw.mods.fml.common.eventhandler.SubscribeEvent;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import net.minecraft.world.ChunkCoordIntPair;
+import net.minecraft.world.World;
+import net.minecraft.world.chunk.Chunk;
+import net.minecraftforge.common.MinecraftForge;
+import net.minecraftforge.event.world.WorldEvent;
+import org.apache.commons.io.FileUtils;
+
+import javax.annotation.ParametersAreNonnullByDefault;
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.DataOutput;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.lang.ref.WeakReference;
+import java.lang.reflect.Array;
+import java.nio.file.AtomicMoveNotSupportedException;
+import java.nio.file.Files;
+import java.nio.file.StandardCopyOption;
+import java.util.Arrays;
+import java.util.Map;
+import java.util.Objects;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.function.Function;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * A utility to save all kinds of data that is a function of any chunk.
+ * <p>
+ * GregTech takes care of saving and loading the data from disk, and an efficient mechanism to locate it.
+ * Subclass only need to define the exact scheme of each element data (by overriding the three protected abstract method)
+ * <p>
+ * Oh, there is no limit on how large your data is, though you'd not have the familiar NBT interface, but DataOutput
+ * should be reasonably common anyway.
+ * <p>
+ * It should be noted this class is NOT thread safe.
+ * <p>
+ * Element cannot be null.
+ * <p>
+ * TODO: Implement automatic region unloading.
+ *
+ * @param <T> data element type
+ * @author glease
+ */
+@ParametersAreNonnullByDefault
+public abstract class GT_ChunkAssociatedData<T extends GT_ChunkAssociatedData.IData> {
+ private static final Map<String, GT_ChunkAssociatedData<?>> instances = new ConcurrentHashMap<>();
+ private static final int IO_PARALLELISM = Math.min(8, Math.max(1, Runtime.getRuntime().availableProcessors()) * 2 / 3);
+ private static final ExecutorService IO_WORKERS = Executors.newWorkStealingPool(IO_PARALLELISM);
+ private static final Pattern FILE_PATTERN = Pattern.compile("(.+)\\.(-?\\d+)\\.(-?\\d+)\\.dat");
+
+ static {
+ // register event handler
+ new EventHandler();
+ }
+
+ protected final String mId;
+ protected final Class<T> elementtype;
+ private final int regionLength;
+ private final int version;
+ private final boolean saveDefaults;
+ /**
+ * Data is stored as a `(world id -> (super region id -> super region data))` hash map.
+ * where super region's size is determined by regionSize.
+ * Here it is called super region, to not confuse with vanilla's regions.
+ */
+ private final Map<Integer, Map<ChunkCoordIntPair, SuperRegion>> masterMap = new ConcurrentHashMap<>();
+
+ /**
+ * Initialize this instance.
+ *
+ * @param aId An arbitrary, but globally unique identifier for what this data is
+ * @param elementType The class of this element type. Used to create arrays.
+ * @param regionLength The length of one super region. Each super region will contain {@code regionLength * regionLength} chunks
+ * @param version An integer marking the version of this data. Useful later when the data's serialized form changed.
+ */
+ protected GT_ChunkAssociatedData(String aId, Class<T> elementType, int regionLength, byte version, boolean saveDefaults) {
+ if (regionLength * regionLength > Short.MAX_VALUE || regionLength <= 0)
+ throw new IllegalArgumentException("Region invalid: " + regionLength);
+ if (!IData.class.isAssignableFrom(elementType))
+ throw new IllegalArgumentException("Data type invalid");
+ if (aId.contains("."))
+ throw new IllegalArgumentException("ID cannot contains dot");
+ this.mId = aId;
+ this.elementtype = elementType;
+ this.regionLength = regionLength;
+ this.version = version;
+ this.saveDefaults = saveDefaults;
+ if (instances.putIfAbsent(aId, this) != null)
+ throw new IllegalArgumentException("Duplicate GT_ChunkAssociatedData: " + aId);
+ }
+
+ private ChunkCoordIntPair getRegionID(int aChunkX, int aChunkZ) {
+ return new ChunkCoordIntPair(aChunkX / regionLength, aChunkZ / regionLength);
+ }
+
+ /**
+ * Get a reference to data of the chunk that tile entity is in.
+ * The returned reference should be mutable.
+ */
+ public final T get(IGregTechTileEntity tileEntity) {
+ return get(tileEntity.getWorld(), tileEntity.getXCoord() >> 4, tileEntity.getZCoord() >> 4);
+ }
+
+ public final T get(Chunk chunk) {
+ return get(chunk.worldObj, chunk.xPosition, chunk.zPosition);
+ }
+
+ public final T get(World world, ChunkCoordIntPair coord) {
+ return get(world, coord.chunkXPos, coord.chunkZPos);
+ }
+
+ public final T get(World world, int chunkX, int chunkZ) {
+ SuperRegion region = masterMap.computeIfAbsent(world.provider.dimensionId, ignored -> new ConcurrentHashMap<>())
+ .computeIfAbsent(getRegionID(chunkX, chunkZ), c -> new SuperRegion(world, c));
+ return region.get(chunkX % regionLength, chunkZ % regionLength);
+ }
+
+ protected final void set(World world, int chunkX, int chunkZ, T data) {
+ SuperRegion region = masterMap.computeIfAbsent(world.provider.dimensionId, ignored -> new ConcurrentHashMap<>())
+ .computeIfAbsent(getRegionID(chunkX, chunkZ), c -> new SuperRegion(world, c));
+ region.set(chunkX % regionLength, chunkZ % regionLength, data);
+ }
+
+ protected final boolean isCreated(int dimId, int chunkX, int chunkZ) {
+ Map<ChunkCoordIntPair, SuperRegion> dimData = masterMap.getOrDefault(dimId, null);
+ if (dimData == null) return false;
+
+ SuperRegion region = dimData.getOrDefault(getRegionID(chunkX, chunkZ), null);
+ if (region == null) return false;
+
+ return region.isCreated(chunkX % regionLength, chunkZ % regionLength);
+ }
+
+ public void clear() {
+ if (GT_Values.debugWorldData) {
+ long dirtyRegionCount = masterMap.values().stream()
+ .flatMap(m -> m.values().stream())
+ .filter(SuperRegion::isDirty)
+ .count();
+ if (dirtyRegionCount > 0)
+ GT_Log.out.println("Clearing ChunkAssociatedData with " + dirtyRegionCount + " regions dirty. Data might have been lost!");
+ }
+ masterMap.clear();
+ }
+
+ public void save() {
+ saveRegions(masterMap.values().stream().flatMap(m -> m.values().stream()));
+ }
+
+ public void save(World world) {
+ saveRegions(masterMap.get(world.provider.dimensionId).values().stream());
+ }
+
+ private void saveRegions(Stream<SuperRegion> stream) {
+ stream.filter(r -> !r.isDirty())
+ .map(c -> (Runnable) c::save)
+ .map(r -> CompletableFuture.runAsync(r, IO_WORKERS))
+ .reduce(CompletableFuture::allOf)
+ .ifPresent(f -> {
+ try {
+ f.get();
+ } catch (Exception e) {
+ GT_Log.err.println("Data save error: " + mId);
+ e.printStackTrace(GT_Log.err);
+ }
+ });
+ }
+
+ protected abstract void writeElement(DataOutput output, T element, World world, int chunkX, int chunkZ) throws IOException;
+
+ protected abstract T readElement(DataInput input, int version, World world, int chunkX, int chunkZ) throws IOException;
+
+ protected abstract T createElement(World world, int chunkX, int chunkZ);
+
+ /**
+ * Clear all mappings, regardless of whether they are dirty
+ */
+ public static void clearAll() {
+ for (GT_ChunkAssociatedData<?> d : instances.values()) d.clear();
+ }
+
+ /**
+ * Save all mappings
+ */
+ public static void saveAll() {
+ for (GT_ChunkAssociatedData<?> d : instances.values()) d.save();
+ }
+
+ /**
+ * Load data for all chunks for a given world.
+ * Current data for that world will be discarded. If this is what you intended, call {@link #save(World)} beforehand.
+ * <p>
+ * Be aware of the memory consumption though.
+ */
+ protected void loadAll(World w) {
+ if (GT_Values.debugWorldData && masterMap.containsKey(w.provider.dimensionId))
+ GT_Log.err.println("Reloading ChunkAssociatedData " + mId + " for world " + w.provider.dimensionId + " discards old data!");
+ if (!getSaveDirectory(w).isDirectory())
+ // nothing to load...
+ return;
+ try {
+ Map<ChunkCoordIntPair, SuperRegion> worldData = Files.list(getSaveDirectory(w).toPath())
+ .map(f -> {
+ Matcher matcher = FILE_PATTERN.matcher(f.getFileName().toString());
+ return matcher.matches() ? matcher : null;
+ })
+ .filter(Objects::nonNull)
+ .filter(m -> mId.equals(m.group(1)))
+ .map(m -> CompletableFuture.supplyAsync(() -> new SuperRegion(w, Integer.parseInt(m.group(2)), Integer.parseInt(m.group(3))), IO_WORKERS))
+ .map(f -> {
+ try {
+ return f.get();
+ } catch (Exception e) {
+ GT_Log.err.println("Error loading region");
+ e.printStackTrace(GT_Log.err);
+ return null;
+ }
+ })
+ .filter(Objects::nonNull)
+ .collect(Collectors.toMap(SuperRegion::getCoord, Function.identity()));
+ masterMap.put(w.provider.dimensionId, worldData);
+ } catch (IOException e) {
+ GT_Log.err.println("Error loading all region");
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+
+ protected File getSaveDirectory(World w) {
+ return new File(w.getSaveHandler().getWorldDirectory(), "gregtech");
+ }
+
+ public interface IData {
+ /**
+ * @return Whether the data is different from chunk default
+ */
+ boolean isSameAsDefault();
+ }
+
+ protected final class SuperRegion {
+ private final T[] data = createData();
+ private final File backingStorage;
+ private final WeakReference<World> world;
+ private final ChunkCoordIntPair coord;
+
+ private SuperRegion(World world, int chunkX, int chunkZ) {
+ this.world = new WeakReference<>(world);
+ this.coord = new ChunkCoordIntPair(chunkX, chunkZ);
+ backingStorage = new File(getSaveDirectory(world), String.format("%s.%d.%d.dat", mId, chunkX, chunkZ));
+ if (backingStorage.isFile())
+ load();
+ }
+
+ private SuperRegion(World world, ChunkCoordIntPair coord) {
+ this.world = new WeakReference<>(world);
+ this.coord = coord;
+ backingStorage = new File(getSaveDirectory(world), String.format("%s.%d.%d.dat", mId, coord.chunkXPos, coord.chunkZPos));
+ if (backingStorage.isFile())
+ load();
+ }
+
+ @SuppressWarnings("unchecked")
+ private T[] createData() {
+ return (T[]) Array.newInstance(elementtype, regionLength * regionLength);
+ }
+
+ public T get(int subRegionX, int subRegionZ) {
+ int index = getIndex(subRegionX, subRegionZ);
+ T datum = data[index];
+ if (datum == null) {
+ World world = Objects.requireNonNull(this.world.get());
+ T newElem = createElement(world, coord.chunkXPos * regionLength + subRegionX, coord.chunkZPos * regionLength + subRegionZ);
+ data[index] = newElem;
+ return newElem;
+ }
+ return datum;
+ }
+
+ public void set(int subRegionX, int subRegionZ, T data) {
+ this.data[getIndex(subRegionX, subRegionZ)] = data;
+ }
+
+ public boolean isCreated(int subRegionX, int subRegionZ) {
+ return this.data[getIndex(subRegionX, subRegionZ)] == null;
+ }
+
+ public ChunkCoordIntPair getCoord() {
+ return coord;
+ }
+
+ private int getIndex(int subRegionX, int subRegionY) {
+ return subRegionX * regionLength + subRegionY;
+ }
+
+ private int getChunkX(int index) {
+ return index / regionLength + coord.chunkXPos;
+ }
+
+ private int getChunkZ(int index) {
+ return index % regionLength + coord.chunkZPos;
+ }
+
+ public boolean isDirty() {
+ for (T datum : data) {
+ if (datum != null && datum.isSameAsDefault())
+ return true;
+ }
+ return false;
+ }
+
+ public void save() {
+ try {
+ save0();
+ } catch (IOException e) {
+ GT_Log.err.println("Error saving data " + backingStorage.getPath());
+ e.printStackTrace(GT_Log.err);
+ }
+ }
+
+ private void save0() throws IOException {
+ if (!isDirty())
+ return;
+ //noinspection ResultOfMethodCallIgnored
+ backingStorage.getParentFile().mkdirs();
+ File tmpFile = getTmpFile();
+ World world = Objects.requireNonNull(this.world.get(), "Attempting to save region of another world!");
+ try (DataOutputStream output = new DataOutputStream(new FileOutputStream(tmpFile))) {
+ int ptr = 0;
+ boolean nullRange = data[0] == null;
+ // write a magic byte as storage format version
+ output.writeByte(0);
+ // write a magic byte as data format version
+ output.writeByte(version);
+ output.writeBoolean(nullRange);
+ while (ptr < data.length) {
+ // work out how long is this range
+ int rangeStart = ptr;
+ while (ptr < data.length && (data[ptr] == null || (!saveDefaults && data[ptr].isSameAsDefault())) == nullRange)
+ ptr++;
+ // write range length
+ output.writeShort(ptr - rangeStart);
+ if (!nullRange)
+ // write element data
+ for (int i = rangeStart; i < ptr; i++)
+ writeElement(output, data[i], world, getChunkX(ptr), getChunkZ(ptr));
+ // or not
+ nullRange = !nullRange;
+ }
+ }
+ // first try to replace the destination file
+ // since atomic operation, no need to keep the backup in place
+ try {
+ Files.move(tmpFile.toPath(), backingStorage.toPath(), StandardCopyOption.REPLACE_EXISTING, StandardCopyOption.ATOMIC_MOVE);
+ } catch (AtomicMoveNotSupportedException ignored) {
+ // in case some dumb system/jre combination would cause this
+ // or if **somehow** two file inside the same directory belongs two separate filesystem
+ FileUtils.copyFile(tmpFile, backingStorage);
+ }
+ }
+
+ public void load() {
+ try {
+ loadFromFile(backingStorage);
+ } catch (IOException | RuntimeException e) {
+ GT_Log.err.println("Primary storage file broken in " + backingStorage.getPath());
+ e.printStackTrace(GT_Log.err);
+ // in case the primary storage is broken
+ try {
+ loadFromFile(getTmpFile());
+ } catch (IOException | RuntimeException e2) {
+ GT_Log.err.println("Backup storage file broken in " + backingStorage.getPath());
+ e2.printStackTrace(GT_Log.err);
+ }
+ }
+ }
+
+ private void loadFromFile(File file) throws IOException {
+ World world = Objects.requireNonNull(this.world.get(), "Attempting to load region of another world!");
+ try (DataInputStream input = new DataInputStream(new FileInputStream(file))) {
+ boolean nullRange = input.readBoolean();
+ int ptr = 0;
+ while (ptr != data.length) {
+ int rangeEnd = ptr + input.readUnsignedShort();
+ if (!nullRange) {
+ for (; ptr < rangeEnd; ptr++) {
+ data[ptr] = readElement(input, version, world, getChunkX(ptr), getChunkZ(ptr));
+ }
+ } else {
+ Arrays.fill(data, ptr, rangeEnd, null);
+ ptr = rangeEnd;
+ }
+ }
+ }
+ }
+
+ private File getTmpFile() {
+ return new File(backingStorage.getParentFile(), backingStorage.getName() + ".tmp");
+ }
+ }
+
+ public static class EventHandler {
+ private EventHandler() {
+ MinecraftForge.EVENT_BUS.register(this);
+ }
+
+ @SubscribeEvent
+ public void onWorldSave(WorldEvent.Save e) {
+ for (GT_ChunkAssociatedData<?> d : instances.values()) {
+ d.save(e.world);
+ }
+ }
+
+ @SubscribeEvent
+ public void onWorldUnload(WorldEvent.Unload e) {
+ for (GT_ChunkAssociatedData<?> d : instances.values()) {
+ // there is no need to explicitly do a save here
+ // forge will send a WorldEvent.Save on server thread before this event is distributed
+ d.masterMap.remove(e.world.provider.dimensionId);
+ }
+ }
+ }
+}
diff --git a/src/main/java/gregtech/api/util/GT_Utility.java b/src/main/java/gregtech/api/util/GT_Utility.java
index 16d22be9ef..2ae09b6adf 100644
--- a/src/main/java/gregtech/api/util/GT_Utility.java
+++ b/src/main/java/gregtech/api/util/GT_Utility.java
@@ -12,13 +12,24 @@ import gregtech.api.GregTech_API;
import gregtech.api.damagesources.GT_DamageSources;
import gregtech.api.damagesources.GT_DamageSources.DamageSourceHotItem;
import gregtech.api.enchants.Enchantment_Radioactivity;
-import gregtech.api.enums.*;
+import gregtech.api.enums.GT_Values;
+import gregtech.api.enums.ItemList;
+import gregtech.api.enums.Materials;
+import gregtech.api.enums.OrePrefixes;
+import gregtech.api.enums.SubTag;
+import gregtech.api.enums.Textures;
+import gregtech.api.enums.ToolDictNames;
import gregtech.api.events.BlockScanningEvent;
import gregtech.api.interfaces.IBlockContainer;
import gregtech.api.interfaces.IDebugableBlock;
import gregtech.api.interfaces.IProjectileItem;
import gregtech.api.interfaces.ITexture;
-import gregtech.api.interfaces.tileentity.*;
+import gregtech.api.interfaces.tileentity.IBasicEnergyContainer;
+import gregtech.api.interfaces.tileentity.ICoverable;
+import gregtech.api.interfaces.tileentity.IGregTechDeviceInformation;
+import gregtech.api.interfaces.tileentity.IGregTechTileEntity;
+import gregtech.api.interfaces.tileentity.IMachineProgress;
+import gregtech.api.interfaces.tileentity.IUpgradableMachine;
import gregtech.api.items.GT_EnergyArmor_Item;
import gregtech.api.items.GT_Generic_Item;
import gregtech.api.items.GT_MetaGenerated_Tool;
@@ -28,7 +39,7 @@ import gregtech.api.objects.GT_ItemStack;
import gregtech.api.objects.ItemData;
import gregtech.api.threads.GT_Runnable_Sound;
import gregtech.api.util.extensions.ArrayExt;
-import gregtech.common.GT_Proxy;
+import gregtech.common.GT_Pollution;
import gregtech.common.blocks.GT_Block_Ores_Abstract;
import ic2.api.recipe.IRecipeInput;
import ic2.api.recipe.RecipeInputItemStack;
@@ -37,7 +48,11 @@ import ic2.api.recipe.RecipeOutput;
import net.minecraft.block.Block;
import net.minecraft.enchantment.Enchantment;
import net.minecraft.enchantment.EnchantmentHelper;
-import net.minecraft.entity.*;
+import net.minecraft.entity.Entity;
+import net.minecraft.entity.EntityList;
+import net.minecraft.entity.EntityLiving;
+import net.minecraft.entity.EntityLivingBase;
+import net.minecraft.entity.EnumCreatureAttribute;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.entity.player.EntityPlayerMP;
@@ -59,9 +74,14 @@ import net.minecraft.potion.Potion;
import net.minecraft.potion.PotionEffect;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.tileentity.TileEntityChest;
-import net.minecraft.util.*;
+import net.minecraft.util.AxisAlignedBB;
+import net.minecraft.util.ChatComponentText;
+import net.minecraft.util.DamageSource;
+import net.minecraft.util.EnumChatFormatting;
+import net.minecraft.util.MathHelper;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
+import net.minecraft.world.chunk.Chunk;
import net.minecraftforge.common.DimensionManager;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.common.util.BlockSnapshot;
@@ -70,8 +90,13 @@ import net.minecraftforge.common.util.FakePlayerFactory;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.event.ForgeEventFactory;
import net.minecraftforge.event.world.BlockEvent;
-import net.minecraftforge.fluids.*;
+import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidContainerRegistry.FluidContainerData;
+import net.minecraftforge.fluids.FluidRegistry;
+import net.minecraftforge.fluids.FluidStack;
+import net.minecraftforge.fluids.FluidTankInfo;
+import net.minecraftforge.fluids.IFluidContainerItem;
+import net.minecraftforge.fluids.IFluidHandler;
import net.minecraftforge.oredict.OreDictionary;
import javax.annotation.Nullable;
@@ -79,16 +104,34 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.NumberFormat;
-import java.text.DecimalFormatSymbols;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
import java.util.Map.Entry;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.UUID;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.function.Supplier;
import static gregtech.GT_Mod.GT_FML_LOGGER;
-import static gregtech.api.enums.GT_Values.*;
-import static gregtech.common.GT_Proxy.GTPOLLUTION;
+import static gregtech.api.enums.GT_Values.D1;
+import static gregtech.api.enums.GT_Values.DW;
+import static gregtech.api.enums.GT_Values.E;
+import static gregtech.api.enums.GT_Values.GT;
+import static gregtech.api.enums.GT_Values.L;
+import static gregtech.api.enums.GT_Values.M;
+import static gregtech.api.enums.GT_Values.NW;
+import static gregtech.api.enums.GT_Values.V;
+import static gregtech.api.enums.GT_Values.W;
import static gregtech.common.GT_UndergroundOil.undergroundOilReadInformation;
/**
@@ -2186,23 +2229,19 @@ public class GT_Utility {
}
}
+ Chunk currentChunk = aWorld.getChunkFromBlockCoords(aX, aZ);
if (aPlayer.capabilities.isCreativeMode) {
- FluidStack tFluid = undergroundOilReadInformation(aWorld.getChunkFromBlockCoords(aX,aZ));//-# to only read
+ FluidStack tFluid = undergroundOilReadInformation(currentChunk);//-# to only read
if (tFluid!=null)
tList.add(EnumChatFormatting.GOLD + tFluid.getLocalizedName() + EnumChatFormatting.RESET + ": " + EnumChatFormatting.YELLOW + formatNumbers(tFluid.amount) + EnumChatFormatting.RESET + " L");
else
tList.add(EnumChatFormatting.GOLD + trans("201","Nothing") + EnumChatFormatting.RESET + ": " + EnumChatFormatting.YELLOW + '0' + EnumChatFormatting.RESET + " L");
}
// if(aPlayer.capabilities.isCreativeMode){
- int[] chunkData = GT_Proxy.dimensionWiseChunkData.get(aWorld.provider.dimensionId).get(aWorld.getChunkFromBlockCoords(aX,aZ).getChunkCoordIntPair());
- if(chunkData != null){
- if(chunkData[GTPOLLUTION]>0){
- tList.add(trans("202","Pollution in Chunk: ") + EnumChatFormatting.RED + formatNumbers(chunkData[GTPOLLUTION]) + EnumChatFormatting.RESET + trans("203"," gibbl"));
- }else{
- tList.add(EnumChatFormatting.GREEN+trans("204","No Pollution in Chunk! HAYO!")+EnumChatFormatting.RESET);
- }
- }else{
- tList.add(EnumChatFormatting.GREEN+trans("204","No Pollution in Chunk! HAYO!")+EnumChatFormatting.RESET);
+ if (GT_Pollution.hasPollution(currentChunk)) {
+ tList.add(trans("202", "Pollution in Chunk: ") + EnumChatFormatting.RED + formatNumbers(GT_Pollution.getPollution(currentChunk)) + EnumChatFormatting.RESET + trans("203", " gibbl"));
+ } else {
+ tList.add(EnumChatFormatting.GREEN + trans("204", "No Pollution in Chunk! HAYO!") + EnumChatFormatting.RESET);
}
try {