aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authoriamblackornot <nkzshinnik@gmail.com>2023-10-21 13:16:22 +0300
committerGitHub <noreply@github.com>2023-10-21 12:16:22 +0200
commita2e23af5cbd85d085ce2003402560aad4bb87a52 (patch)
tree7872d1db1774161833b8d3bd73a293b86417c3b7 /src
parent2466d880d95a0584f5beb7a205070b0e3fc47549 (diff)
downloadGT5-Unofficial-a2e23af5cbd85d085ce2003402560aad4bb87a52.tar.gz
GT5-Unofficial-a2e23af5cbd85d085ce2003402560aad4bb87a52.tar.bz2
GT5-Unofficial-a2e23af5cbd85d085ce2003402560aad4bb87a52.zip
A new approach for block updates in BaseMetaTileEntity (#2342)
* - added 0,5s cooldown on BaseMetaTileEntity texture render update * - changed to RandomCooldown to make visual representation of the target object more relevant to its state * - implemented a BlockUpdateHandler, making the update cooldowns chunk-based - left commented out debug code * - now BaseMetaTileEntity tracks last time a texture update was issued and skips update if parent chunk was already updated since last update issue * - reworked BlockUpdateHandler to a singleton doing update work on client tick, this way update logic is fully encapsulated and gets rid of some comparisons needed to sync updates * - fixed a bug with crash on quitting the game - forgot to add moved sources - cleaned up debug code - added description commentary * - updated buildscript * - switched to internal tick counter, cause server time is unreliable and crashes client https://github.com/GTNewHorizons/GT-New-Horizons-Modpack/issues/14742 - removed subclass aliases - switched to XSTR instead of java's Random - IllegalArugmentException instead of InvalidParameterException - added client side config option to enable/disable this feature (by default is off) --------- Co-authored-by: iamblackornot <nkzshinnnik@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java8
-rw-r--r--src/main/java/gregtech/api/objects/blockupdate/BlockUpdateHandler.java117
-rw-r--r--src/main/java/gregtech/api/objects/blockupdate/Cooldown.java27
-rw-r--r--src/main/java/gregtech/api/objects/blockupdate/RandomCooldown.java31
-rw-r--r--src/main/java/gregtech/common/GT_Proxy.java5
-rw-r--r--src/main/java/gregtech/loaders/preload/GT_PreLoad.java2
6 files changed, 188 insertions, 2 deletions
diff --git a/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java b/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java
index a7236e164d..8755bacf7f 100644
--- a/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java
+++ b/src/main/java/gregtech/api/metatileentity/BaseMetaTileEntity.java
@@ -72,6 +72,7 @@ import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_BasicMachin
import gregtech.api.metatileentity.implementations.GT_MetaTileEntity_Hatch;
import gregtech.api.net.GT_Packet_TileEntity;
import gregtech.api.objects.GT_ItemStack;
+import gregtech.api.objects.blockupdate.BlockUpdateHandler;
import gregtech.api.util.GT_CoverBehaviorBase;
import gregtech.api.util.GT_Log;
import gregtech.api.util.GT_ModHandler;
@@ -333,8 +334,11 @@ public class BaseMetaTileEntity extends CommonMetaTileEntity
}
if (mNeedsUpdate) {
- worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
- // worldObj.func_147479_m(xCoord, yCoord, zCoord);
+ if (GT_Mod.gregtechproxy.mUseBlockUpdateHandler) {
+ BlockUpdateHandler.Instance.enqueueBlockUpdate(worldObj, getLocation());
+ } else {
+ worldObj.markBlockForUpdate(xCoord, yCoord, zCoord);
+ }
mNeedsUpdate = false;
}
}
diff --git a/src/main/java/gregtech/api/objects/blockupdate/BlockUpdateHandler.java b/src/main/java/gregtech/api/objects/blockupdate/BlockUpdateHandler.java
new file mode 100644
index 0000000000..e8f084ea34
--- /dev/null
+++ b/src/main/java/gregtech/api/objects/blockupdate/BlockUpdateHandler.java
@@ -0,0 +1,117 @@
+package gregtech.api.objects.blockupdate;
+
+import java.util.HashMap;
+
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.entity.EntityClientPlayerMP;
+import net.minecraft.world.ChunkCoordIntPair;
+import net.minecraft.world.World;
+import net.minecraft.world.chunk.Chunk;
+
+import appeng.api.util.WorldCoord;
+import cpw.mods.fml.common.FMLCommonHandler;
+import cpw.mods.fml.common.eventhandler.SubscribeEvent;
+import cpw.mods.fml.common.gameevent.TickEvent.ClientTickEvent;
+import cpw.mods.fml.common.gameevent.TickEvent.Phase;
+import cpw.mods.fml.relauncher.Side;
+import cpw.mods.fml.relauncher.SideOnly;
+import gregtech.api.enums.TickTime;
+
+// this is a middleware for block updates
+// Greg's BaseMetaTileEntity uses World::markBlockForUpdate() to update the texture of a machine
+// World::markBlockForUpdate() triggers block updates of all blocks within the same chunk
+// this class makes sure chunk updates are perfmormed only once even if several blocks requested update
+// (valid obly for requests made using BlockUpdateHandler::enqueueBlockUpdate)
+// and introduces a per chunk cooldown to slow the things a bit
+// cause too frequent updates are not necessary for visual appearance of a block
+
+@SideOnly(Side.CLIENT)
+public class BlockUpdateHandler {
+
+ public static final int MIN_UPDATE_COOLDOWN = TickTime.SECOND / 2;
+ public static final int MAX_UPDATE_COOLDOWN = TickTime.SECOND;
+
+ public final static BlockUpdateHandler Instance = new BlockUpdateHandler();
+
+ private BlockUpdateHandler() {
+
+ blocksToUpdate = new HashMap<ChunkCoordIntPair, WorldCoord>();
+ cooldowns = new HashMap<ChunkCoordIntPair, RandomCooldown>();
+
+ FMLCommonHandler.instance()
+ .bus()
+ .register(this);
+ }
+
+ public void enqueueBlockUpdate(World world, WorldCoord pos) {
+
+ var player = getPlayer();
+
+ if (world != player.worldObj) return;
+
+ ResetDataIfPlayerWorldChanged(player);
+
+ blocksToUpdate.put(getBlockChunkCoords(world, pos), pos);
+ }
+
+ @SubscribeEvent
+ public void OnClientTickEvent(ClientTickEvent event) {
+
+ if (event.phase != Phase.START) return;
+
+ ResetDataIfPlayerWorldChanged(getPlayer());
+
+ var it = blocksToUpdate.entrySet()
+ .iterator();
+
+ while (it.hasNext()) {
+
+ var entry = it.next();
+ ChunkCoordIntPair chunkCoords = entry.getKey();
+ WorldCoord blockCoords = entry.getValue();
+
+ RandomCooldown cooldown = cooldowns.get(chunkCoords);
+
+ if (cooldown == null) {
+ cooldown = new RandomCooldown(MIN_UPDATE_COOLDOWN, MAX_UPDATE_COOLDOWN);
+ cooldowns.put(chunkCoords, cooldown);
+ }
+
+ if (!cooldown.hasPassed(internalTickCounter)) continue;
+
+ currWorld.markBlockForUpdate(blockCoords.x, blockCoords.y, blockCoords.z);
+ cooldown.set(internalTickCounter);
+ it.remove();
+ }
+
+ ++internalTickCounter;
+ }
+
+ private EntityClientPlayerMP getPlayer() {
+ return Minecraft.getMinecraft().thePlayer;
+ }
+
+ private void ResetDataIfPlayerWorldChanged(EntityClientPlayerMP player) {
+
+ if (player == null) return;
+
+ World playerWorld = player.worldObj;
+
+ if (currWorld != playerWorld) {
+ blocksToUpdate.clear();
+ cooldowns.clear();
+ currWorld = playerWorld;
+ }
+ }
+
+ private ChunkCoordIntPair getBlockChunkCoords(World world, WorldCoord pos) {
+
+ Chunk chunk = world.getChunkFromBlockCoords(pos.x, pos.z);
+ return chunk.getChunkCoordIntPair();
+ }
+
+ private HashMap<ChunkCoordIntPair, WorldCoord> blocksToUpdate;
+ private HashMap<ChunkCoordIntPair, RandomCooldown> cooldowns;
+ private World currWorld = null;
+ private long internalTickCounter = 0;
+}
diff --git a/src/main/java/gregtech/api/objects/blockupdate/Cooldown.java b/src/main/java/gregtech/api/objects/blockupdate/Cooldown.java
new file mode 100644
index 0000000000..e00fc1c770
--- /dev/null
+++ b/src/main/java/gregtech/api/objects/blockupdate/Cooldown.java
@@ -0,0 +1,27 @@
+package gregtech.api.objects.blockupdate;
+
+public class Cooldown {
+
+ public Cooldown(int aLengthInTicks) {
+
+ if (aLengthInTicks <= 0) throw new IllegalArgumentException("length should be a positive non-zero number");
+
+ this.lengthInTicks = aLengthInTicks;
+ this.lastTimeStarted = 0;
+ }
+
+ public void set(long currTickTime) {
+ lastTimeStarted = currTickTime;
+ }
+
+ public boolean hasPassed(long currTickTime) {
+ return currTickTime - lastTimeStarted >= lengthInTicks;
+ }
+
+ public long getLastTimeStarted() {
+ return lastTimeStarted;
+ }
+
+ private long lastTimeStarted;
+ protected int lengthInTicks;
+}
diff --git a/src/main/java/gregtech/api/objects/blockupdate/RandomCooldown.java b/src/main/java/gregtech/api/objects/blockupdate/RandomCooldown.java
new file mode 100644
index 0000000000..d275c29744
--- /dev/null
+++ b/src/main/java/gregtech/api/objects/blockupdate/RandomCooldown.java
@@ -0,0 +1,31 @@
+package gregtech.api.objects.blockupdate;
+
+import static gregtech.api.objects.XSTR.XSTR_INSTANCE;
+
+public class RandomCooldown extends Cooldown {
+
+ public RandomCooldown(int aMinLengthInTicks, int aMaxLengthInTicks) {
+
+ super(aMinLengthInTicks);
+
+ if (aMinLengthInTicks <= 0)
+ throw new IllegalArgumentException("min length should be a positive non-zero number");
+ if (aMaxLengthInTicks <= 0)
+ throw new IllegalArgumentException("max length should be a positive non-zero number");
+ if (aMinLengthInTicks > aMaxLengthInTicks)
+ throw new IllegalArgumentException("min length should be less or equal to max length");
+
+ this.minLengthInTicks = aMinLengthInTicks;
+ this.maxLengthInTicks = aMaxLengthInTicks;
+ }
+
+ @Override
+ public void set(long currTickTime) {
+
+ super.set(currTickTime);
+ lengthInTicks = minLengthInTicks + XSTR_INSTANCE.nextInt(maxLengthInTicks - minLengthInTicks + 1);
+ }
+
+ private int minLengthInTicks;
+ private int maxLengthInTicks;
+}
diff --git a/src/main/java/gregtech/common/GT_Proxy.java b/src/main/java/gregtech/common/GT_Proxy.java
index ffa6d617b8..8897bfb6e4 100644
--- a/src/main/java/gregtech/common/GT_Proxy.java
+++ b/src/main/java/gregtech/common/GT_Proxy.java
@@ -658,6 +658,11 @@ public abstract class GT_Proxy implements IGT_Mod, IGuiHandler, IFuelHandler, IG
public boolean mRenderPollutionFog = true;
/**
+ * This enables BaseMetaTileEntity block updates handled by BlockUpdateHandler
+ */
+ public boolean mUseBlockUpdateHandler = false;
+
+ /**
* This makes cover tabs visible on GregTech machines
*/
public boolean mCoverTabsVisible = true;
diff --git a/src/main/java/gregtech/loaders/preload/GT_PreLoad.java b/src/main/java/gregtech/loaders/preload/GT_PreLoad.java
index 730aba52a0..749cb06eda 100644
--- a/src/main/java/gregtech/loaders/preload/GT_PreLoad.java
+++ b/src/main/java/gregtech/loaders/preload/GT_PreLoad.java
@@ -835,6 +835,8 @@ public class GT_PreLoad {
.get("render", "RenderItemDurabilityBar", true);
GT_Mod.gregtechproxy.mRenderItemChargeBar = GregTech_API.sClientDataFile
.get("render", "RenderItemChargeBar", true);
+ GT_Mod.gregtechproxy.mUseBlockUpdateHandler = GregTech_API.sClientDataFile
+ .get("render", "UseBlockUpdateHandler", false);
GT_Mod.gregtechproxy.mCoverTabsVisible = GregTech_API.sClientDataFile
.get("interface", "DisplayCoverTabs", true);