Compare commits
29 Commits
master
...
develop/gt
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
27048e08bf | ||
|
|
5923000d3b | ||
|
|
680a1ebfd4 | ||
|
|
28c5d0a8f4 | ||
|
|
54e0d8459d | ||
|
|
2821f8d024 | ||
|
|
55c58ff89f | ||
|
|
eace9531ea | ||
|
|
66e815f613 | ||
|
|
5996882b72 | ||
|
|
342a9510d7 | ||
|
|
9f703d89dc | ||
|
|
a4905c2a3f | ||
|
|
e6dd8381bd | ||
|
|
2cf457fde3 | ||
|
|
0b1077a20e | ||
|
|
c9797d3f6c | ||
|
|
9bbeb97b1b | ||
|
|
573a63bab7 | ||
|
|
50d74cafb0 | ||
|
|
9c69bc9175 | ||
|
|
81be9efab4 | ||
|
|
c106cf1be7 | ||
|
|
05f14e8150 | ||
|
|
71b7bca977 | ||
|
|
c48f712c8b | ||
|
|
d8d734bfaf | ||
|
|
0db446b056 | ||
|
|
2e230dcad6 |
42
build.gradle
42
build.gradle
|
|
@ -70,6 +70,15 @@ repositories {
|
||||||
}
|
}
|
||||||
maven { url "https://repo.spongepowered.org/maven" }
|
maven { url "https://repo.spongepowered.org/maven" }
|
||||||
maven { url "https://dl.cloudsmith.io/public/geckolib3/geckolib/maven/" }
|
maven { url "https://dl.cloudsmith.io/public/geckolib3/geckolib/maven/" }
|
||||||
|
maven { // Registrate
|
||||||
|
url = "https://maven.tterrag.com/"
|
||||||
|
content {
|
||||||
|
// need to be specific here due to version overlaps
|
||||||
|
includeGroup("com.jozufozu.flywheel")
|
||||||
|
includeGroup("com.tterrag.registrate")
|
||||||
|
includeGroup("com.simibubi.create")
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
@ -105,18 +114,45 @@ dependencies {
|
||||||
modImplementation "curse.maven:jade-324717:${jade_version}"
|
modImplementation "curse.maven:jade-324717:${jade_version}"
|
||||||
|
|
||||||
// GregTech
|
// GregTech
|
||||||
modCompileOnly "curse.maven:gregtechceu-modern-890405:${gregtech_version}"
|
modImplementation "curse.maven:gregtechceu-modern-890405:${gregtech_version}"
|
||||||
modCompileOnly "curse.maven:ldlib-626676:${ldlib_version}"
|
modImplementation "curse.maven:ldlib-626676:5775541"
|
||||||
|
modImplementation files('libs/gtlcore-1.2.2.4-fix8.jar')
|
||||||
|
modImplementation("dev:gtmthings-1.3.5.b")
|
||||||
|
modImplementation("dev:resourcefullib-forge-1.20.1-2.1.29")
|
||||||
|
modImplementation("dev:resourcefulconfig-forge-1.20.1-2.1.3")
|
||||||
|
modImplementation("dev:botarium-forge-1.20.1-2.3.4")
|
||||||
|
modImplementation("dev:ad_astra-forge-1.20.1-1.15.20")
|
||||||
|
implementation(annotationProcessor("io.github.llamalad7:mixinextras-common:0.2.0"))
|
||||||
|
implementation(include("io.github.llamalad7:mixinextras-forge:0.2.0"))
|
||||||
|
modImplementation("com.tterrag.registrate:Registrate:MC1.20-1.3.11")
|
||||||
|
modImplementation("curse.maven:kubejs-238086:5454840")
|
||||||
|
modImplementation("curse.maven:rhino-416294:6186971")
|
||||||
|
|
||||||
//curios
|
//curios
|
||||||
modImplementation "curse.maven:curios-309927:${curios_version}"
|
modImplementation "curse.maven:curios-309927:${curios_version}"
|
||||||
|
|
||||||
// Runtime test
|
// Runtime test
|
||||||
|
modRuntimeOnly "curse.maven:curios-309927:${curios_version}"
|
||||||
|
modImplementation "curse.maven:jade-324717:5339264"
|
||||||
modRuntimeOnly "dev.architectury:architectury-forge:9.2.14"
|
modRuntimeOnly "dev.architectury:architectury-forge:9.2.14"
|
||||||
modRuntimeOnly "curse.maven:cloth-config-348521:5729105"
|
modRuntimeOnly "curse.maven:cloth-config-348521:5729105"
|
||||||
|
|
||||||
//jec
|
//jec
|
||||||
modImplementation "curse.maven:just-enough-characters-250702:6680042"
|
modImplementation "curse.maven:just-enough-characters-250702:6680042"
|
||||||
|
modCompileOnly "curse.maven:just-enough-characters-250702:6680042"
|
||||||
|
|
||||||
|
//拼音搜索
|
||||||
|
modRuntimeOnly("dev:jecharacters-1.20.1-forge-4.5.11-dev-shadow")
|
||||||
|
//输入法冲突
|
||||||
|
modRuntimeOnly("curse.maven:cloth-config-348521:5729105")
|
||||||
|
modRuntimeOnly("curse.maven:IMBlocker-483760:6922546")
|
||||||
|
|
||||||
|
//mae2
|
||||||
|
// modRuntimeOnly "curse.maven:modern-ae2-additions-1028068:6827727"
|
||||||
|
modCompileOnly "curse.maven:modern-ae2-additions-1028068:6827727"
|
||||||
|
|
||||||
|
//aea
|
||||||
|
modImplementation "curse.maven:advancedae-1084104:6939473"
|
||||||
|
|
||||||
//geckolib
|
//geckolib
|
||||||
modRuntimeOnly "curse.maven:geckolib-388172:6920925"
|
modRuntimeOnly "curse.maven:geckolib-388172:6920925"
|
||||||
|
|
@ -130,8 +166,10 @@ dependencies {
|
||||||
//ftbteams
|
//ftbteams
|
||||||
modCompileOnly "curse.maven:ftb-teams-forge-404468:6130786"
|
modCompileOnly "curse.maven:ftb-teams-forge-404468:6130786"
|
||||||
modCompileOnly "curse.maven:ftb-library-forge-404465:6807424"
|
modCompileOnly "curse.maven:ftb-library-forge-404465:6807424"
|
||||||
|
modCompileOnly "curse.maven:ftb-chunk-forge-314906:6431735"
|
||||||
modRuntimeOnly "curse.maven:ftb-teams-forge-404468:6130786"
|
modRuntimeOnly "curse.maven:ftb-teams-forge-404468:6130786"
|
||||||
modRuntimeOnly "curse.maven:ftb-library-forge-404465:6807424"
|
modRuntimeOnly "curse.maven:ftb-library-forge-404465:6807424"
|
||||||
|
modRuntimeOnly "curse.maven:ftb-chunk-forge-314906:6431735"
|
||||||
}
|
}
|
||||||
|
|
||||||
compileJava {
|
compileJava {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ org.gradle.jvmargs=-Xmx1G
|
||||||
loom.platform = forge
|
loom.platform = forge
|
||||||
|
|
||||||
# Mod properties
|
# Mod properties
|
||||||
mod_version = 1.4.4
|
mod_version = 1.4.5-gtl
|
||||||
maven_group = com.extendedae_plus
|
maven_group = com.extendedae_plus
|
||||||
archives_name = extendedae_plus
|
archives_name = extendedae_plus
|
||||||
|
|
||||||
|
|
@ -26,7 +26,7 @@ rei_version=12.0.622
|
||||||
cloth_config_version=9.0.94
|
cloth_config_version=9.0.94
|
||||||
projecte_version=4901949
|
projecte_version=4901949
|
||||||
appliede_version=5364294
|
appliede_version=5364294
|
||||||
gregtech_version=5369020
|
gregtech_version=5753724
|
||||||
ldlib_version=5394816
|
ldlib_version=5394816
|
||||||
ie_version=5224387
|
ie_version=5224387
|
||||||
mixin_version=0.8.4
|
mixin_version=0.8.4
|
||||||
|
|
|
||||||
BIN
libs/ad_astra-forge-1.20.1-1.15.20.jar
Normal file
BIN
libs/ad_astra-forge-1.20.1-1.15.20.jar
Normal file
Binary file not shown.
BIN
libs/botarium-forge-1.20.1-2.3.4.jar
Normal file
BIN
libs/botarium-forge-1.20.1-2.3.4.jar
Normal file
Binary file not shown.
BIN
libs/gtlcore-1.2.2.4-fix8.jar
Normal file
BIN
libs/gtlcore-1.2.2.4-fix8.jar
Normal file
Binary file not shown.
BIN
libs/gtmthings-1.3.5.b.jar
Normal file
BIN
libs/gtmthings-1.3.5.b.jar
Normal file
Binary file not shown.
BIN
libs/jecharacters-1.20.1-forge-4.5.11-dev-shadow.jar
Normal file
BIN
libs/jecharacters-1.20.1-forge-4.5.11-dev-shadow.jar
Normal file
Binary file not shown.
BIN
libs/resourcefulconfig-forge-1.20.1-2.1.3.jar
Normal file
BIN
libs/resourcefulconfig-forge-1.20.1-2.1.3.jar
Normal file
Binary file not shown.
BIN
libs/resourcefullib-forge-1.20.1-2.1.29.jar
Normal file
BIN
libs/resourcefullib-forge-1.20.1-2.1.29.jar
Normal file
Binary file not shown.
|
|
@ -22,7 +22,7 @@
|
||||||
"item": "appflux:energy_processor"
|
"item": "appflux:energy_processor"
|
||||||
},
|
},
|
||||||
"M": {
|
"M": {
|
||||||
"tag": "forge:gems/redstone"
|
"item": "appflux:redstone_crystal"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"pattern": [
|
"pattern": [
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
"item": "appflux:core_256k"
|
"item": "appflux:core_256k"
|
||||||
},
|
},
|
||||||
"M": {
|
"M": {
|
||||||
"tag": "forge:ingots/sky_insulating_resin"
|
"item": "appflux:sky_harden_insulating_resin"
|
||||||
},
|
},
|
||||||
"O": {
|
"O": {
|
||||||
"item": "extendedae_plus:oblivion_singularity"
|
"item": "extendedae_plus:oblivion_singularity"
|
||||||
|
|
|
||||||
|
|
@ -132,6 +132,14 @@ public final class ModConfig {
|
||||||
@Configurable.ValueUpdateCallback(method = "onEntityTickerMultipliersUpdate")
|
@Configurable.ValueUpdateCallback(method = "onEntityTickerMultipliersUpdate")
|
||||||
public String[] entityTickerMultipliers = {};
|
public String[] entityTickerMultipliers = {};
|
||||||
|
|
||||||
|
@Configurable
|
||||||
|
@Configurable.Comment(value = {
|
||||||
|
"限制合成样板自动上传仅进入分子操纵者",
|
||||||
|
"开启后,合成样板将只自动上传到分子操纵者,不再上传至装配矩阵"
|
||||||
|
})
|
||||||
|
@Configurable.Synchronized
|
||||||
|
public boolean restrictCraftingPatternToMolecular = false;
|
||||||
|
|
||||||
private static final ScheduledExecutorService EXECUTOR = Executors.newSingleThreadScheduledExecutor();
|
private static final ScheduledExecutorService EXECUTOR = Executors.newSingleThreadScheduledExecutor();
|
||||||
private static ScheduledFuture<?> pendingPowerTask;
|
private static ScheduledFuture<?> pendingPowerTask;
|
||||||
private static final Object POWER_LOCK = new Object();
|
private static final Object POWER_LOCK = new Object();
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,6 @@ import com.extendedae_plus.items.BasicCoreItem;
|
||||||
import com.extendedae_plus.items.materials.EntitySpeedCardItem;
|
import com.extendedae_plus.items.materials.EntitySpeedCardItem;
|
||||||
import com.extendedae_plus.util.ModCheckUtils;
|
import com.extendedae_plus.util.ModCheckUtils;
|
||||||
import com.glodblock.github.appflux.common.AFItemAndBlock;
|
import com.glodblock.github.appflux.common.AFItemAndBlock;
|
||||||
import com.glodblock.github.appflux.util.AFTags;
|
|
||||||
import com.glodblock.github.extendedae.common.EPPItemAndBlock;
|
import com.glodblock.github.extendedae.common.EPPItemAndBlock;
|
||||||
import gripe._90.megacells.definition.MEGAItems;
|
import gripe._90.megacells.definition.MEGAItems;
|
||||||
import net.minecraft.data.PackOutput;
|
import net.minecraft.data.PackOutput;
|
||||||
|
|
@ -289,7 +288,7 @@ public class CraftingRecipes extends RecipeProvider {
|
||||||
.pattern("MCM")
|
.pattern("MCM")
|
||||||
.pattern("EBE")
|
.pattern("EBE")
|
||||||
.pattern("MEM")
|
.pattern("MEM")
|
||||||
.define('M', AFTags.REDSTONE_GEM)
|
.define('M', AFItemAndBlock.REDSTONE_CRYSTAL)
|
||||||
.define('C', AFItemAndBlock.CORE_16k)
|
.define('C', AFItemAndBlock.CORE_16k)
|
||||||
.define('E', AFItemAndBlock.ENERGY_PROCESSOR)
|
.define('E', AFItemAndBlock.ENERGY_PROCESSOR)
|
||||||
.defineNbt('B', base)
|
.defineNbt('B', base)
|
||||||
|
|
@ -315,7 +314,7 @@ public class CraftingRecipes extends RecipeProvider {
|
||||||
.pattern("MOM")
|
.pattern("MOM")
|
||||||
.pattern("CBC")
|
.pattern("CBC")
|
||||||
.pattern("MCM")
|
.pattern("MCM")
|
||||||
.define('M', AFTags.SKY_RESIN_INGOT)
|
.define('M', AFItemAndBlock.SKY_HARDEN_INSULATING_RESIN)
|
||||||
.define('O', ModItems.OBLIVION_SINGULARITY.get())
|
.define('O', ModItems.OBLIVION_SINGULARITY.get())
|
||||||
.define('C', AFItemAndBlock.CORE_256k)
|
.define('C', AFItemAndBlock.CORE_256k)
|
||||||
.defineNbt('B', BasicCoreItem.energyStage(2))
|
.defineNbt('B', BasicCoreItem.energyStage(2))
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
package com.extendedae_plus.mixin.ae2.autopattern.gtceu;
|
||||||
|
|
||||||
|
import appeng.api.crafting.IPatternDetails;
|
||||||
|
import appeng.crafting.pattern.AEProcessingPattern;
|
||||||
|
import com.extendedae_plus.api.crafting.ScaledProcessingPattern;
|
||||||
|
import com.extendedae_plus.api.smartDoubling.ISmartDoublingAwarePattern;
|
||||||
|
import com.google.common.collect.BiMap;
|
||||||
|
import org.gtlcore.gtlcore.common.machine.multiblock.part.ae.MEPatternBufferPartMachine;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Pseudo;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Pseudo
|
||||||
|
@Mixin(value = MEPatternBufferPartMachine.class, remap = false)
|
||||||
|
public class GTLCoreMEPatternBufferPartMachineMixin {
|
||||||
|
|
||||||
|
@Final
|
||||||
|
@Shadow
|
||||||
|
private BiMap<IPatternDetails, Integer> patternSlotMap;
|
||||||
|
|
||||||
|
// 设置样板总成是否翻倍
|
||||||
|
@Inject(method = "getAvailablePatterns", at = @At(value = "INVOKE", target = "Ljava/util/stream/Stream;toList()Ljava/util/List;", shift = At.Shift.BEFORE))
|
||||||
|
private void beforeToList(CallbackInfoReturnable<List<IPatternDetails>> cir) {
|
||||||
|
if (patternSlotMap == null) return;
|
||||||
|
for (Map.Entry<IPatternDetails, Integer> entry : patternSlotMap.entrySet()) {
|
||||||
|
IPatternDetails key = entry.getKey();
|
||||||
|
if (key instanceof AEProcessingPattern proc && proc instanceof ISmartDoublingAwarePattern aware) {
|
||||||
|
aware.eap$setAllowScaling(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重定向containsKey检查
|
||||||
|
@Redirect(method = "pushPattern(Lappeng/api/crafting/IPatternDetails;[Lappeng/api/stacks/KeyCounter;)Z",
|
||||||
|
at = @At(value = "INVOKE", target = "Lcom/google/common/collect/BiMap;containsKey(Ljava/lang/Object;)Z"))
|
||||||
|
private boolean redirectContainsKey(BiMap<IPatternDetails, ?> detailsSlotMap, Object key) {
|
||||||
|
try {
|
||||||
|
// 如果key是ScaledProcessingPattern类型,尝试用其原始pattern进行判断
|
||||||
|
if (key instanceof ScaledProcessingPattern scaled) {
|
||||||
|
IPatternDetails base = scaled.getOriginal();
|
||||||
|
if (base != null) {
|
||||||
|
// 避免递归重定向,直接遍历keySet判断
|
||||||
|
for (IPatternDetails d : detailsSlotMap.keySet()) {
|
||||||
|
if (Objects.equals(d, base)) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 常规判断,遍历keySet
|
||||||
|
for (IPatternDetails d : detailsSlotMap.keySet()) {
|
||||||
|
if (Objects.equals(d, key)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (Throwable t) {
|
||||||
|
// 出现异常时,回退到常规判断
|
||||||
|
for (IPatternDetails d : detailsSlotMap.keySet()) {
|
||||||
|
if (Objects.equals(d, key)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Redirect(method = "pushPattern(Lappeng/api/crafting/IPatternDetails;[Lappeng/api/stacks/KeyCounter;)Z",
|
||||||
|
at = @At(value = "INVOKE", target = "Lcom/google/common/collect/BiMap;get(Ljava/lang/Object;)Ljava/lang/Object;"))
|
||||||
|
private Object redirectGet(BiMap<IPatternDetails, ?> detailsSlotMap, Object key) {
|
||||||
|
try {
|
||||||
|
// 如果是 ScaledProcessingPattern,优先尝试其原始 pattern 对应的值
|
||||||
|
if (key instanceof ScaledProcessingPattern scaled) {
|
||||||
|
IPatternDetails base = scaled.getOriginal();
|
||||||
|
if (base != null) {
|
||||||
|
for (Map.Entry<IPatternDetails, ?> e : detailsSlotMap.entrySet()) {
|
||||||
|
if (Objects.equals(e.getKey(), base)) {
|
||||||
|
return e.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 常规查找:遍历 entrySet 避免再次调用 BiMap.get 导致递归重定向
|
||||||
|
for (Map.Entry<IPatternDetails, ?> e : detailsSlotMap.entrySet()) {
|
||||||
|
if (Objects.equals(e.getKey(), key)) {
|
||||||
|
return e.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (Throwable t) {
|
||||||
|
for (Map.Entry<IPatternDetails, ?> e : detailsSlotMap.entrySet()) {
|
||||||
|
if (Objects.equals(e.getKey(), key)) {
|
||||||
|
return e.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
package com.extendedae_plus.mixin.ae2.autopattern.gtceu;
|
||||||
|
|
||||||
|
import appeng.api.crafting.IPatternDetails;
|
||||||
|
import appeng.crafting.pattern.AEProcessingPattern;
|
||||||
|
import com.extendedae_plus.api.crafting.ScaledProcessingPattern;
|
||||||
|
import com.extendedae_plus.api.smartDoubling.ISmartDoublingAwarePattern;
|
||||||
|
import com.google.common.collect.BiMap;
|
||||||
|
import com.gregtechceu.gtceu.integration.ae2.machine.MEPatternBufferPartMachine;
|
||||||
|
import org.spongepowered.asm.mixin.Final;
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.Pseudo;
|
||||||
|
import org.spongepowered.asm.mixin.Shadow;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@Pseudo
|
||||||
|
@Mixin(value = MEPatternBufferPartMachine.class, remap = false)
|
||||||
|
public class MEPatternBufferPartMachineMixin {
|
||||||
|
|
||||||
|
@Shadow
|
||||||
|
@Final
|
||||||
|
private BiMap<IPatternDetails, Integer> detailsSlotMap;
|
||||||
|
|
||||||
|
// 设置样板总成是否翻倍
|
||||||
|
@Inject(method = "getAvailablePatterns", at = @At(value = "INVOKE", target = "Ljava/util/stream/Stream;toList()Ljava/util/List;", shift = At.Shift.BEFORE))
|
||||||
|
private void beforeToList(CallbackInfoReturnable<List<IPatternDetails>> cir) {
|
||||||
|
if (detailsSlotMap == null) return;
|
||||||
|
for (Map.Entry<IPatternDetails, Integer> entry : detailsSlotMap.entrySet()) {
|
||||||
|
IPatternDetails key = entry.getKey();
|
||||||
|
if (key instanceof AEProcessingPattern proc && proc instanceof ISmartDoublingAwarePattern aware) {
|
||||||
|
aware.eap$setAllowScaling(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 重定向containsKey检查
|
||||||
|
@Redirect(method = "pushPattern(Lappeng/api/crafting/IPatternDetails;[Lappeng/api/stacks/KeyCounter;)Z",
|
||||||
|
at = @At(value = "INVOKE", target = "Lcom/google/common/collect/BiMap;containsKey(Ljava/lang/Object;)Z"))
|
||||||
|
private boolean redirectContainsKey(BiMap<IPatternDetails, ?> detailsSlotMap, Object key) {
|
||||||
|
try {
|
||||||
|
// 如果key是ScaledProcessingPattern类型,尝试用其原始pattern进行判断
|
||||||
|
if (key instanceof ScaledProcessingPattern scaled) {
|
||||||
|
IPatternDetails base = scaled.getOriginal();
|
||||||
|
if (base != null) {
|
||||||
|
// 避免递归重定向,直接遍历keySet判断
|
||||||
|
for (IPatternDetails d : detailsSlotMap.keySet()) {
|
||||||
|
if (Objects.equals(d, base)) return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 常规判断,遍历keySet
|
||||||
|
for (IPatternDetails d : detailsSlotMap.keySet()) {
|
||||||
|
if (Objects.equals(d, key)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} catch (Throwable t) {
|
||||||
|
// 出现异常时,回退到常规判断
|
||||||
|
for (IPatternDetails d : detailsSlotMap.keySet()) {
|
||||||
|
if (Objects.equals(d, key)) return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Redirect(method = "pushPattern(Lappeng/api/crafting/IPatternDetails;[Lappeng/api/stacks/KeyCounter;)Z",
|
||||||
|
at = @At(value = "INVOKE", target = "Lcom/google/common/collect/BiMap;get(Ljava/lang/Object;)Ljava/lang/Object;"))
|
||||||
|
private Object redirectGet(BiMap<IPatternDetails, ?> detailsSlotMap, Object key) {
|
||||||
|
try {
|
||||||
|
// 如果是 ScaledProcessingPattern,优先尝试其原始 pattern 对应的值
|
||||||
|
if (key instanceof ScaledProcessingPattern scaled) {
|
||||||
|
IPatternDetails base = scaled.getOriginal();
|
||||||
|
if (base != null) {
|
||||||
|
for (Map.Entry<IPatternDetails, ?> e : detailsSlotMap.entrySet()) {
|
||||||
|
if (Objects.equals(e.getKey(), base)) {
|
||||||
|
return e.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 常规查找:遍历 entrySet 避免再次调用 BiMap.get 导致递归重定向
|
||||||
|
for (Map.Entry<IPatternDetails, ?> e : detailsSlotMap.entrySet()) {
|
||||||
|
if (Objects.equals(e.getKey(), key)) {
|
||||||
|
return e.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
} catch (Throwable t) {
|
||||||
|
for (Map.Entry<IPatternDetails, ?> e : detailsSlotMap.entrySet()) {
|
||||||
|
if (Objects.equals(e.getKey(), key)) {
|
||||||
|
return e.getValue();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -4,6 +4,8 @@ import appeng.api.crafting.PatternDetailsHelper;
|
||||||
import appeng.menu.me.items.PatternEncodingTermMenu;
|
import appeng.menu.me.items.PatternEncodingTermMenu;
|
||||||
import appeng.menu.slot.RestrictedInputSlot;
|
import appeng.menu.slot.RestrictedInputSlot;
|
||||||
import appeng.parts.encoding.EncodingMode;
|
import appeng.parts.encoding.EncodingMode;
|
||||||
|
import com.extendedae_plus.config.ModConfig;
|
||||||
|
import com.extendedae_plus.util.uploadPattern.GTMatrixUploadUtil;
|
||||||
import com.extendedae_plus.util.uploadPattern.MatrixUploadUtil;
|
import com.extendedae_plus.util.uploadPattern.MatrixUploadUtil;
|
||||||
import com.glodblock.github.glodium.network.packet.sync.IActionHolder;
|
import com.glodblock.github.glodium.network.packet.sync.IActionHolder;
|
||||||
import com.glodblock.github.glodium.network.packet.sync.Paras;
|
import com.glodblock.github.glodium.network.packet.sync.Paras;
|
||||||
|
|
@ -47,7 +49,9 @@ public abstract class ContainerPatternEncodingTermMenuMixin implements IActionHo
|
||||||
}
|
}
|
||||||
var stack = this.encodedPatternSlot != null ? this.encodedPatternSlot.getItem() : net.minecraft.world.item.ItemStack.EMPTY;
|
var stack = this.encodedPatternSlot != null ? this.encodedPatternSlot.getItem() : net.minecraft.world.item.ItemStack.EMPTY;
|
||||||
if (stack != null && !stack.isEmpty() && PatternDetailsHelper.isEncodedPattern(stack)) {
|
if (stack != null && !stack.isEmpty() && PatternDetailsHelper.isEncodedPattern(stack)) {
|
||||||
|
if (!ModConfig.INSTANCE.restrictCraftingPatternToMolecular)
|
||||||
MatrixUploadUtil.uploadFromEncodingMenuToMatrix(sp, menu);
|
MatrixUploadUtil.uploadFromEncodingMenuToMatrix(sp, menu);
|
||||||
|
else GTMatrixUploadUtil.uploadFromEncodingMenuToMatrix(sp, menu);
|
||||||
} else {
|
} else {
|
||||||
// 槽位可能尚未同步到位,继续下一 tick 重试
|
// 槽位可能尚未同步到位,继续下一 tick 重试
|
||||||
if (attemptsLeft > 0) {
|
if (attemptsLeft > 0) {
|
||||||
|
|
@ -105,7 +109,9 @@ public abstract class ContainerPatternEncodingTermMenuMixin implements IActionHo
|
||||||
// 为避免与 AE2 后续同步竞争,切到下一 tick 执行
|
// 为避免与 AE2 后续同步竞争,切到下一 tick 执行
|
||||||
sp.server.execute(() -> {
|
sp.server.execute(() -> {
|
||||||
try {
|
try {
|
||||||
|
if (!ModConfig.INSTANCE.restrictCraftingPatternToMolecular)
|
||||||
MatrixUploadUtil.uploadFromEncodingMenuToMatrix(sp, menu);
|
MatrixUploadUtil.uploadFromEncodingMenuToMatrix(sp, menu);
|
||||||
|
else GTMatrixUploadUtil.uploadFromEncodingMenuToMatrix(sp, menu);
|
||||||
} catch (Throwable ignored) {
|
} catch (Throwable ignored) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
@ -117,7 +123,9 @@ public abstract class ContainerPatternEncodingTermMenuMixin implements IActionHo
|
||||||
private void onEncodePatternReturn(CallbackInfoReturnable<ItemStack> cir) {
|
private void onEncodePatternReturn(CallbackInfoReturnable<ItemStack> cir) {
|
||||||
ItemStack itemStack = cir.getReturnValue();
|
ItemStack itemStack = cir.getReturnValue();
|
||||||
if (itemStack != null && !itemStack.isEmpty()) {
|
if (itemStack != null && !itemStack.isEmpty()) {
|
||||||
itemStack.getOrCreateTag().putString("encodePlayer", this.epp$player.getGameProfile().getName());
|
itemStack.getOrCreateTag()
|
||||||
|
.putString("encodePlayer", this.epp$player.getGameProfile()
|
||||||
|
.getName());
|
||||||
cir.setReturnValue(itemStack);
|
cir.setReturnValue(itemStack);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
package com.extendedae_plus.mixin.gtceu;
|
||||||
|
|
||||||
|
import appeng.api.crafting.PatternDetailsHelper;
|
||||||
|
import appeng.api.stacks.AEKey;
|
||||||
|
import com.extendedae_plus.content.ClientPatternHighlightStore;
|
||||||
|
import com.extendedae_plus.util.GuiUtil;
|
||||||
|
import com.gregtechceu.gtceu.integration.ae2.gui.widget.slot.AEPatternViewSlotWidget;
|
||||||
|
import com.lowdragmc.lowdraglib.gui.widget.SlotWidget;
|
||||||
|
import com.lowdragmc.lowdraglib.utils.Position;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
|
import net.minecraft.world.inventory.Slot;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
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.CallbackInfo;
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
@Mixin(value = AEPatternViewSlotWidget.class, remap = false)
|
||||||
|
public abstract class AEPatternViewSlotWidgetMixin {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在 AEPatternViewSlotWidget.drawBackgroundTexture(...) 尾部注入绘制数字逻辑
|
||||||
|
*/
|
||||||
|
@Inject(method = "drawBackgroundTexture", at = @At("TAIL"))
|
||||||
|
private void onDrawInBackgroundTail(GuiGraphics graphics, int mouseX, int mouseY, CallbackInfo ci) {
|
||||||
|
if (!AEPatternViewSlotWidget.class.isInstance(this)) return;
|
||||||
|
// 把 this 强转为 SlotWidget(目标类继承自 SlotWidget)
|
||||||
|
SlotWidget self = (SlotWidget) (Object) this;
|
||||||
|
|
||||||
|
Slot handler = self.getHandler();
|
||||||
|
if (handler == null) return;
|
||||||
|
|
||||||
|
// 使用 getRealStack 来尊重 setItemHook 的渲染替换
|
||||||
|
ItemStack displayStack = self.getRealStack(handler.getItem());
|
||||||
|
if (displayStack == null || displayStack.isEmpty()) return;
|
||||||
|
|
||||||
|
ItemStack stack = handler.getItem();
|
||||||
|
Position pos = self.getPosition(); // 来自 Widget 的方法,继承可用
|
||||||
|
try {
|
||||||
|
var details = PatternDetailsHelper.decodePattern(stack, Minecraft.getInstance().level, false);
|
||||||
|
if (details != null && details.getOutputs() != null && details.getOutputs().length > 0) {
|
||||||
|
AEKey key = details.getOutputs()[0].what();
|
||||||
|
if (key != null && ClientPatternHighlightStore.hasHighlight(key)) {
|
||||||
|
GuiUtil.drawSlotRainbowHighlight(graphics, pos.x + 1, pos.y + 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable ignore) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package com.extendedae_plus.mixin.gtceu;
|
||||||
|
|
||||||
|
import com.extendedae_plus.content.ClientPatternHighlightStore;
|
||||||
|
import com.lowdragmc.lowdraglib.gui.modular.ModularUIGuiContainer;
|
||||||
|
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.CallbackInfo;
|
||||||
|
|
||||||
|
@Mixin(value = ModularUIGuiContainer.class, remap = false)
|
||||||
|
public class ModularUIGuiContainerCloseMixin {
|
||||||
|
|
||||||
|
@Inject(method = "removed", at = @At("HEAD"))
|
||||||
|
private void onRemoved(CallbackInfo ci) {
|
||||||
|
try {
|
||||||
|
ClientPatternHighlightStore.clearAll();
|
||||||
|
} catch (Throwable ignored) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
package com.extendedae_plus.mixin.gtceu;
|
||||||
|
|
||||||
|
import com.extendedae_plus.util.GuiUtil;
|
||||||
|
import com.gregtechceu.gtceu.integration.ae2.gui.widget.slot.AEPatternViewSlotWidget;
|
||||||
|
import com.lowdragmc.lowdraglib.gui.util.DrawerHelper;
|
||||||
|
import com.lowdragmc.lowdraglib.gui.widget.SlotWidget;
|
||||||
|
import com.lowdragmc.lowdraglib.utils.Position;
|
||||||
|
import com.lowdragmc.lowdraglib.utils.Size;
|
||||||
|
import com.mojang.blaze3d.systems.RenderSystem;
|
||||||
|
import net.minecraft.client.gui.GuiGraphics;
|
||||||
|
import net.minecraft.world.inventory.Slot;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import net.minecraftforge.api.distmarker.Dist;
|
||||||
|
import net.minecraftforge.api.distmarker.OnlyIn;
|
||||||
|
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.CallbackInfo;
|
||||||
|
|
||||||
|
|
||||||
|
@OnlyIn(Dist.CLIENT)
|
||||||
|
@Mixin(value = SlotWidget.class, remap = false)
|
||||||
|
public abstract class SlotWidgetMixin {
|
||||||
|
/**
|
||||||
|
* 在 SlotWidget.drawInBackground(...) 尾部注入绘制数字逻辑
|
||||||
|
*/
|
||||||
|
@Inject(method = "drawInBackground(Lnet/minecraft/client/gui/GuiGraphics;IIF)V", at = @At("TAIL"))
|
||||||
|
private void onDrawInBackgroundTail(GuiGraphics graphics, int mouseX, int mouseY, float partialTicks, CallbackInfo ci) {
|
||||||
|
if (!AEPatternViewSlotWidget.class.isInstance(this)) return;
|
||||||
|
// 把 this 强转为 SlotWidget(目标类继承自 SlotWidget)
|
||||||
|
SlotWidget self = (SlotWidget) (Object) this;
|
||||||
|
|
||||||
|
Slot handler = self.getHandler();
|
||||||
|
if (handler == null) return;
|
||||||
|
|
||||||
|
// 使用 getRealStack 来尊重 setItemHook 的渲染替换
|
||||||
|
ItemStack displayStack = self.getRealStack(handler.getItem());
|
||||||
|
if (displayStack == null || displayStack.isEmpty()) return;
|
||||||
|
|
||||||
|
ItemStack stack = handler.getItem();
|
||||||
|
|
||||||
|
String patternOutputText = GuiUtil.getPatternOutputText(stack);
|
||||||
|
|
||||||
|
Position pos = self.getPosition(); // 来自 Widget 的方法,继承可用
|
||||||
|
Size size = self.getSize(); // 同上
|
||||||
|
|
||||||
|
graphics.pose().pushPose();
|
||||||
|
graphics.pose().translate(0.0F, 0.0F, 300.0F);
|
||||||
|
RenderSystem.disableDepthTest();
|
||||||
|
DrawerHelper.drawStringFixedCorner(
|
||||||
|
graphics,
|
||||||
|
patternOutputText,
|
||||||
|
pos.x + size.width,
|
||||||
|
pos.y + size.height,
|
||||||
|
0xFFFFFFFF,
|
||||||
|
true,
|
||||||
|
0.75f);
|
||||||
|
RenderSystem.enableDepthTest();
|
||||||
|
graphics.pose().popPose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,10 +16,15 @@ import com.extendedae_plus.network.SetBlockHighlightS2CPacket;
|
||||||
import com.extendedae_plus.network.SetPatternHighlightS2CPacket;
|
import com.extendedae_plus.network.SetPatternHighlightS2CPacket;
|
||||||
import com.extendedae_plus.network.provider.SetProviderPageS2CPacket;
|
import com.extendedae_plus.network.provider.SetProviderPageS2CPacket;
|
||||||
import com.extendedae_plus.util.PatternProviderDataUtil;
|
import com.extendedae_plus.util.PatternProviderDataUtil;
|
||||||
|
import com.glodblock.github.extendedae.client.render.EAEHighlightHandler;
|
||||||
import com.glodblock.github.glodium.util.GlodUtil;
|
import com.glodblock.github.glodium.util.GlodUtil;
|
||||||
|
import com.gregtechceu.gtceu.api.gui.factory.MachineUIFactory;
|
||||||
|
import com.gregtechceu.gtceu.api.machine.MetaMachine;
|
||||||
|
import net.minecraft.core.BlockPos;
|
||||||
import net.minecraft.network.FriendlyByteBuf;
|
import net.minecraft.network.FriendlyByteBuf;
|
||||||
import net.minecraft.network.chat.Component;
|
import net.minecraft.network.chat.Component;
|
||||||
import net.minecraft.server.level.ServerPlayer;
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.world.level.Level;
|
||||||
import net.minecraftforge.network.NetworkDirection;
|
import net.minecraftforge.network.NetworkDirection;
|
||||||
import net.minecraftforge.network.NetworkEvent;
|
import net.minecraftforge.network.NetworkEvent;
|
||||||
|
|
||||||
|
|
@ -70,12 +75,23 @@ public class CraftingMonitorOpenProviderC2SPacket {
|
||||||
|
|
||||||
// 遍历所有样板,找到第一个可用 Provider 并打开 UI
|
// 遍历所有样板,找到第一个可用 Provider 并打开 UI
|
||||||
for (var pattern : patterns) {
|
for (var pattern : patterns) {
|
||||||
var provider = PatternLocator.findValidProvider(craftingService, pattern, grid);
|
var provider = CraftingMonitorOpenProviderC2SPacket.PatternLocator.findValidProvider(craftingService, pattern, grid);
|
||||||
if (provider == null) continue;
|
if (provider == null) {
|
||||||
|
for (var pd : craftingService.getProviders(pattern)) {
|
||||||
|
if (pd instanceof com.gregtechceu.gtceu.integration.ae2.machine.MEPatternBufferPartMachine machine) {
|
||||||
|
gtmOpenUI(machine, player, pattern);
|
||||||
|
return;
|
||||||
|
} else if (pd instanceof org.gtlcore.gtlcore.common.machine.multiblock.part.ae.MEPatternBufferPartMachine machine) {
|
||||||
|
gtmOpenUI(machine, player, pattern);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
ProviderUIHelper.openProviderUI(provider, pattern, player);
|
ProviderUIHelper.openProviderUI(provider, pattern, player);
|
||||||
} catch (Exception ignored) {}
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
context.setPacketHandled(true);
|
context.setPacketHandled(true);
|
||||||
|
|
@ -83,6 +99,44 @@ public class CraftingMonitorOpenProviderC2SPacket {
|
||||||
|
|
||||||
// ===================== 内部工具类 =====================
|
// ===================== 内部工具类 =====================
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 兼容gtm
|
||||||
|
*
|
||||||
|
* @param machine 样板总成
|
||||||
|
* @param player 玩家
|
||||||
|
* @param pattern 样板
|
||||||
|
*/
|
||||||
|
private static void gtmOpenUI(MetaMachine machine, ServerPlayer player, IPatternDetails pattern) {
|
||||||
|
try {
|
||||||
|
BlockPos pos = machine.getPos();
|
||||||
|
Level level = machine.getLevel();
|
||||||
|
if (pos == null || level == null) return;
|
||||||
|
if (!level.isClientSide) { // 确保在服务器端执行
|
||||||
|
MachineUIFactory.INSTANCE.openUI(MetaMachine.getMachine(level, pos), player);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 聊天提示
|
||||||
|
player.displayClientMessage(
|
||||||
|
Component.translatable(
|
||||||
|
"chat.extendedae_plus.terminal.pos",
|
||||||
|
pos.toShortString(),
|
||||||
|
level.dimension().location().getPath(),
|
||||||
|
(int) Math.sqrt(player.blockPosition().distSqr(pos))
|
||||||
|
),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
|
||||||
|
// 最后发送高亮包,保证界面已打开
|
||||||
|
if (pattern.getOutputs() != null && pattern.getOutputs().length > 0 && pattern.getOutputs()[0] != null) {
|
||||||
|
AEKey key = pattern.getOutputs()[0].what();
|
||||||
|
ModNetwork.CHANNEL.sendTo(new SetPatternHighlightS2CPacket(key, true), player.connection.connection, NetworkDirection.PLAY_TO_CLIENT);
|
||||||
|
}
|
||||||
|
|
||||||
|
EAEHighlightHandler.highlight(pos, level.dimension(), System.currentTimeMillis() + 15000);
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* GridHelper: 从菜单中获取网格实例
|
* GridHelper: 从菜单中获取网格实例
|
||||||
*/
|
*/
|
||||||
|
|
@ -91,6 +145,7 @@ public class CraftingMonitorOpenProviderC2SPacket {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取菜单对应的 Grid
|
* 获取菜单对应的 Grid
|
||||||
|
*
|
||||||
* @param menu 当前 AEBaseMenu
|
* @param menu 当前 AEBaseMenu
|
||||||
* @return Grid 或 null
|
* @return Grid 或 null
|
||||||
*/
|
*/
|
||||||
|
|
@ -111,6 +166,7 @@ public class CraftingMonitorOpenProviderC2SPacket {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查找提供指定样板的可用 Provider
|
* 查找提供指定样板的可用 Provider
|
||||||
|
*
|
||||||
* @param cs CraftingService
|
* @param cs CraftingService
|
||||||
* @param pattern 样板
|
* @param pattern 样板
|
||||||
* @param grid 当前 Grid
|
* @param grid 当前 Grid
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,179 @@
|
||||||
|
package com.extendedae_plus.util.uploadPattern;
|
||||||
|
|
||||||
|
import appeng.api.crafting.IPatternDetails;
|
||||||
|
import appeng.api.crafting.PatternDetailsHelper;
|
||||||
|
import appeng.api.inventories.InternalInventory;
|
||||||
|
import appeng.api.networking.IGrid;
|
||||||
|
import appeng.api.networking.IGridNode;
|
||||||
|
import appeng.core.definitions.AEItems;
|
||||||
|
import appeng.crafting.pattern.AECraftingPattern;
|
||||||
|
import appeng.crafting.pattern.AESmithingTablePattern;
|
||||||
|
import appeng.crafting.pattern.AEStonecuttingPattern;
|
||||||
|
import appeng.menu.me.items.PatternEncodingTermMenu;
|
||||||
|
import appeng.menu.slot.RestrictedInputSlot;
|
||||||
|
import com.extendedae_plus.mixin.ae2.accessor.PatternEncodingTermMenuAccessor;
|
||||||
|
import net.minecraft.network.chat.Component;
|
||||||
|
import net.minecraft.server.level.ServerPlayer;
|
||||||
|
import net.minecraft.world.item.ItemStack;
|
||||||
|
import org.gtlcore.gtlcore.common.machine.multiblock.part.ae.MEMolecularAssemblerIOPartMachine;
|
||||||
|
import org.gtlcore.gtlcore.integration.ae2.AEUtils;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static com.extendedae_plus.util.GlobalSendMessage.sendPlayerMessage;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gtlcore 分子操纵者样板上传
|
||||||
|
* 用于从 AE2 的样板编码终端上传至分子操纵者(仅合成样板)。
|
||||||
|
*/
|
||||||
|
public final class GTMatrixUploadUtil {
|
||||||
|
private GTMatrixUploadUtil() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从 AE2 的样板编码终端菜单上传当前“已编码合成样板”至 gtlcore 分子操纵者(仅合成样板)
|
||||||
|
*
|
||||||
|
* @param player 服务器玩家
|
||||||
|
* @param menu PatternEncodingTermMenu
|
||||||
|
*/
|
||||||
|
public static void uploadFromEncodingMenuToMatrix(ServerPlayer player, PatternEncodingTermMenu menu) {
|
||||||
|
if (player == null || menu == null) return;
|
||||||
|
// 读取已编码槽位的物品
|
||||||
|
RestrictedInputSlot encodedSlot = ((PatternEncodingTermMenuAccessor) menu).eap$getEncodedPatternSlot();
|
||||||
|
ItemStack stack = encodedSlot.getItem();
|
||||||
|
if (stack.isEmpty() || !PatternDetailsHelper.isEncodedPattern(stack)) return;
|
||||||
|
|
||||||
|
// 仅允许“合成/锻造台/切石机样板”
|
||||||
|
IPatternDetails details = PatternDetailsHelper.decodePattern(stack, player.level());
|
||||||
|
if (!(details instanceof AECraftingPattern
|
||||||
|
|| details instanceof AESmithingTablePattern
|
||||||
|
|| details instanceof AEStonecuttingPattern)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!AEUtils.molecularFilter(stack, player.level())){
|
||||||
|
player.sendSystemMessage(Component.literal("ExtendedAE Plus: 分子操纵者不支持该类型样板"));
|
||||||
|
refundBlankPattern(player, menu, stack.getCount());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取 AE 网络
|
||||||
|
IGridNode node = menu.getNetworkNode();
|
||||||
|
if (node == null) return;
|
||||||
|
|
||||||
|
IGrid grid = node.getGrid();
|
||||||
|
if (grid == null) return;
|
||||||
|
|
||||||
|
int stackCount = stack.getCount();
|
||||||
|
ItemStack toInsert = stack.copy();
|
||||||
|
|
||||||
|
// 收集所有可用的装配矩阵(图样模块)内部库存并逐一尝试(遵循其过滤规则)
|
||||||
|
List<InternalInventory> inventories = findAllGTMatrixPatternInventories(grid);
|
||||||
|
|
||||||
|
// 在尝试上传之前,检查装配矩阵是否已经存在相同样板(物品与NBT完全一致)
|
||||||
|
if (GTMatrixContainsPattern(inventories, stack)) {
|
||||||
|
// 直接提醒并跳过上传,并将同等数量的空白样板放回空白样板槽,否则退回玩家背包
|
||||||
|
sendPlayerMessage(player, Component.translatable("extendedae_plus.upload_to_GTMatrix.repetition"));
|
||||||
|
refundBlankPattern(player, menu, stackCount);
|
||||||
|
encodedSlot.set(ItemStack.EMPTY);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 尝试插入
|
||||||
|
for (InternalInventory inv : inventories) {
|
||||||
|
if (inv == null) continue;
|
||||||
|
ItemStack remain = inv.addItems(toInsert);
|
||||||
|
if (remain.getCount() < stackCount) {
|
||||||
|
completeUploadSuccess(player, encodedSlot, stack, remain);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 未找到可用矩阵或全部拒收
|
||||||
|
sendPlayerMessage(player,
|
||||||
|
inventories.isEmpty()
|
||||||
|
? Component.translatable("extendedae_plus.upload_to_matrix.fail_no_GTMatrix")
|
||||||
|
: Component.translatable("extendedae_plus.upload_to_GTMatrix.fail_full"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 在给定 AE Grid 中收集在线的GT分子的用于外部插入的内部库存。
|
||||||
|
*/
|
||||||
|
private static List<InternalInventory> findAllGTMatrixPatternInventories(IGrid grid) {
|
||||||
|
List<InternalInventory> result = new ArrayList<>();
|
||||||
|
if (grid == null) return result;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 获取网络中所有 Pattern Tile
|
||||||
|
Set<MEMolecularAssemblerIOPartMachine> allTiles = grid.getMachines(MEMolecularAssemblerIOPartMachine.class);
|
||||||
|
|
||||||
|
for (MEMolecularAssemblerIOPartMachine tile : allTiles) {
|
||||||
|
if (tile == null || !tile.isFormed() || !tile.getMainNode()
|
||||||
|
.isActive()) continue;
|
||||||
|
InternalInventory inv = tile.getTerminalPatternInventory();
|
||||||
|
if (inv != null) {
|
||||||
|
result.add(inv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Throwable ignored) {
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查GT分子装配矩阵中是否已存在与给定样板完全相同的物品(含NBT)。
|
||||||
|
*/
|
||||||
|
// todo
|
||||||
|
private static boolean GTMatrixContainsPattern(@NotNull List<InternalInventory> inventories, @NotNull ItemStack pattern) {
|
||||||
|
for (InternalInventory inv : inventories) {
|
||||||
|
if (inv == null) continue;
|
||||||
|
for (int i = 0; i < inv.size(); i++) {
|
||||||
|
ItemStack s = inv.getStackInSlot(i);
|
||||||
|
if (!s.isEmpty() && ItemStack.isSameItemSameTags(s, pattern)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传成功后处理:清空编码槽,发送提示。
|
||||||
|
*/
|
||||||
|
private static void completeUploadSuccess(ServerPlayer player, RestrictedInputSlot encodedSlot, ItemStack stack, ItemStack remain) {
|
||||||
|
int inserted = stack.getCount() - remain.getCount();
|
||||||
|
if (inserted > 0) {
|
||||||
|
stack.shrink(inserted);
|
||||||
|
if (stack.isEmpty()) encodedSlot.set(ItemStack.EMPTY);
|
||||||
|
sendPlayerMessage(player, Component.translatable("extendedae_plus.upload_to_GTMatrix.success"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当发现重复样板时返还空白样板。
|
||||||
|
*/
|
||||||
|
private static void refundBlankPattern(ServerPlayer player, PatternEncodingTermMenu menu, int count) {
|
||||||
|
try {
|
||||||
|
var accessor = (PatternEncodingTermMenuAccessor) menu;
|
||||||
|
var blankSlot = accessor.eap$getBlankPatternSlot();
|
||||||
|
ItemStack blanks = AEItems.BLANK_PATTERN.stack(count);
|
||||||
|
if (blankSlot != null && blankSlot.mayPlace(blanks)) {
|
||||||
|
ItemStack remain = blankSlot.safeInsert(blanks);
|
||||||
|
if (!remain.isEmpty() && player != null) {
|
||||||
|
player.getInventory()
|
||||||
|
.placeItemBackInInventory(remain, false);
|
||||||
|
}
|
||||||
|
} else if (player != null) {
|
||||||
|
player.getInventory()
|
||||||
|
.placeItemBackInInventory(blanks, false);
|
||||||
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
if (player != null) {
|
||||||
|
player.getInventory()
|
||||||
|
.placeItemBackInInventory(AEItems.BLANK_PATTERN.stack(count), false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -85,12 +85,6 @@ public final class MatrixUploadUtil {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 未找到可用矩阵或全部拒收
|
|
||||||
sendPlayerMessage(player,
|
|
||||||
inventories.isEmpty()
|
|
||||||
? Component.translatable("extendedae_plus.upload_to_matrix.fail_no_matrix")
|
|
||||||
: Component.translatable("extendedae_plus.upload_to_matrix.fail_full"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -28,16 +28,16 @@ item_ids:
|
||||||
|
|
||||||
## 合成配方
|
## 合成配方
|
||||||
### 4x并行处理单元
|
### 4x并行处理单元
|
||||||
<Recipe id="extendedae_plus:4x_crafting_accelerator" />
|
<Recipe id="extendedae_plus:network/crafting/4x_crafting_accelerator" />
|
||||||
|
|
||||||
### 16x并行处理单元
|
### 16x并行处理单元
|
||||||
<Recipe id="extendedae_plus:16x_crafting_accelerator" />
|
<Recipe id="extendedae_plus:network/crafting/16x_crafting_accelerator" />
|
||||||
|
|
||||||
### 64x并行处理单元
|
### 64x并行处理单元
|
||||||
<Recipe id="extendedae_plus:64x_crafting_accelerator" />
|
<Recipe id="extendedae_plus:network/crafting/64x_crafting_accelerator" />
|
||||||
|
|
||||||
### 256x并行处理单元
|
### 256x并行处理单元
|
||||||
<Recipe id="extendedae_plus:256x_crafting_accelerator" />
|
<Recipe id="extendedae_plus:network/crafting/256x_crafting_accelerator" />
|
||||||
|
|
||||||
### 1024x并行处理单元
|
### 1024x并行处理单元
|
||||||
<Recipe id="extendedae_plus:1024x_crafting_accelerator" />
|
<Recipe id="extendedae_plus:network/crafting/1024x_crafting_accelerator" />
|
||||||
|
|
|
||||||
|
|
@ -29,16 +29,16 @@ This mod introduces five higher-tier **Parallel Processing Units**, which are co
|
||||||
## Crafting Recipes
|
## Crafting Recipes
|
||||||
|
|
||||||
### 4x Parallel Processing Unit
|
### 4x Parallel Processing Unit
|
||||||
<Recipe id="extendedae_plus:4x_crafting_accelerator" />
|
<Recipe id="extendedae_plus:network/crafting/4x_crafting_accelerator" />
|
||||||
|
|
||||||
### 16x Parallel Processing Unit
|
### 16x Parallel Processing Unit
|
||||||
<Recipe id="extendedae_plus:16x_crafting_accelerator" />
|
<Recipe id="extendedae_plus:network/crafting/16x_crafting_accelerator" />
|
||||||
|
|
||||||
### 64x Parallel Processing Unit
|
### 64x Parallel Processing Unit
|
||||||
<Recipe id="extendedae_plus:64x_crafting_accelerator" />
|
<Recipe id="extendedae_plus:network/crafting/64x_crafting_accelerator" />
|
||||||
|
|
||||||
### 256x Parallel Processing Unit
|
### 256x Parallel Processing Unit
|
||||||
<Recipe id="extendedae_plus:256x_crafting_accelerator" />
|
<Recipe id="extendedae_plus:network/crafting/256x_crafting_accelerator" />
|
||||||
|
|
||||||
### 1024x Parallel Processing Unit
|
### 1024x Parallel Processing Unit
|
||||||
<Recipe id="extendedae_plus:1024x_crafting_accelerator" />
|
<Recipe id="extendedae_plus:network/crafting/1024x_crafting_accelerator" />
|
||||||
|
|
|
||||||
|
|
@ -70,13 +70,30 @@
|
||||||
|
|
||||||
"extendedae_plus.upload_to_matrix": "Upload to Assembly Matrix",
|
"extendedae_plus.upload_to_matrix": "Upload to Assembly Matrix",
|
||||||
"extendedae_plus.upload_to_matrix.success": "Pattern uploaded to the assembly matrix",
|
"extendedae_plus.upload_to_matrix.success": "Pattern uploaded to the assembly matrix",
|
||||||
|
"extendedae_plus.upload_to_GTMatrix.success": "The template has been uploaded to the molecular manipulator",
|
||||||
"extendedae_plus.upload_to_matrix.fail_not_crafting": "Only crafting patterns are supported; processing patterns will be ignored",
|
"extendedae_plus.upload_to_matrix.fail_not_crafting": "Only crafting patterns are supported; processing patterns will be ignored",
|
||||||
"extendedae_plus.upload_to_matrix.fail_no_matrix": "No formed assembly matrix found in the current network",
|
"extendedae_plus.upload_to_matrix.fail_no_matrix": "No formed assembly matrix found in the current network",
|
||||||
|
"extendedae_plus.upload_to_matrix.fail_no_GTMatrix": "No formed molecular manipulators were found in the current network",
|
||||||
"extendedae_plus.upload_to_matrix.fail_full": "The assembly matrix pattern inventory is full or cannot insert",
|
"extendedae_plus.upload_to_matrix.fail_full": "The assembly matrix pattern inventory is full or cannot insert",
|
||||||
|
"extendedae_plus.upload_to_GTMatrix.fail_full": "The Molecular Manipulator's pattern inventory is full or cannot accept the pattern",
|
||||||
|
"extendedae_plus.upload_to_matrix.repetition": "The Assembly Matrix already contains the same pattern, upload skipped and blank pattern returned",
|
||||||
|
"extendedae_plus.upload_to_GTMatrix.repetition": "The Molecular Manipulator already contains the same pattern, upload skipped and blank pattern returned",
|
||||||
|
"extendedae_plus.upload_to_GTMatrix.fail_full": "The sample compartment of the molecular manipulator is full or cannot be inserted",
|
||||||
|
"extendedae_plus.upload_to_matrix.repetition": "The assembly matrix already exists on the same board, and the upload is skipped and a blank template is returned",
|
||||||
|
"extendedae_plus.upload_to_GTMatrix.repetition": "The same board already exists for the molecular manipulator, skipping the upload and returning the blank template",
|
||||||
|
|
||||||
"extendedae_plus.upload_to_matrix.repetition": "The Assembly Matrix already contains the same pattern. Upload skipped and blank pattern returned.",
|
"extendedae_plus.upload_to_matrix.repetition": "The Assembly Matrix already contains the same pattern. Upload skipped and blank pattern returned.",
|
||||||
|
|
||||||
"chat.extendedae_plus.terminal.pos": "The crafting plan's corresponding provider is now highlighted at: %s, Dimension: %s (%s blocks away)",
|
"chat.extendedae_plus.terminal.pos": "The crafting plan's corresponding provider is now highlighted at: %s, Dimension: %s (%s blocks away)",
|
||||||
|
|
||||||
|
"extendedae_plus.upload_to_GTMatrix.fail_full": "The sample compartment of the molecular manipulator is full or cannot be inserted",
|
||||||
|
"extendedae_plus.upload_to_matrix.repetition": "The assembly matrix already exists on the same board, and the upload is skipped and a blank template is returned",
|
||||||
|
"extendedae_plus.upload_to_GTMatrix.repetition": "The same board already exists for the molecular manipulator, skipping the upload and returning the blank template",
|
||||||
|
|
||||||
|
"extendedae_plus.upload_to_GTMatrix.fail_full": "The Molecular Manipulator's pattern inventory is full or cannot accept the pattern",
|
||||||
|
"extendedae_plus.upload_to_matrix.repetition": "The Assembly Matrix already contains the same pattern, upload skipped and blank pattern returned",
|
||||||
|
"extendedae_plus.upload_to_GTMatrix.repetition": "The Molecular Manipulator already contains the same pattern, upload skipped and blank pattern returned",
|
||||||
|
|
||||||
"extendedae_plus.gui.advanced_blocking.title": "Smart Blocking",
|
"extendedae_plus.gui.advanced_blocking.title": "Smart Blocking",
|
||||||
"extendedae_plus.gui.advanced_blocking.enabled_desc": "Will not block the same recipe type (requires vanilla blocking mode enabled)",
|
"extendedae_plus.gui.advanced_blocking.enabled_desc": "Will not block the same recipe type (requires vanilla blocking mode enabled)",
|
||||||
"extendedae_plus.gui.advanced_blocking.disabled_desc": "Use vanilla blocking logic",
|
"extendedae_plus.gui.advanced_blocking.disabled_desc": "Use vanilla blocking logic",
|
||||||
|
|
@ -142,6 +159,7 @@
|
||||||
"config.extendedae_plus.option.entityTickerMultipliers": "Entity Ticker Extra Consumption Multipliers",
|
"config.extendedae_plus.option.entityTickerMultipliers": "Entity Ticker Extra Consumption Multipliers",
|
||||||
"config.extendedae_plus.option.craftingPauseThreshold": "AE synthesis calculation pause check threshold",
|
"config.extendedae_plus.option.craftingPauseThreshold": "AE synthesis calculation pause check threshold",
|
||||||
"config.extendedae_plus.option.prioritizeDiskEnergy": "Prioritize FE energy from disk (requires Applied Flux)",
|
"config.extendedae_plus.option.prioritizeDiskEnergy": "Prioritize FE energy from disk (requires Applied Flux)",
|
||||||
|
"config.extendedae_plus.option.restrictCraftingPatternToMolecular": "Restrict automatic upload of synthetic templates to only molecular manipulators",
|
||||||
|
|
||||||
"item.extendedae_plus.channel_card": "Channel Card",
|
"item.extendedae_plus.channel_card": "Channel Card",
|
||||||
"item.extendedae_plus.channel_card.channel": "Frequency: %s",
|
"item.extendedae_plus.channel_card.channel": "Frequency: %s",
|
||||||
|
|
|
||||||
|
|
@ -70,12 +70,17 @@
|
||||||
|
|
||||||
"extendedae_plus.upload_to_matrix": "上传到装配矩阵",
|
"extendedae_plus.upload_to_matrix": "上传到装配矩阵",
|
||||||
"extendedae_plus.upload_to_matrix.success": "样板已上传到装配矩阵",
|
"extendedae_plus.upload_to_matrix.success": "样板已上传到装配矩阵",
|
||||||
|
"extendedae_plus.upload_to_GTMatrix.success": "样板已上传到分子操纵者",
|
||||||
"extendedae_plus.upload_to_matrix.fail_not_crafting": "仅支持上传合成样板,处理样板将被忽略",
|
"extendedae_plus.upload_to_matrix.fail_not_crafting": "仅支持上传合成样板,处理样板将被忽略",
|
||||||
"extendedae_plus.upload_to_matrix.fail_no_matrix": "未在当前网络中找到已成型的装配矩阵",
|
"extendedae_plus.upload_to_matrix.fail_no_matrix": "未在当前网络中找到已成型的装配矩阵",
|
||||||
|
"extendedae_plus.upload_to_matrix.fail_no_GTMatrix": "未在当前网络中找到已成型的分子操纵者",
|
||||||
"extendedae_plus.upload_to_matrix.fail_full": "装配矩阵的样板仓已满或无法插入",
|
"extendedae_plus.upload_to_matrix.fail_full": "装配矩阵的样板仓已满或无法插入",
|
||||||
|
"extendedae_plus.upload_to_GTMatrix.fail_full": "分子操纵者的样板仓已满或无法插入",
|
||||||
"extendedae_plus.upload_to_matrix.repetition": "装配矩阵已存在相同样板,已跳过上传并返还空白样板",
|
"extendedae_plus.upload_to_matrix.repetition": "装配矩阵已存在相同样板,已跳过上传并返还空白样板",
|
||||||
|
"extendedae_plus.upload_to_GTMatrix.repetition": "分子操纵者已存在相同样板,已跳过上传并返还空白样板",
|
||||||
|
|
||||||
"chat.extendedae_plus.terminal.pos": "合成计划对应供应器现在突出显示在:%s,维度:%s (%s个方块外)",
|
"chat.extendedae_plus.terminal.pos": "合成计划对应供应器现在突出显示在:%s,维度:%s (%s个方块外)",
|
||||||
|
"extendedae_plus.upload_to_GTMatrix.repetition": "分子操纵者已存在相同样板,已跳过上传并返还空白样板",
|
||||||
|
|
||||||
"extendedae_plus.gui.advanced_blocking.title": "智能阻挡",
|
"extendedae_plus.gui.advanced_blocking.title": "智能阻挡",
|
||||||
"extendedae_plus.gui.advanced_blocking.enabled_desc": "对于同一种配方将不再阻挡 (需要启用原版阻挡模式)",
|
"extendedae_plus.gui.advanced_blocking.enabled_desc": "对于同一种配方将不再阻挡 (需要启用原版阻挡模式)",
|
||||||
|
|
@ -142,6 +147,7 @@
|
||||||
"config.extendedae_plus.option.entityTickerMultipliers": "实体加速器额外消耗倍率",
|
"config.extendedae_plus.option.entityTickerMultipliers": "实体加速器额外消耗倍率",
|
||||||
"config.extendedae_plus.option.prioritizeDiskEnergy": "优先从磁盘提取FE能量(仅当Applied Flux模组存在时生效)",
|
"config.extendedae_plus.option.prioritizeDiskEnergy": "优先从磁盘提取FE能量(仅当Applied Flux模组存在时生效)",
|
||||||
"config.extendedae_plus.option.craftingPauseThreshold": "AE合成计算暂停检查阈值",
|
"config.extendedae_plus.option.craftingPauseThreshold": "AE合成计算暂停检查阈值",
|
||||||
|
"config.extendedae_plus.option.restrictCraftingPatternToMolecular": "限制合成样板自动上传仅进入分子操纵者",
|
||||||
|
|
||||||
"item.extendedae_plus.channel_card": "频道卡",
|
"item.extendedae_plus.channel_card": "频道卡",
|
||||||
"item.extendedae_plus.channel_card.channel": "频率:%s",
|
"item.extendedae_plus.channel_card.channel": "频率:%s",
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,9 @@
|
||||||
"extendedae.client.HighlightButtonMixin",
|
"extendedae.client.HighlightButtonMixin",
|
||||||
"extendedae.client.gui.GuiExPatternProviderMixin",
|
"extendedae.client.gui.GuiExPatternProviderMixin",
|
||||||
"extendedae.client.gui.GuiExPatternTerminalMixin",
|
"extendedae.client.gui.GuiExPatternTerminalMixin",
|
||||||
|
"gtceu.AEPatternViewSlotWidgetMixin",
|
||||||
|
"gtceu.ModularUIGuiContainerCloseMixin",
|
||||||
|
"gtceu.SlotWidgetMixin",
|
||||||
"jei.EncodePatternTransferHandlerMixin",
|
"jei.EncodePatternTransferHandlerMixin",
|
||||||
"jei.EncodingHelperMixin",
|
"jei.EncodingHelperMixin",
|
||||||
"jei.accessor.BookmarkOverlayAccessor",
|
"jei.accessor.BookmarkOverlayAccessor",
|
||||||
|
|
@ -56,6 +59,8 @@
|
||||||
"ae2.autopattern.CraftingSimulationStateAccessor",
|
"ae2.autopattern.CraftingSimulationStateAccessor",
|
||||||
"ae2.autopattern.CraftingSimulationStateMixin",
|
"ae2.autopattern.CraftingSimulationStateMixin",
|
||||||
"ae2.autopattern.PatternProviderLogicContainsRedirectMixin",
|
"ae2.autopattern.PatternProviderLogicContainsRedirectMixin",
|
||||||
|
"ae2.autopattern.gtceu.GTLCoreMEPatternBufferPartMachineMixin",
|
||||||
|
"ae2.autopattern.gtceu.MEPatternBufferPartMachineMixin",
|
||||||
"ae2.compat.PatternProviderCompatMixin",
|
"ae2.compat.PatternProviderCompatMixin",
|
||||||
"ae2.compat.PatternProviderLogicCompatMixin",
|
"ae2.compat.PatternProviderLogicCompatMixin",
|
||||||
"ae2.compat.PatternProviderLogicHostCompatMixin",
|
"ae2.compat.PatternProviderLogicHostCompatMixin",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user