From c90e7ad7e6997e513c1ea9268344afdbfaac2524 Mon Sep 17 00:00:00 2001 From: GaLi <3096147684@qq.com> Date: Tue, 7 Apr 2026 11:28:38 +0800 Subject: [PATCH] =?UTF-8?q?=E9=95=9C=E5=83=8F=E6=A0=B7=E6=9D=BF=E4=BE=9B?= =?UTF-8?q?=E5=BA=94=E5=99=A8=E6=80=A7=E8=83=BD=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- build.gradle | 3 + .../ae2/MirrorPatternProviderBlockEntity.java | 149 ++++++++---------- .../CraftingSimulationStateMixin.java | 36 ++++- 3 files changed, 104 insertions(+), 84 deletions(-) diff --git a/build.gradle b/build.gradle index 824b58b..142f695 100644 --- a/build.gradle +++ b/build.gradle @@ -180,6 +180,9 @@ dependencies { //biggerae2 // runtimeOnly "curse.maven:bigger-ae2-1013772:6587078" + //obs性能监测 + implementation "curse.maven:observable-509575:6697124" + implementation "curse.maven:kotlin-for-forge-351264:7471280" runtimeOnly fileTree(dir: 'libs', includes: ['*.jar']) 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 83bc154..f612a73 100644 --- a/src/main/java/com/extendedae_plus/content/ae2/MirrorPatternProviderBlockEntity.java +++ b/src/main/java/com/extendedae_plus/content/ae2/MirrorPatternProviderBlockEntity.java @@ -37,7 +37,9 @@ public class MirrorPatternProviderBlockEntity extends PatternProviderBlockEntity private static final String TAG_MASTER = "mirrorMaster"; private static final String TAG_MASTER_DIMENSION = "dimension"; private static final String TAG_MASTER_POS = "pos"; - private static final int SYNC_INTERVAL = 2; + private static final int FAST_SYNC_INTERVAL = 2; + private static final int STABLE_SYNC_INTERVAL = 20; + private static final int UNLOADED_MASTER_RETRY_INTERVAL = 40; 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); @@ -48,6 +50,8 @@ public class MirrorPatternProviderBlockEntity extends PatternProviderBlockEntity @Nullable private BlockPos masterPos; + private long nextSyncTick = Long.MIN_VALUE; + public MirrorPatternProviderBlockEntity(BlockPos pos, BlockState blockState) { super(ModBlockEntities.MIRROR_PATTERN_PROVIDER_BE.get(), pos, blockState); } @@ -74,18 +78,19 @@ public class MirrorPatternProviderBlockEntity extends PatternProviderBlockEntity } private void serverTick(ServerLevel level) { - if (Math.floorMod(level.getGameTime() + this.getBlockPos().asLong(), SYNC_INTERVAL) != 0) { + if (level.getGameTime() < this.nextSyncTick) { return; } - this.syncBoundMaster(); + this.nextSyncTick = level.getGameTime() + this.syncBoundMaster(); } @Override public void onReady() { super.onReady(); if (this.getLevel() instanceof ServerLevel serverLevel) { - this.syncBoundMaster(); + this.scheduleImmediateSync(); + this.nextSyncTick = serverLevel.getGameTime() + this.syncBoundMaster(); } } @@ -109,6 +114,7 @@ public class MirrorPatternProviderBlockEntity extends PatternProviderBlockEntity this.masterDimension = null; this.masterPos = null; + this.scheduleImmediateSync(); if (data.contains(TAG_MASTER, Tag.TAG_COMPOUND)) { var masterTag = data.getCompound(TAG_MASTER); if (masterTag.contains(TAG_MASTER_DIMENSION, Tag.TAG_STRING) && masterTag.contains(TAG_MASTER_POS, Tag.TAG_LONG)) { @@ -148,7 +154,6 @@ public class MirrorPatternProviderBlockEntity extends PatternProviderBlockEntity return false; } - this.bindToMaster(master); this.syncFromMaster(master); return true; } @@ -172,13 +177,11 @@ public class MirrorPatternProviderBlockEntity extends PatternProviderBlockEntity return false; } - var changed = !Objects.equals(this.masterDimension, master.dimension()) || !Objects.equals(this.masterPos, master.pos()); - this.masterDimension = master.dimension(); - this.masterPos = master.pos().immutable(); + var changed = this.setBoundMaster(master.dimension(), master.pos()); if (changed) { - this.saveChanges(); - this.markForClientUpdate(); + this.flushStateChanges(); } + this.scheduleImmediateSync(); return true; } @@ -227,16 +230,21 @@ public class MirrorPatternProviderBlockEntity extends PatternProviderBlockEntity return Component.translatable("extendedae_plus.message.mirror_pattern_provider.missing_master"); } - private void syncBoundMaster() { + private int syncBoundMaster() { var master = this.getMaster(); if (master != null) { - this.syncFromMaster(master); - return; + return this.syncFromMaster(master) ? FAST_SYNC_INTERVAL : STABLE_SYNC_INTERVAL; } if (this.shouldClearBrokenBinding()) { - this.clearMasterBinding(true); + if (this.clearMasterBinding(true)) { + this.flushStateChanges(); + return FAST_SYNC_INTERVAL; + } + return STABLE_SYNC_INTERVAL; } + + return UNLOADED_MASTER_RETRY_INTERVAL; } private boolean shouldClearBrokenBinding() { @@ -258,7 +266,7 @@ public class MirrorPatternProviderBlockEntity extends PatternProviderBlockEntity return !isValidMaster(masterLevel.getBlockEntity(this.masterPos)); } - private void clearMasterBinding(boolean clearMirroredPatterns) { + private boolean clearMasterBinding(boolean clearMirroredPatterns) { var hadBinding = this.masterDimension != null || this.masterPos != null; this.masterDimension = null; @@ -269,30 +277,15 @@ public class MirrorPatternProviderBlockEntity extends PatternProviderBlockEntity changed |= this.clearMirroredPatterns(); } - if (changed) { - this.saveChanges(); - this.markForClientUpdate(); - } + return changed; } - private boolean bindToMaster(PatternProviderBlockEntity master) { - var masterLevel = master.getLevel(); - if (masterLevel == null) { - return false; - } + private boolean setBoundMaster(ResourceKey dimension, BlockPos pos) { + var newPos = pos.immutable(); + var changed = !Objects.equals(this.masterDimension, dimension) || !Objects.equals(this.masterPos, newPos); - var newDimension = masterLevel.dimension(); - var newPos = master.getBlockPos().immutable(); - var changed = !Objects.equals(this.masterDimension, newDimension) || !Objects.equals(this.masterPos, newPos); - - this.masterDimension = newDimension; + this.masterDimension = dimension; this.masterPos = newPos; - - if (changed) { - this.saveChanges(); - this.markForClientUpdate(); - } - return changed; } @@ -314,13 +307,17 @@ public class MirrorPatternProviderBlockEntity extends PatternProviderBlockEntity } private boolean syncFromMaster(PatternProviderBlockEntity master) { - var changed = this.bindToMaster(master); + var masterLevel = master.getLevel(); + if (masterLevel == null) { + return false; + } + + var changed = this.setBoundMaster(masterLevel.dimension(), master.getBlockPos()); changed |= this.syncMirroredSettings(master); changed |= this.syncMirroredPatterns(master); if (changed) { - this.saveChanges(); - this.markForClientUpdate(); + this.flushStateChanges(); } return changed; @@ -360,72 +357,62 @@ public class MirrorPatternProviderBlockEntity extends PatternProviderBlockEntity private boolean syncMirroredPatterns(PatternProviderBlockEntity master) { var mirrorInventory = this.getPatternInventory(); - var desiredInventory = this.createDesiredPatternInventory(master); + var masterInventory = asPatternInventory(master.getLogic().getPatternInv()); + var mirrorSize = mirrorInventory.size(); + var masterSize = masterInventory.size(); + var changed = false; - if (this.hasSamePatterns(desiredInventory, mirrorInventory)) { - return false; + for (int slot = 0; slot < mirrorSize; slot++) { + var desiredStack = slot < masterSize ? masterInventory.getStackInSlot(slot) : ItemStack.EMPTY; + var currentStack = mirrorInventory.getStackInSlot(slot); + if (!sameStack(desiredStack, currentStack)) { + mirrorInventory.setItemDirect(slot, desiredStack.isEmpty() ? ItemStack.EMPTY : desiredStack.copy()); + changed = true; + } } - mirrorInventory.fromItemContainerContents(desiredInventory.toItemContainerContents()); - this.getLogic().updatePatterns(); - return true; + if (changed) { + this.getLogic().updatePatterns(); + } + + return changed; } private boolean clearMirroredPatterns() { var patternInventory = this.getPatternInventory(); - if (this.isPatternInventoryEmpty(patternInventory)) { - return false; - } + var changed = false; - patternInventory.fromItemContainerContents(ItemContainerContents.EMPTY); - this.getLogic().updatePatterns(); - return true; - } - - private boolean hasSamePatterns(AppEngInternalInventory masterInventory, AppEngInternalInventory mirrorInventory) { - if (masterInventory.size() != mirrorInventory.size()) { - return false; - } - - for (int slot = 0; slot < masterInventory.size(); slot++) { - if (!sameStack(masterInventory.getStackInSlot(slot), mirrorInventory.getStackInSlot(slot))) { - return false; + for (int slot = 0; slot < patternInventory.size(); slot++) { + if (!patternInventory.getStackInSlot(slot).isEmpty()) { + patternInventory.setItemDirect(slot, ItemStack.EMPTY); + changed = true; } } - return true; - } - - private boolean isPatternInventoryEmpty(AppEngInternalInventory inventory) { - for (int slot = 0; slot < inventory.size(); slot++) { - if (!inventory.getStackInSlot(slot).isEmpty()) { - return false; - } + if (changed) { + this.getLogic().updatePatterns(); } - return true; + return changed; } private AppEngInternalInventory getPatternInventory() { return ((MirrorLogic) this.getLogic()).getActualPatternInventory(); } - private AppEngInternalInventory createDesiredPatternInventory(PatternProviderBlockEntity master) { - var desiredInventory = new AppEngInternalInventory(this.getPatternInventory().size()); - var masterInventory = asPatternInventory(master.getLogic().getPatternInv()); - var copySlotCount = Math.min(masterInventory.size(), desiredInventory.size()); - - for (int slot = 0; slot < copySlotCount; slot++) { - desiredInventory.setItemDirect(slot, masterInventory.getStackInSlot(slot).copy()); - } - - return desiredInventory; - } - private static AppEngInternalInventory asPatternInventory(Object inventory) { return (AppEngInternalInventory) inventory; } + private void flushStateChanges() { + this.saveChanges(); + this.markForClientUpdate(); + } + + private void scheduleImmediateSync() { + this.nextSyncTick = Long.MIN_VALUE; + } + private static int getMirrorPatternSlotCapacity() { int pageMultiplier = 1; try { diff --git a/src/main/java/com/extendedae_plus/mixin/ae2/autopattern/CraftingSimulationStateMixin.java b/src/main/java/com/extendedae_plus/mixin/ae2/autopattern/CraftingSimulationStateMixin.java index d602383..a42e898 100644 --- a/src/main/java/com/extendedae_plus/mixin/ae2/autopattern/CraftingSimulationStateMixin.java +++ b/src/main/java/com/extendedae_plus/mixin/ae2/autopattern/CraftingSimulationStateMixin.java @@ -5,16 +5,18 @@ import appeng.crafting.CraftingCalculation; import appeng.crafting.CraftingPlan; import appeng.crafting.inv.CraftingSimulationState; import appeng.me.service.CraftingService; +import appeng.api.networking.crafting.ICraftingProvider; +import com.extendedae_plus.api.crafting.ScaledProcessingPattern; import com.extendedae_plus.api.smartDoubling.ICraftingCalculationExt; import com.extendedae_plus.api.smartDoubling.ISmartDoublingAwarePattern; import com.extendedae_plus.config.ModConfigs; import com.extendedae_plus.util.smartDoubling.PatternScaler; -import com.google.common.collect.Iterables; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; @@ -32,6 +34,7 @@ public abstract class CraftingSimulationStateMixin { Map crafts = accessor.getCrafts(); // 存放最终分配后的 crafts Map finalCrafts = new LinkedHashMap<>(); + Map providerCountCache = new HashMap<>(); for (Map.Entry entry : crafts.entrySet()) { IPatternDetails processingPattern = entry.getKey(); @@ -60,7 +63,11 @@ public abstract class CraftingSimulationStateMixin { // 检查是否开启 provider 轮询分配功能 if (ModConfigs.PROVIDER_ROUND_ROBIN_ENABLE.getRaw()) { CraftingService craftingService = (CraftingService) ((ICraftingCalculationExt) calculation).getGrid().getCraftingService(); - int providerCount = Math.max(Iterables.size(craftingService.getProviders(processingPattern)), 1); + int providerCount = Math.max( + providerCountCache.computeIfAbsent( + getProviderCacheKey(processingPattern), + key -> countProvidersUpTo(craftingService.getProviders(key), totalAmount)), + 1); // totalAmount < providerCount → 只激活 totalAmount 台 provider if (totalAmount < providerCount) { @@ -106,4 +113,27 @@ public abstract class CraftingSimulationStateMixin { crafts.clear(); crafts.putAll(finalCrafts); } -} \ No newline at end of file + + private static IPatternDetails getProviderCacheKey(IPatternDetails pattern) { + if (pattern instanceof ScaledProcessingPattern scaled) { + return scaled.getOriginal(); + } + return pattern; + } + + private static int countProvidersUpTo(Iterable providers, long maxNeeded) { + int count = 0; + int limit = maxNeeded <= 0 + ? Integer.MAX_VALUE + : maxNeeded >= Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) maxNeeded; + + for (var ignored : providers) { + count++; + if (count >= limit) { + break; + } + } + + return count; + } +}