Skip to content

Commit

Permalink
Update EntityCache with configurable Timeout for Info Overlay and Sav…
Browse files Browse the repository at this point in the history
…e via Servux cache.
  • Loading branch information
sakura-ryoko committed Nov 19, 2024
1 parent cdd69c6 commit ea21b42
Show file tree
Hide file tree
Showing 13 changed files with 2,833 additions and 31 deletions.
2 changes: 2 additions & 0 deletions src/main/java/fi/dy/masa/litematica/config/Configs.java
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ public static class Generic
public static final ConfigBoolean EASY_PLACE_VANILLA_REACH = new ConfigBoolean("easyPlaceVanillaReach", false).apply(GENERIC_KEY);
public static final ConfigBoolean ENTITY_DATA_SYNC = new ConfigBoolean("entityDataSync", true).apply(GENERIC_KEY);
public static final ConfigBoolean ENTITY_DATA_SYNC_BACKUP = new ConfigBoolean("entityDataSyncBackup", true).apply(GENERIC_KEY);
public static final ConfigFloat ENTITY_DATA_SYNC_CACHE_TIMEOUT= new ConfigFloat("entityDataSyncCacheTimeout", 2.0f, 0.25f, 30.0f).apply(GENERIC_KEY);
public static final ConfigBoolean ENTITY_DATA_LOAD_NBT = new ConfigBoolean("entityDataSyncLoadNbt", true).apply(GENERIC_KEY);
public static final ConfigBoolean EXECUTE_REQUIRE_TOOL = new ConfigBoolean("executeRequireHoldingTool", true).apply(GENERIC_KEY);
public static final ConfigBoolean FIX_CHEST_MIRROR = new ConfigBoolean("fixChestMirror", true).apply(GENERIC_KEY);
Expand Down Expand Up @@ -124,6 +125,7 @@ public static class Generic
EASY_PLACE_VANILLA_REACH,
ENTITY_DATA_SYNC,
ENTITY_DATA_SYNC_BACKUP,
ENTITY_DATA_SYNC_CACHE_TIMEOUT,
ENTITY_DATA_LOAD_NBT,
EXECUTE_REQUIRE_TOOL,
FIX_CHEST_MIRROR,
Expand Down
47 changes: 29 additions & 18 deletions src/main/java/fi/dy/masa/litematica/data/EntitiesDataStorage.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,12 @@
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.mob.PiglinEntity;
import net.minecraft.entity.passive.AbstractHorseEntity;
import net.minecraft.entity.passive.VillagerEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.inventory.DoubleInventory;
import net.minecraft.inventory.Inventory;
import net.minecraft.inventory.SimpleInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtList;
import net.minecraft.registry.Registries;
import net.minecraft.registry.entry.RegistryEntry;
import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.Identifier;
import net.minecraft.util.Util;
import net.minecraft.util.math.BlockPos;
Expand All @@ -39,8 +32,6 @@
import net.minecraft.world.World;

import fi.dy.masa.malilib.interfaces.IClientTickHandler;
import fi.dy.masa.malilib.mixin.IMixinAbstractHorseEntity;
import fi.dy.masa.malilib.mixin.IMixinPiglinEntity;
import fi.dy.masa.malilib.network.ClientPlayHandler;
import fi.dy.masa.malilib.network.IPluginClientPlayHandler;
import fi.dy.masa.malilib.util.Constants;
Expand Down Expand Up @@ -213,7 +204,7 @@ public void reset(boolean isLogout)
else
{
Litematica.debugLog("EntitiesDataStorage#reset() - dimension change or log-in");
this.serverTickTime = System.currentTimeMillis() - (this.cacheTimeout + 5) * 1000L;
this.serverTickTime = System.currentTimeMillis() - (this.getCacheTimeout() + 5000L);
this.tickCache();
this.serverTickTime = System.currentTimeMillis();
this.clientWorld = mc.world;
Expand All @@ -225,19 +216,31 @@ public void reset(boolean isLogout)
this.pendingEntitiesQueue.clear();
}

private long getCacheTimeout()
{
return (long) (MathHelper.clamp(Configs.Generic.ENTITY_DATA_SYNC_CACHE_TIMEOUT.getFloatValue(), 0.25f, 30.0f) * 1000L);
}

private long getCacheTimeoutLong()
{
return (long) (MathHelper.clamp((Configs.Generic.ENTITY_DATA_SYNC_CACHE_TIMEOUT.getFloatValue() * this.longCacheTimeout), 120.0f, 300.0f) * 1000L);
}

