diff --git a/src/main/java/com/extendedae_plus/api/bridge/PatternProviderLogicSyncBridge.java b/src/main/java/com/extendedae_plus/api/bridge/PatternProviderLogicSyncBridge.java new file mode 100644 index 0000000..cbb45bd --- /dev/null +++ b/src/main/java/com/extendedae_plus/api/bridge/PatternProviderLogicSyncBridge.java @@ -0,0 +1,5 @@ +package com.extendedae_plus.api.bridge; + +public interface PatternProviderLogicSyncBridge { + long eap$getPatternSyncVersion(); +} diff --git a/src/main/java/com/extendedae_plus/content/ae2/MirrorPatternProviderBlockEntity.java b/src/main/java/com/extendedae_plus/content/ae2/MirrorPatternProviderBlockEntity.java index e75a0ca..2d56c35 100644 --- a/src/main/java/com/extendedae_plus/content/ae2/MirrorPatternProviderBlockEntity.java +++ b/src/main/java/com/extendedae_plus/content/ae2/MirrorPatternProviderBlockEntity.java @@ -10,6 +10,7 @@ import appeng.helpers.patternprovider.PatternProviderLogic; import appeng.util.CustomNameUtil; import appeng.util.SettingsFrom; import appeng.util.inv.AppEngInternalInventory; +import com.extendedae_plus.api.bridge.PatternProviderLogicSyncBridge; import com.extendedae_plus.config.ModConfig; import com.extendedae_plus.init.ModBlockEntities; import net.minecraft.core.BlockPos; @@ -40,6 +41,7 @@ public class MirrorPatternProviderBlockEntity extends PatternProviderBlockEntity private static final int AE2_PATTERN_SLOTS = 9; private static final int EXTENDED_PATTERN_PROVIDER_BASE_SLOTS = 36; private static final InternalInventory DISABLED_PATTERN_INVENTORY = new AppEngInternalInventory(0); + private static final long UNKNOWN_PATTERN_SYNC_VERSION = Long.MIN_VALUE; @Nullable private ResourceKey masterDimension; @@ -48,6 +50,8 @@ public class MirrorPatternProviderBlockEntity extends PatternProviderBlockEntity private BlockPos masterPos; private long nextSyncTick = Long.MIN_VALUE; + private long lastSyncedPatternVersion = UNKNOWN_PATTERN_SYNC_VERSION; + private boolean needsUnboundPatternCleanup; public MirrorPatternProviderBlockEntity(BlockPos pos, BlockState blockState) { super(ModBlockEntities.MIRROR_PATTERN_PROVIDER_BE.get(), pos, blockState); @@ -113,6 +117,8 @@ public class MirrorPatternProviderBlockEntity extends PatternProviderBlockEntity this.masterDimension = null; this.masterPos = null; this.scheduleImmediateSync(); + this.invalidatePatternSyncState(); + this.needsUnboundPatternCleanup = true; if (data.contains(TAG_MASTER, Tag.TAG_COMPOUND)) { var masterTag = data.getCompound(TAG_MASTER); if (masterTag.contains(TAG_MASTER_DIMENSION, Tag.TAG_STRING) @@ -120,6 +126,7 @@ public class MirrorPatternProviderBlockEntity extends PatternProviderBlockEntity this.masterDimension = ResourceKey.create(Registries.DIMENSION, new ResourceLocation(masterTag.getString(TAG_MASTER_DIMENSION))); this.masterPos = BlockPos.of(masterTag.getLong(TAG_MASTER_POS)); + this.needsUnboundPatternCleanup = false; } } } @@ -209,6 +216,16 @@ public class MirrorPatternProviderBlockEntity extends PatternProviderBlockEntity } private int syncBoundMaster() { + if (this.masterDimension == null || this.masterPos == null) { + if (this.needsUnboundPatternCleanup) { + this.needsUnboundPatternCleanup = false; + if (this.clearMirroredPatterns()) { + this.flushStateChanges(); + } + } + return UNLOADED_MASTER_RETRY_INTERVAL; + } + var master = this.getMaster(); if (master != null) { return this.syncFromMaster(master) ? FAST_SYNC_INTERVAL : STABLE_SYNC_INTERVAL; @@ -226,7 +243,11 @@ public class MirrorPatternProviderBlockEntity extends PatternProviderBlockEntity } private boolean shouldClearBrokenBinding() { - if (this.masterDimension == null || this.masterPos == null || !(this.getLevel() instanceof ServerLevel serverLevel)) { + if (this.masterDimension == null || this.masterPos == null) { + return false; + } + + if (!(this.getLevel() instanceof ServerLevel serverLevel)) { return true; } @@ -243,6 +264,8 @@ public class MirrorPatternProviderBlockEntity extends PatternProviderBlockEntity this.masterDimension = null; this.masterPos = null; + this.invalidatePatternSyncState(); + this.needsUnboundPatternCleanup = false; var changed = hadBinding; if (clearMirroredPatterns) { @@ -258,6 +281,10 @@ public class MirrorPatternProviderBlockEntity extends PatternProviderBlockEntity this.masterDimension = dimension; this.masterPos = newPos; + this.needsUnboundPatternCleanup = false; + if (changed) { + this.invalidatePatternSyncState(); + } return changed; } @@ -267,9 +294,10 @@ public class MirrorPatternProviderBlockEntity extends PatternProviderBlockEntity return false; } - var changed = this.setBoundMaster(masterLevel.dimension(), master.getBlockPos()); + var bindingChanged = this.setBoundMaster(masterLevel.dimension(), master.getBlockPos()); + var changed = bindingChanged; changed |= this.syncMirroredSettings(master); - changed |= this.syncMirroredPatterns(master); + changed |= this.syncMirroredPatterns(master, bindingChanged); if (changed) { this.flushStateChanges(); @@ -315,7 +343,13 @@ public class MirrorPatternProviderBlockEntity extends PatternProviderBlockEntity != master.getBlockState().getValue(PatternProviderBlock.PUSH_DIRECTION); } - private boolean syncMirroredPatterns(PatternProviderBlockEntity master) { + private boolean syncMirroredPatterns(PatternProviderBlockEntity master, boolean forceSync) { + var masterPatternVersion = getPatternSyncVersion(master); + if (!forceSync && masterPatternVersion != UNKNOWN_PATTERN_SYNC_VERSION + && masterPatternVersion == this.lastSyncedPatternVersion) { + return false; + } + var mirrorInventory = this.getPatternInventory(); var masterInventory = asPatternInventory(master.getLogic().getPatternInv()); var mirrorSize = mirrorInventory.size(); @@ -335,6 +369,12 @@ public class MirrorPatternProviderBlockEntity extends PatternProviderBlockEntity this.getLogic().updatePatterns(); } + if (masterPatternVersion != UNKNOWN_PATTERN_SYNC_VERSION) { + this.lastSyncedPatternVersion = masterPatternVersion; + } else if (changed) { + this.invalidatePatternSyncState(); + } + return changed; } @@ -390,6 +430,10 @@ public class MirrorPatternProviderBlockEntity extends PatternProviderBlockEntity this.nextSyncTick = Long.MIN_VALUE; } + private void invalidatePatternSyncState() { + this.lastSyncedPatternVersion = UNKNOWN_PATTERN_SYNC_VERSION; + } + @Nullable private ServerLevel getMasterLevel(ServerLevel serverLevel) { if (serverLevel.dimension() == this.masterDimension) { @@ -420,6 +464,14 @@ public class MirrorPatternProviderBlockEntity extends PatternProviderBlockEntity return ItemStack.isSameItemSameTags(left, right) && left.getCount() == right.getCount(); } + private static long getPatternSyncVersion(PatternProviderBlockEntity master) { + if (master.getLogic() instanceof PatternProviderLogicSyncBridge bridge) { + return bridge.eap$getPatternSyncVersion(); + } + + return UNKNOWN_PATTERN_SYNC_VERSION; + } + public static boolean isSupportedMaster(@Nullable BlockEntity blockEntity) { return blockEntity instanceof PatternProviderBlockEntity && !(blockEntity instanceof MirrorPatternProviderBlockEntity) diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/helpers/patternprovider/PatternProviderLogicSyncVersionMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/helpers/patternprovider/PatternProviderLogicSyncVersionMixin.java new file mode 100644 index 0000000..af8cdc1 --- /dev/null +++ b/src/main/java/com/extendedae_plus/mixin/ae2/helpers/patternprovider/PatternProviderLogicSyncVersionMixin.java @@ -0,0 +1,26 @@ +package com.extendedae_plus.mixin.ae2.helpers.patternprovider; + +import appeng.helpers.patternprovider.PatternProviderLogic; +import appeng.util.inv.AppEngInternalInventory; +import com.extendedae_plus.api.bridge.PatternProviderLogicSyncBridge; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +@Mixin(value = PatternProviderLogic.class, remap = false) +public abstract class PatternProviderLogicSyncVersionMixin implements PatternProviderLogicSyncBridge { + @Unique + private long eap$patternSyncVersion; + + @Inject(method = "onChangeInventory", at = @At("TAIL")) + private void eap$trackPatternInventoryChanges(AppEngInternalInventory inv, int slot, CallbackInfo ci) { + this.eap$patternSyncVersion++; + } + + @Override + public long eap$getPatternSyncVersion() { + return this.eap$patternSyncVersion; + } +} diff --git a/src/main/resources/extendedae_plus.mixins.json b/src/main/resources/extendedae_plus.mixins.json index 00fb489..0c4af53 100644 --- a/src/main/resources/extendedae_plus.mixins.json +++ b/src/main/resources/extendedae_plus.mixins.json @@ -71,6 +71,7 @@ "ae2.helpers.InterfaceLogicUpgradesMixin", "ae2.helpers.patternprovider.PatternProviderLogicAdvancedMixin", "ae2.helpers.patternprovider.PatternProviderLogicDoublingMixin", + "ae2.helpers.patternprovider.PatternProviderLogicSyncVersionMixin", "ae2.helpers.patternprovider.PatternProviderLogicTickerMixin", "ae2.items.MemoryCardItemMixin", "ae2.menu.ContainerPatternEncodingTermMenuMixin",