添加并行处理单元

This commit is contained in:
GaLi 2025-08-22 19:30:26 +08:00
parent 4195d2a176
commit 41a6a21498
41 changed files with 422 additions and 2 deletions

View File

@ -3,7 +3,7 @@ org.gradle.jvmargs=-Xmx1G
loom.platform = forge
# Mod properties
mod_version = 1.3.2-fix1
mod_version = 1.3.3
maven_group = com.extendedae_plus
archives_name = extendedae_plus

View File

@ -15,6 +15,11 @@ import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.config.ModConfig;
import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
import net.minecraftforge.fml.javafmlmod.FMLJavaModLoadingContext;
import net.minecraft.resources.ResourceLocation;
import com.extendedae_plus.client.ClientProxy;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.fml.DistExecutor;
/**
* ExtendedAE Plus 主mod类
@ -24,6 +29,14 @@ public class ExtendedAEPlus {
public static final String MODID = "extendedae_plus";
// 在类加载时尽可能早在客户端注册内置模型避免首次资源加载时错过
static {
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> () -> {
System.out.println("[ExtendedAE_Plus] Static init: register built-in models");
ClientProxy.init();
});
}
public ExtendedAEPlus() {
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
@ -41,6 +54,9 @@ public class ExtendedAEPlus {
// 注册通用配置
ModLoadingContext.get().registerConfig(ModConfig.Type.COMMON, ModConfigs.COMMON_SPEC);
// 构造期在客户端再确保一次注册幂等
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> ClientProxy::init);
}
/**
@ -54,4 +70,11 @@ public class ExtendedAEPlus {
MenuLocators.register(CuriosItemLocator.class, CuriosItemLocator::writeToPacket, CuriosItemLocator::readFromPacket);
});
}
/**
* 便捷方法生成 ResourceLocation
*/
public static ResourceLocation id(String path) {
return new ResourceLocation(MODID, path);
}
}

View File

@ -0,0 +1,20 @@
package com.extendedae_plus.client;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.client.event.ModelEvent;
import net.minecraftforge.eventbus.api.SubscribeEvent;
import net.minecraftforge.fml.common.Mod;
/**
* 确保在模型烘焙/资源重载期间也会注册内置模型避免在刷新资源后丢失内置模型映射
*/
@Mod.EventBusSubscriber(value = Dist.CLIENT, bus = Mod.EventBusSubscriber.Bus.MOD)
public final class ClientModelEvents {
private ClientModelEvents() {}
@SubscribeEvent
public static void onRegisterAdditional(ModelEvent.RegisterAdditional event) {
// 在每次模型重载开始时确保内置模型已注册
ClientProxy.init();
}
}

View File

@ -0,0 +1,37 @@
package com.extendedae_plus.client;
import appeng.client.render.crafting.CraftingCubeModel;
import com.extendedae_plus.ExtendedAEPlus;
import com.extendedae_plus.client.render.crafting.EPlusCraftingCubeModelProvider;
import com.extendedae_plus.content.crafting.EPlusCraftingUnitType;
import com.extendedae_plus.hooks.BuiltInModelHooks;
/**
* 客户端模型注册参照 MAE2 的做法将 formed 模型注册为内置模型
*/
public final class ClientProxy {
private ClientProxy() {}
private static boolean REGISTERED = false;
public static void init() {
if (REGISTERED) return;
REGISTERED = true;
// 注册四种形成态模型为内置模型使用 *_formed_v2 避免与现有 JSON 冲突
BuiltInModelHooks.addBuiltInModel(
ExtendedAEPlus.id("block/crafting/4x_accelerator_formed_v2"),
new CraftingCubeModel(new EPlusCraftingCubeModelProvider(EPlusCraftingUnitType.ACCELERATOR_4x)));
BuiltInModelHooks.addBuiltInModel(
ExtendedAEPlus.id("block/crafting/16x_accelerator_formed_v2"),
new CraftingCubeModel(new EPlusCraftingCubeModelProvider(EPlusCraftingUnitType.ACCELERATOR_16x)));
BuiltInModelHooks.addBuiltInModel(
ExtendedAEPlus.id("block/crafting/64x_accelerator_formed_v2"),
new CraftingCubeModel(new EPlusCraftingCubeModelProvider(EPlusCraftingUnitType.ACCELERATOR_64x)));
BuiltInModelHooks.addBuiltInModel(
ExtendedAEPlus.id("block/crafting/256x_accelerator_formed_v2"),
new CraftingCubeModel(new EPlusCraftingCubeModelProvider(EPlusCraftingUnitType.ACCELERATOR_256x)));
}
}

