From fb2a2a831d698dceb644b9514b3256a472e234f0 Mon Sep 17 00:00:00 2001 From: C-H716 <1536152356@qq.com> Date: Sat, 13 Sep 2025 12:50:47 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E5=AE=9E=E4=BD=93?= =?UTF-8?q?=E5=8A=A0=E9=80=9F=E5=8D=A1=E6=9B=BF=E6=8D=A2=E5=8A=A0=E9=80=9F?= =?UTF-8?q?=E5=8D=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gradle.properties | 2 +- .../com/extendedae_plus/ExtendedAEPlus.java | 3 +- .../upgrades/EntitySpeedCardItem.java | 81 +++++++++++ .../ae/menu/EntitySpeedTickerMenu.java | 30 +++-- .../ae/parts/EntitySpeedTickerPart.java | 27 ++-- .../ae/screen/EntitySpeedTickerScreen.java | 7 +- .../client/ClientRegistrar.java | 6 + .../extendedae_plus/init/ModCreativeTabs.java | 6 + .../com/extendedae_plus/init/ModItems.java | 22 ++- .../extendedae_plus/init/UpgradeCards.java | 4 +- .../com/extendedae_plus/util/PowerUtils.java | 127 ++++++++++++++---- .../assets/extendedae_plus/lang/en_us.json | 7 + .../assets/extendedae_plus/lang/zh_cn.json | 7 + .../models/item/entity_speed_card.json | 14 ++ .../models/item/entity_speed_card_x1.json | 6 + .../models/item/entity_speed_card_x16.json | 6 + .../models/item/entity_speed_card_x2.json | 6 + .../models/item/entity_speed_card_x4.json | 6 + .../models/item/entity_speed_card_x8.json | 6 + .../textures/item/entity_speed_card_x16.png | Bin 0 -> 2323 bytes .../textures/item/entity_speed_card_x2.png | Bin 0 -> 2084 bytes .../textures/item/entity_speed_card_x4.png | Bin 0 -> 2326 bytes .../textures/item/entity_speed_card_x8.png | Bin 0 -> 2307 bytes 23 files changed, 312 insertions(+), 61 deletions(-) create mode 100644 src/main/java/com/extendedae_plus/ae/definitions/upgrades/EntitySpeedCardItem.java create mode 100644 src/main/resources/assets/extendedae_plus/models/item/entity_speed_card.json create mode 100644 src/main/resources/assets/extendedae_plus/models/item/entity_speed_card_x1.json create mode 100644 src/main/resources/assets/extendedae_plus/models/item/entity_speed_card_x16.json create mode 100644 src/main/resources/assets/extendedae_plus/models/item/entity_speed_card_x2.json create mode 100644 src/main/resources/assets/extendedae_plus/models/item/entity_speed_card_x4.json create mode 100644 src/main/resources/assets/extendedae_plus/models/item/entity_speed_card_x8.json create mode 100644 src/main/resources/assets/extendedae_plus/textures/item/entity_speed_card_x16.png create mode 100644 src/main/resources/assets/extendedae_plus/textures/item/entity_speed_card_x2.png create mode 100644 src/main/resources/assets/extendedae_plus/textures/item/entity_speed_card_x4.png create mode 100644 src/main/resources/assets/extendedae_plus/textures/item/entity_speed_card_x8.png diff --git a/gradle.properties b/gradle.properties index d471976..2524cfb 100644 --- a/gradle.properties +++ b/gradle.properties @@ -3,7 +3,7 @@ org.gradle.jvmargs=-Xmx1G loom.platform = forge # Mod properties -mod_version = 1.4.1 +mod_version = 1.4.1-entitySpeedTicker maven_group = com.extendedae_plus archives_name = extendedae_plus diff --git a/src/main/java/com/extendedae_plus/ExtendedAEPlus.java b/src/main/java/com/extendedae_plus/ExtendedAEPlus.java index 76f30ba..aefcb30 100644 --- a/src/main/java/com/extendedae_plus/ExtendedAEPlus.java +++ b/src/main/java/com/extendedae_plus/ExtendedAEPlus.java @@ -32,8 +32,7 @@ public class ExtendedAEPlus { public ExtendedAEPlus() { IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); - // 在客户端尽早注册内置模型,保证首次资源加载前映射已建立(仿照 AE2 的 AppEngClient 构造期注册) - DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> ClientRegistrar::initBuiltInModels); + // 客户端的内置模型注册将在客户端事件阶段执行(见 ClientModEvents),不要在构造器中提前执行 // 注册mod初始化事件 modEventBus.addListener(this::commonSetup); diff --git a/src/main/java/com/extendedae_plus/ae/definitions/upgrades/EntitySpeedCardItem.java b/src/main/java/com/extendedae_plus/ae/definitions/upgrades/EntitySpeedCardItem.java new file mode 100644 index 0000000..cc97d98 --- /dev/null +++ b/src/main/java/com/extendedae_plus/ae/definitions/upgrades/EntitySpeedCardItem.java @@ -0,0 +1,81 @@ +package com.extendedae_plus.ae.definitions.upgrades; + +import appeng.items.materials.UpgradeCardItem; +import com.extendedae_plus.init.ModItems; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.network.chat.Component; +import net.minecraft.network.chat.MutableComponent; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.item.TooltipFlag; +import net.minecraft.world.level.Level; +import net.minecraftforge.api.distmarker.Dist; +import net.minecraftforge.api.distmarker.OnlyIn; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * 单一的实体加速卡 Item,通过 ItemStack 的 NBT 存储 exponent(0/1/2/3)来区分等级 + */ +public class EntitySpeedCardItem extends UpgradeCardItem { + public static final String NBT_MULTIPLIER = "EAS:mult"; + + public EntitySpeedCardItem(Properties props) { + super(props); + } + + public static ItemStack withMultiplier(int multiplier) { + ItemStack s = new ItemStack(ModItems.ENTITY_SPEED_CARD.get()); + CompoundTag t = s.getOrCreateTag(); + t.putInt(NBT_MULTIPLIER, multiplier); + s.setTag(t); + return s; + } + + public static int readMultiplier(ItemStack stack) { + if (stack == null || stack.isEmpty()) return 1; + CompoundTag t = stack.getTag(); + if (t == null) return 1; + int v = t.getInt(NBT_MULTIPLIER); + return v <= 0 ? 1 : v; + } + + @Override + public @NotNull Component getName(@NotNull ItemStack stack) { + int mult = readMultiplier(stack); + String key; + switch (mult) { + case 2 -> key = "item." + com.extendedae_plus.ExtendedAEPlus.MODID + ".entity_speed_card.x2"; + case 4 -> key = "item." + com.extendedae_plus.ExtendedAEPlus.MODID + ".entity_speed_card.x4"; + case 8 -> key = "item." + com.extendedae_plus.ExtendedAEPlus.MODID + ".entity_speed_card.x8"; + case 16 -> key = "item." + com.extendedae_plus.ExtendedAEPlus.MODID + ".entity_speed_card.x16"; + default -> key = "item." + com.extendedae_plus.ExtendedAEPlus.MODID + ".entity_speed_card.x1"; + } + return Component.translatable(key); + } + + + public List getTooltipLines(ItemStack stack) { + int mult = readMultiplier(stack); + long cap = 1L; + switch (mult) { + case 16 -> cap = 1024L; + case 8 -> cap = 256L; + case 4 -> cap = 64L; + case 2 -> cap = 8L; + } + MutableComponent line1 = Component.translatable("tooltip." + com.extendedae_plus.ExtendedAEPlus.MODID + ".entity_speed_card.multiplier", "x" + mult); + MutableComponent line2 = Component.translatable("tooltip." + com.extendedae_plus.ExtendedAEPlus.MODID + ".entity_speed_card.max", cap); + return List.of(line1, line2); + } + + @OnlyIn(Dist.CLIENT) + @Override + public void appendHoverText(ItemStack stack, Level level, List lines, TooltipFlag flag) { + super.appendHoverText(stack, level, lines, flag); + // add our custom tooltip lines (multiplier and max) + lines.addAll(this.getTooltipLines(stack)); + } +} + + diff --git a/src/main/java/com/extendedae_plus/ae/menu/EntitySpeedTickerMenu.java b/src/main/java/com/extendedae_plus/ae/menu/EntitySpeedTickerMenu.java index b8269dc..6eb75e2 100644 --- a/src/main/java/com/extendedae_plus/ae/menu/EntitySpeedTickerMenu.java +++ b/src/main/java/com/extendedae_plus/ae/menu/EntitySpeedTickerMenu.java @@ -7,8 +7,10 @@ import appeng.menu.slot.OptionalFakeSlot; import com.extendedae_plus.ae.parts.EntitySpeedTickerPart; import com.extendedae_plus.ae.screen.EntitySpeedTickerScreen; import com.extendedae_plus.config.ModConfigs; +import com.extendedae_plus.init.ModItems; import com.extendedae_plus.init.ModMenuTypes; import com.extendedae_plus.util.ConfigParsingUtils; +import com.extendedae_plus.util.PowerUtils; import net.minecraft.client.Minecraft; import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.level.block.entity.BlockEntity; @@ -16,16 +18,15 @@ import net.minecraftforge.registries.ForgeRegistries; // 实体加速器菜单,负责与客户端界面同步数据 public class EntitySpeedTickerMenu extends UpgradeableMenu { - // 已安装的速度卡数量 - public int speedCardCount; + @GuiSync(716) public boolean accelerateEnabled = true; + // 已安装的实体加速卡数量(用于能耗计算) + @GuiSync(717) public int entitySpeedCardCount; // 已安装的能量卡数量 - public int energyCardCount; - // 当前生效的倍率(从配置中读取并同步) - public double multiplier = 1.0; - - @GuiSync(716) - public boolean accelerateEnabled = true; - + @GuiSync(718) public int energyCardCount; + // 当前生效的配置倍率(从配置中读取并同步) + // 当前计算出的生效速度(product of multipliers),同步给客户端用于显示 + @GuiSync(719) public int effectiveSpeed = 1; + @GuiSync(720) public double multiplier = 1.0; public boolean getAccelerateEnabled() { return this.accelerateEnabled; @@ -51,8 +52,8 @@ public class EntitySpeedTickerMenu extends UpgradeableMenu) blockEntity.getType()); if (blockEntityTicker == null) return; - int speedCardCount = getUpgrades().getInstalledUpgrades(AEItems.SPEED_CARD); + // 使用集中定义的 CardDef 列表,支持以后添加等级或改倍率而无需修改此逻辑 int energyCardCount = getUpgrades().getInstalledUpgrades(AEItems.ENERGY_CARD); - // 计算本次 tick 所需能量 - // - 基础消耗为 512 - // - 加速卡的数量对能耗有分段增长: - // 0: 无增长 - // 1: 翻倍 - // 2-6: 指数增长(较快) - // 7-8: 幂级数增长(极高) - // 使用工具类统一计算增长因子与原始功耗,并从网络中抽取对应能量 - double requiredPower = PowerUtils.getFinalPower(speedCardCount, energyCardCount); + // 使用已注册的单一 Item 计算已安装卡数量(总计,用于能耗计算) + int entitySpeedCardCount = getUpgrades().getInstalledUpgrades(ModItems.ENTITY_SPEED_CARD.get()); + + // 使用工具方法从槽位直接计算乘积并应用 cap(最多 8 张卡) + long product = PowerUtils.computeProductWithCapFromStacks(this.getUpgrades(), 8); + + // 如果没有任何实体加速卡,则不进行加速且不消耗额外能量(只保留部件的被动功耗) + if (entitySpeedCardCount <= 0) return; + + // 计算本次 tick 所需能量:使用工具类根据 product 计算最终能耗 + double requiredPower = PowerUtils.computeFinalPowerForProduct(product, energyCardCount); + + int speed = (int) product; double multiplier = 1.0; for (ConfigParsingUtils.MultiplierEntry me : ConfigParsingUtils.getCachedMultiplierEntries(ModConfigs.EntitySpeedTickerMultipliers.get())) { @@ -241,7 +246,7 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka if (extractedPower < requiredPower) return; // 计算加速倍数:基于 2 的次方,并把 8 张映射到最大 1024x(2^10) - int speed = PowerUtils.getSpeedMultiplier(speedCardCount); + // 已由 product 计算得到 speed;上面已在没有卡时提前返回 // 执行 tick 操作 for (int i = 0; i < speed - 1; i++) { diff --git a/src/main/java/com/extendedae_plus/ae/screen/EntitySpeedTickerScreen.java b/src/main/java/com/extendedae_plus/ae/screen/EntitySpeedTickerScreen.java index e57748d..7a1f390 100644 --- a/src/main/java/com/extendedae_plus/ae/screen/EntitySpeedTickerScreen.java +++ b/src/main/java/com/extendedae_plus/ae/screen/EntitySpeedTickerScreen.java @@ -76,15 +76,14 @@ public class EntitySpeedTickerScreen extends Up } private void textData() { - int speedCardCount = getMenu().speedCardCount; int energyCardCount = getMenu().energyCardCount; double multiplier = getMenu().multiplier; + int effectiveSpeed = getMenu().effectiveSpeed; - double finalPower = PowerUtils.getFinalPower(speedCardCount, energyCardCount); - int speed = PowerUtils.getSpeedMultiplier(speedCardCount); + double finalPower = PowerUtils.computeFinalPowerForProduct(effectiveSpeed, energyCardCount); double remainingRatio = PowerUtils.getRemainingRatio(energyCardCount); - setTextContent("speed", Component.translatable("screen.extendedae_plus.entity_speed_ticker.speed", speed)); + setTextContent("speed", Component.translatable("screen.extendedae_plus.entity_speed_ticker.speed", effectiveSpeed)); setTextContent("energy", Component.translatable("screen.extendedae_plus.entity_speed_ticker.energy", Platform.formatPower(finalPower, false))); setTextContent("power_ratio", Component.translatable("screen.extendedae_plus.entity_speed_ticker.power_ratio", PowerUtils.formatPercentage(remainingRatio))); setTextContent("multiplier", Component.translatable("screen.extendedae_plus.entity_speed_ticker.multiplier", String.format("%.2fx", multiplier))); diff --git a/src/main/java/com/extendedae_plus/client/ClientRegistrar.java b/src/main/java/com/extendedae_plus/client/ClientRegistrar.java index 4da808b..61a24bc 100644 --- a/src/main/java/com/extendedae_plus/client/ClientRegistrar.java +++ b/src/main/java/com/extendedae_plus/client/ClientRegistrar.java @@ -3,14 +3,17 @@ package com.extendedae_plus.client; import appeng.client.render.crafting.CraftingCubeModel; import appeng.init.client.InitScreens; import com.extendedae_plus.ExtendedAEPlus; +import com.extendedae_plus.ae.definitions.upgrades.EntitySpeedCardItem; import com.extendedae_plus.ae.menu.EntitySpeedTickerMenu; import com.extendedae_plus.ae.screen.EntitySpeedTickerScreen; import com.extendedae_plus.client.render.crafting.EPlusCraftingCubeModelProvider; import com.extendedae_plus.client.screen.GlobalProviderModesScreen; import com.extendedae_plus.content.crafting.EPlusCraftingUnitType; import com.extendedae_plus.hooks.BuiltInModelHooks; +import com.extendedae_plus.init.ModItems; import com.extendedae_plus.init.ModMenuTypes; import net.minecraft.client.gui.screens.MenuScreens; +import net.minecraft.client.renderer.item.ItemProperties; import net.minecraftforge.client.ConfigScreenHandler; import net.minecraftforge.fml.ModLoadingContext; @@ -28,6 +31,9 @@ public final class ClientRegistrar { public static void initBuiltInModels() { if (REGISTERED) return; REGISTERED = true; + // 注册 Item property,用于根据 ItemStack 的 NBT exponent 切换模型 + ItemProperties.register(ModItems.ENTITY_SPEED_CARD.get(), ExtendedAEPlus.id("mult"), + (stack, world, entity, seed) -> (float) EntitySpeedCardItem.readMultiplier(stack)); // 注册四种形成态模型为内置模型 BuiltInModelHooks.addBuiltInModel( ExtendedAEPlus.id("block/crafting/4x_accelerator_formed_v2"), diff --git a/src/main/java/com/extendedae_plus/init/ModCreativeTabs.java b/src/main/java/com/extendedae_plus/init/ModCreativeTabs.java index d44b721..68bdba4 100644 --- a/src/main/java/com/extendedae_plus/init/ModCreativeTabs.java +++ b/src/main/java/com/extendedae_plus/init/ModCreativeTabs.java @@ -27,6 +27,12 @@ public final class ModCreativeTabs { output.accept(ModItems.ACCELERATOR_256x.get()); output.accept(ModItems.ACCELERATOR_1024x.get()); output.accept(ModItems.ENTITY_TICKER_PART_ITEM.get()); + + // 放入四个预设的 stacks(x2,x4,x8,x16),使用 ModItems 工厂创建 + output.accept(ModItems.createEntitySpeedCardStack(2)); + output.accept(ModItems.createEntitySpeedCardStack(4)); + output.accept(ModItems.createEntitySpeedCardStack(8)); + output.accept(ModItems.createEntitySpeedCardStack(16)); }) .build()); } diff --git a/src/main/java/com/extendedae_plus/init/ModItems.java b/src/main/java/com/extendedae_plus/init/ModItems.java index c3ee08c..7341c99 100644 --- a/src/main/java/com/extendedae_plus/init/ModItems.java +++ b/src/main/java/com/extendedae_plus/init/ModItems.java @@ -4,6 +4,7 @@ import appeng.api.parts.IPart; import appeng.api.parts.PartModels; import appeng.items.parts.PartModelsHelper; import com.extendedae_plus.ExtendedAEPlus; +import com.extendedae_plus.ae.definitions.upgrades.EntitySpeedCardItem; import com.extendedae_plus.ae.items.EntitySpeedTickerPartItem; import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.Item; @@ -52,9 +53,17 @@ public final class ModItems { () -> new BlockItem(ModBlocks.ACCELERATOR_1024x.get(), new Item.Properties()) ); - public static final RegistryObject ENTITY_TICKER_PART_ITEM = - ITEMS.register("entity_speed_ticker", - () -> new EntitySpeedTickerPartItem(new Item.Properties())); + public static final RegistryObject ENTITY_TICKER_PART_ITEM = ITEMS.register( + "entity_speed_ticker", + () -> new EntitySpeedTickerPartItem(new Item.Properties()) + ); + + // AE Upgrade Cards: 实体加速卡(四个等级:x2,x4,x8,x16) + // 单一实体加速卡 Item(不同等级由 ItemStack.nbt 存储) + public static final RegistryObject ENTITY_SPEED_CARD = ITEMS.register( + "entity_speed_card", + () -> new EntitySpeedCardItem(new Item.Properties()) + ); /** * 为 PartItem 注册 AE2 部件模型。 @@ -67,4 +76,11 @@ public final class ModItems { ) ); } + + /** + * 工厂:创建带 multiplier 的实体加速卡 ItemStack(2/4/8/16) + */ + public static net.minecraft.world.item.ItemStack createEntitySpeedCardStack(int multiplier) { + return EntitySpeedCardItem.withMultiplier(multiplier); + } } diff --git a/src/main/java/com/extendedae_plus/init/UpgradeCards.java b/src/main/java/com/extendedae_plus/init/UpgradeCards.java index 8c7dd5d..ddd73d4 100644 --- a/src/main/java/com/extendedae_plus/init/UpgradeCards.java +++ b/src/main/java/com/extendedae_plus/init/UpgradeCards.java @@ -8,8 +8,10 @@ import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent; public class UpgradeCards { public UpgradeCards(final FMLCommonSetupEvent event) { event.enqueueWork(() -> { - Upgrades.add(AEItems.SPEED_CARD, ModItems.ENTITY_TICKER_PART_ITEM.get(), 8, "group.entity_ticker.name"); + // 现有:把 Entity Ticker 的部件注册为处理 SPEED/ENERGY 卡的宿主 Upgrades.add(AEItems.ENERGY_CARD, ModItems.ENTITY_TICKER_PART_ITEM.get(), 8, "group.entity_ticker.name"); + // 使用单一的 UpgradeCard Item 作为注册键,总共允许安装 4 张(不同等级由 ItemStack NBT 区分) + Upgrades.add(ModItems.ENTITY_SPEED_CARD.get(), ModItems.ENTITY_TICKER_PART_ITEM.get(), 4, "group.entity_ticker.name"); }); } } \ No newline at end of file diff --git a/src/main/java/com/extendedae_plus/util/PowerUtils.java b/src/main/java/com/extendedae_plus/util/PowerUtils.java index b86bef1..18219e0 100644 --- a/src/main/java/com/extendedae_plus/util/PowerUtils.java +++ b/src/main/java/com/extendedae_plus/util/PowerUtils.java @@ -1,5 +1,6 @@ package com.extendedae_plus.util; +import com.extendedae_plus.ae.definitions.upgrades.EntitySpeedCardItem; import com.extendedae_plus.config.ModConfigs; /** @@ -7,23 +8,111 @@ import com.extendedae_plus.config.ModConfigs; */ public final class PowerUtils { private PowerUtils() {} - + // ---- 重构后的 API ---- /** - * 计算加速卡数量对应的加速倍率(返回 2 的幂次方) - * 0 张卡 = 1x,8 张卡 = 1024x + * 将 card multipliers(按插槽序)计算乘积并应用 cap 规则(见 capForHighestMultiplier) + * @param multipliers iterable of per-card multipliers + * @param maxCards 最多计入的卡数 + * @return 被 cap 约束后的乘积 */ - public static int getSpeedMultiplier(int speedCardCount) { - if (speedCardCount <= 0) return 1; - // 线性映射 0~8 -> 0~10,最大 2^10=1024 - int exponent = (int) Math.round((10.0 / 8.0) * speedCardCount); - exponent = Math.min(exponent, 10); - return (int) Math.pow(2, exponent); + public static long computeProductWithCap(Iterable multipliers, int maxCards) { + long product = 1L; + int considered = 0; + int highest = 1; + for (Integer m : multipliers) { + if (m == null) continue; + if (considered >= maxCards) break; + int mult = m.intValue(); + if (mult <= 0) mult = 1; + product *= mult; + highest = Math.max(highest, mult); + considered++; + } + long cap = capForHighestMultiplier(highest); + return Math.min(product, cap); } /** - * 计算加速卡数量对应的能耗增长因子 - * 0: 1x,1: 2x,2-6: 2^(2*count),7-8: 2^(3*count) + * 根据最高单卡 multiplier 返回 cap 值 */ + public static long capForHighestMultiplier(int highestMultiplier) { + if (highestMultiplier >= 16) return 1024L; + if (highestMultiplier >= 8) return 256L; + if (highestMultiplier >= 4) return 64L; + if (highestMultiplier >= 2) return 8L; + return 1L; + } + + /** + * 从菜单对象读取前 maxCards 个加速卡的 multiplier 并计算 product with cap + */ + public static long computeProductWithCapFromMenu(appeng.menu.implementations.UpgradeableMenu menu, int maxCards) { + java.util.List list = new java.util.ArrayList<>(); + int considered = 0; + for (var stack : menu.getUpgrades()) { + if (considered >= maxCards) break; + if (stack != null && !stack.isEmpty() && stack.getItem() instanceof EntitySpeedCardItem) { + int multVal = EntitySpeedCardItem.readMultiplier(stack); + int count = Math.min(stack.getCount(), maxCards - considered); + for (int i = 0; i < count; i++) { + list.add(multVal); + considered++; + if (considered >= maxCards) break; + } + } + } + return computeProductWithCap(list, maxCards); + } + + /** + * 从一组 ItemStack(升级槽)直接计算 product with cap(最多 maxCards) + */ + public static long computeProductWithCapFromStacks(Iterable stacks, int maxCards) { + java.util.List list = new java.util.ArrayList<>(); + int considered = 0; + for (var stack : stacks) { + if (considered >= maxCards) break; + if (stack != null && !stack.isEmpty() && stack.getItem() instanceof EntitySpeedCardItem) { + int multVal = EntitySpeedCardItem.readMultiplier(stack); + int count = Math.min(stack.getCount(), maxCards - considered); + for (int i = 0; i < count; i++) { + list.add(multVal); + considered++; + if (considered >= maxCards) break; + } + } + } + return computeProductWithCap(list, maxCards); + } + + /** + * 计算最终消耗:把 product 转换为等效卡数(log2)并调用 getFinalPower + */ + public static double computeFinalPowerForProduct(long product, int energyCardCount) { + if (product <= 1L) return 0.0; + double base = ModConfigs.EntitySpeedTickerCost.get(); + + // 计算以2为底的对数(用于分档与公式) + double log2 = Math.log(product) / Math.log(2.0); + + // 分档:product==2 为一档;4..256 为中档;512..1024 为高档 + double raw; + if (product == 2L) { + // 轻量档:线性小幅增长 + raw = base * 4; + } else if (product <= 256L) { + // 中档:增长放缓(使用 1.5 * log2) + raw = base * Math.pow(2.0, 1.5 * log2) * 2; + } else { + // 高档:增长较快(使用 2.5 * log2) + raw = base * Math.pow(2.0, 2.5 * log2); + } + + double reduction = getReductionPercent(energyCardCount); + return raw * (1.0 - reduction) / 8.0; + } + + /* ----------------- legacy helpers (restored) ----------------- */ public static double getGrowthFactor(int speedCardCount) { if (speedCardCount <= 0) return 1.0; if (speedCardCount == 1) return 2.0; @@ -31,20 +120,11 @@ public final class PowerUtils { return Math.pow(2.0, 3.0 * speedCardCount); } - /** - * 计算加速卡数量对应的原始能耗(未减免) - * @param speedCardCount 加速卡数量 - * @return 原始能耗 - */ public static double getRawPower(int speedCardCount) { double base = ModConfigs.EntitySpeedTickerCost.get(); return base * getGrowthFactor(speedCardCount); } - /** - * 计算能源卡数量对应的能耗减免百分比 - * 0: 0%,1: 10%,8: 50%,2-7: 0.5*(1-0.7^n) - */ public static double getReductionPercent(int energyCardCount) { if (energyCardCount <= 0) return 0.0; if (energyCardCount == 1) return 0.1; @@ -52,16 +132,9 @@ public final class PowerUtils { return 0.5 * (1.0 - Math.pow(0.7, energyCardCount)); } - /** - * 计算最终能耗(浮点数) - * @param speedCardCount 加速卡数量 - * @param energyCardCount 能源卡数量 - * @return 最终能耗(double) - */ public static double getFinalPower(int speedCardCount, int energyCardCount) { double raw = getRawPower(speedCardCount); double reduction = getReductionPercent(energyCardCount); - // 返回与实际抽取值一致的浮点能耗(在原实现基础上再除以 2,以降低能耗) return raw * (1.0 - reduction) / 4.0; } diff --git a/src/main/resources/assets/extendedae_plus/lang/en_us.json b/src/main/resources/assets/extendedae_plus/lang/en_us.json index 768e2f4..7dde8f6 100644 --- a/src/main/resources/assets/extendedae_plus/lang/en_us.json +++ b/src/main/resources/assets/extendedae_plus/lang/en_us.json @@ -17,6 +17,13 @@ "item.extendedae_plus.256x_crafting_accelerator": "256x Crafting Accelerator", "item.extendedae_plus.1024x_crafting_accelerator": "1024x Crafting Accelerator", "item.extendedae_plus.network_pattern_controller": "Pattern Supplier State Controller", + "item.extendedae_plus.entity_speed_card": "Entity Acceleration Card", + "item.extendedae_plus.entity_speed_card.x2": "Entity Acceleration Card (x2)", + "item.extendedae_plus.entity_speed_card.x4": "Entity Acceleration Card (x4)", + "item.extendedae_plus.entity_speed_card.x8": "Entity Acceleration Card (x8)", + "item.extendedae_plus.entity_speed_card.x16": "Entity Acceleration Card (x16)", + "tooltip.extendedae_plus.entity_speed_card.multiplier": "Multiplier: %s", + "tooltip.extendedae_plus.entity_speed_card.max": "Max effective: %s x", "block.extendedae_plus.wireless_transceiver": "Wireless Transceiver", "block.extendedae_plus.4x_crafting_accelerator": "4x Crafting Accelerator", diff --git a/src/main/resources/assets/extendedae_plus/lang/zh_cn.json b/src/main/resources/assets/extendedae_plus/lang/zh_cn.json index 1179156..7126a2c 100644 --- a/src/main/resources/assets/extendedae_plus/lang/zh_cn.json +++ b/src/main/resources/assets/extendedae_plus/lang/zh_cn.json @@ -17,6 +17,13 @@ "item.extendedae_plus.256x_crafting_accelerator": "256x并行处理单元", "item.extendedae_plus.1024x_crafting_accelerator": "1024x并行处理单元", "item.extendedae_plus.network_pattern_controller": "样板供应器状态控制器", + "item.extendedae_plus.entity_speed_card": "实体加速卡", + "item.extendedae_plus.entity_speed_card.x2": "实体加速卡 (x2)", + "item.extendedae_plus.entity_speed_card.x4": "实体加速卡 (x4)", + "item.extendedae_plus.entity_speed_card.x8": "实体加速卡 (x8)", + "item.extendedae_plus.entity_speed_card.x16": "实体加速卡 (x16)", + "tooltip.extendedae_plus.entity_speed_card.multiplier": "乘数: %s", + "tooltip.extendedae_plus.entity_speed_card.max": "最大生效: %s 倍", "block.extendedae_plus.wireless_transceiver": "无线收发器", "block.extendedae_plus.4x_crafting_accelerator": "4x并行处理单元", diff --git a/src/main/resources/assets/extendedae_plus/models/item/entity_speed_card.json b/src/main/resources/assets/extendedae_plus/models/item/entity_speed_card.json new file mode 100644 index 0000000..b33694f --- /dev/null +++ b/src/main/resources/assets/extendedae_plus/models/item/entity_speed_card.json @@ -0,0 +1,14 @@ +{ + "parent": "item/generated", + "overrides": [ + { "predicate": { "extendedae_plus:mult": 2.0 }, "model": "extendedae_plus:item/entity_speed_card_x2" }, + { "predicate": { "extendedae_plus:mult": 4.0 }, "model": "extendedae_plus:item/entity_speed_card_x4" }, + { "predicate": { "extendedae_plus:mult": 8.0 }, "model": "extendedae_plus:item/entity_speed_card_x8" }, + { "predicate": { "extendedae_plus:mult": 16.0 }, "model": "extendedae_plus:item/entity_speed_card_x16" } + ], + "textures": { + "layer0": "extendedae_plus:item/entity_speed_card_x2" + } +} + + diff --git a/src/main/resources/assets/extendedae_plus/models/item/entity_speed_card_x1.json b/src/main/resources/assets/extendedae_plus/models/item/entity_speed_card_x1.json new file mode 100644 index 0000000..1107187 --- /dev/null +++ b/src/main/resources/assets/extendedae_plus/models/item/entity_speed_card_x1.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { "layer0": "extendedae_plus:item/entity_speed_card_x2" } +} + + diff --git a/src/main/resources/assets/extendedae_plus/models/item/entity_speed_card_x16.json b/src/main/resources/assets/extendedae_plus/models/item/entity_speed_card_x16.json new file mode 100644 index 0000000..b1cd950 --- /dev/null +++ b/src/main/resources/assets/extendedae_plus/models/item/entity_speed_card_x16.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { "layer0": "extendedae_plus:item/entity_speed_card_x16" } +} + + diff --git a/src/main/resources/assets/extendedae_plus/models/item/entity_speed_card_x2.json b/src/main/resources/assets/extendedae_plus/models/item/entity_speed_card_x2.json new file mode 100644 index 0000000..1107187 --- /dev/null +++ b/src/main/resources/assets/extendedae_plus/models/item/entity_speed_card_x2.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { "layer0": "extendedae_plus:item/entity_speed_card_x2" } +} + + diff --git a/src/main/resources/assets/extendedae_plus/models/item/entity_speed_card_x4.json b/src/main/resources/assets/extendedae_plus/models/item/entity_speed_card_x4.json new file mode 100644 index 0000000..dc0dfcf --- /dev/null +++ b/src/main/resources/assets/extendedae_plus/models/item/entity_speed_card_x4.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { "layer0": "extendedae_plus:item/entity_speed_card_x4" } +} + + diff --git a/src/main/resources/assets/extendedae_plus/models/item/entity_speed_card_x8.json b/src/main/resources/assets/extendedae_plus/models/item/entity_speed_card_x8.json new file mode 100644 index 0000000..0b75b61 --- /dev/null +++ b/src/main/resources/assets/extendedae_plus/models/item/entity_speed_card_x8.json @@ -0,0 +1,6 @@ +{ + "parent": "item/generated", + "textures": { "layer0": "extendedae_plus:item/entity_speed_card_x8" } +} + + diff --git a/src/main/resources/assets/extendedae_plus/textures/item/entity_speed_card_x16.png b/src/main/resources/assets/extendedae_plus/textures/item/entity_speed_card_x16.png new file mode 100644 index 0000000000000000000000000000000000000000..74e75d30731dd8fca0610ffbcee9fab9a3eae780 GIT binary patch literal 2323 zcmb_e4Qvx-7`_c~g8>-~WJ4I2TZn+W-cNh&-9g93TDCGew=vidG+yt%u4QenTyJZ) ziQ)n%;3T>Xlf>;hz)B(!eJ~MW8_g)NjOJ=Nuv6FUx zHgLIfs}(S%I=@(~E*Cio8=rxW3-OS^3seCOc|E=WA2MTMULIa+!vuzgA!@l9%hCd( zrS<|eTUG$d=_p(zNg6eAIuq+K8TD*BN|Q80kTgM2IK}Z4$&)M^`C%}eB02dY%fv`9 zcxT33s_N$nA{Y$nf_j~-lo1riaT*6r;}C%ds(h*t!hM0XE(Qw-h>F{Q86f<=G7OEDkfz4vZV9q+XTjDu};~3V+;DX*r;}UHUaL!55I4J@nFtH}a z=>%Q#EwWglbyl0->2gUHA;-T_4GbwVdQrpykW9FqF&J?{APuD~hz0-_vsiAqA?K0z& zNRO07bP2vP09Q@|d-7x+&zGGl|C`J`Z`S{p456);oem@JHDCByx3v{EGCTwqZ0$0- zRlu9*W&?b%P72&gT84gVLXg-rnWCKS3FChfNlIT??st1899ze@*Qn%FCA^+yT&(Y3ws4&<4V_L$9$>lYi;chwA^ zv$gP$b+W_$wUwCJe`eF|mh&rXHlM9Zjhp`J+`Rdp#raQPOqiEgGjN`_N5QB;NOJNp z%hah0Qk!i0j+Vxleb*+&SG5}3e;)I~jtM2ltebYJ4Z~}f+Ny7iTlnU|<8>pDzOTpS z4zF7=Ra(8Hzk^w_YsR^)XO5OPT%gi#rLRz(gL8hMH(B5R1$*lzgYd|_#J=(MF&lI5 zjc^kvbrZENCO zD*u!O>`~JH*d9FPN>TVBV nm9ka+2DGh9&g3ryJ96Gwp+Wk&la0C-?Dka%eDUi@gpR& literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/extendedae_plus/textures/item/entity_speed_card_x2.png b/src/main/resources/assets/extendedae_plus/textures/item/entity_speed_card_x2.png new file mode 100644 index 0000000000000000000000000000000000000000..950d6235b841728e91ca61bca4531f8c5df3cc3f GIT binary patch literal 2084 zcmbVN3s4kg9A9uS#4r-y8ZK*MOzz(9agV*#1BpYqkpsdTgkG|@``xi|cYEwE-T^6M zI;E*OI>n&Yh=!trrgb{vW0Wa;jYV4ds4T{GvOFH!lD6>+bc5xGZx}y;97mG!O##yDK}%8svufyD?qbE z37{r|!a0)EqDB*8q#Z^>8a)-&l3Kln)M_XSr%Vh*G9-v^hzQ#>ZqyfK^1v zE{g8HN)_~3Mzsb)k3KV3@baQxPVKh=SXc#^F|}$qN#k0BozyaVnxPEOk~Bk-y-=IT z3(l(kP!mq2*-2PkEu*FHfx@2QS%rNlnCBR$D0x^Iu;5``K;!eeFf@`zCQEdS5)_8+ z(n2n5Hpc3e71qlEtHq4LmsHbqAbLemmKsJW~o;atGb~-2n5Bd7o@+AR&Xso+G ztLln}j5^8z3_P#HDLrq(O|%Z+4vIG6BWW*PQ}kkAkzhN_t56j+|Rts z&VR7=M=NEor~cLlY{vg%J)9Pb}Xv# z_0G!$_{g@#tkI*}GMf|H8;SP3{niOe!sCwA=GwZIbM7Kj-e7`_^&j|K=XDeQo(YaK zTdWmVUrf5a@cM%9|2p);Eh{@l8nremZfW$4SaiwNp$U8AXY42%gc|irw+Oi(n%BI0 zrDqrt`*-`4r|$$CZY)p^XP=Z$zd)pRB%j@N{-suHI^NTLE+5%4EvAV;;+HB3n;uIZ zdv2Eh<-*TWtjA_18rEMCPrY*B%wyJl5q`_`WhzF#||r6~DTT+2H)cEpl1O)Y^+jMh*M6zJB$=qFHUb$8P*&#e|IL72`(QPj_DH8vZ;h|9GqB zWW6`BI=yb{-FbE1uFbLIn=bGRw_0vqiuP>War8HA$WHf&3!8Eb>$7L4G}P=N{*3x+ zdtKMQoXqvt8e(26X>4i^^6~kn_p@id$R56T<)v*c3jyE6BnvU263wHU- z_oAmPus!wjWW^{Uokx}Kb;&n_y3Tm~V*QO8f4$4!J#i0Gdh}TH^gG96CbvD2J!$i& z7nX0|w|w~yOTMRZ=<2gw5}kXA8b1bIq@2Bedvy1p&$pRweG^pw$F13UmYvU)F8&AH CZrfJ? literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/extendedae_plus/textures/item/entity_speed_card_x4.png b/src/main/resources/assets/extendedae_plus/textures/item/entity_speed_card_x4.png new file mode 100644 index 0000000000000000000000000000000000000000..1c440cc5d52c9a6d175d3c68e1021627a4fed8a4 GIT binary patch literal 2326 zcmb_e2}~4M7#{0U14|Do#AY) zhKk0cghhy8V#Z$8fmSj9(}VcTeMy=-DGxV-hA)- zzyJTgd2g26r)9*(439w&BsSA($%g0WwWDto{2$eMPk^U>e(Nj+LHfsQM+EZmrwIrW zwbtXvQFCllc~SQ21W9%RU5VEZ(Fij6l@h-o<^vUVf;^AUj9uNm4?{hY8Jo%2NSi+m zxINag0GM7j%^{ZMi=2eL@-jNPgogxPpbBV-x4@_HC1xzh%foAJn845=M9nv2DOx}@ z$7V;<krfVlu(^u#fTEYPf$8i%P9zy#4yfZ7$^t^mqY>-059;V3dB-jtlurG zvf`E>K^=a4UjSHJn=KsUp<2A&a0o?BFM?@=3i432;wbe4A{!`jVL$}wMNsA#EgL_d z765`O2OP3o(A_C}w`7zy>KJtVOpi~Ji|0i6GNr#$e7mk4NGuz?dX~G&vxDC0$>1#J2^e1WW1tLlm@O;d zfiId+(34eDB|%05+VmX$?X_JY?VYOKtw!?(8Mx&lHktEQQOn2%%rFWSTE;Teyv)yKV z7U`j~h;G4`2jI#{V9%b+)A_PX<$sfT;LZB~k|DJ9vddw_gXRl9>#?@NMh1uAf~{SK zw+eU@-fVym)+qqDl6U%ipNb&8k~1wS4)*<;>e{S$A)#SW#?}1o=DO9{qX(gJaeb3d zSf|FvN5zkewo^%Q&rQ@NAFAKD;Aq9c#Xk%iap1rPYH)l~``q@1QD^6^`Y8b&QPFy) z@yvH)+w5~D&Kq%at?Aa@wuP;2Z@2z6qZ~bJ$mnyhtutbZZe7}Irz5K>drzs&iTr%m z_5r!4+85ohe`Mc1KN2}yJGi!K0-+lG1h)c^5 z`|QhW3L`sC3>|c0@#dN5R$XZVSC7xy(Y`ZrN5zo2%6kjO{8~3K&&nX~h^p*k6Y#Q* z+_D=*ms*)p{k_H0lnj@^19B1*Hf)SJl)7ol<(sM7_kR!{ zoyo`5pZf6bwey!IA=SrMj%zhF_qE4XSR3>ER5olp*<}4P>jKq_aQb%*uBx2SxbdsT zPgcLXZF}d1lY5%im!s(VBhhU`_nqsPIP*YNYQ~E3^cJCiY{rsdQ}3L=*fO^|`gBcA wTKu9G?#SO272=?Xkv7|%R literal 0 HcmV?d00001 diff --git a/src/main/resources/assets/extendedae_plus/textures/item/entity_speed_card_x8.png b/src/main/resources/assets/extendedae_plus/textures/item/entity_speed_card_x8.png new file mode 100644 index 0000000000000000000000000000000000000000..1b51f61e79ea7abcbfa069b2dd18277a57b45027 GIT binary patch literal 2307 zcmb_e32f6=7&f#kv|A6Y92E@VnvKE0@sZfE4WX2VBZ3s#hEZUYIrd8vn%HUVlD3>< z8ilffC|Ad^acW~oNE_0`1}n$9a%hE>t$+lG!nmi62@ryb!JgAJD~wBMksRC4-~0aW z|NqbLdEvO+k;zFtk`M$*c8s#;!*iN(bWVW(y>C7c;VCgVYNCc9FQ*$v2W0iy32nq8h0Za8qy|i)th#}zJP?Fv1R0!F9u%b#prdY3>{D#m^<8@~)F<1p35=6;26KSd zH>xrO3MzA5Qe}z6%UISBba1%<2?9VD(ei*_(S&jv7U31(wJ}U!Xau5{*syFPAX?}g zhvujufbu2^mq?OEt-Q&~xvi|38;H^*%@8C_P!vw_0!0cWhem%G3>T6;LcV=OG#I?I zVP0Ji3Iq`jhfQI#NevYf6wmVp2TkJ;fom0tE|%kp)~AiZ4m2s`3+g^qK@CRHt(NIF z3`%XyArOqwDq6Houwq2H7$hhYY2*|E%2Es$EDQM~!DWd6eh>hPu0bpn!v?*ou4-QO z3DmL24+Vg=bvk1)9;+n~h=tJf;nQIn(Ske{t+^_KfXD}$S{9PP@aa%yA0wNfkP`x; zu7+Hy>Tm1RxHics&6*gr-vpl`t6{Bwy9vN9>cEB>UBgKZr&$+C3k)Yv>;RGzNU{~` zRAry1qCJ$yDYJ{D1ez8o>qAiJ8ClfDXM$x(@Tj4H2ov@N#9}}Mm0}Eyl~Kr1{b~pX zhU&}_6;7w%P&8dsB;c^yFqpH+=aU5qm?<+&u{c9}Se)c77TnFS3~muA4<`YU<~Y7> zzFn2djLsVKTU{=z66E+ds?6~`!>~Ngu{4jHX~@QzB`YpcvXuoE$>Ju(Hny=LAAHe7 ze|uI#l?)jzlpC8)mjOARg1T$>qRM0&I= zl2=rU0bDr=?8TFLK3}$~{BJUkyjlNWGK8^SwmOV>)O?X=?bcS<$jA^}u#L;uRsnBf zn+;H4okDOcIneF?Z3O9v!QFQZ}3iPLLNU+8P4@NT1*IW`~PP(8fk zdr9+_<&N8UU-XZEA4yA5q zN}#5p@U_a8Klh*8ee~v_)ay(Ar!H}$6Iu>*?b(t?SEspK=8;aM`Uecz5X^A?Ts!mj z&`C81QsU>XxHfX|&0c*c;kVvSpZfi0~ zGZ(*pCGo@YN#2cze;r$Tc>ca)mzgnn#lP*x@;7}mHrOvtudO*V>%FF#DdSxeKP{^7 zKW6)EXAPgV(1r7NcO37==rnV@9*l?ytF7Mj8(-CTy>