private void tickCache()
{
long nowTime = System.currentTimeMillis();
long blockTimeout = (this.cacheTimeout) * 1000L;
long entityTimeout = (this.cacheTimeout / 2) * 1000L;
long blockTimeout = this.getCacheTimeout();
long entityTimeout = this.getCacheTimeout() * 2;
int count;
boolean beEmpty = false;
boolean entEmpty = false;

// Use LongTimeouts when saving a Litematic Selection,
// which is pretty much the standard value x 30 (min 120, max 300 seconds)
if (this.shouldUseLongTimeout)
{
blockTimeout = this.longCacheTimeout * 1000L;
entityTimeout = (this.longCacheTimeout / 2) * 1000L;
blockTimeout = this.getCacheTimeoutLong();
entityTimeout = this.getCacheTimeoutLong();
}

synchronized (this.blockEntityCache)
Expand All @@ -250,7 +253,7 @@ private void tickCache()

if (nowTime - pair.getLeft() > blockTimeout || pair.getLeft() - nowTime > 0)
{
Litematica.debugLog("entityCache: be at pos [{}] has timed out", pos.toShortString());
Litematica.debugLog("entityCache: be at pos [{}] has timed out by [{}] ms", pos.toShortString(), blockTimeout);
this.blockEntityCache.remove(pos);
}
else
Expand All @@ -275,7 +278,7 @@ private void tickCache()

if (nowTime - pair.getLeft() > entityTimeout || pair.getLeft() - nowTime > 0)
{
Litematica.debugLog("entityCache: entity Id [{}] has timed out", entityId);
Litematica.debugLog("entityCache: entity Id [{}] has timed out by [{}] ms", entityId, entityTimeout);
this.entityCache.remove(entityId);
}
else
Expand Down Expand Up @@ -479,7 +482,10 @@ else if (world.getBlockState(pos).getBlock() instanceof BlockEntityProvider)
NbtCompound nbt = be.createNbtWithIdentifyingData(world.getRegistryManager());
Pair<BlockEntity, NbtCompound> pair = Pair.of(be, nbt);

this.blockEntityCache.put(pos, Pair.of(System.currentTimeMillis(), pair));
synchronized (this.blockEntityCache)
{
this.blockEntityCache.put(pos, Pair.of(System.currentTimeMillis(), pair));
}

return pair;
}
Expand Down Expand Up @@ -512,7 +518,12 @@ else if (world.getBlockState(pos).getBlock() instanceof BlockEntityProvider)
if (entity != null && entity.saveSelfNbt(nbt))
{
Pair<Entity, NbtCompound> pair = Pair.of(entity, nbt);
this.entityCache.put(entityId, Pair.of(System.currentTimeMillis(), pair));

synchronized (this.entityCache)
{
this.entityCache.put(entityId, Pair.of(System.currentTimeMillis(), pair));
}

return pair;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,6 @@ public static int renderInventoryOverlay(BlockInfoAlignment align, LeftRight sid

if (ctx != null && ctx.inv() != null)
{
//final InventoryRenderType type = fi.dy.masa.malilib.render.InventoryOverlay.getInventoryType(inv);
final InventoryProperties props = fi.dy.masa.malilib.render.InventoryOverlay.getInventoryPropsTemp(ctx.type(), ctx.inv().size());

//Litematica.logger.error("render(): type [{}], inv [{}], be [{}], nbt [{}]", ctx.type().name(), ctx.inv().size(), ctx.be() != null, ctx.nbt() != null ? ctx.nbt().getString("id") : new NbtCompound());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -532,8 +532,8 @@ private static NbtCompound processComponentsTag(NbtCompound nbt, String itemId,
beNbt.putString("id", itemId);
}
case "minecraft:block_state" -> outNbt.put("BlockStateTag", processBlockState(nbt.get(key)));
case "minecraft:block_entity_data" -> processBlockEntityData(nbt.get(key), beNbt);
case "minecraft:bucket_entity_data" -> processBucketEntityData(nbt.get(key), beNbt);
case "minecraft:block_entity_data" -> processBlockEntityData(nbt.get(key), beNbt, minecraftDataVersion, registryManager); // TODO --> check that this works or not
case "minecraft:bucket_entity_data" -> processBucketEntityData(nbt.get(key), beNbt, minecraftDataVersion, registryManager);
case "minecraft:bundle_contents" -> outNbt.put("Items", processItemsTag(nbt.getList(key, Constants.NBT.TAG_COMPOUND), minecraftDataVersion, registryManager));
case "minecraft:can_break" -> outNbt.put("CanDestroy", nbt.get(key));
case "minecraft:can_place_on" -> outNbt.put("CanPlaceOn", nbt.get(key));
Expand Down Expand Up @@ -670,10 +670,13 @@ private static void processLodestoneTracker(NbtElement oldEle, NbtCompound outNb
}
}

private static void processBucketEntityData(NbtElement oldTags, NbtCompound beNbt)
private static void processBucketEntityData(NbtElement oldTags, NbtCompound beNbt, int minecraftDataVersion, @Nonnull DynamicRegistryManager registryManager)
{
NbtCompound oldNbt = (NbtCompound) oldTags;

// NbtCompound newNbt = downgradeEntity_to_1_20_4(oldNbt, minecraftDataVersion, registryManager);
// beNbt.copyFrom(newNbt);

for (String key : oldNbt.getKeys())
{
beNbt.put(key, oldNbt.get(key));
Expand Down Expand Up @@ -873,13 +876,13 @@ private static boolean processUnbreakable(NbtElement oldNbt)
return false;
}

private static void processBlockEntityData(NbtElement oldBeData, NbtCompound beNbt)
private static void processBlockEntityData(NbtElement oldBeData, NbtCompound beNbt, int minecraftDataVersion, @Nonnull DynamicRegistryManager registryManager)
{
NbtCompound oldData = (NbtCompound) oldBeData;
NbtCompound newData = downgradeBlockEntity_to_1_20_4((NbtCompound) oldBeData, minecraftDataVersion, registryManager);

for (String key : oldData.getKeys())
for (String key : newData.getKeys())
{
beNbt.put(key, oldData.get(key));
beNbt.put(key, newData.get(key));
}
}

Expand Down
19 changes: 18 additions & 1 deletion src/main/java/fi/dy/masa/litematica/util/InventoryUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public class InventoryUtils
{
private static final List<Integer> PICK_BLOCKABLE_SLOTS = new ArrayList<>();
private static int nextPickSlotIndex;
private static Pair<BlockPos, InventoryOverlay.Context> lastBlockEntityContext = null;

public static void setPickBlockableSlots(String configStr)
{
Expand Down Expand Up @@ -334,7 +335,23 @@ public static int findSlotWithBoxWithItem(ScreenHandler container, ItemStack sta

//Litematica.logger.warn("getTarget():2: pos [{}], be [{}], nbt [{}]", pos.toShortString(), be != null, nbt != null);

return getTargetInventoryFromBlock(world, pos, be, nbt);
InventoryOverlay.Context ctx = getTargetInventoryFromBlock(world, pos, be, nbt);

if (lastBlockEntityContext != null && !lastBlockEntityContext.getLeft().equals(pos))
{
lastBlockEntityContext = null;
}

if (ctx != null &&
(ctx.inv() != null && !ctx.inv().isEmpty()))
{
lastBlockEntityContext = Pair.of(pos, ctx);
return ctx;
}
else if (lastBlockEntityContext != null && lastBlockEntityContext.getLeft().equals(pos))
{
return lastBlockEntityContext.getRight();
}
}

return null;
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/assets/litematica/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
"litematica.config.generic.name.easyPlaceVanillaReach": "easyPlaceVanillaReach",
"litematica.config.generic.name.entityDataSync": "entityDataSync",
"litematica.config.generic.name.entityDataSyncBackup": "entityDataSyncBackup",
"litematica.config.generic.name.entityDataSyncCacheTimeout": "entityDataSyncCacheTimeout",
"litematica.config.generic.name.entityDataSyncLoadNbt": "entityDataSyncLoadNbt",
"litematica.config.generic.name.executeRequireHoldingTool": "executeRequireHoldingTool",
"litematica.config.generic.name.fixChestMirror": "fixChestMirror",
Expand Down Expand Up @@ -256,6 +257,7 @@
"litematica.config.generic.comment.easyPlaceVanillaReach": "If enabled, reduces reach distance from +1.0 to the\nVanilla value so servers don't reject placement of\nfar blocks.",
"litematica.config.generic.comment.entityDataSync": "Use the Entity Data Sync protocol from Servux\nto obtain Entity Data from the server",
"litematica.config.generic.comment.entityDataSyncBackup": "Use the Vanilla NBT Query method when Servux\nis not available. This method requires Operator Privileges.",
"litematica.config.generic.comment.entityDataSyncCacheTimeout": "The Cache timeout value in seconds that\nthe Entity Cache keeps records for.\nA lower value means more frequent updates, but\nyou may want to consider a higher value if\nyour litematics fail to save with all of the NBT data.",
"litematica.config.generic.comment.entityDataSyncLoadNbt": "Load the synced NBT data into the Client World.\n§6WARNING! This feature will cause incompatibility\n§6with other mods that rely on this data.",
"litematica.config.generic.comment.executeRequireHoldingTool": "Require holding an enabled tool item\nfor the executeOperation hotkey to work",
"litematica.config.generic.comment.fixChestMirror": "Enable a fix to the broken chest mirror code in vanilla",
Expand Down
Loading

0 comments on commit ea21b42

Please sign in to comment.