View File

@ -0,0 +1,86 @@
package com.extendedae_plus.client.render.crafting;
import appeng.client.render.crafting.AbstractCraftingUnitModelProvider;
import appeng.client.render.crafting.LightBakedModel;
import com.extendedae_plus.ExtendedAEPlus;
import com.extendedae_plus.content.crafting.EPlusCraftingUnitType;
import net.minecraft.client.renderer.RenderType;
import net.minecraft.client.renderer.texture.TextureAtlas;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.model.BakedModel;
import net.minecraft.client.resources.model.Material;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.util.RandomSource;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraftforge.client.ChunkRenderTypeSet;
import net.minecraftforge.client.model.data.ModelData;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.function.Function;
/**
* 参照 MAE2 DynamicCraftingCubeModelProvider实现形成态光照模型
*/
public class EPlusCraftingCubeModelProvider
extends AbstractCraftingUnitModelProvider<EPlusCraftingUnitType> {
public static final ChunkRenderTypeSet CUTOUT = ChunkRenderTypeSet.of(RenderType.cutout());
private static final List<Material> MATERIALS = new ArrayList<>();
// MAE2 一致将环形边框与基础发光底图放在本模组命名空间
protected static final Material RING_CORNER = texture(ExtendedAEPlus.MODID, "ring_corner");
protected static final Material RING_SIDE_HOR = texture(ExtendedAEPlus.MODID, "ring_side_hor");
protected static final Material RING_SIDE_VER = texture(ExtendedAEPlus.MODID, "ring_side_ver");
protected static final Material LIGHT_BASE = texture(ExtendedAEPlus.MODID, "light_base");
// 我们自己的亮面贴图formed 时使用
protected static final Material ACCELERATOR_4X_LIGHT = texture(ExtendedAEPlus.MODID,
"4x_accelerator_light");
protected static final Material ACCELERATOR_16X_LIGHT = texture(ExtendedAEPlus.MODID,
"16x_accelerator_light");
protected static final Material ACCELERATOR_64X_LIGHT = texture(ExtendedAEPlus.MODID,
"64x_accelerator_light");
protected static final Material ACCELERATOR_256X_LIGHT = texture(ExtendedAEPlus.MODID,
"256x_accelerator_light");
public EPlusCraftingCubeModelProvider(EPlusCraftingUnitType type) {
super(type);
}
@Override
public List<Material> getMaterials() {
return Collections.unmodifiableList(MATERIALS);
}
@Override
public BakedModel getBakedModel(Function<Material, TextureAtlasSprite> spriteGetter) {
TextureAtlasSprite ringCorner = spriteGetter.apply(RING_CORNER);
TextureAtlasSprite ringSideHor = spriteGetter.apply(RING_SIDE_HOR);
TextureAtlasSprite ringSideVer = spriteGetter.apply(RING_SIDE_VER);
return new LightBakedModel(ringCorner, ringSideHor, ringSideVer,
spriteGetter.apply(LIGHT_BASE), this.getLightMaterial(spriteGetter)) {
public ChunkRenderTypeSet getRenderTypes(BlockState state, RandomSource rand, ModelData data) {
return CUTOUT;
}
};
}
private TextureAtlasSprite getLightMaterial(Function<Material, TextureAtlasSprite> textureGetter) {
return switch (this.type) {
case ACCELERATOR_4x -> textureGetter.apply(ACCELERATOR_4X_LIGHT);
case ACCELERATOR_16x -> textureGetter.apply(ACCELERATOR_16X_LIGHT);
case ACCELERATOR_64x -> textureGetter.apply(ACCELERATOR_64X_LIGHT);
case ACCELERATOR_256x -> textureGetter.apply(ACCELERATOR_256X_LIGHT);
};
}
private static Material texture(String namespace, String name) {
var mat = new Material(TextureAtlas.LOCATION_BLOCKS,
new ResourceLocation(namespace, "block/crafting/" + name));
MATERIALS.add(mat);
return mat;
}
}

