feat: 添加实体加速卡替换加速卡

This commit is contained in:
C-H716 2025-09-13 12:50:47 +08:00
parent e697552b6b
commit fb2a2a831d
23 changed files with 312 additions and 61 deletions

View File

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

View File

@ -32,8 +32,7 @@ public class ExtendedAEPlus {
public ExtendedAEPlus() { public ExtendedAEPlus() {
IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus(); IEventBus modEventBus = FMLJavaModLoadingContext.get().getModEventBus();
// 在客户端尽早注册内置模型保证首次资源加载前映射已建立仿照 AE2 AppEngClient 构造期注册 // 客户端的内置模型注册将在客户端事件阶段执行 ClientModEvents不要在构造器中提前执行
DistExecutor.unsafeRunWhenOn(Dist.CLIENT, () -> ClientRegistrar::initBuiltInModels);
// 注册mod初始化事件 // 注册mod初始化事件
modEventBus.addListener(this::commonSetup); modEventBus.addListener(this::commonSetup);

View File

@ -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 存储 exponent0/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<Component> 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<Component> lines, TooltipFlag flag) {
super.appendHoverText(stack, level, lines, flag);
// add our custom tooltip lines (multiplier and max)
lines.addAll(this.getTooltipLines(stack));
}
}

View File

@ -7,8 +7,10 @@ import appeng.menu.slot.OptionalFakeSlot;
import com.extendedae_plus.ae.parts.EntitySpeedTickerPart; import com.extendedae_plus.ae.parts.EntitySpeedTickerPart;
import com.extendedae_plus.ae.screen.EntitySpeedTickerScreen; import com.extendedae_plus.ae.screen.EntitySpeedTickerScreen;
import com.extendedae_plus.config.ModConfigs; import com.extendedae_plus.config.ModConfigs;
import com.extendedae_plus.init.ModItems;
import com.extendedae_plus.init.ModMenuTypes; import com.extendedae_plus.init.ModMenuTypes;
import com.extendedae_plus.util.ConfigParsingUtils; import com.extendedae_plus.util.ConfigParsingUtils;
import com.extendedae_plus.util.PowerUtils;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.world.entity.player.Inventory; import net.minecraft.world.entity.player.Inventory;
import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.entity.BlockEntity;
@ -16,16 +18,15 @@ import net.minecraftforge.registries.ForgeRegistries;
// 实体加速器菜单负责与客户端界面同步数据 // 实体加速器菜单负责与客户端界面同步数据
public class EntitySpeedTickerMenu extends UpgradeableMenu<EntitySpeedTickerPart> { public class EntitySpeedTickerMenu extends UpgradeableMenu<EntitySpeedTickerPart> {
// 已安装的速度卡数量 @GuiSync(716) public boolean accelerateEnabled = true;
public int speedCardCount; // 已安装的实体加速卡数量用于能耗计算
@GuiSync(717) public int entitySpeedCardCount;
// 已安装的能量卡数量 // 已安装的能量卡数量
public int energyCardCount; @GuiSync(718) public int energyCardCount;
// 当前生效的倍率从配置中读取并同步 // 当前生效的配置倍率从配置中读取并同步
public double multiplier = 1.0; // 当前计算出的生效速度product of multipliers同步给客户端用于显示
@GuiSync(719) public int effectiveSpeed = 1;
@GuiSync(716) @GuiSync(720) public double multiplier = 1.0;
public boolean accelerateEnabled = true;
public boolean getAccelerateEnabled() { public boolean getAccelerateEnabled() {
return this.accelerateEnabled; return this.accelerateEnabled;
@ -51,8 +52,8 @@ public class EntitySpeedTickerMenu extends UpgradeableMenu<EntitySpeedTickerPart
@Override @Override
public void onServerDataSync() { public void onServerDataSync() {
super.onServerDataSync(); super.onServerDataSync();
// 重新统计卡和能量卡数量 // 重新统计实体加速卡和能量卡数量
this.speedCardCount = this.getUpgrades().getInstalledUpgrades(AEItems.SPEED_CARD); this.entitySpeedCardCount = this.getUpgrades().getInstalledUpgrades(ModItems.ENTITY_SPEED_CARD.get());
this.energyCardCount = this.getUpgrades().getInstalledUpgrades(AEItems.ENERGY_CARD); this.energyCardCount = this.getUpgrades().getInstalledUpgrades(AEItems.ENERGY_CARD);
// 计算当前面向方块的倍率服务器端并同步给客户端 // 计算当前面向方块的倍率服务器端并同步给客户端
@ -70,6 +71,9 @@ public class EntitySpeedTickerMenu extends UpgradeableMenu<EntitySpeedTickerPart
} catch (Exception ignored) {} } catch (Exception ignored) {}
this.multiplier = mult; this.multiplier = mult;
// 计算生效速度使用工具类从菜单直接计算 product with cap最多 8
this.effectiveSpeed = (int) PowerUtils.computeProductWithCapFromMenu(this, 8);
// 如果在客户端刷新界面 // 如果在客户端刷新界面
if (isClientSide()) { if (isClientSide()) {
if (Minecraft.getInstance().screen instanceof EntitySpeedTickerScreen screen) { if (Minecraft.getInstance().screen instanceof EntitySpeedTickerScreen screen) {
@ -84,8 +88,10 @@ public class EntitySpeedTickerMenu extends UpgradeableMenu<EntitySpeedTickerPart
super.onSlotChange(slot); super.onSlotChange(slot);
// 客户端重新统计卡数量并刷新界面 // 客户端重新统计卡数量并刷新界面
if (isClientSide()) { if (isClientSide()) {
this.speedCardCount = this.getUpgrades().getInstalledUpgrades(AEItems.SPEED_CARD); this.entitySpeedCardCount = this.getUpgrades().getInstalledUpgrades(ModItems.ENTITY_SPEED_CARD.get());
this.energyCardCount = this.getUpgrades().getInstalledUpgrades(AEItems.ENERGY_CARD); this.energyCardCount = this.getUpgrades().getInstalledUpgrades(AEItems.ENERGY_CARD);
// 立即在客户端计算生效速度以便界面即时反馈使用与服务端相同的工具方法最多 8 张卡
this.effectiveSpeed = (int) PowerUtils.computeProductWithCapFromMenu(this, 8);
if (Minecraft.getInstance().screen instanceof EntitySpeedTickerScreen screen) { if (Minecraft.getInstance().screen instanceof EntitySpeedTickerScreen screen) {
screen.refreshGui(); screen.refreshGui();
} }

View File

@ -20,6 +20,7 @@ import appeng.parts.automation.UpgradeablePart;
import com.extendedae_plus.ExtendedAEPlus; import com.extendedae_plus.ExtendedAEPlus;
import com.extendedae_plus.ae.menu.EntitySpeedTickerMenu; import com.extendedae_plus.ae.menu.EntitySpeedTickerMenu;
import com.extendedae_plus.config.ModConfigs; import com.extendedae_plus.config.ModConfigs;
import com.extendedae_plus.init.ModItems;
import com.extendedae_plus.init.ModMenuTypes; import com.extendedae_plus.init.ModMenuTypes;
import com.extendedae_plus.util.ConfigParsingUtils; import com.extendedae_plus.util.ConfigParsingUtils;
import com.extendedae_plus.util.PowerUtils; import com.extendedae_plus.util.PowerUtils;
@ -209,18 +210,22 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
.getTicker(this.getLevel(), (BlockEntityType<T>) blockEntity.getType()); .getTicker(this.getLevel(), (BlockEntityType<T>) blockEntity.getType());
if (blockEntityTicker == null) return; if (blockEntityTicker == null) return;
int speedCardCount = getUpgrades().getInstalledUpgrades(AEItems.SPEED_CARD); // 使用集中定义的 CardDef 列表支持以后添加等级或改倍率而无需修改此逻辑
int energyCardCount = getUpgrades().getInstalledUpgrades(AEItems.ENERGY_CARD); int energyCardCount = getUpgrades().getInstalledUpgrades(AEItems.ENERGY_CARD);
// 计算本次 tick 所需能量 // 使用已注册的单一 Item 计算已安装卡数量总计用于能耗计算
// - 基础消耗为 512 int entitySpeedCardCount = getUpgrades().getInstalledUpgrades(ModItems.ENTITY_SPEED_CARD.get());
// - 加速卡的数量对能耗有分段增长
// 0: 无增长 // 使用工具方法从槽位直接计算乘积并应用 cap最多 8 张卡
// 1: 翻倍 long product = PowerUtils.computeProductWithCapFromStacks(this.getUpgrades(), 8);
// 2-6: 指数增长较快
// 7-8: 幂级数增长极高 // 如果没有任何实体加速卡则不进行加速且不消耗额外能量只保留部件的被动功耗
// 使用工具类统一计算增长因子与原始功耗并从网络中抽取对应能量 if (entitySpeedCardCount <= 0) return;
double requiredPower = PowerUtils.getFinalPower(speedCardCount, energyCardCount);
// 计算本次 tick 所需能量使用工具类根据 product 计算最终能耗
double requiredPower = PowerUtils.computeFinalPowerForProduct(product, energyCardCount);
int speed = (int) product;
double multiplier = 1.0; double multiplier = 1.0;
for (ConfigParsingUtils.MultiplierEntry me : ConfigParsingUtils.getCachedMultiplierEntries(ModConfigs.EntitySpeedTickerMultipliers.get())) { for (ConfigParsingUtils.MultiplierEntry me : ConfigParsingUtils.getCachedMultiplierEntries(ModConfigs.EntitySpeedTickerMultipliers.get())) {
@ -241,7 +246,7 @@ public class EntitySpeedTickerPart extends UpgradeablePart implements IGridTicka
if (extractedPower < requiredPower) return; if (extractedPower < requiredPower) return;
// 计算加速倍数基于 2 的次方并把 8 张映射到最大 1024x2^10 // 计算加速倍数基于 2 的次方并把 8 张映射到最大 1024x2^10
int speed = PowerUtils.getSpeedMultiplier(speedCardCount); // 已由 product 计算得到 speed上面已在没有卡时提前返回
// 执行 tick 操作 // 执行 tick 操作
for (int i = 0; i < speed - 1; i++) { for (int i = 0; i < speed - 1; i++) {

View File

@ -76,15 +76,14 @@ public class EntitySpeedTickerScreen<C extends EntitySpeedTickerMenu> extends Up
} }
private void textData() { private void textData() {
int speedCardCount = getMenu().speedCardCount;
int energyCardCount = getMenu().energyCardCount; int energyCardCount = getMenu().energyCardCount;
double multiplier = getMenu().multiplier; double multiplier = getMenu().multiplier;
int effectiveSpeed = getMenu().effectiveSpeed;
double finalPower = PowerUtils.getFinalPower(speedCardCount, energyCardCount); double finalPower = PowerUtils.computeFinalPowerForProduct(effectiveSpeed, energyCardCount);
int speed = PowerUtils.getSpeedMultiplier(speedCardCount);
double remainingRatio = PowerUtils.getRemainingRatio(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("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("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))); setTextContent("multiplier", Component.translatable("screen.extendedae_plus.entity_speed_ticker.multiplier", String.format("%.2fx", multiplier)));

View File

@ -3,14 +3,17 @@ package com.extendedae_plus.client;
import appeng.client.render.crafting.CraftingCubeModel; import appeng.client.render.crafting.CraftingCubeModel;
import appeng.init.client.InitScreens; import appeng.init.client.InitScreens;
import com.extendedae_plus.ExtendedAEPlus; 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.menu.EntitySpeedTickerMenu;
import com.extendedae_plus.ae.screen.EntitySpeedTickerScreen; import com.extendedae_plus.ae.screen.EntitySpeedTickerScreen;
import com.extendedae_plus.client.render.crafting.EPlusCraftingCubeModelProvider; import com.extendedae_plus.client.render.crafting.EPlusCraftingCubeModelProvider;
import com.extendedae_plus.client.screen.GlobalProviderModesScreen; import com.extendedae_plus.client.screen.GlobalProviderModesScreen;
import com.extendedae_plus.content.crafting.EPlusCraftingUnitType; import com.extendedae_plus.content.crafting.EPlusCraftingUnitType;
import com.extendedae_plus.hooks.BuiltInModelHooks; import com.extendedae_plus.hooks.BuiltInModelHooks;
import com.extendedae_plus.init.ModItems;
import com.extendedae_plus.init.ModMenuTypes; import com.extendedae_plus.init.ModMenuTypes;
import net.minecraft.client.gui.screens.MenuScreens; import net.minecraft.client.gui.screens.MenuScreens;
import net.minecraft.client.renderer.item.ItemProperties;
import net.minecraftforge.client.ConfigScreenHandler; import net.minecraftforge.client.ConfigScreenHandler;
import net.minecraftforge.fml.ModLoadingContext; import net.minecraftforge.fml.ModLoadingContext;
@ -28,6 +31,9 @@ public final class ClientRegistrar {
public static void initBuiltInModels() { public static void initBuiltInModels() {
if (REGISTERED) return; if (REGISTERED) return;
REGISTERED = true; 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( BuiltInModelHooks.addBuiltInModel(
ExtendedAEPlus.id("block/crafting/4x_accelerator_formed_v2"), ExtendedAEPlus.id("block/crafting/4x_accelerator_formed_v2"),

View File

@ -27,6 +27,12 @@ public final class ModCreativeTabs {
output.accept(ModItems.ACCELERATOR_256x.get()); output.accept(ModItems.ACCELERATOR_256x.get());
output.accept(ModItems.ACCELERATOR_1024x.get()); output.accept(ModItems.ACCELERATOR_1024x.get());
output.accept(ModItems.ENTITY_TICKER_PART_ITEM.get()); output.accept(ModItems.ENTITY_TICKER_PART_ITEM.get());
// 放入四个预设的 stacksx2,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()); .build());
} }

View File

@ -4,6 +4,7 @@ import appeng.api.parts.IPart;
import appeng.api.parts.PartModels; import appeng.api.parts.PartModels;
import appeng.items.parts.PartModelsHelper; import appeng.items.parts.PartModelsHelper;
import com.extendedae_plus.ExtendedAEPlus; import com.extendedae_plus.ExtendedAEPlus;
import com.extendedae_plus.ae.definitions.upgrades.EntitySpeedCardItem;
import com.extendedae_plus.ae.items.EntitySpeedTickerPartItem; import com.extendedae_plus.ae.items.EntitySpeedTickerPartItem;
import net.minecraft.world.item.BlockItem; import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.Item; import net.minecraft.world.item.Item;
@ -52,9 +53,17 @@ public final class ModItems {
() -> new BlockItem(ModBlocks.ACCELERATOR_1024x.get(), new Item.Properties()) () -> new BlockItem(ModBlocks.ACCELERATOR_1024x.get(), new Item.Properties())
); );
public static final RegistryObject<EntitySpeedTickerPartItem> ENTITY_TICKER_PART_ITEM = public static final RegistryObject<EntitySpeedTickerPartItem> ENTITY_TICKER_PART_ITEM = ITEMS.register(
ITEMS.register("entity_speed_ticker", "entity_speed_ticker",
() -> new EntitySpeedTickerPartItem(new Item.Properties())); () -> new EntitySpeedTickerPartItem(new Item.Properties())
);
// AE Upgrade Cards: 实体加速卡四个等级x2,x4,x8,x16
// 单一实体加速卡 Item不同等级由 ItemStack.nbt 存储
public static final RegistryObject<EntitySpeedCardItem> ENTITY_SPEED_CARD = ITEMS.register(
"entity_speed_card",
() -> new EntitySpeedCardItem(new Item.Properties())
);
/** /**
* PartItem 注册 AE2 部件模型 * PartItem 注册 AE2 部件模型
@ -67,4 +76,11 @@ public final class ModItems {
) )
); );
} }
/**
* 工厂创建带 multiplier 的实体加速卡 ItemStack2/4/8/16
*/
public static net.minecraft.world.item.ItemStack createEntitySpeedCardStack(int multiplier) {
return EntitySpeedCardItem.withMultiplier(multiplier);
}
} }

View File

@ -8,8 +8,10 @@ import net.minecraftforge.fml.event.lifecycle.FMLCommonSetupEvent;
public class UpgradeCards { public class UpgradeCards {
public UpgradeCards(final FMLCommonSetupEvent event) { public UpgradeCards(final FMLCommonSetupEvent event) {
event.enqueueWork(() -> { 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"); 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");
}); });
} }
} }

View File

@ -1,5 +1,6 @@
package com.extendedae_plus.util; package com.extendedae_plus.util;
import com.extendedae_plus.ae.definitions.upgrades.EntitySpeedCardItem;
import com.extendedae_plus.config.ModConfigs; import com.extendedae_plus.config.ModConfigs;
/** /**
@ -7,23 +8,111 @@ import com.extendedae_plus.config.ModConfigs;
*/ */
public final class PowerUtils { public final class PowerUtils {
private PowerUtils() {} private PowerUtils() {}
// ---- 重构后的 API ----
/** /**
* 计算加速卡数量对应的加速倍率返回 2 的幂次方 * card multipliers按插槽序计算乘积并应用 cap 规则 capForHighestMultiplier
* 0 张卡 = 1x8 张卡 = 1024x * @param multipliers iterable of per-card multipliers
* @param maxCards 最多计入的卡数
* @return cap 约束后的乘积
*/ */
public static int getSpeedMultiplier(int speedCardCount) { public static long computeProductWithCap(Iterable<Integer> multipliers, int maxCards) {
if (speedCardCount <= 0) return 1; long product = 1L;
// 线性映射 0~8 -> 0~10最大 2^10=1024 int considered = 0;
int exponent = (int) Math.round((10.0 / 8.0) * speedCardCount); int highest = 1;
exponent = Math.min(exponent, 10); for (Integer m : multipliers) {
return (int) Math.pow(2, exponent); 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);
} }
/** /**
* 计算加速卡数量对应的能耗增长因子 * 根据最高单卡 multiplier 返回 cap
* 0: 1x1: 2x2-6: 2^(2*count)7-8: 2^(3*count)
*/ */
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<Integer> 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<net.minecraft.world.item.ItemStack> stacks, int maxCards) {
java.util.List<Integer> 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) { public static double getGrowthFactor(int speedCardCount) {
if (speedCardCount <= 0) return 1.0; if (speedCardCount <= 0) return 1.0;
if (speedCardCount == 1) return 2.0; if (speedCardCount == 1) return 2.0;
@ -31,20 +120,11 @@ public final class PowerUtils {
return Math.pow(2.0, 3.0 * speedCardCount); return Math.pow(2.0, 3.0 * speedCardCount);
} }
/**
* 计算加速卡数量对应的原始能耗未减免
* @param speedCardCount 加速卡数量
* @return 原始能耗
*/
public static double getRawPower(int speedCardCount) { public static double getRawPower(int speedCardCount) {
double base = ModConfigs.EntitySpeedTickerCost.get(); double base = ModConfigs.EntitySpeedTickerCost.get();
return base * getGrowthFactor(speedCardCount); return base * getGrowthFactor(speedCardCount);
} }
/**
* 计算能源卡数量对应的能耗减免百分比
* 0: 0%1: 10%8: 50%2-7: 0.5*(1-0.7^n)
*/
public static double getReductionPercent(int energyCardCount) { public static double getReductionPercent(int energyCardCount) {
if (energyCardCount <= 0) return 0.0; if (energyCardCount <= 0) return 0.0;
if (energyCardCount == 1) return 0.1; if (energyCardCount == 1) return 0.1;
@ -52,16 +132,9 @@ public final class PowerUtils {
return 0.5 * (1.0 - Math.pow(0.7, energyCardCount)); return 0.5 * (1.0 - Math.pow(0.7, energyCardCount));
} }
/**
* 计算最终能耗浮点数
* @param speedCardCount 加速卡数量
* @param energyCardCount 能源卡数量
* @return 最终能耗double
*/
public static double getFinalPower(int speedCardCount, int energyCardCount) { public static double getFinalPower(int speedCardCount, int energyCardCount) {
double raw = getRawPower(speedCardCount); double raw = getRawPower(speedCardCount);
double reduction = getReductionPercent(energyCardCount); double reduction = getReductionPercent(energyCardCount);
// 返回与实际抽取值一致的浮点能耗在原实现基础上再除以 2以降低能耗
return raw * (1.0 - reduction) / 4.0; return raw * (1.0 - reduction) / 4.0;
} }

View File

@ -17,6 +17,13 @@
"item.extendedae_plus.256x_crafting_accelerator": "256x Crafting Accelerator", "item.extendedae_plus.256x_crafting_accelerator": "256x Crafting Accelerator",
"item.extendedae_plus.1024x_crafting_accelerator": "1024x Crafting Accelerator", "item.extendedae_plus.1024x_crafting_accelerator": "1024x Crafting Accelerator",
"item.extendedae_plus.network_pattern_controller": "Pattern Supplier State Controller", "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.wireless_transceiver": "Wireless Transceiver",
"block.extendedae_plus.4x_crafting_accelerator": "4x Crafting Accelerator", "block.extendedae_plus.4x_crafting_accelerator": "4x Crafting Accelerator",

View File

@ -17,6 +17,13 @@
"item.extendedae_plus.256x_crafting_accelerator": "256x并行处理单元", "item.extendedae_plus.256x_crafting_accelerator": "256x并行处理单元",
"item.extendedae_plus.1024x_crafting_accelerator": "1024x并行处理单元", "item.extendedae_plus.1024x_crafting_accelerator": "1024x并行处理单元",
"item.extendedae_plus.network_pattern_controller": "样板供应器状态控制器", "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.wireless_transceiver": "无线收发器",
"block.extendedae_plus.4x_crafting_accelerator": "4x并行处理单元", "block.extendedae_plus.4x_crafting_accelerator": "4x并行处理单元",

View File

@ -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"
}
}

View File

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": { "layer0": "extendedae_plus:item/entity_speed_card_x2" }
}

View File

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": { "layer0": "extendedae_plus:item/entity_speed_card_x16" }
}

View File

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": { "layer0": "extendedae_plus:item/entity_speed_card_x2" }
}

View File

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": { "layer0": "extendedae_plus:item/entity_speed_card_x4" }
}

View File

@ -0,0 +1,6 @@
{
"parent": "item/generated",
"textures": { "layer0": "extendedae_plus:item/entity_speed_card_x8" }
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB