From 0a8d5f0d9b6659deeaaf32a98dd6f108261a1256 Mon Sep 17 00:00:00 2001 From: Dimitri Date: Thu, 30 Jul 2026 14:58:11 +0200 Subject: [PATCH] adding the diplay logic in the reactor but still debugging to understand why there is no information with the goggles on --- .../9732d134b83831a56ebe496b16cec71e982962ee | 6 +- .../controller/ReactorControllerBlock.java | 1 + .../ReactorControllerBlockEntity.java | 59 +++++--- .../display/ReactorDisplayState.java | 141 +++++++++++++++++ .../display/ReactorGoggleTooltipRenderer.java | 142 ++++++++++++++++++ .../snapshot/ReactorInputSnapshot.java | 32 ++++ .../snapshot/ReactorInputSnapshotBuilder.java | 49 ++++++ 7 files changed, 409 insertions(+), 21 deletions(-) create mode 100644 src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/display/ReactorDisplayState.java create mode 100644 src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/display/ReactorGoggleTooltipRenderer.java create mode 100644 src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/snapshot/ReactorInputSnapshot.java create mode 100644 src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/snapshot/ReactorInputSnapshotBuilder.java diff --git a/src/generated/resources/.cache/9732d134b83831a56ebe496b16cec71e982962ee b/src/generated/resources/.cache/9732d134b83831a56ebe496b16cec71e982962ee index 3d0ab5a..2ed0364 100644 --- a/src/generated/resources/.cache/9732d134b83831a56ebe496b16cec71e982962ee +++ b/src/generated/resources/.cache/9732d134b83831a56ebe496b16cec71e982962ee @@ -1,4 +1,4 @@ -// 1.21.1 2026-07-28T15:27:40.454156 Registrate Provider for createnuclear [Registries, Data Maps, Recipes, Advancements, Loot Tables, Tags (enchantments), Tags (blocks), Tags (items), Tags (fluids), Tags (entity_types), generic_server_provider, Blockstates, Item models, Lang (en_us/en_ud), generic_client_provider] +// 1.21.1 2026-07-30T13:56:32.1235816 Registrate Provider for createnuclear [Registries, Data Maps, Recipes, Advancements, Loot Tables, Tags (enchantments), Tags (blocks), Tags (items), Tags (fluids), Tags (entity_types), generic_server_provider, Blockstates, Item models, Lang (en_us/en_ud), generic_client_provider] 0b2c76c9cff305eacfdfb57c4b703f94ca6dc903 assets/createnuclear/blockstates/autunite.json 5d06bc544bcbeb7443178d66955bb5101cf696da assets/createnuclear/blockstates/autunite_pillar.json 5b375444ac5057e63776f4991589c57824574b4a assets/createnuclear/blockstates/cut_autunite.json @@ -47,8 +47,8 @@ b9c915389ea6cf8338d20c48e908591f8baa2108 assets/createnuclear/blockstates/small_ 643a4d44b491a84d0d26e1a8944dffc40e83ce14 assets/createnuclear/blockstates/thorium_ore.json de2884054a21315d8b167f64b206be331d388420 assets/createnuclear/blockstates/uranium.json 4557f548df100ae1d05e3b5711797225f6a39673 assets/createnuclear/blockstates/uranium_ore.json -ec0b4fa9b99c97e1812fbf1d2e7c21f17a3cf2ca assets/createnuclear/lang/en_ud.json -d79b3c4818d54f51162b121c29f4ef1d6375131c assets/createnuclear/lang/en_us.json +46428ebfaf97ee42e7922a2fd718d3375dee250a assets/createnuclear/lang/en_ud.json +047f04e738d57d18518c55cc24c9dd94ac149d6c assets/createnuclear/lang/en_us.json a8495d2cd5e38213683becaf1c84b2852f8b06f5 assets/createnuclear/models/block/autunite_natural_0.json 29394a22ee8655dc22ea51563411505fbcfd2dab assets/createnuclear/models/block/autunite_natural_1.json 9e4f83de1ca7a9ab5363f43fc7c3f7f4ec6164d5 assets/createnuclear/models/block/autunite_natural_2.json diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorControllerBlock.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorControllerBlock.java index 0569b00..c96d663 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorControllerBlock.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorControllerBlock.java @@ -36,6 +36,7 @@ @SuppressWarnings("deprecation") public class ReactorControllerBlock extends HorizontalDirectionalReactorBlock implements IWrenchable, IBE { public static final BooleanProperty ASSEMBLED = BooleanProperty.create("assembled"); + public static final BooleanProperty ACTIVE = BooleanProperty.create("active"); public ReactorControllerBlock(Properties properties) { super(properties); diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorControllerBlockEntity.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorControllerBlockEntity.java index cbe4890..da6669b 100644 --- a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorControllerBlockEntity.java +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/ReactorControllerBlockEntity.java @@ -35,7 +35,11 @@ import net.nuclearteam.createnuclear.content.multiblock.IHeat; import net.nuclearteam.createnuclear.content.multiblock.bluePrintItem.PatternData; import net.nuclearteam.createnuclear.content.multiblock.bluePrintItem.ReactorBluePrintData; +import net.nuclearteam.createnuclear.content.multiblock.controller.display.ReactorDisplayState; +import net.nuclearteam.createnuclear.content.multiblock.controller.display.ReactorGoggleTooltipRenderer; import net.nuclearteam.createnuclear.content.multiblock.controller.manager.*; +import net.nuclearteam.createnuclear.content.multiblock.controller.snapshot.ReactorInputSnapshot; +import net.nuclearteam.createnuclear.content.multiblock.controller.snapshot.ReactorInputSnapshotBuilder; import net.nuclearteam.createnuclear.content.multiblock.input.fluid.FluidLockManager; import net.nuclearteam.createnuclear.content.multiblock.input.fluid.PersistentFluidLocks; import net.nuclearteam.createnuclear.content.multiblock.input.fluid.ReactorFluidInputEntity; @@ -146,6 +150,10 @@ public class ReactorControllerBlockEntity extends SmartBlockEntity implements II private final ReactorInputFluidManagerI inputFluidManager; private final ReactorAlarmManagerI alarmManager; + private ReactorDisplayState displayState = ReactorDisplayState.EMPTY; + + //private final IReactorHeatUpdateCoordinator heatCoordinator; + // Client Display Data (Synced via NBT) private Map clientDisplayItems = new HashMap<>(); private List clientDisplayFluids = new ArrayList<>(); @@ -302,6 +310,14 @@ public void setLiquidLife(double l) { this.liquidLife = l; } + public void setDisplayState(ReactorDisplayState state) { + this.displayState = state; + } + + public ReactorDisplayState getDisplayState() { + return this.displayState; + } + /** * Main constructor allowing dependency injection for testability and DIP * compliance. @@ -336,27 +352,14 @@ public boolean getAssembled() { // permet de savoir si le réacteur est formé o @Override public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) { - if(!configuredPattern.isEmpty()) { - CreateLang.translate("gui.gauge.info_header").style(ChatFormatting.GRAY).forGoggles(tooltip); - IHeat.HeatLevel.getName("reactor_controller").style(ChatFormatting.GRAY).forGoggles(tooltip); + CompoundTag patternTag = this.getConfiguredPatternTag(); - IHeat.HeatLevel.getFormattedHeatText(heat).forGoggles(tooltip); - - if (fuelItem.isEmpty()) { - // if rod empty we initialize it at 1 (and display it as 0) to avoid having air item displayed instead of the rod - IHeat.HeatLevel.getFormattedItemText(new ItemStack(CNItems.URANIUM_ROD.asItem(), 1), true).forGoggles(tooltip); - } else { - IHeat.HeatLevel.getFormattedItemText(fuelItem, false).forGoggles(tooltip); - } - - if (fuelItem.isEmpty()) { - // if rod empty we initialize it at 1 (and display it as 0) to avoid having air item displayed instead of the rod - IHeat.HeatLevel.getFormattedItemText(new ItemStack(CNItems.GRAPHITE_ROD.asItem(), 1), true).forGoggles(tooltip); - } else { - IHeat.HeatLevel.getFormattedItemText(coolerItem, false).forGoggles(tooltip); - } + if (patternTag == null || patternTag.isEmpty()) { + return false; } + ReactorGoggleTooltipRenderer.render(tooltip, displayState, patternTag.getInt("heat"), isPlayerSneaking, reactorSize); + return true; } @@ -422,6 +425,22 @@ public enum State { ON, OFF } + private void updateReactorStateVisibility() { + if (level == null || level.isClientSide) return; + + BlockState state = getBlockState(); + if (!(state.getBlock() instanceof ReactorControllerBlock)) return; + + boolean currentActive = state.getValue(ReactorControllerBlock.ACTIVE); + + // The reactor is "ACTIVE" (ON) only if it is assembled AND has the resources required to run + /*boolean targetActive = isAssembled() && heatCoordinator.canRun(getConfiguredPattern(), getDisplayState(), getInputFluidManager(), level, getAssembled()); + + if (currentActive != targetActive) { + level.setBlock(worldPosition, state.setValue(ReactorControllerBlock.ACTIVE, targetActive), 3); + }*/ + } + @Override public void tick() { super.tick(); @@ -481,6 +500,10 @@ public void tick() { return; } } + + ReactorInputSnapshot snapshot = ReactorInputSnapshotBuilder.build(level, inputManager, inputFluidManager); + this.displayState = new ReactorDisplayState(snapshot.items(), snapshot.fluids(), snapshot.maxFluidCapacity()); + this.notifyUpdate(); } } diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/display/ReactorDisplayState.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/display/ReactorDisplayState.java new file mode 100644 index 0000000..69d6e1d --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/display/ReactorDisplayState.java @@ -0,0 +1,141 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.display; + +import net.minecraft.core.HolderLookup; +import net.minecraft.nbt.CompoundTag; +import net.minecraft.nbt.ListTag; +import net.minecraft.nbt.Tag; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; +import net.minecraft.core.registries.BuiltInRegistries; +import net.nuclearteam.createnuclear.content.logistics.BigFluidStack; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +/** + * Immutable snapshot of the data the reactor controller exposes for client-side + * display (e.g. the Goggles tooltip rendered by {@link ReactorGoggleTooltipRenderer}). + *