View File

@ -0,0 +1,42 @@
package com.extendedae_plus.content.crafting;
import appeng.block.crafting.ICraftingUnitType;
import net.minecraft.world.item.Item;
import com.extendedae_plus.init.ModItems;
public enum EPlusCraftingUnitType implements ICraftingUnitType {
ACCELERATOR_4x(0, 4),
ACCELERATOR_16x(0, 16),
ACCELERATOR_64x(0, 64),
ACCELERATOR_256x(0, 256);
private final long storage;
private final int threads;
EPlusCraftingUnitType(long storage, int threads) {
this.storage = storage;
this.threads = threads;
}
@Override
public long getStorageBytes() {
return this.storage;
}
@Override
public int getAcceleratorThreads() {
// 返回真实线程值单块可能超过 16上限校验已由 mixin 绕过
return this.threads;
}
@Override
public Item getItemFromType() {
return switch (this) {
case ACCELERATOR_4x -> ModItems.ACCELERATOR_4x.get();
case ACCELERATOR_16x -> ModItems.ACCELERATOR_16x.get();
case ACCELERATOR_64x -> ModItems.ACCELERATOR_64x.get();
case ACCELERATOR_256x -> ModItems.ACCELERATOR_256x.get();
};
}
}

View File

@ -0,0 +1,27 @@
package com.extendedae_plus.hooks;
import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.resources.ResourceLocation;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 复刻 Fabric 的内置模型注册能力 AE2/MAE2 相同实现
*/
public final class BuiltInModelHooks {
private static final Map<ResourceLocation, UnbakedModel> BUILTIN_MODELS = new ConcurrentHashMap<>();
private BuiltInModelHooks() {}
public static void addBuiltInModel(ResourceLocation id, UnbakedModel model) {
var prev = BUILTIN_MODELS.putIfAbsent(id, model);
if (prev != null) {
throw new IllegalStateException("Duplicate built-in model ID: " + id);
}
}
public static UnbakedModel getBuiltInModel(ResourceLocation id) {
return BUILTIN_MODELS.get(id);
}
}

View File

@ -2,6 +2,10 @@ package com.extendedae_plus.init;
import com.extendedae_plus.ExtendedAEPlus;
import com.extendedae_plus.content.wireless.WirelessTransceiverBlock;
import com.extendedae_plus.content.crafting.EPlusCraftingUnitType;
import appeng.block.crafting.CraftingUnitBlock;
import appeng.blockentity.crafting.CraftingBlockEntity;
import appeng.core.definitions.AEBlockEntities;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.state.BlockBehaviour;
import net.minecraft.world.level.material.MapColor;
@ -23,4 +27,41 @@ public final class ModBlocks {
.requiresCorrectToolForDrops()
)
);
// Crafting Accelerators (reuse MAE2 textures/models)
public static final RegistryObject<CraftingUnitBlock> ACCELERATOR_4x = BLOCKS.register(
"4x_crafting_accelerator",
() -> {
var b = new CraftingUnitBlock(EPlusCraftingUnitType.ACCELERATOR_4x);
b.setBlockEntity(CraftingBlockEntity.class, AEBlockEntities.CRAFTING_UNIT, null, null);
return b;
}
);
public static final RegistryObject<CraftingUnitBlock> ACCELERATOR_16x = BLOCKS.register(
"16x_crafting_accelerator",
() -> {
var b = new CraftingUnitBlock(EPlusCraftingUnitType.ACCELERATOR_16x);
b.setBlockEntity(CraftingBlockEntity.class, AEBlockEntities.CRAFTING_UNIT, null, null);
return b;
}
);
public static final RegistryObject<CraftingUnitBlock> ACCELERATOR_64x = BLOCKS.register(
"64x_crafting_accelerator",
() -> {
var b = new CraftingUnitBlock(EPlusCraftingUnitType.ACCELERATOR_64x);
b.setBlockEntity(CraftingBlockEntity.class, AEBlockEntities.CRAFTING_UNIT, null, null);
return b;
}
);
public static final RegistryObject<CraftingUnitBlock> ACCELERATOR_256x = BLOCKS.register(
"256x_crafting_accelerator",
() -> {
var b = new CraftingUnitBlock(EPlusCraftingUnitType.ACCELERATOR_256x);
b.setBlockEntity(CraftingBlockEntity.class, AEBlockEntities.CRAFTING_UNIT, null, null);
return b;
}
);
}

