diff --git a/src/main/java/com/atsuishio/superbwarfare/block/entity/ChargingStationBlockEntity.java b/src/main/java/com/atsuishio/superbwarfare/block/entity/ChargingStationBlockEntity.java index bd4db2e88..494713b3f 100644 --- a/src/main/java/com/atsuishio/superbwarfare/block/entity/ChargingStationBlockEntity.java +++ b/src/main/java/com/atsuishio/superbwarfare/block/entity/ChargingStationBlockEntity.java @@ -10,8 +10,10 @@ import net.minecraft.core.HolderLookup; import net.minecraft.core.NonNullList; import net.minecraft.core.component.DataComponents; import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.IntTag; import net.minecraft.network.chat.Component; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.Container; import net.minecraft.world.ContainerHelper; import net.minecraft.world.MenuProvider; @@ -27,13 +29,17 @@ import net.minecraft.world.level.Level; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; +import net.neoforged.neoforge.capabilities.BlockCapabilityCache; import net.neoforged.neoforge.capabilities.Capabilities; +import net.neoforged.neoforge.capabilities.ICapabilityProvider; import net.neoforged.neoforge.energy.EnergyStorage; +import net.neoforged.neoforge.energy.IEnergyStorage; +import net.neoforged.neoforge.items.IItemHandler; +import net.neoforged.neoforge.items.wrapper.SidedInvWrapper; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; -import java.util.concurrent.atomic.AtomicInteger; /** * Energy Data Slot Code based on @GoryMoon's Chargers @@ -52,40 +58,63 @@ public class ChargingStationBlockEntity extends BlockEntity implements WorldlyCo protected NonNullList items = NonNullList.withSize(2, ItemStack.EMPTY); - private EnergyStorage energyHandler; - // TODO SidedInvWrapper Energy -// private LazyOptional[] itemHandlers = SidedInvWrapper.create(this, Direction.UP, Direction.DOWN, Direction.NORTH); + private BlockCapabilityCache capCache; + + @Override + public void onLoad() { + super.onLoad(); + + if (level != null && !level.isClientSide) { + this.capCache = BlockCapabilityCache.create( + Capabilities.EnergyStorage.BLOCK, + (ServerLevel) level, + this.getBlockPos(), + null + ); + } + } + public int fuelTick = 0; public int maxFuelTick = DEFAULT_FUEL_TIME; public boolean showRange = false; protected final ContainerEnergyData dataAccess = new ContainerEnergyData() { - public long get(int pIndex) { + public int get(int pIndex) { return switch (pIndex) { case 0 -> ChargingStationBlockEntity.this.fuelTick; case 1 -> ChargingStationBlockEntity.this.maxFuelTick; case 2 -> { - AtomicInteger energy = new AtomicInteger(); -// ChargingStationBlockEntity.this.getCapability(Capabilities.ENERGY).ifPresent(consumer -> energy.set(consumer.getEnergyStored())); - yield energy.get(); + var level = ChargingStationBlockEntity.this.level; + if (level == null) yield 0; + + var cap = level.getCapability(Capabilities.EnergyStorage.BLOCK, ChargingStationBlockEntity.this.getBlockPos(), null); + if (cap == null) yield 0; + + yield cap.getEnergyStored(); } case 3 -> ChargingStationBlockEntity.this.showRange ? 1 : 0; default -> 0; }; } - public void set(int pIndex, long pValue) { + public void set(int pIndex, int pValue) { switch (pIndex) { case 0: - ChargingStationBlockEntity.this.fuelTick = (int) pValue; + ChargingStationBlockEntity.this.fuelTick = pValue; break; case 1: - ChargingStationBlockEntity.this.maxFuelTick = (int) pValue; + ChargingStationBlockEntity.this.maxFuelTick = pValue; break; case 2: -// ChargingStationBlockEntity.this.getCapability(Capabilities.ENERGY).ifPresent(consumer -> consumer.receiveEnergy((int) pValue, false)); + var level = ChargingStationBlockEntity.this.level; + if (level == null) return; + + var cap = level.getCapability(Capabilities.EnergyStorage.BLOCK, ChargingStationBlockEntity.this.getBlockPos(), null); + if (cap == null) return; + + cap.receiveEnergy((int) pValue, false); break; case 3: ChargingStationBlockEntity.this.showRange = pValue == 1; @@ -100,8 +129,6 @@ public class ChargingStationBlockEntity extends BlockEntity implements WorldlyCo public ChargingStationBlockEntity(BlockPos pos, BlockState state) { super(ModBlockEntities.CHARGING_STATION.get(), pos, state); - - this.energyHandler = new EnergyStorage(MAX_ENERGY); } public static void serverTick(Level pLevel, BlockPos pPos, BlockState pState, ChargingStationBlockEntity blockEntity) { @@ -110,7 +137,9 @@ public class ChargingStationBlockEntity extends BlockEntity implements WorldlyCo setChanged(pLevel, pPos, pState); } - var handler = blockEntity.energyHandler; + var handler = blockEntity.capCache.getCapability(); + if (handler == null) return; + int energy = handler.getEnergyStored(); if (energy > 0) { blockEntity.chargeEntity(handler); @@ -191,7 +220,7 @@ public class ChargingStationBlockEntity extends BlockEntity implements WorldlyCo } } - private void chargeEntity(EnergyStorage handler) { + private void chargeEntity(IEnergyStorage handler) { if (this.level == null) return; if (this.level.getGameTime() % 20 != 0) return; @@ -206,7 +235,7 @@ public class ChargingStationBlockEntity extends BlockEntity implements WorldlyCo this.setChanged(); } - private void chargeItemStack(EnergyStorage handler) { + private void chargeItemStack(IEnergyStorage handler) { ItemStack stack = this.getItem(SLOT_CHARGE); if (stack.isEmpty()) return; @@ -220,7 +249,7 @@ public class ChargingStationBlockEntity extends BlockEntity implements WorldlyCo this.setChanged(); } - private void chargeBlock(EnergyStorage handler) { + private void chargeBlock(IEnergyStorage handler) { if (this.level == null) return; for (Direction direction : Direction.values()) { @@ -248,8 +277,11 @@ public class ChargingStationBlockEntity extends BlockEntity implements WorldlyCo protected void loadAdditional(@NotNull CompoundTag tag, HolderLookup.@NotNull Provider registries) { super.loadAdditional(tag, registries); - if (tag.contains("Energy")) { -// getCapability(Capabilities.ENERGY).ifPresent(handler -> ((EnergyStorage) handler).deserializeNBT(tag.get("Energy"))); + if (tag.contains("Energy") && this.capCache.getCapability() != null) { + var energy = tag.get("Energy"); + if (energy instanceof IntTag) { + ((EnergyStorage) this.capCache.getCapability()).deserializeNBT(registries, energy); + } } this.fuelTick = tag.getInt("FuelTick"); this.maxFuelTick = tag.getInt("MaxFuelTick"); @@ -262,7 +294,9 @@ public class ChargingStationBlockEntity extends BlockEntity implements WorldlyCo protected void saveAdditional(@NotNull CompoundTag tag, HolderLookup.@NotNull Provider registries) { super.saveAdditional(tag, registries); -// getCapability(Capabilities.ENERGY).ifPresent(handler -> tag.put("Energy", ((EnergyStorage) handler).serializeNBT())); + if (this.capCache != null && this.capCache.getCapability() != null) { + tag.put("Energy", IntTag.valueOf(this.capCache.getCapability().getEnergyStored())); + } tag.putInt("FuelTick", this.fuelTick); tag.putInt("MaxFuelTick", this.maxFuelTick); tag.putBoolean("ShowRange", this.showRange); @@ -363,35 +397,39 @@ public class ChargingStationBlockEntity extends BlockEntity implements WorldlyCo return compoundtag; } + public static class EnergyStorageProvider implements ICapabilityProvider { + + private final IEnergyStorage energy = new EnergyStorage(MAX_ENERGY); + + @Override + public @Nullable IEnergyStorage getCapability(@NotNull ChargingStationBlockEntity object, Direction context) { + return energy; + } + } + + + public static class ItemHandlerProvider implements ICapabilityProvider { + + private IItemHandler[] itemHandlers; + + @Override + public @Nullable IItemHandler getCapability(@NotNull ChargingStationBlockEntity object, Direction context) { + if (context == null || object.isRemoved()) return null; + + if (itemHandlers == null) { + this.itemHandlers = new IItemHandler[]{ + new SidedInvWrapper(object, Direction.UP), + new SidedInvWrapper(object, Direction.DOWN), + new SidedInvWrapper(object, Direction.NORTH), + }; + } + + return switch (context) { + case UP -> itemHandlers[0]; + case DOWN -> itemHandlers[1]; + default -> itemHandlers[2]; + }; + } + } -// @Override -// public LazyOptional getCapability(Capability cap, Direction side) { -// if (cap == Capabilities.ENERGY) { -// return energyHandler.cast(); -// } -// if (!this.remove && side != null && cap == Capabilities.ITEM_HANDLER) { -// if (side == Direction.UP) { -// return itemHandlers[0].cast(); -// } else if (side == Direction.DOWN) { -// return itemHandlers[1].cast(); -// } else { -// return itemHandlers[2].cast(); -// } -// } -// return super.getCapability(cap, side); -// } -// -// @Override -// public void invalidateCaps() { -// super.invalidateCaps(); -// for (LazyOptional itemHandler : itemHandlers) itemHandler.invalidate(); -// energyHandler.invalidate(); -// } -// -// @Override -// public void reviveCaps() { -// super.reviveCaps(); -// this.itemHandlers = SidedInvWrapper.create(this, Direction.UP, Direction.DOWN, Direction.NORTH); -// this.energyHandler = LazyOptional.of(() -> new EnergyStorage(MAX_ENERGY)); -// } } diff --git a/src/main/java/com/atsuishio/superbwarfare/block/entity/CreativeChargingStationBlockEntity.java b/src/main/java/com/atsuishio/superbwarfare/block/entity/CreativeChargingStationBlockEntity.java index 72b13455d..750d817da 100644 --- a/src/main/java/com/atsuishio/superbwarfare/block/entity/CreativeChargingStationBlockEntity.java +++ b/src/main/java/com/atsuishio/superbwarfare/block/entity/CreativeChargingStationBlockEntity.java @@ -5,12 +5,17 @@ import com.atsuishio.superbwarfare.init.ModBlockEntities; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.network.protocol.game.ClientboundBlockEntityDataPacket; +import net.minecraft.server.level.ServerLevel; import net.minecraft.world.entity.Entity; import net.minecraft.world.level.block.entity.BlockEntity; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.phys.AABB; +import net.neoforged.neoforge.capabilities.BlockCapabilityCache; import net.neoforged.neoforge.capabilities.Capabilities; +import net.neoforged.neoforge.capabilities.ICapabilityProvider; import net.neoforged.neoforge.energy.IEnergyStorage; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import java.util.List; @@ -21,17 +26,30 @@ public class CreativeChargingStationBlockEntity extends BlockEntity { public static final int CHARGE_RADIUS = 8; - private final IEnergyStorage energyHandler; + private BlockCapabilityCache capCache; + + @Override + public void onLoad() { + super.onLoad(); + + if (level != null && !level.isClientSide) { + this.capCache = BlockCapabilityCache.create( + Capabilities.EnergyStorage.BLOCK, + (ServerLevel) level, + this.getBlockPos(), + null + ); + } + } public CreativeChargingStationBlockEntity(BlockPos pos, BlockState state) { super(ModBlockEntities.CREATIVE_CHARGING_STATION.get(), pos, state); - this.energyHandler = new InfinityEnergyStorage(); } public static void serverTick(CreativeChargingStationBlockEntity blockEntity) { if (blockEntity.level == null) return; - if (blockEntity.energyHandler != null) { + if (blockEntity.capCache != null) { blockEntity.chargeEntity(); blockEntity.chargeBlock(); } @@ -72,4 +90,14 @@ public class CreativeChargingStationBlockEntity extends BlockEntity { return ClientboundBlockEntityDataPacket.create(this); } + public static class EnergyStorageProvider implements ICapabilityProvider { + + private final IEnergyStorage energy = new InfinityEnergyStorage(); + + @Override + public @Nullable IEnergyStorage getCapability(@NotNull CreativeChargingStationBlockEntity object, Direction context) { + if (object.isRemoved()) return null; + return energy; + } + } } diff --git a/src/main/java/com/atsuishio/superbwarfare/block/entity/FuMO25BlockEntity.java b/src/main/java/com/atsuishio/superbwarfare/block/entity/FuMO25BlockEntity.java index d6d757704..e5c5c7f2b 100644 --- a/src/main/java/com/atsuishio/superbwarfare/block/entity/FuMO25BlockEntity.java +++ b/src/main/java/com/atsuishio/superbwarfare/block/entity/FuMO25BlockEntity.java @@ -59,7 +59,7 @@ public class FuMO25BlockEntity extends BlockEntity implements MenuProvider, GeoB protected final ContainerEnergyData dataAccess = new ContainerEnergyData() { // TODO energy @Override - public long get(int pIndex) { + public int get(int pIndex) { return switch (pIndex) { // case 0 -> FuMO25BlockEntity.this.energyHandler.map(EnergyStorage::getEnergyStored).orElse(0); case 1 -> FuMO25BlockEntity.this.type.ordinal(); @@ -71,15 +71,15 @@ public class FuMO25BlockEntity extends BlockEntity implements MenuProvider, GeoB } @Override - public void set(int pIndex, long pValue) { + public void set(int pIndex, int pValue) { switch (pIndex) { case 0 -> { } // FuMO25BlockEntity.this.energyHandler.ifPresent(handler -> handler.receiveEnergy((int) pValue, false)); case 1 -> FuMO25BlockEntity.this.type = FuncType.values()[(int) pValue]; - case 2 -> FuMO25BlockEntity.this.time = (int) pValue; + case 2 -> FuMO25BlockEntity.this.time = pValue; case 3 -> FuMO25BlockEntity.this.powered = pValue == 1; - case 4 -> FuMO25BlockEntity.this.tick = (int) pValue; + case 4 -> FuMO25BlockEntity.this.tick = pValue; } } diff --git a/src/main/java/com/atsuishio/superbwarfare/capability/ModCapabilities.java b/src/main/java/com/atsuishio/superbwarfare/capability/ModCapabilities.java index 1d7a487e8..ee2c5e436 100644 --- a/src/main/java/com/atsuishio/superbwarfare/capability/ModCapabilities.java +++ b/src/main/java/com/atsuishio/superbwarfare/capability/ModCapabilities.java @@ -1,13 +1,51 @@ package com.atsuishio.superbwarfare.capability; import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.block.entity.ChargingStationBlockEntity; +import com.atsuishio.superbwarfare.block.entity.CreativeChargingStationBlockEntity; +import com.atsuishio.superbwarfare.capability.energy.BlockEnergyStorageProvider; +import com.atsuishio.superbwarfare.capability.energy.ItemEnergyProvider; import com.atsuishio.superbwarfare.capability.laser.LaserCapability; +import com.atsuishio.superbwarfare.capability.laser.LaserCapabilityProvider; import com.atsuishio.superbwarfare.capability.player.PlayerVariable; +import com.atsuishio.superbwarfare.capability.player.PlayerVariablesProvider; +import com.atsuishio.superbwarfare.init.ModBlockEntities; +import com.atsuishio.superbwarfare.init.ModItems; +import com.atsuishio.superbwarfare.item.BatteryItem; +import com.atsuishio.superbwarfare.item.CreativeChargingStationBlockItem; +import net.minecraft.world.entity.EntityType; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.capabilities.Capabilities; import net.neoforged.neoforge.capabilities.EntityCapability; +import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent; +@EventBusSubscriber(modid = ModUtils.MODID, bus = EventBusSubscriber.Bus.MOD) public class ModCapabilities { public static final EntityCapability LASER_CAPABILITY = EntityCapability.createVoid(ModUtils.loc("laser_capability"), LaserCapability.class); public static final EntityCapability PLAYER_VARIABLE = EntityCapability.createVoid(ModUtils.loc("player_variable"), PlayerVariable.class); + @SubscribeEvent + public static void registerCapabilities(RegisterCapabilitiesEvent event) { + event.registerEntity(ModCapabilities.LASER_CAPABILITY, EntityType.PLAYER, new LaserCapabilityProvider()); + event.registerEntity(ModCapabilities.PLAYER_VARIABLE, EntityType.PLAYER, new PlayerVariablesProvider()); + + // 充电站 + event.registerBlockEntity(Capabilities.EnergyStorage.BLOCK, ModBlockEntities.CHARGING_STATION.value(), new BlockEnergyStorageProvider<>(ChargingStationBlockEntity.MAX_ENERGY)); + // TODO HANDLER + event.registerBlockEntity(Capabilities.ItemHandler.BLOCK, ModBlockEntities.CHARGING_STATION.value(), new ChargingStationBlockEntity.ItemHandlerProvider()); + + // 创造模式充电站 + event.registerBlockEntity(Capabilities.EnergyStorage.BLOCK, ModBlockEntities.CREATIVE_CHARGING_STATION.value(), new CreativeChargingStationBlockEntity.EnergyStorageProvider()); + event.registerItem(Capabilities.EnergyStorage.ITEM, new CreativeChargingStationBlockItem.EnergyStorageProvider(), ModItems.CREATIVE_CHARGING_STATION.value()); + + // 电池 + for (var item : ModItems.ITEMS.getEntries()) { + if (item.get() instanceof BatteryItem battery) { + event.registerItem(Capabilities.EnergyStorage.ITEM, new ItemEnergyProvider(battery.maxEnergy), battery); + } + } + + } } diff --git a/src/main/java/com/atsuishio/superbwarfare/capability/energy/BlockEnergyStorageProvider.java b/src/main/java/com/atsuishio/superbwarfare/capability/energy/BlockEnergyStorageProvider.java new file mode 100644 index 000000000..62e32e11c --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/capability/energy/BlockEnergyStorageProvider.java @@ -0,0 +1,24 @@ +package com.atsuishio.superbwarfare.capability.energy; + +import net.minecraft.core.Direction; +import net.neoforged.neoforge.capabilities.ICapabilityProvider; +import net.neoforged.neoforge.energy.EnergyStorage; +import net.neoforged.neoforge.energy.IEnergyStorage; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +// TODO 共用实例问题 +// TODO 序列化问题 +public class BlockEnergyStorageProvider implements ICapabilityProvider { + + private final IEnergyStorage energy; + + public BlockEnergyStorageProvider(int maxEnergy) { + this.energy = new EnergyStorage(maxEnergy); + } + + @Override + public @Nullable IEnergyStorage getCapability(@NotNull T object, Direction context) { + return energy; + } +} \ No newline at end of file diff --git a/src/main/java/com/atsuishio/superbwarfare/capability/energy/ItemEnergyProvider.java b/src/main/java/com/atsuishio/superbwarfare/capability/energy/ItemEnergyProvider.java index df6911d0e..d955931c6 100644 --- a/src/main/java/com/atsuishio/superbwarfare/capability/energy/ItemEnergyProvider.java +++ b/src/main/java/com/atsuishio/superbwarfare/capability/energy/ItemEnergyProvider.java @@ -5,18 +5,17 @@ import net.neoforged.neoforge.capabilities.ICapabilityProvider; import net.neoforged.neoforge.energy.EnergyStorage; import net.neoforged.neoforge.energy.IEnergyStorage; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class ItemEnergyProvider implements ICapabilityProvider { - private final ItemStack stack; private final EnergyStorage energyStorage; - public ItemEnergyProvider(ItemStack stack, int energyCapacity) { - this.stack = stack; + public ItemEnergyProvider(int energyCapacity) { this.energyStorage = new EnergyStorage(energyCapacity); } @Override - public @org.jetbrains.annotations.Nullable IEnergyStorage getCapability(@NotNull ItemStack object, Void context) { + public @Nullable IEnergyStorage getCapability(@NotNull ItemStack object, Void context) { return energyStorage; } } diff --git a/src/main/java/com/atsuishio/superbwarfare/capability/laser/LaserCapabilityProvider.java b/src/main/java/com/atsuishio/superbwarfare/capability/laser/LaserCapabilityProvider.java index b83ee659c..c1dde6195 100644 --- a/src/main/java/com/atsuishio/superbwarfare/capability/laser/LaserCapabilityProvider.java +++ b/src/main/java/com/atsuishio/superbwarfare/capability/laser/LaserCapabilityProvider.java @@ -1,21 +1,14 @@ package com.atsuishio.superbwarfare.capability.laser; -import com.atsuishio.superbwarfare.ModUtils; -import com.atsuishio.superbwarfare.capability.ModCapabilities; import net.minecraft.core.HolderLookup; import net.minecraft.nbt.CompoundTag; -import net.minecraft.world.entity.EntityType; import net.minecraft.world.entity.player.Player; -import net.neoforged.bus.api.SubscribeEvent; -import net.neoforged.fml.common.EventBusSubscriber; import net.neoforged.neoforge.capabilities.ICapabilityProvider; -import net.neoforged.neoforge.capabilities.RegisterCapabilitiesEvent; import net.neoforged.neoforge.common.util.INBTSerializable; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.UnknownNullability; -@EventBusSubscriber(modid = ModUtils.MODID, bus = EventBusSubscriber.Bus.MOD) public class LaserCapabilityProvider implements ICapabilityProvider, INBTSerializable { private final LaserCapability instance = new LaserCapability(); @@ -34,9 +27,4 @@ public class LaserCapabilityProvider implements ICapabilityProvider, INBTSerializable { private final PlayerVariable playerVariables = new PlayerVariable(); @@ -34,9 +28,4 @@ public class PlayerVariablesProvider implements ICapabilityProvider 0 || GunsTool.getGunDoubleTag(stack, "Headshot", 0) > 0; + return false; + } + + protected boolean shouldRenderEditTooltip() { +// if (this.stack.getItem() instanceof GunItem gunItem) { +// return gunItem.isCustomizable(stack); +// } + return false; + } + + protected boolean shouldRenderPerks() { +// return PerkHelper.getPerkByType(stack, Perk.Type.AMMO) != null || PerkHelper.getPerkByType(stack, Perk.Type.DAMAGE) != null || PerkHelper.getPerkByType(stack, Perk.Type.FUNCTIONAL) != null; + return false; + } + + /** + * 渲染武器伤害和射速 + */ + protected void renderDamageAndRpmTooltip(Font font, GuiGraphics guiGraphics, int x, int y) { + guiGraphics.drawString(font, getDamageComponent(), x, y, 0xFFFFFF); + int xo = font.width(getDamageComponent().getVisualOrderText()); + guiGraphics.drawString(font, getRpmComponent(), x + xo + 16, y, 0xFFFFFF); + } + + /** + * 获取武器伤害的文本组件 + */ + protected Component getDamageComponent() { +// double damage = GunsTool.getGunDoubleTag(stack, "Damage", 0) * TooltipTool.perkDamage(stack); +// return Component.translatable("des.superbwarfare.guns.damage").withStyle(ChatFormatting.GRAY) +// .append(Component.literal("").withStyle(ChatFormatting.RESET)) +// .append(Component.literal(FormatTool.format1D(damage) + (TooltipTool.heBullet(stack) ? " + " +// + FormatTool.format1D(0.8 * damage * (1 + 0.1 * TooltipTool.heBulletLevel(stack))) : "")).withStyle(ChatFormatting.GREEN)); + return Component.literal(""); + } + + /** + * 获取武器射速的文本组件 + */ + protected Component getRpmComponent() { +// if (this.stack.getItem() instanceof GunItem gunItem && gunItem.isAutoWeapon(this.stack)) { +// return Component.translatable("des.superbwarfare.guns.rpm").withStyle(ChatFormatting.GRAY) +// .append(Component.literal("").withStyle(ChatFormatting.RESET)) +// .append(Component.literal(FormatTool.format0D(GunsTool.getGunIntTag(stack, "RPM", 0))) +// .withStyle(ChatFormatting.GREEN)); +// } + return Component.literal(""); + } + + /** + * 渲染武器等级和强化点数 + */ + protected void renderLevelAndUpgradePointTooltip(Font font, GuiGraphics guiGraphics, int x, int y) { + guiGraphics.drawString(font, getLevelComponent(), x, y, 0xFFFFFF); + int xo = font.width(getLevelComponent().getVisualOrderText()); + guiGraphics.drawString(font, getUpgradePointComponent(), x + xo + 16, y, 0xFFFFFF); + } + + /** + * 获取武器等级文本组件 + */ + protected Component getLevelComponent() { +// int level = GunsTool.getGunIntTag(stack, "Level", 0); +// double rate = GunsTool.getGunDoubleTag(stack, "Exp", 0) / (20 * Math.pow(level, 2) + 160 * level + 20); + + ChatFormatting formatting; +// if (level < 10) { +// formatting = ChatFormatting.WHITE; +// } else if (level < 20) { +// formatting = ChatFormatting.AQUA; +// } else if (level < 30) { +// formatting = ChatFormatting.LIGHT_PURPLE; +// } else if (level < 40) { +// formatting = ChatFormatting.GOLD; +// } else { +// formatting = ChatFormatting.RED; +// } + +// return Component.translatable("des.superbwarfare.guns.level").withStyle(ChatFormatting.GRAY) +// .append(Component.literal("").withStyle(ChatFormatting.RESET)) +// .append(Component.literal(level + "").withStyle(formatting).withStyle(ChatFormatting.BOLD)) +// .append(Component.literal("").withStyle(ChatFormatting.RESET)) +// .append(Component.literal(" (" + FormatTool.DECIMAL_FORMAT_2ZZZ.format(rate * 100) + "%)").withStyle(ChatFormatting.GRAY)); + return Component.literal(""); + } + + /** + * 获取武器强化点数文本组件 + */ + protected Component getUpgradePointComponent() { +// int upgradePoint = Mth.floor(GunsTool.getGunDoubleTag(stack, "UpgradePoint", 0)); +// return Component.translatable("des.superbwarfare.guns.upgrade_point").withStyle(ChatFormatting.GRAY) +// .append(Component.literal("").withStyle(ChatFormatting.RESET)) +// .append(Component.literal(String.valueOf(upgradePoint)).withStyle(ChatFormatting.WHITE).withStyle(ChatFormatting.BOLD)); + return Component.literal(""); + } + + /** + * 渲染武器穿甲比例和爆头倍率 + */ + protected void renderBypassAndHeadshotTooltip(Font font, GuiGraphics guiGraphics, int x, int y) { + guiGraphics.drawString(font, getBypassComponent(), x, y, 0xFFFFFF); + int xo = font.width(getBypassComponent().getVisualOrderText()); + guiGraphics.drawString(font, getHeadshotComponent(), x + xo + 16, y, 0xFFFFFF); + } + + /** + * 获取武器穿甲比例文本组件 + */ + protected Component getBypassComponent() { + double perkBypassArmorRate = 0; +// var perk = PerkHelper.getPerkByType(stack, Perk.Type.AMMO); +// +// if (perk instanceof AmmoPerk ammoPerk) { +// int level = PerkHelper.getItemPerkLevel(perk, stack); +// perkBypassArmorRate = ammoPerk.bypassArmorRate + (perk == ModPerks.AP_BULLET.get() ? 0.05f * (level - 1) : 0); +// } +// double bypassRate = Math.max(GunsTool.getGunDoubleTag(stack, "BypassesArmor", 0) + perkBypassArmorRate, 0); + +// return Component.translatable("des.superbwarfare.guns.bypass").withStyle(ChatFormatting.GRAY) +// .append(Component.literal("").withStyle(ChatFormatting.RESET)) +// .append(Component.literal(FormatTool.format2D(bypassRate * 100, "%")).withStyle(ChatFormatting.GOLD)); + return Component.literal(""); + } + + /** + * 获取武器爆头倍率文本组件 + */ + protected Component getHeadshotComponent() { +// double headshot = GunsTool.getGunDoubleTag(stack, "Headshot", 0); +// return Component.translatable("des.superbwarfare.guns.headshot").withStyle(ChatFormatting.GRAY) +// .append(Component.literal("").withStyle(ChatFormatting.RESET)) +// .append(Component.literal(FormatTool.format1D(headshot, "x")).withStyle(ChatFormatting.AQUA)); + return Component.literal(""); + } + + /** + * 渲染武器改装信息 + */ + protected void renderWeaponEditTooltip(Font font, GuiGraphics guiGraphics, int x, int y) { + guiGraphics.drawString(font, getEditComponent(), x, y + 10, 0xFFFFFF); + } + + /** + * 获取武器改装信息文本组件 + */ + protected Component getEditComponent() { + return Component.translatable("des.superbwarfare.guns.edit", "[" + ModKeyMappings.EDIT_MODE.getKey().getDisplayName().getString() + "]") + .withStyle(ChatFormatting.LIGHT_PURPLE).withStyle(ChatFormatting.ITALIC); + } + + /** + * 渲染武器模组缩略图 + */ + protected void renderPerksShortcut(Font font, GuiGraphics guiGraphics, int x, int y) { + guiGraphics.pose().pushPose(); + + int xOffset = -20; + +// Perk ammoPerk = PerkHelper.getPerkByType(stack, Perk.Type.AMMO); +// if (ammoPerk != null && PerkHelper.getPerkItem(ammoPerk).isPresent()) { +// xOffset += 20; +// +// var ammoItem = PerkHelper.getPerkItem(ammoPerk).get().get(); +// ItemStack perkStack = ammoItem.getDefaultInstance(); +// +// CompoundTag ammoTag = PerkHelper.getPerkTag(stack, Perk.Type.AMMO); +// if (!ammoTag.isEmpty()) { +// int level = PerkHelper.getItemPerkLevel(ammoPerk, stack); +// perkStack.setCount(level); +// } +// guiGraphics.renderItem(perkStack, x + xOffset, y + 2); +// guiGraphics.renderItemDecorations(font, perkStack, x + xOffset, y + 2); +// } +// +// Perk funcPerk = PerkHelper.getPerkByType(stack, Perk.Type.FUNCTIONAL); +// if (funcPerk != null && PerkHelper.getPerkItem(funcPerk).isPresent()) { +// xOffset += 20; +// +// var funcItem = PerkHelper.getPerkItem(funcPerk).get().get(); +// ItemStack perkStack = funcItem.getDefaultInstance(); +// +// CompoundTag funcTag = PerkHelper.getPerkTag(stack, Perk.Type.FUNCTIONAL); +// if (!funcTag.isEmpty()) { +// int level = PerkHelper.getItemPerkLevel(funcPerk, stack); +// perkStack.setCount(level); +// } +// +// guiGraphics.renderItem(perkStack, x + xOffset, y + 2); +// guiGraphics.renderItemDecorations(font, perkStack, x + xOffset, y + 2); +// } +// +// Perk damagePerk = PerkHelper.getPerkByType(stack, Perk.Type.DAMAGE); +// if (damagePerk != null && PerkHelper.getPerkItem(damagePerk).isPresent()) { +// xOffset += 20; +// +// var damageItem = PerkHelper.getPerkItem(damagePerk).get().get(); +// ItemStack perkStack = damageItem.getDefaultInstance(); +// +// CompoundTag damageTag = PerkHelper.getPerkTag(stack, Perk.Type.DAMAGE); +// if (!damageTag.isEmpty()) { +// int level = PerkHelper.getItemPerkLevel(damagePerk, stack); +// perkStack.setCount(level); +// } +// +// guiGraphics.renderItem(perkStack, x + xOffset, y + 2); +// guiGraphics.renderItemDecorations(font, perkStack, x + xOffset, y + 2); +// } + + guiGraphics.pose().popPose(); + } + + /** + * 渲染武器模组详细信息 + */ + protected void renderPerks(Font font, GuiGraphics guiGraphics, int x, int y) { + guiGraphics.pose().pushPose(); + + guiGraphics.drawString(font, Component.translatable("perk.superbwarfare.tips").withStyle(ChatFormatting.GOLD).withStyle(ChatFormatting.UNDERLINE), x, y + 10, 0xFFFFFF); + + int yOffset = -5; + +// Perk ammoPerk = PerkHelper.getPerkByType(stack, Perk.Type.AMMO); +// if (ammoPerk != null && PerkHelper.getPerkItem(ammoPerk).isPresent()) { +// yOffset += 25; +// var ammoItem = PerkHelper.getPerkItem(ammoPerk).get().get(); +// guiGraphics.renderItem(ammoItem.getDefaultInstance(), x, y + 4 + yOffset); +// +// CompoundTag ammoTag = PerkHelper.getPerkTag(stack, Perk.Type.AMMO); +// if (!ammoTag.isEmpty()) { +// var ids = ammoTag.getString("id").split(":"); +// if (ids.length > 1) { +// String id = ids[1]; +// var ammoComponent = Component.translatable("item.superbwarfare." + id).withStyle(ChatFormatting.YELLOW) +// .append(Component.literal(" ").withStyle(ChatFormatting.RESET)) +// .append(Component.literal(" Lvl. " + ammoTag.getInt("level")).withStyle(ChatFormatting.WHITE)); +// var ammoDesComponent = Component.translatable("des.superbwarfare." + id).withStyle(ChatFormatting.GRAY); +// +// guiGraphics.drawString(font, ammoComponent, x + 20, y + yOffset + 2, 0xFFFFFF); +// guiGraphics.drawString(font, ammoDesComponent, x + 20, y + yOffset + 12, 0xFFFFFF); +// } +// } +// } +// +// Perk funcPerk = PerkHelper.getPerkByType(stack, Perk.Type.FUNCTIONAL); +// if (funcPerk != null && PerkHelper.getPerkItem(funcPerk).isPresent()) { +// yOffset += 25; +// var funcItem = PerkHelper.getPerkItem(funcPerk).get().get(); +// guiGraphics.renderItem(funcItem.getDefaultInstance(), x, y + 4 + yOffset); +// +// CompoundTag funcTag = PerkHelper.getPerkTag(stack, Perk.Type.FUNCTIONAL); +// if (!funcTag.isEmpty()) { +// var ids = funcTag.getString("id").split(":"); +// if (ids.length > 1) { +// String id = ids[1]; +// var funcComponent = Component.translatable("item.superbwarfare." + id).withStyle(ChatFormatting.GREEN) +// .append(Component.literal(" ").withStyle(ChatFormatting.RESET)) +// .append(Component.literal(" Lvl. " + funcTag.getInt("level")).withStyle(ChatFormatting.WHITE)); +// var funcDesComponent = Component.translatable("des.superbwarfare." + id).withStyle(ChatFormatting.GRAY); +// +// guiGraphics.drawString(font, funcComponent, x + 20, y + yOffset + 2, 0xFFFFFF); +// guiGraphics.drawString(font, funcDesComponent, x + 20, y + yOffset + 12, 0xFFFFFF); +// } +// } +// } +// +// Perk damagePerk = PerkHelper.getPerkByType(stack, Perk.Type.DAMAGE); +// if (damagePerk != null && PerkHelper.getPerkItem(damagePerk).isPresent()) { +// yOffset += 25; +// var damageItem = PerkHelper.getPerkItem(damagePerk).get().get(); +// guiGraphics.renderItem(damageItem.getDefaultInstance(), x, y + 4 + yOffset); +// +// CompoundTag damageTag = PerkHelper.getPerkTag(stack, Perk.Type.DAMAGE); +// if (!damageTag.isEmpty()) { +// var ids = damageTag.getString("id").split(":"); +// if (ids.length > 1) { +// String id = ids[1]; +// var damageComponent = Component.translatable("item.superbwarfare." + id).withStyle(ChatFormatting.RED) +// .append(Component.literal(" ").withStyle(ChatFormatting.RESET)) +// .append(Component.literal(" Lvl. " + damageTag.getInt("level")).withStyle(ChatFormatting.WHITE)); +// var damageDesComponent = Component.translatable("des.superbwarfare." + id).withStyle(ChatFormatting.GRAY); +// +// guiGraphics.drawString(font, damageComponent, x + 20, y + yOffset + 2, 0xFFFFFF); +// guiGraphics.drawString(font, damageDesComponent, x + 20, y + yOffset + 12, 0xFFFFFF); +// } +// } +// } + + guiGraphics.pose().popPose(); + } + + protected int getDefaultMaxWidth(Font font) { + int width = font.width(getDamageComponent().getVisualOrderText()) + font.width(getRpmComponent().getVisualOrderText()) + 16; + width = Math.max(width, font.width(getLevelComponent().getVisualOrderText()) + font.width(getUpgradePointComponent().getVisualOrderText()) + 16); + if (shouldRenderBypassAndHeadshotTooltip()) { + width = Math.max(width, font.width(getBypassComponent().getVisualOrderText()) + font.width(getHeadshotComponent().getVisualOrderText()) + 16); + } + if (shouldRenderEditTooltip()) { + width = Math.max(width, font.width(getEditComponent().getVisualOrderText()) + 16); + } + + return width + 4; + } + + protected int getMaxPerkDesWidth(Font font) { + if (!shouldRenderPerks()) return 0; + + int width = 0; + +// CompoundTag ammoTag = PerkHelper.getPerkTag(stack, Perk.Type.AMMO); +// if (!ammoTag.isEmpty()) { +// var ids = ammoTag.getString("id").split(":"); +// if (ids.length > 1) { +// String id = ids[1]; +// var ammoDesComponent = Component.translatable("des.superbwarfare." + id).withStyle(ChatFormatting.GRAY); +// width = Math.max(width, font.width(ammoDesComponent)); +// } +// } +// +// CompoundTag funcTag = PerkHelper.getPerkTag(stack, Perk.Type.FUNCTIONAL); +// if (!funcTag.isEmpty()) { +// var ids = funcTag.getString("id").split(":"); +// if (ids.length > 1) { +// String id = ids[1]; +// var funcDesComponent = Component.translatable("des.superbwarfare." + id).withStyle(ChatFormatting.GRAY); +// width = Math.max(width, font.width(funcDesComponent)); +// } +// } +// +// CompoundTag damageTag = PerkHelper.getPerkTag(stack, Perk.Type.DAMAGE); +// if (!damageTag.isEmpty()) { +// var ids = damageTag.getString("id").split(":"); +// if (ids.length > 1) { +// String id = ids[1]; +// var damageDesComponent = Component.translatable("des.superbwarfare." + id).withStyle(ChatFormatting.GRAY); +// width = Math.max(width, font.width(damageDesComponent)); +// } +// } + + return width + 25; + } + + @Override + public int getHeight() { + int height = Math.max(20, this.height); + + if (shouldRenderBypassAndHeadshotTooltip()) height += 10; + if (shouldRenderEditTooltip()) height += 20; + if (shouldRenderPerks()) { + if (!Screen.hasShiftDown()) { + height += 16; + } else { + height += 16; +// if (PerkHelper.getPerkByType(stack, Perk.Type.AMMO) != null) { +// height += 25; +// } +// if (PerkHelper.getPerkByType(stack, Perk.Type.FUNCTIONAL) != null) { +// height += 25; +// } +// if (PerkHelper.getPerkByType(stack, Perk.Type.DAMAGE) != null) { +// height += 25; +// } + } + } + + return height; + } + + @Override + public int getWidth(@NotNull Font font) { + if (Screen.hasShiftDown()) { + int width = getMaxPerkDesWidth(font); + return width == 0 ? Math.max(this.width, getDefaultMaxWidth(font)) : Math.max(width, getDefaultMaxWidth(font)); + } else { + return getDefaultMaxWidth(font); + } + } + +} diff --git a/src/main/java/com/atsuishio/superbwarfare/client/tooltip/ClientLauncherImageTooltip.java b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/ClientLauncherImageTooltip.java new file mode 100644 index 000000000..e1bc48e2e --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/ClientLauncherImageTooltip.java @@ -0,0 +1,28 @@ +package com.atsuishio.superbwarfare.client.tooltip; + +import com.atsuishio.superbwarfare.client.tooltip.component.GunImageComponent; +import net.minecraft.network.chat.Component; + +public class ClientLauncherImageTooltip extends ClientGunImageTooltip { + + public ClientLauncherImageTooltip(GunImageComponent tooltip) { + super(tooltip); + } + + @Override + protected Component getDamageComponent() { + // TODO GunInfo +// double damage = GunsTool.getGunDoubleTag(stack, "Damage", 0) * TooltipTool.perkDamage(stack); +// int perkLevel = PerkHelper.getItemPerkLevel(ModPerks.MICRO_MISSILE.get(), stack); +// if (perkLevel > 0) damage *= 1.1f + perkLevel * 0.1f; +// +// double explosionDamage = GunsTool.getGunDoubleTag(stack, "ExplosionDamage", 0); + +// return Component.translatable("des.superbwarfare.guns.damage").withStyle(ChatFormatting.GRAY) +// .append(Component.literal("").withStyle(ChatFormatting.RESET)) +// .append(Component.literal(FormatTool.format1D(damage)).withStyle(ChatFormatting.GREEN) +// .append(Component.literal("").withStyle(ChatFormatting.RESET)) +// .append(Component.literal(" + " + FormatTool.format1D(explosionDamage)).withStyle(ChatFormatting.GOLD))); + return Component.literal(""); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/client/tooltip/ClientSecondaryCataclysmImageTooltip.java b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/ClientSecondaryCataclysmImageTooltip.java new file mode 100644 index 000000000..f4ecd7701 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/ClientSecondaryCataclysmImageTooltip.java @@ -0,0 +1,28 @@ +package com.atsuishio.superbwarfare.client.tooltip; + +import com.atsuishio.superbwarfare.client.tooltip.component.GunImageComponent; +import net.minecraft.network.chat.Component; + +public class ClientSecondaryCataclysmImageTooltip extends ClientEnergyImageTooltip { + + public ClientSecondaryCataclysmImageTooltip(GunImageComponent tooltip) { + super(tooltip); + } + + @Override + protected Component getDamageComponent() { + // TODO GunInfo +// double damage = GunsTool.getGunDoubleTag(stack, "Damage", 0) * TooltipTool.perkDamage(stack); +// int perkLevel = PerkHelper.getItemPerkLevel(ModPerks.MICRO_MISSILE.get(), stack); +// if (perkLevel > 0) damage *= 1.1f + perkLevel * 0.1f; +// +// double explosionDamage = GunsTool.getGunDoubleTag(stack, "ExplosionDamage", 0); +// +// return Component.translatable("des.superbwarfare.guns.damage").withStyle(ChatFormatting.GRAY) +// .append(Component.literal("").withStyle(ChatFormatting.RESET)) +// .append(Component.literal(FormatTool.format1D(damage)).withStyle(ChatFormatting.GREEN) +// .append(Component.literal("").withStyle(ChatFormatting.RESET)) +// .append(Component.literal(" + " + FormatTool.format1D(explosionDamage)).withStyle(ChatFormatting.GOLD))); + return Component.literal(""); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/client/tooltip/ClientSentinelImageTooltip.java b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/ClientSentinelImageTooltip.java new file mode 100644 index 000000000..bdf993986 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/ClientSentinelImageTooltip.java @@ -0,0 +1,37 @@ +package com.atsuishio.superbwarfare.client.tooltip; + +import com.atsuishio.superbwarfare.client.tooltip.component.GunImageComponent; +import net.minecraft.network.chat.Component; +import net.neoforged.neoforge.capabilities.Capabilities; + +public class ClientSentinelImageTooltip extends ClientEnergyImageTooltip { + + public ClientSentinelImageTooltip(GunImageComponent tooltip) { + super(tooltip); + } + + @Override + protected Component getDamageComponent() { + var cap = stack.getCapability(Capabilities.EnergyStorage.ITEM); + + // TODO GunInfo + + if (cap != null && cap.getEnergyStored() > 0) { +// double damage = (GunsTool.getGunDoubleTag(stack, "Damage", 0) + +// GunsTool.getGunDoubleTag(stack, "ChargedDamage", 0)) +// * TooltipTool.perkDamage(stack); +// return Component.translatable("des.superbwarfare.guns.damage").withStyle(ChatFormatting.GRAY) +// .append(Component.literal("").withStyle(ChatFormatting.RESET)) +// .append(Component.literal(FormatTool.format1D(damage) + (TooltipTool.heBullet(stack) ? " + " + +// FormatTool.format1D(0.8 * damage * (1 + 0.1 * TooltipTool.heBulletLevel(stack))) : "")) +// .withStyle(ChatFormatting.AQUA).withStyle(ChatFormatting.BOLD)); + } else { +// double damage = GunsTool.getGunDoubleTag(stack, "Damage", 0) * TooltipTool.perkDamage(stack); +// return Component.translatable("des.superbwarfare.guns.damage").withStyle(ChatFormatting.GRAY) +// .append(Component.literal("").withStyle(ChatFormatting.RESET)) +// .append(Component.literal(FormatTool.format1D(damage) + (TooltipTool.heBullet(stack) ? +// FormatTool.format1D(0.4 * damage * (1 + 0.1 * TooltipTool.heBulletLevel(stack))) : "")).withStyle(ChatFormatting.GREEN)); + } + return Component.literal(""); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/client/tooltip/ClientShotgunImageTooltip.java b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/ClientShotgunImageTooltip.java new file mode 100644 index 000000000..028079adc --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/ClientShotgunImageTooltip.java @@ -0,0 +1,37 @@ +package com.atsuishio.superbwarfare.client.tooltip; + +import com.atsuishio.superbwarfare.client.tooltip.component.GunImageComponent; +import net.minecraft.network.chat.Component; + +public class ClientShotgunImageTooltip extends ClientGunImageTooltip { + + public ClientShotgunImageTooltip(GunImageComponent tooltip) { + super(tooltip); + } + + @Override + protected Component getDamageComponent() { + boolean slug = false; + + // TODO perk +// var perk = PerkHelper.getPerkByType(stack, Perk.Type.AMMO); +// if (perk instanceof AmmoPerk ammoPerk && ammoPerk.slug) { +// slug = true; +// } +// +// if (slug) { +// double damage = GunsTool.getGunDoubleTag(stack, "Damage", 0) * GunsTool.getGunIntTag(stack, "ProjectileAmount", 1) * TooltipTool.perkDamage(stack); +// return Component.translatable("des.superbwarfare.guns.damage").withStyle(ChatFormatting.GRAY) +// .append(Component.literal("").withStyle(ChatFormatting.RESET)) +// .append(Component.literal(FormatTool.format1D(damage) + (TooltipTool.heBullet(stack) ? " + " + +// FormatTool.format1D(0.8 * damage * (1 + 0.1 * TooltipTool.heBulletLevel(stack))) : "")).withStyle(ChatFormatting.GREEN)); +// } else { +// double damage = GunsTool.getGunDoubleTag(stack, "Damage", 0) * TooltipTool.perkDamage(stack); +// return Component.translatable("des.superbwarfare.guns.damage").withStyle(ChatFormatting.GRAY) +// .append(Component.literal("").withStyle(ChatFormatting.RESET)) +// .append(Component.literal(FormatTool.format1D(damage) + " * " + FormatTool.format0D(GunsTool.getGunIntTag(stack, "ProjectileAmount", 1))).withStyle(ChatFormatting.GREEN)); +// } + + return Component.literal(""); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/client/tooltip/TooltipRegistry.java b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/TooltipRegistry.java new file mode 100644 index 000000000..6f5535589 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/TooltipRegistry.java @@ -0,0 +1,33 @@ +package com.atsuishio.superbwarfare.client.tooltip; + +import com.atsuishio.superbwarfare.client.tooltip.component.*; +import net.neoforged.api.distmarker.Dist; +import net.neoforged.bus.api.SubscribeEvent; +import net.neoforged.fml.common.EventBusSubscriber; +import net.neoforged.neoforge.client.event.EntityRenderersEvent; +import net.neoforged.neoforge.client.event.RegisterClientTooltipComponentFactoriesEvent; + +@EventBusSubscriber(bus = EventBusSubscriber.Bus.MOD, value = Dist.CLIENT) +public class TooltipRegistry { + + @SubscribeEvent + public static void registerTooltip(RegisterClientTooltipComponentFactoriesEvent event) { + event.register(GunImageComponent.class, ClientGunImageTooltip::new); + event.register(ShotgunImageComponent.class, ClientShotgunImageTooltip::new); + event.register(BocekImageComponent.class, ClientBocekImageTooltip::new); + event.register(EnergyImageComponent.class, ClientEnergyImageTooltip::new); + event.register(CellImageComponent.class, ClientCellImageTooltip::new); + event.register(SentinelImageComponent.class, ClientSentinelImageTooltip::new); + event.register(LauncherImageComponent.class, ClientLauncherImageTooltip::new); + event.register(SecondaryCataclysmImageComponent.class, ClientSecondaryCataclysmImageTooltip::new); + event.register(ChargingStationImageComponent.class, ClientChargingStationImageTooltip::new); + } + + @SubscribeEvent + public static void registerRenderers(EntityRenderersEvent.RegisterRenderers event) { + // TODO block entity renderer +// event.registerBlockEntityRenderer(ModBlockEntities.CONTAINER.get(), context -> new ContainerBlockEntityRenderer()); +// event.registerBlockEntityRenderer(ModBlockEntities.FUMO_25.get(), context -> new FuMO25BlockEntityRenderer()); +// event.registerBlockEntityRenderer(ModBlockEntities.CHARGING_STATION.get(), context -> new ChargingStationBlockEntityRenderer()); + } +} diff --git a/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/BocekImageComponent.java b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/BocekImageComponent.java new file mode 100644 index 000000000..c21a063be --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/BocekImageComponent.java @@ -0,0 +1,19 @@ +package com.atsuishio.superbwarfare.client.tooltip.component; + +import net.minecraft.world.item.ItemStack; + +public class BocekImageComponent extends GunImageComponent { + + public int width; + public int height; + public ItemStack stack; + + public BocekImageComponent(int width, int height, ItemStack stack) { + super(width, height, stack); + } + + public BocekImageComponent(ItemStack stack) { + this(32, 16, stack); + } + +} \ No newline at end of file diff --git a/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/CellImageComponent.java b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/CellImageComponent.java new file mode 100644 index 000000000..054ab9469 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/CellImageComponent.java @@ -0,0 +1,19 @@ +package com.atsuishio.superbwarfare.client.tooltip.component; + +import net.minecraft.world.item.ItemStack; + +public class CellImageComponent extends GunImageComponent { + + public int width; + public int height; + public ItemStack stack; + + public CellImageComponent(int width, int height, ItemStack stack) { + super(width, height, stack); + } + + public CellImageComponent(ItemStack stack) { + this(32, 16, stack); + } + +} \ No newline at end of file diff --git a/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/ChargingStationImageComponent.java b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/ChargingStationImageComponent.java new file mode 100644 index 000000000..43732a66a --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/ChargingStationImageComponent.java @@ -0,0 +1,18 @@ +package com.atsuishio.superbwarfare.client.tooltip.component; + +import net.minecraft.world.item.ItemStack; + +public class ChargingStationImageComponent extends GunImageComponent { + + public int width; + public int height; + public ItemStack stack; + + public ChargingStationImageComponent(int width, int height, ItemStack stack) { + super(width, height, stack); + } + + public ChargingStationImageComponent(ItemStack stack) { + this(32, 16, stack); + } +} \ No newline at end of file diff --git a/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/EnergyImageComponent.java b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/EnergyImageComponent.java new file mode 100644 index 000000000..60cae7708 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/EnergyImageComponent.java @@ -0,0 +1,19 @@ +package com.atsuishio.superbwarfare.client.tooltip.component; + +import net.minecraft.world.item.ItemStack; + +public class EnergyImageComponent extends GunImageComponent { + + public int width; + public int height; + public ItemStack stack; + + public EnergyImageComponent(int width, int height, ItemStack stack) { + super(width, height, stack); + } + + public EnergyImageComponent(ItemStack stack) { + this(32, 16, stack); + } + +} \ No newline at end of file diff --git a/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/GunImageComponent.java b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/GunImageComponent.java new file mode 100644 index 000000000..3a9477d6c --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/GunImageComponent.java @@ -0,0 +1,22 @@ +package com.atsuishio.superbwarfare.client.tooltip.component; + +import net.minecraft.world.inventory.tooltip.TooltipComponent; +import net.minecraft.world.item.ItemStack; + +public class GunImageComponent implements TooltipComponent { + + public int width; + public int height; + public ItemStack stack; + + public GunImageComponent(int width, int height, ItemStack stack) { + this.width = width; + this.height = height; + this.stack = stack; + } + + public GunImageComponent(ItemStack stack) { + this(32, 16, stack); + } + +} \ No newline at end of file diff --git a/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/LauncherImageComponent.java b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/LauncherImageComponent.java new file mode 100644 index 000000000..5e9bed042 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/LauncherImageComponent.java @@ -0,0 +1,19 @@ +package com.atsuishio.superbwarfare.client.tooltip.component; + +import net.minecraft.world.item.ItemStack; + +public class LauncherImageComponent extends GunImageComponent { + + public int width; + public int height; + public ItemStack stack; + + public LauncherImageComponent(int width, int height, ItemStack stack) { + super(width, height, stack); + } + + public LauncherImageComponent(ItemStack stack) { + this(32, 16, stack); + } + +} \ No newline at end of file diff --git a/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/SecondaryCataclysmImageComponent.java b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/SecondaryCataclysmImageComponent.java new file mode 100644 index 000000000..3c1243f4c --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/SecondaryCataclysmImageComponent.java @@ -0,0 +1,19 @@ +package com.atsuishio.superbwarfare.client.tooltip.component; + +import net.minecraft.world.item.ItemStack; + +public class SecondaryCataclysmImageComponent extends GunImageComponent { + + public int width; + public int height; + public ItemStack stack; + + public SecondaryCataclysmImageComponent(int width, int height, ItemStack stack) { + super(width, height, stack); + } + + public SecondaryCataclysmImageComponent(ItemStack stack) { + this(32, 16, stack); + } + +} \ No newline at end of file diff --git a/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/SentinelImageComponent.java b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/SentinelImageComponent.java new file mode 100644 index 000000000..0d313c0c1 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/SentinelImageComponent.java @@ -0,0 +1,19 @@ +package com.atsuishio.superbwarfare.client.tooltip.component; + +import net.minecraft.world.item.ItemStack; + +public class SentinelImageComponent extends GunImageComponent { + + public int width; + public int height; + public ItemStack stack; + + public SentinelImageComponent(int width, int height, ItemStack stack) { + super(width, height, stack); + } + + public SentinelImageComponent(ItemStack stack) { + this(32, 16, stack); + } + +} \ No newline at end of file diff --git a/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/ShotgunImageComponent.java b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/ShotgunImageComponent.java new file mode 100644 index 000000000..9867b1fb2 --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/client/tooltip/component/ShotgunImageComponent.java @@ -0,0 +1,19 @@ +package com.atsuishio.superbwarfare.client.tooltip.component; + +import net.minecraft.world.item.ItemStack; + +public class ShotgunImageComponent extends GunImageComponent { + + public int width; + public int height; + public ItemStack stack; + + public ShotgunImageComponent(int width, int height, ItemStack stack) { + super(width, height, stack); + } + + public ShotgunImageComponent(ItemStack stack) { + this(32, 16, stack); + } + +} \ No newline at end of file diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModItems.java b/src/main/java/com/atsuishio/superbwarfare/init/ModItems.java index bfbe7eb18..2fabf6a90 100644 --- a/src/main/java/com/atsuishio/superbwarfare/init/ModItems.java +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModItems.java @@ -155,11 +155,11 @@ public class ModItems { public static final DeferredHolder SCHEELITE = ITEMS.register("scheelite", () -> new Item(new Item.Properties())); public static final DeferredHolder RAW_SILVER = ITEMS.register("raw_silver", () -> new Item(new Item.Properties())); // public static final DeferredHolder DOG_TAG = ITEMS.register("dog_tag", DogTag::new); -// public static final DeferredHolder CELL = ITEMS.register("cell", () -> new BatteryItem(24000, new Item.Properties())); -// public static final DeferredHolder BATTERY = ITEMS.register("battery", () -> new BatteryItem(100000, new Item.Properties())); -// public static final DeferredHolder SMALL_BATTERY_PACK = ITEMS.register("small_battery_pack", () -> new BatteryItem(500000, new Item.Properties())); -// public static final DeferredHolder MEDIUM_BATTERY_PACK = ITEMS.register("medium_battery_pack", () -> new BatteryItem(5000000, new Item.Properties())); -// public static final DeferredHolder LARGE_BATTERY_PACK = ITEMS.register("large_battery_pack", () -> new BatteryItem(20000000, new Item.Properties())); + public static final DeferredHolder CELL = ITEMS.register("cell", () -> new BatteryItem(24000, new Item.Properties())); + public static final DeferredHolder BATTERY = ITEMS.register("battery", () -> new BatteryItem(100000, new Item.Properties())); + public static final DeferredHolder SMALL_BATTERY_PACK = ITEMS.register("small_battery_pack", () -> new BatteryItem(500000, new Item.Properties())); + public static final DeferredHolder MEDIUM_BATTERY_PACK = ITEMS.register("medium_battery_pack", () -> new BatteryItem(5000000, new Item.Properties())); + public static final DeferredHolder LARGE_BATTERY_PACK = ITEMS.register("large_battery_pack", () -> new BatteryItem(20000000, new Item.Properties())); // public static final DeferredHolder TRANSCRIPT = ITEMS.register("transcript", Transcript::new); public static final DeferredHolder FIRING_PARAMETERS = ITEMS.register("firing_parameters", FiringParameters::new); @@ -245,7 +245,7 @@ public class ModItems { public static final DeferredHolder DRAGON_TEETH = block(ModBlocks.DRAGON_TEETH); public static final DeferredHolder REFORGING_TABLE = block(ModBlocks.REFORGING_TABLE); public static final DeferredHolder CHARGING_STATION = block(ModBlocks.CHARGING_STATION); - public static final DeferredHolder CREATIVE_CHARGING_STATION = BLOCKS.register("creative_charging_station", CreativeChargingStationBlockItem::new); + public static final DeferredHolder CREATIVE_CHARGING_STATION = BLOCKS.register("creative_charging_station", CreativeChargingStationBlockItem::new); public static final DeferredHolder LEAD_BLOCK = block(ModBlocks.LEAD_BLOCK); public static final DeferredHolder STEEL_BLOCK = block(ModBlocks.STEEL_BLOCK); public static final DeferredHolder TUNGSTEN_BLOCK = block(ModBlocks.TUNGSTEN_BLOCK); diff --git a/src/main/java/com/atsuishio/superbwarfare/init/ModTabs.java b/src/main/java/com/atsuishio/superbwarfare/init/ModTabs.java index 0413e7896..f042e82b5 100644 --- a/src/main/java/com/atsuishio/superbwarfare/init/ModTabs.java +++ b/src/main/java/com/atsuishio/superbwarfare/init/ModTabs.java @@ -1,6 +1,7 @@ package com.atsuishio.superbwarfare.init; import com.atsuishio.superbwarfare.ModUtils; +import com.atsuishio.superbwarfare.item.BatteryItem; import net.minecraft.core.registries.Registries; import net.minecraft.network.chat.Component; import net.minecraft.world.item.CreativeModeTab; @@ -93,7 +94,21 @@ public class ModTabs { () -> CreativeModeTab.builder() .title(Component.translatable("item_group.superbwarfare.item")) .icon(() -> new ItemStack(ModItems.FIRING_PARAMETERS.get())) - .displayItems((param, output) -> ModItems.ITEMS.getEntries().forEach(registryObject -> output.accept(registryObject.get()))) + .displayItems((param, output) -> ModItems.ITEMS.getEntries().forEach(registryObject -> { + // TODO container, armor plate +// if (registryObject.get() == ModItems.CONTAINER.get()) { + if (false) { +// CONTAINER_ENTITIES.stream().map(Supplier::get).forEach(output::accept); + } else { + output.accept(registryObject.get()); +// if (registryObject.get() == ModItems.ARMOR_PLATE.get()) { +// output.accept(ArmorPlate.getInfiniteInstance()); +// } + if (registryObject.get() instanceof BatteryItem batteryItem) { + output.accept(batteryItem.makeFullEnergyStack()); + } + } + })) .build()); public static final DeferredHolder BLOCK_TAB = TABS.register("block", diff --git a/src/main/java/com/atsuishio/superbwarfare/item/BatteryItem.java b/src/main/java/com/atsuishio/superbwarfare/item/BatteryItem.java new file mode 100644 index 000000000..8f421416d --- /dev/null +++ b/src/main/java/com/atsuishio/superbwarfare/item/BatteryItem.java @@ -0,0 +1,58 @@ +package com.atsuishio.superbwarfare.item; + +import com.atsuishio.superbwarfare.client.tooltip.component.CellImageComponent; +import net.minecraft.world.inventory.tooltip.TooltipComponent; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.neoforged.neoforge.capabilities.Capabilities; +import org.jetbrains.annotations.NotNull; + +import java.util.Optional; + +public class BatteryItem extends Item { + + public int maxEnergy; + + public BatteryItem(int maxEnergy, Properties properties) { + super(properties.stacksTo(1)); + this.maxEnergy = maxEnergy; + } + + @Override + public boolean isBarVisible(ItemStack pStack) { + var cap = pStack.getCapability(Capabilities.EnergyStorage.ITEM); + if (cap == null) return false; + return cap.getEnergyStored() != cap.getMaxEnergyStored(); + } + + @Override + public int getBarWidth(ItemStack pStack) { + var energy = 0; + var cap = pStack.getCapability(Capabilities.EnergyStorage.ITEM); + if (cap != null) { + energy = cap.getEnergyStored(); + } + + return Math.round((float) energy * 13.0F / maxEnergy); + } + + @Override + public int getBarColor(@NotNull ItemStack pStack) { + return 0xFFFF00; + } + + @Override + public @NotNull Optional getTooltipImage(@NotNull ItemStack pStack) { + return Optional.of(new CellImageComponent(pStack)); + } + + public ItemStack makeFullEnergyStack() { + ItemStack stack = new ItemStack(this); + var cap = stack.getCapability(Capabilities.EnergyStorage.ITEM); + if (cap == null) return stack; + + cap.receiveEnergy(maxEnergy, false); + return stack; + } + +} diff --git a/src/main/java/com/atsuishio/superbwarfare/item/CreativeChargingStationBlockItem.java b/src/main/java/com/atsuishio/superbwarfare/item/CreativeChargingStationBlockItem.java index 510225555..7b1327144 100644 --- a/src/main/java/com/atsuishio/superbwarfare/item/CreativeChargingStationBlockItem.java +++ b/src/main/java/com/atsuishio/superbwarfare/item/CreativeChargingStationBlockItem.java @@ -1,8 +1,15 @@ package com.atsuishio.superbwarfare.item; +import com.atsuishio.superbwarfare.capability.energy.InfinityEnergyStorage; import com.atsuishio.superbwarfare.init.ModBlocks; +import com.atsuishio.superbwarfare.init.ModItems; import net.minecraft.world.item.BlockItem; +import net.minecraft.world.item.ItemStack; import net.minecraft.world.item.Rarity; +import net.neoforged.neoforge.capabilities.ICapabilityProvider; +import net.neoforged.neoforge.energy.IEnergyStorage; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class CreativeChargingStationBlockItem extends BlockItem { @@ -10,14 +17,15 @@ public class CreativeChargingStationBlockItem extends BlockItem { super(ModBlocks.CREATIVE_CHARGING_STATION.get(), new Properties().rarity(Rarity.EPIC).stacksTo(1)); } - // TODO capability -// @Override -// public ICapabilityProvider initCapabilities(ItemStack stack, CompoundTag tag) { -// return new ICapabilityProvider() { -// @Override -// public @NotNull LazyOptional getCapability(@NotNull Capability cap, @Nullable Direction side) { -// return ForgeCapabilities.ENERGY.orEmpty(cap, LazyOptional.of(InfinityEnergyStorage::new)); -// } -// }; -// } + public static class EnergyStorageProvider implements ICapabilityProvider { + + private final IEnergyStorage energy = new InfinityEnergyStorage(); + + @Override + public @Nullable IEnergyStorage getCapability(@NotNull ItemStack object, Void context) { + if (object.getItem() != ModItems.CREATIVE_CHARGING_STATION.get()) return null; + return energy; + } + } + } diff --git a/src/main/java/com/atsuishio/superbwarfare/menu/ChargingStationMenu.java b/src/main/java/com/atsuishio/superbwarfare/menu/ChargingStationMenu.java index e8a4033c4..31f4c68b0 100644 --- a/src/main/java/com/atsuishio/superbwarfare/menu/ChargingStationMenu.java +++ b/src/main/java/com/atsuishio/superbwarfare/menu/ChargingStationMenu.java @@ -39,6 +39,7 @@ public class ChargingStationMenu extends EnergyMenu { this.addSlot(new Slot(container, 0, 44, 54)); this.addSlot(new ChargingSlot(container, 1, 116, 54)); + this.addDataSlots(containerData); for (int i = 0; i < 3; ++i) { for (int j = 0; j < 9; ++j) { diff --git a/src/main/java/com/atsuishio/superbwarfare/menu/EnergyMenu.java b/src/main/java/com/atsuishio/superbwarfare/menu/EnergyMenu.java index f1d560745..6cb835d2f 100644 --- a/src/main/java/com/atsuishio/superbwarfare/menu/EnergyMenu.java +++ b/src/main/java/com/atsuishio/superbwarfare/menu/EnergyMenu.java @@ -48,12 +48,10 @@ public abstract class EnergyMenu extends AbstractContainerMenu { } public void setData(int id, int data) { + super.setData(id, data); this.containerEnergyDataSlots.get(id).set(data); } - public void setData(int id, long data) { - this.containerEnergyDataSlots.get(id).set(data); - } // @SubscribeEvent // public static void onContainerOpened(PlayerContainerEvent.Open event) { diff --git a/src/main/java/com/atsuishio/superbwarfare/network/dataslot/ContainerEnergyData.java b/src/main/java/com/atsuishio/superbwarfare/network/dataslot/ContainerEnergyData.java index 53abc739d..d32e7b374 100644 --- a/src/main/java/com/atsuishio/superbwarfare/network/dataslot/ContainerEnergyData.java +++ b/src/main/java/com/atsuishio/superbwarfare/network/dataslot/ContainerEnergyData.java @@ -1,10 +1,12 @@ package com.atsuishio.superbwarfare.network.dataslot; -public interface ContainerEnergyData { +import net.minecraft.world.inventory.ContainerData; - long get(int pIndex); +public interface ContainerEnergyData extends ContainerData { - void set(int pIndex, long pValue); + int get(int pIndex); + + void set(int pIndex, int pValue); int getCount(); } diff --git a/src/main/java/com/atsuishio/superbwarfare/network/dataslot/ContainerEnergyDataSlot.java b/src/main/java/com/atsuishio/superbwarfare/network/dataslot/ContainerEnergyDataSlot.java index 6c92fe746..56179f809 100644 --- a/src/main/java/com/atsuishio/superbwarfare/network/dataslot/ContainerEnergyDataSlot.java +++ b/src/main/java/com/atsuishio/superbwarfare/network/dataslot/ContainerEnergyDataSlot.java @@ -5,29 +5,31 @@ package com.atsuishio.superbwarfare.network.dataslot; */ public abstract class ContainerEnergyDataSlot { - private long prevValue; + private int prevValue; public ContainerEnergyDataSlot() { } public static ContainerEnergyDataSlot forContainer(final ContainerEnergyData data, final int index) { return new ContainerEnergyDataSlot() { - public long get() { + public int get() { return data.get(index); } - public void set(long value) { + @Override + public void set(int value) { data.set(index, value); } + }; } - public abstract long get(); + public abstract int get(); - public abstract void set(long value); + public abstract void set(int value); public boolean checkAndClearUpdateFlag() { - long tmp = this.get(); + int tmp = this.get(); boolean changed = tmp != this.prevValue; this.prevValue = tmp; return changed; diff --git a/src/main/java/com/atsuishio/superbwarfare/network/dataslot/SimpleEnergyData.java b/src/main/java/com/atsuishio/superbwarfare/network/dataslot/SimpleEnergyData.java index b48faf85a..f515204ab 100644 --- a/src/main/java/com/atsuishio/superbwarfare/network/dataslot/SimpleEnergyData.java +++ b/src/main/java/com/atsuishio/superbwarfare/network/dataslot/SimpleEnergyData.java @@ -5,19 +5,19 @@ package com.atsuishio.superbwarfare.network.dataslot; */ public class SimpleEnergyData implements ContainerEnergyData { - private final long[] data; + private final int[] data; public SimpleEnergyData(int size) { - this.data = new long[size]; + this.data = new int[size]; } @Override - public long get(int index) { + public int get(int index) { return this.data[index]; } @Override - public void set(int index, long value) { + public void set(int index, int value) { this.data[index] = value; }