+ * Instances are produced server-side once per tick from the live input inventories + * and tanks, then synced to the client through the block entity's {@code clientPacket} + * NBT via {@link #serializeNBT(HolderLookup.Provider)} / {@link #deserializeNBT(HolderLookup.Provider, CompoundTag)}. This data is + * transient sync data only: it is not part of the persisted save NBT, so its layout + * can evolve freely without migration concerns. + *

+ * Usage: + *

{@code
+ * // Server side, e.g. in tick():
+ * this.displayState = new ReactorDisplayState(items, fluids, maxFluidCapacity);
+ *
+ * // Writing the client packet:
+ * compound.put("displayState", displayState.serializeNBT());
+ *
+ * // Reading the client packet:
+ * displayState = compound.contains("displayState")
+ *         ? ReactorDisplayState.deserializeNBT(compound.getCompound("displayState"))
+ *         : ReactorDisplayState.EMPTY;
+ * }
+ * + * @param items item rods currently loaded, mapped to their stacked count + * @param fluids fluids currently loaded in the input tanks + * @param maxFluidCapacity combined capacity (in millibuckets) of all input fluid tanks + */ +public record ReactorDisplayState(Map items, List fluids, long maxFluidCapacity) { + static final String COMPONENT_ITEM = "Item"; + static final String COMPONENT_COUNT = "Count"; + static final String COMPONENT_CLIENT_DISPLAY_ITEMS = "clientDisplayItems"; + static final String COMPONENT_CLIENT_DISPLAY_FLUIDS = "clientDisplayFluids"; + static final String COMPONENT_CLIENT_MAX_FLUIDS_CAPACITY = "clientMaxFluidCapacity"; + + /** + * Shared empty instance, used before the first tick has populated any display + * data and as the fallback when the client packet doesn't carry a display state. + */ + public static final ReactorDisplayState EMPTY = new ReactorDisplayState(Map.of(), List.of(), 0); + + /** + * Defensively copies the given collections so the record stays immutable + * regardless of how the caller's collections are mutated afterwards. + */ + public ReactorDisplayState { + items = Map.copyOf(items); + fluids = List.copyOf(fluids); + } + + /** + * Serializes this state into NBT for inclusion in the block entity's + * {@code clientPacket} data. Pair with {@link #deserializeNBT(HolderLookup.Provider, CompoundTag)} + * to restore an equivalent instance on the client. + * @param registries holder lookup provider for serialization + * @return a new {@link CompoundTag} containing the serialized item map, + * fluid list and max fluid capacity + */ + public CompoundTag serializeNBT(HolderLookup.Provider registries) { + CompoundTag compound = new CompoundTag(); + + ListTag displayItemsTag = new ListTag(); + for (Entry entry : items().entrySet()) { + CompoundTag tag = new CompoundTag(); + ResourceLocation rl = BuiltInRegistries.ITEM.getKey(entry.getKey()); + if (rl != null) { + tag.putString(COMPONENT_ITEM, rl.toString()); + } + tag.putInt(COMPONENT_COUNT, entry.getValue()); + displayItemsTag.add(tag); + } + compound.put(COMPONENT_CLIENT_DISPLAY_ITEMS, displayItemsTag); + + ListTag displayFluidsTag = new ListTag(); + for (BigFluidStack stack : fluids()) { + displayFluidsTag.add(stack.write(registries)); + } + compound.put(COMPONENT_CLIENT_DISPLAY_FLUIDS, displayFluidsTag); + + compound.putLong(COMPONENT_CLIENT_MAX_FLUIDS_CAPACITY, maxFluidCapacity()); + + return compound; + } + + /** + * Reconstructs a {@link ReactorDisplayState} from NBT previously produced by + * {@link #serializeNBT(HolderLookup.Provider)}. Acts as a static factory since records cannot be + * mutated in place. + *

+ * Missing keys are treated as empty/zero, so a compound that contains none of + * the expected entries yields an instance equivalent to {@link #EMPTY}. + * + * @param compound the {@code displayState} compound from the client packet + * @return a new immutable {@link ReactorDisplayState} built from the given NBT + */ + public static ReactorDisplayState deserializeNBT(HolderLookup.Provider registries, CompoundTag compound) { + Map items = new HashMap<>(); + if (compound.contains(COMPONENT_CLIENT_DISPLAY_ITEMS)) { + ListTag list = compound.getList(COMPONENT_CLIENT_DISPLAY_ITEMS, Tag.TAG_COMPOUND); + for (int i = 0; i < list.size(); i++) { + CompoundTag tag = list.getCompound(i); + ResourceLocation rl = ResourceLocation.tryParse(tag.getString(COMPONENT_ITEM)); + if (rl != null) { + Item item = BuiltInRegistries.ITEM.get(rl); + if (item != null) { + items.put(item, tag.getInt(COMPONENT_COUNT)); + } + } + } + } + + List fluids = new ArrayList<>(); + if (compound.contains(COMPONENT_CLIENT_DISPLAY_FLUIDS)) { + ListTag list = compound.getList(COMPONENT_CLIENT_DISPLAY_FLUIDS, Tag.TAG_COMPOUND); + for (int i = 0; i < list.size(); i++) { + fluids.add(BigFluidStack.read(registries, list.getCompound(i))); + } + } + + long maxFluidCapacity = compound.getLong(COMPONENT_CLIENT_MAX_FLUIDS_CAPACITY); + + return new ReactorDisplayState(items, fluids, maxFluidCapacity); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/display/ReactorGoggleTooltipRenderer.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/display/ReactorGoggleTooltipRenderer.java new file mode 100644 index 0000000..c677ae5 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/display/ReactorGoggleTooltipRenderer.java @@ -0,0 +1,142 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.display; + +import com.simibubi.create.foundation.item.TooltipHelper; +import com.simibubi.create.foundation.utility.CreateLang; +import net.minecraft.ChatFormatting; +import net.minecraft.network.chat.Component; +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.nuclearteam.createnuclear.content.logistics.BigFluidStack; +import net.nuclearteam.createnuclear.content.multiblock.IHeat; +import net.nuclearteam.createnuclear.foundation.utility.CreateNuclearLang; + +import java.util.List; +import java.util.Map; + +/** + * Builds the Goggles tooltip shown when looking at an assembled reactor controller. + *

+ * This is a stateless presentation helper: it only reads from a + * {@link ReactorDisplayState} snapshot (plus the current heat level) and appends the + * resulting lines to the tooltip. It performs no NBT access, inventory lookups or + * other block-entity-specific logic, keeping the rendering separate from the block + * entity's data/state management. + *

+ * Typical usage from {@code ReactorControllerBlockEntity#addToGoggleTooltip}: + *

{@code
+ * @Override
+ * public boolean addToGoggleTooltip(List tooltip, boolean isPlayerSneaking) {
+ *     CompoundTag patternTag = this.getConfiguredPatternTag();
+ *     if (patternTag == null || patternTag.isEmpty()) {
+ *         return false;
+ *     }
+ *     ReactorGoggleTooltipRenderer.render(tooltip, displayState, patternTag.getInt("heat"), isPlayerSneaking);
+ *     return true;
+ * }
+ * }
+ */ +public final class ReactorGoggleTooltipRenderer { + private ReactorGoggleTooltipRenderer() {} + + /** + * Appends the reactor controller's Goggles tooltip lines to {@code tooltip}. + *

+ * Renders, in order: the gauge info header, the reactor heat level, the loaded + * item rods (or a placeholder if none), and the loaded fluids with their fill + * ratio as a progress bar (or a placeholder if none). + * + * @param tooltip the tooltip line list to append to + * @param state the current display snapshot (items, fluids, max fluid capacity) + * @param heat the reactor's current heat value, used to render the heat tooltip line + * @param isPlayerSneaking whether the viewing player is sneaking (currently unused, + * kept for signature parity with other goggle tooltip providers) + */ + public static void render(List tooltip, ReactorDisplayState state, int heat, boolean isPlayerSneaking, int reactorSize) { + renderHeaderAndHeat(tooltip, heat, reactorSize); + renderItemRods(tooltip, state); + renderFluidTanks(tooltip, state); + } + + /** + * Appends the gauge info header and the reactor's current heat level line. + * + * @param tooltip the tooltip line list to append to + * @param heat the reactor's current heat value + */ + private static void renderHeaderAndHeat(List tooltip, int heat, int reactorSize) { + CreateLang.translate("gui.gauge.info_header") + .style(ChatFormatting.GRAY) + .forGoggles(tooltip); + IHeat.HeatLevel.getName("reactor_controller").style(ChatFormatting.GRAY).forGoggles(tooltip); + + IHeat.HeatLevel.getFormattedHeatText(heat/*, reactorSize*/).forGoggles(tooltip); + } + + /** + * Appends one line per loaded item rod with its stacked count, or a placeholder + * line showing a count of 0 if no rods are loaded. + * + * @param tooltip the tooltip line list to append to + * @param state the current display snapshot + */ + private static void renderItemRods(List tooltip, ReactorDisplayState state) { + if (state.items().isEmpty()) { + CreateNuclearLang.builder() + .add(Component.translatable("createnuclear.tooltip.item.empty.rod").withStyle(ChatFormatting.GRAY)) + .add(CreateNuclearLang.number(0).style(ChatFormatting.GOLD)) + .forGoggles(tooltip); + } else { + for (Map.Entry entry : state.items().entrySet()) { + ItemStack stack = new ItemStack(entry.getKey()); + int count = entry.getValue(); + CreateNuclearLang.itemName(stack) + .style(ChatFormatting.GRAY) + .text(": ") + .add(CreateNuclearLang.number(count).style(ChatFormatting.GOLD)) + .forGoggles(tooltip); + } + } + } + + /** + * Appends one line per loaded fluid with a fill-ratio progress bar relative to + * {@link ReactorDisplayState#maxFluidCapacity()}, or a "no fluid" placeholder + * with an empty progress bar if no fluids are loaded. + * + * @param tooltip the tooltip line list to append to + * @param state the current display snapshot + */ + private static void renderFluidTanks(List tooltip, ReactorDisplayState state) { + if (state.fluids().isEmpty()) { + CreateNuclearLang.translate("tooltip.fluid.none") + .style(ChatFormatting.GRAY) + .forGoggles(tooltip); + + CreateNuclearLang.builder() + .text(TooltipHelper.makeProgressBar(5, 0)) + .style(ChatFormatting.BLUE) + .space() + .text("0%") + .forGoggles(tooltip); + } else { + long maxCapacity = state.maxFluidCapacity(); + for (BigFluidStack stack : state.fluids()) { + float fillRatio = maxCapacity > 0 ? (float) stack.amount / maxCapacity : 0; + if (fillRatio >= 0.99f) + fillRatio = 1.0f; + int filledBars = Math.round(fillRatio * 5); + + CreateNuclearLang.translate("tooltip.fluid", stack.stack.getHoverName()) + .style(ChatFormatting.GRAY) + .forGoggles(tooltip); + + CreateNuclearLang.builder() + .text(TooltipHelper.makeProgressBar(5, filledBars)) + .style(ChatFormatting.BLUE) + .space() + .text(Math.round(fillRatio * 100) + "%") + .forGoggles(tooltip); + } + } + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/snapshot/ReactorInputSnapshot.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/snapshot/ReactorInputSnapshot.java new file mode 100644 index 0000000..b9e5575 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/snapshot/ReactorInputSnapshot.java @@ -0,0 +1,32 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.snapshot; + +import net.minecraft.world.item.Item; +import net.nuclearteam.createnuclear.content.logistics.BigFluidStack; + +import java.util.List; +import java.util.Map; + +/** + * Snapshot of the reactor's inputs, collected once per tick. + *

+ * {@code items} reflects the items actually present (for tooltip display). + * {@code bigFuelItem}/{@code bigCoolerItem} are derived from + * {@link net.nuclearteam.createnuclear.content.multiblock.input.item.VirtualReactorInputsItem} and always represent, respectively, + * Uranium Rod / Graphite Rod (generic tag-based count, fixed identity) — + * do not use these fields to infer the actual item type loaded. + *

+ * The elements of {@code fluids} ({@link BigFluidStack}) remain mutable + * (public fields); this snapshot only guarantees immutability of the + * list/map structure, not of their contents. + */ + +public record ReactorInputSnapshot(Map items, List fluids, long maxFluidCapacity) { + public static final ReactorInputSnapshot EMPTY = new ReactorInputSnapshot( + Map.of(), List.of(), 0 + ); + + public ReactorInputSnapshot { + items = Map.copyOf(items); + fluids = List.copyOf(fluids); + } +} diff --git a/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/snapshot/ReactorInputSnapshotBuilder.java b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/snapshot/ReactorInputSnapshotBuilder.java new file mode 100644 index 0000000..9396e27 --- /dev/null +++ b/src/main/java/net/nuclearteam/createnuclear/content/multiblock/controller/snapshot/ReactorInputSnapshotBuilder.java @@ -0,0 +1,49 @@ +package net.nuclearteam.createnuclear.content.multiblock.controller.snapshot; + +import net.minecraft.world.item.Item; +import net.minecraft.world.item.ItemStack; +import net.minecraft.world.level.Level; +import net.neoforged.neoforge.fluids.capability.IFluidHandler; +import net.neoforged.neoforge.items.IItemHandler; +import net.nuclearteam.createnuclear.content.logistics.BigFluidStack; +import net.nuclearteam.createnuclear.content.multiblock.controller.manager.ReactorInputFluidManagerI; +import net.nuclearteam.createnuclear.content.multiblock.controller.manager.ReactorInputManagerI; +import net.nuclearteam.createnuclear.content.multiblock.input.fluid.VirtualReactorInputFluid; +import net.nuclearteam.createnuclear.content.multiblock.input.item.VirtualReactorInputsItem; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class ReactorInputSnapshotBuilder { + private ReactorInputSnapshotBuilder() {} + + public static ReactorInputSnapshot build(Level level, ReactorInputManagerI inputManager, ReactorInputFluidManagerI inputFluidManager) { + // Populate display fields for client sync + Map items = new HashMap<>(); + List itemHandlers = inputManager.getItemHandlers(level); + for (IItemHandler h : itemHandlers) { + for (int s = 0; s < h.getSlots(); s++) { + ItemStack st = h.getStackInSlot(s); + if (!st.isEmpty()) { + items.merge(st.getItem(), st.getCount(), Integer::sum); + } + } + } + + long maxFluidCapacity = 0; + for (IFluidHandler h : inputFluidManager.getFuildHandlers(level)) { + if (h.getTanks() > 0) { + maxFluidCapacity += h.getTankCapacity(0); + } + } + + VirtualReactorInputsItem virtualItems = inputManager.getInventory(level); + VirtualReactorInputFluid virtualFluid = inputFluidManager.getInventory(level); + List fluids = VirtualReactorInputFluid.toBigList(virtualFluid.fluids()); + + + + return new ReactorInputSnapshot(items, fluids, maxFluidCapacity); + } +}