View File

@ -20,6 +20,10 @@ public final class ModCreativeTabs {
.displayItems((params, output) -> {
// 将本模组物品加入创造物品栏
output.accept(ModItems.WIRELESS_TRANSCEIVER.get());
output.accept(ModItems.ACCELERATOR_4x.get());
output.accept(ModItems.ACCELERATOR_16x.get());
output.accept(ModItems.ACCELERATOR_64x.get());
output.accept(ModItems.ACCELERATOR_256x.get());
})
.build());
}

View File

@ -16,4 +16,25 @@ public final class ModItems {
"wireless_transceiver",
() -> new BlockItem(ModBlocks.WIRELESS_TRANSCEIVER.get(), new Item.Properties())
);
// Crafting Accelerators
public static final RegistryObject<Item> ACCELERATOR_4x = ITEMS.register(
"4x_crafting_accelerator",
() -> new BlockItem(ModBlocks.ACCELERATOR_4x.get(), new Item.Properties())
);
public static final RegistryObject<Item> ACCELERATOR_16x = ITEMS.register(
"16x_crafting_accelerator",
() -> new BlockItem(ModBlocks.ACCELERATOR_16x.get(), new Item.Properties())
);
public static final RegistryObject<Item> ACCELERATOR_64x = ITEMS.register(
"64x_crafting_accelerator",
() -> new BlockItem(ModBlocks.ACCELERATOR_64x.get(), new Item.Properties())
);
public static final RegistryObject<Item> ACCELERATOR_256x = ITEMS.register(
"256x_crafting_accelerator",
() -> new BlockItem(ModBlocks.ACCELERATOR_256x.get(), new Item.Properties())
);
}

View File

@ -0,0 +1,24 @@
package com.extendedae_plus.mixin.ae2;
import appeng.blockentity.crafting.CraftingBlockEntity;
import appeng.me.cluster.implementations.CraftingCPUCluster;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(value = CraftingCPUCluster.class, remap = false)
public abstract class CraftingCPUClusterMixin {
// Redirect the second call (ordinal=1) to getAcceleratorThreads in addBlockEntity,
// which is used for the per-block <=16 validation in AE2. We return 1 so the check always passes.
@Redirect(
method = "addBlockEntity(Lappeng/blockentity/crafting/CraftingBlockEntity;)V",
at = @At(
value = "INVOKE",
target = "Lappeng/blockentity/crafting/CraftingBlockEntity;getAcceleratorThreads()I",
ordinal = 1
)
)
private int extendedae_plus$onGetThreadsForLimitCheck(CraftingBlockEntity te) {
return 1;
}
}

View File

@ -0,0 +1,33 @@
package com.extendedae_plus.mixin.hooks;
import org.spongepowered.asm.mixin.Mixin;
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.callback.CallbackInfo;
import net.minecraft.client.resources.model.ModelBakery;
import net.minecraft.client.resources.model.UnbakedModel;
import net.minecraft.resources.ResourceLocation;
import com.extendedae_plus.hooks.BuiltInModelHooks;
/**
* 复制 MAE2/AE2 的做法在模型加载时优先查询我们的内置模型表
* 若命中则缓存并阻止继续查找 JSON 模型
*/
@Mixin(ModelBakery.class)
public class ModelBakeryMixin {
@Inject(method = "loadModel", at = @At("HEAD"), cancellable = true)
private void extendedae_plus$loadModelHook(ResourceLocation id, CallbackInfo ci) {
var model = BuiltInModelHooks.getBuiltInModel(id);
if (model != null) {
cacheAndQueueDependencies(id, model);
ci.cancel();
}
}
@Shadow
protected void cacheAndQueueDependencies(ResourceLocation id, UnbakedModel unbakedModel) {
}
}

View File

@ -0,0 +1,6 @@
{
"variants": {
"formed=false": { "model": "extendedae_plus:block/crafting/16x_accelerator" },
"formed=true": { "model": "extendedae_plus:block/crafting/16x_accelerator_formed_v2" }
}
}

View File

@ -0,0 +1,6 @@
{
"variants": {
"formed=false": { "model": "extendedae_plus:block/crafting/256x_accelerator" },
"formed=true": { "model": "extendedae_plus:block/crafting/256x_accelerator_formed_v2" }
}
}

View File

@ -0,0 +1,6 @@
{
"variants": {
"formed=false": { "model": "extendedae_plus:block/crafting/4x_accelerator" },
"formed=true": { "model": "extendedae_plus:block/crafting/4x_accelerator_formed_v2" }
}
}

View File

@ -0,0 +1,6 @@
{
"variants": {
"formed=false": { "model": "extendedae_plus:block/crafting/64x_accelerator" },
"formed=true": { "model": "extendedae_plus:block/crafting/64x_accelerator_formed_v2" }
}
}

View File

@ -0,0 +1,4 @@
{
"parent": "minecraft:block/cube_all",
"textures": { "all": "extendedae_plus:block/crafting/16x_accelerator" }
}

View File

@ -0,0 +1,4 @@
{
"parent": "minecraft:block/cube_all",
"textures": { "all": "extendedae_plus:block/crafting/16x_accelerator_light" }
}

View File

@ -0,0 +1,4 @@
{
"parent": "minecraft:block/cube_all",
"textures": { "all": "extendedae_plus:block/crafting/256x_accelerator" }
}

View File

@ -0,0 +1,4 @@
{
"parent": "minecraft:block/cube_all",
"textures": { "all": "extendedae_plus:block/crafting/256x_accelerator_light" }
}

View File

@ -0,0 +1,4 @@
{
"parent": "minecraft:block/cube_all",
"textures": { "all": "extendedae_plus:block/crafting/4x_accelerator" }
}

View File

@ -0,0 +1,4 @@
{
"parent": "minecraft:block/cube_all",
"textures": { "all": "extendedae_plus:block/crafting/4x_accelerator_light" }
}

View File

@ -0,0 +1,4 @@
{
"parent": "minecraft:block/cube_all",
"textures": { "all": "extendedae_plus:block/crafting/64x_accelerator" }
}

View File

@ -0,0 +1,4 @@
{
"parent": "minecraft:block/cube_all",
"textures": { "all": "extendedae_plus:block/crafting/64x_accelerator_light" }
}

View File

@ -0,0 +1 @@
{ "parent": "extendedae_plus:block/crafting/16x_accelerator" }

View File

@ -0,0 +1 @@
{ "parent": "extendedae_plus:block/crafting/256x_accelerator" }

View File

@ -0,0 +1 @@
{ "parent": "extendedae_plus:block/crafting/4x_accelerator" }

View File

@ -0,0 +1 @@
{ "parent": "extendedae_plus:block/crafting/64x_accelerator" }

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -24,7 +24,8 @@
"extendedae.HighlightButtonMixin",
"extendedae.accessor.GuiExPatternTerminalAccessor",
"extendedae.accessor.GuiExPatternTerminalSlotsRowAccessor",
"jei.EncodePatternTransferHandlerMixin"
"jei.EncodePatternTransferHandlerMixin",
"hooks.ModelBakeryMixin"
],
"mixins": [
"ae2.ContainerPatternEncodingTermMenuMixin",
@ -41,6 +42,7 @@
"extendedae.ContainerExPatternProviderMixin",
"extendedae.ContainerExPatternTerminalMixin",
"extendedae.ContainerWirelessExPatternTerminalMixin",
"ae2.CraftingCPUClusterMixin",
"extendedae.PartExPatternProviderMixin",
"extendedae.TileExPatternProviderMixin"
],