Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -85,30 +85,30 @@ public InteractionResult use(BlockState state, Level worldIn, BlockPos pos, Play
}
else {

if (heldItem.is(CNItems.REACTOR_BLUEPRINT.get()) && controllerBlockEntity.inventory.getItem(0).isEmpty()){
if (heldItem.is(CNItems.REACTOR_BLUEPRINT.get()) && controllerBlockEntity.getInventoryObject().getItem(0).isEmpty()){
withBlockEntityDo(worldIn, pos, be -> {
be.inventory.setStackInSlot(0, heldItem);
be.configuredPattern = heldItem;
be.getInventoryObject().setStackInSlot(0, heldItem);
be.setConfiguredPattern(heldItem);

player.setItemInHand(handIn, ItemStack.EMPTY);
});
return InteractionResult.SUCCESS;

}
else if (heldItem.isEmpty() && !controllerBlockEntity.inventory.getItem(0).isEmpty()) {
else if (heldItem.isEmpty() && !controllerBlockEntity.getInventoryObject().getItem(0).isEmpty()) {
withBlockEntityDo(worldIn, pos, be -> {
player.setItemInHand(handIn, be.inventory.getItem(0));
be.inventory.setStackInSlot(0, ItemStack.EMPTY);
be.configuredPattern = ItemStack.EMPTY;
be.total = 0.0;
player.setItemInHand(handIn, be.getInventoryObject().getItem(0));
be.getInventoryObject().setStackInSlot(0, ItemStack.EMPTY);
be.setConfiguredPattern(ItemStack.EMPTY);
be.setTotal(0.0);
be.rotate(be.getBlockState(), be.getLevel(), 0);
be.notifyUpdate();
});
state.setValue(ASSEMBLED, false);
return InteractionResult.SUCCESS;

}
else if (!heldItem.isEmpty() && !controllerBlockEntity.inventory.getItem(0).isEmpty()) {
else if (!heldItem.isEmpty() && !controllerBlockEntity.getInventoryObject().getItem(0).isEmpty()) {
return InteractionResult.PASS;
}
}
Expand All @@ -120,7 +120,7 @@ public void onRemove(BlockState state, Level worldIn, BlockPos pos, BlockState n
if (!state.hasBlockEntity() || state.getBlock() == newState.getBlock())
return;

withBlockEntityDo(worldIn, pos, be -> ItemHelper.dropContents(worldIn, pos, be.inventory));
withBlockEntityDo(worldIn, pos, be -> ItemHelper.dropContents(worldIn, pos, be.getInventoryObject()));
worldIn.removeBlockEntity(pos);

ReactorControllerBlock controller = (ReactorControllerBlock) state.getBlock();
Expand Down Expand Up @@ -173,13 +173,13 @@ public void Verify(BlockState state, BlockPos pos, Level level, List<? extends P
if (create && !entity.isAssembled()) {
player.sendSystemMessage(Component.translatable("reactor.info.assembled.creator"));
level.setBlockAndUpdate(pos, state.setValue(ASSEMBLED, true));
entity.reactorSize = result.data().getSize();
entity.setMultiblockSize(result.data().getSize());
entity.setAssembled(true);

entity.reactorPos = entity.getStructureBounds(pos, entity.reactorSize, entity.reactorFacing);
entity.setMultiblockStructure(entity.getStructureBounds(pos, entity.getMultiblockSize(), entity.getMultiblockFacing()));
// Register existing special blocks (inputs/outputs) so the controller
// detects ReactorInput/ReactorOutput placed before the controller.
FindSpecialBlocksInReactor(entity.reactorPos, entity, level);
FindSpecialBlocksInReactor(entity.getMultiblockPos(), entity, level);
}
}
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import net.minecraftforge.fluids.capability.IFluidHandler;
import net.minecraftforge.items.IItemHandler;
import net.nuclearteam.createnuclear.*;
import net.nuclearteam.createnuclear.api.multiblock.IMultiblockHost;
import net.nuclearteam.createnuclear.content.logistics.BigFluidStack;
import net.nuclearteam.createnuclear.content.multiblock.CNMultiblock;
import net.nuclearteam.createnuclear.content.multiblock.FluidLockManager;
Expand All @@ -37,6 +38,10 @@
import net.nuclearteam.createnuclear.foundation.utility.CreateNuclearLang;
import net.nuclearteam.createnuclear.content.multiblock.pattern.ReactorPattern;
import net.nuclearteam.createnuclear.content.multiblock.reactorLogic.HeatManager;
import net.nuclearteam.createnuclear.content.multiblock.controller.service.IHeatService;
import net.nuclearteam.createnuclear.content.multiblock.controller.service.DefaultHeatService;
import net.nuclearteam.createnuclear.content.multiblock.controller.service.IPersistenceService;
import net.nuclearteam.createnuclear.content.multiblock.controller.service.DefaultPersistenceService;


import java.util.ArrayList;
Expand All @@ -50,47 +55,81 @@ public class ReactorControllerBlockEntity extends SmartBlockEntity implements II
/** The assembled state is stored in the block state (`ReactorControllerBlock.ASSEMBLED`).
* Use the helper accessors below to query or toggle it to keep entity/blockstate consistent.
*/
public int speed = 16; // This is the result speed of the reactor, change this to change the total capacity
// configurable public surface reduced; fields are private and accessible via getters/setters
private int speed = 16; // This is the result speed of the reactor, change this to change the total capacity

public ReactorControllerBlock controller;
protected ReactorPattern pattern = new ReactorPattern();
public ReactorControllerInventory inventory;
public int countUraniumRod;
public int countGraphiteRod;
public int heat;
private ReactorControllerBlock controller;
private final ReactorPattern pattern = new ReactorPattern();
private final ReactorControllerInventory inventory;
private int countUraniumRod;
private int countGraphiteRod;
private int heat;

public double total;
public CompoundTag screen_pattern = new CompoundTag();
public ItemStack configuredPattern;
private double total;
private CompoundTag screen_pattern = new CompoundTag();
private ItemStack configuredPattern;

private BigItemStack bigFuelItem;
private BigItemStack bigCoolerItem;
private List<BigFluidStack> bigFluidStack;

public int reactorSize = 0;
public String reactorFacing = "null";
private int reactorSize = 0;
private String reactorFacing = "null";
// les pos sont [xMin, xMax, yMin, yMax, zMin, zMax]
public int[] reactorPos;
private int[] reactorPos;
private boolean needsToResolveEntities = false;

private final ReactorInputManagerI inputManager;
private final ReactorOutputManagerI outputManager;
private final ReactorInputFluidManagerI inputFluidManager;

HeatManager heatManager = new HeatManager();
// services (dependencies) - abstracted behind interfaces to follow DIP
private final IHeatService heatService;
private final IPersistenceService persistenceService;

// service fields are injected; implementations live in separate classes

// --- Accessors used by external services (persistence) ---
public ReactorControllerInventory getInventoryObject() { return this.inventory; }
public void deserializeInventory(CompoundTag tag) { this.inventory.deserializeNBT(tag); }
public CompoundTag serializeInventory() { return this.inventory.serializeNBT(); }

public ItemStack getConfiguredPattern() { return this.configuredPattern; }
public void setConfiguredPattern(ItemStack stack) { this.configuredPattern = stack; }

public BigItemStack getBigFuelItem() { return this.bigFuelItem; }
public void setBigFuelItem(BigItemStack b) { this.bigFuelItem = b; }
public BigItemStack getBigCoolerItem() { return this.bigCoolerItem; }
public void setBigCoolerItem(BigItemStack b) { this.bigCoolerItem = b; }

public int getMultiblockSize() { return this.reactorSize; }
public void setMultiblockSize(int s) { this.reactorSize = s; }

public String getMultiblockFacing() { return this.reactorFacing; }
public void setMultiblockFacing(String f) { this.reactorFacing = f; }

public int[] getMultiblockPos() { return this.reactorPos; }
public void setMultiblockStructure(int[] p) { this.reactorPos = p; }

public double getTotal() { return this.total; }
public void setTotal(double t) { this.total = t; }

/** Main constructor allowing dependency injection for testability and DIP compliance. */
public ReactorControllerBlockEntity(BlockEntityType<?> type, BlockPos pos, BlockState state) {
super(type, pos, state);
inventory = new ReactorControllerInventory(this);
configuredPattern = ItemStack.EMPTY;
this.inventory = new ReactorControllerInventory(this);
this.configuredPattern = ItemStack.EMPTY;

this.inputManager = new ReactorInputManager();
this.outputManager = new ReactorOutputManager();
this.inputFluidManager = new ReactorInputFluidManager();

inputManager = new ReactorInputManager();
outputManager = new ReactorOutputManager();
inputFluidManager = new ReactorInputFluidManager();
this.bigFuelItem = new BigItemStack(ItemStack.EMPTY);
this.bigCoolerItem = new BigItemStack(ItemStack.EMPTY);
this.bigFluidStack = new ArrayList<>();

bigFuelItem = new BigItemStack(ItemStack.EMPTY);
bigCoolerItem = new BigItemStack(ItemStack.EMPTY);
bigFluidStack = new ArrayList<>();
this.heatService = new DefaultHeatService(new HeatManager());
this.persistenceService = new DefaultPersistenceService();
}

@Override
Expand Down Expand Up @@ -147,27 +186,12 @@ public boolean addToGoggleTooltip(List<Component> tooltip, boolean isPlayerSneak
@Override
protected void read(CompoundTag compound, boolean clientPacket) {
super.read(compound, clientPacket); // Toujours en premier pour les coordonnées de base

// Lecture des Inputs
// delegate managers and persistence
this.inputManager.read(compound);
this.outputManager.read(compound);
this.inputFluidManager.read(compound);

// 1. Tes nouvelles variables simples
this.reactorSize = compound.getInt("reactorSize");
this.reactorFacing = compound.getString("reactorFacing");
this.reactorPos = compound.getIntArray("reactorPose");
this.total = compound.getDouble("total");

// 2. Gestion des items
if (!clientPacket) {
inventory.deserializeNBT(compound.getCompound("pattern"));
}
configuredPattern = ItemStack.of(compound.getCompound("items"));

bigFuelItem = BigItemStack.read(compound.getCompound("bigFuel"));
bigCoolerItem = BigItemStack.read(compound.getCompound("bigCooler"));

this.persistenceService.readBasicState(this, compound, clientPacket);
this.needsToResolveEntities = true;
}

Expand All @@ -178,23 +202,7 @@ protected void write(CompoundTag compound, boolean clientPacket) {
this.outputManager.write(compound);
this.inputFluidManager.write(compound);

// 1. Tes nouvelles variables simples
compound.putInt("reactorSize", this.reactorSize);
compound.putString("reactorFacing", this.reactorFacing);
if (this.reactorPos != null) {
compound.putIntArray("reactorPose", this.reactorPos);
}

compound.putDouble("total", calculateProgress());

// 2. Gestion des items (Ton code existant)
if (!clientPacket) {
compound.put("pattern", inventory.serializeNBT());
}
compound.put("items", configuredPattern.serializeNBT());

compound.put("bigFuel", bigFuelItem.write());
compound.put("bigCooler", bigCoolerItem.write());
this.persistenceService.writeBasicState(this, compound, clientPacket);

}

Expand All @@ -218,8 +226,8 @@ public double calculateProgress() {
countGraphiteRod = configuredPattern.getOrCreateTag().getInt("countGraphiteRod");
countUraniumRod = configuredPattern.getOrCreateTag().getInt("countUraniumRod");

double totalGraphiteRodLife = (double) heatManager.graphiteTimer / countGraphiteRod;
double totalUraniumRodLife = (double) heatManager.uraniumTimer / countUraniumRod;
double totalGraphiteRodLife = (double) heatService.getGraphiteTimer() / Math.max(1, countGraphiteRod);
double totalUraniumRodLife = (double) heatService.getUraniumTimer() / Math.max(1, countUraniumRod);

return totalGraphiteRodLife + totalUraniumRodLife;
}
Expand Down Expand Up @@ -256,66 +264,77 @@ public void tick() {
super.tick();
if (level.isClientSide)
return;

int heat = (int) configuredPattern.getOrCreateTag().getDouble("heat");
countGraphiteRod = configuredPattern.getOrCreateTag().getInt("countGraphiteRod");
countUraniumRod = configuredPattern.getOrCreateTag().getInt("countUraniumRod");
if (needsToResolveEntities) {
List<IItemHandler> handlers = inputManager.getItemHandlers(level);
CreateNuclear.LOGGER.warn("Resolving inputs after load, handlers found: {}", handlers.size());
needsToResolveEntities = false;

resolveEntitiesIfNeeded();

if (!isAssembled()) return;

// gather IO snapshot
VirtualReactorInputsItem virtualReactorInputsItem = inputManager.getInventory(level);
VirtualReactorInputFluid virtualReactorInputFluid = inputFluidManager.getInventory(level);
this.bigFuelItem = virtualReactorInputsItem.getBigFuelRod();
this.bigCoolerItem = virtualReactorInputsItem.getBigCooledRod();
this.bigFluidStack = VirtualReactorInputFluid.toBigList(virtualReactorInputFluid.fluids());

handleAssembledState(heat);
}

// --- extracted sub-steps to keep single responsibility per method ---
private void resolveEntitiesIfNeeded() {
if (!needsToResolveEntities) return;
List<IItemHandler> handlers = inputManager.getItemHandlers(level);
CreateNuclear.LOGGER.warn("Resolving inputs after load, handlers found: {}", handlers.size());
needsToResolveEntities = false;
this.setChanged();
}

private void handleAssembledState(int heat) {
if (!isReadyToRun()) {
updateHeatOnly();
if (!this.outputManager.getBlocksPosition().isEmpty()) rotate(getBlockState(), getLevel(), 0);
this.setChanged();
this.notifyUpdate();
return;
}
if (isAssembled()) {
List<IItemHandler> handlers = inputManager.getItemHandlers(level);
List<IFluidHandler> fluidHandlers = inputFluidManager.getFuildHandlers(level);
VirtualReactorInputsItem virtualReactorInputsItem = inputManager.getInventory(level);
VirtualReactorInputFluid virtualReactorInputFluid = inputFluidManager.getInventory(level);
bigFuelItem = virtualReactorInputsItem.getBigFuelRod();
bigCoolerItem = virtualReactorInputsItem.getBigCooledRod();
bigFluidStack = VirtualReactorInputFluid.toBigList(virtualReactorInputFluid.fluids());

if (!isEmptyConfiguredPattern() && bigFuelItem.count > 0 && bigCoolerItem.count > 0) {
if (this.inputManager.size() > 0) {
this.setChanged();
this.notifyUpdate();
configuredPattern.getOrCreateTag().putDouble("heat", heatManager.calculateHeat(bigFuelItem, bigCoolerItem, countGraphiteRod, countUraniumRod, inventory));
if (!this.outputManager.getBlocksPosition().isEmpty()) {
rotate(getBlockState(), getLevel(), heat);
}

if (updateTimers()) {
boolean extracted = inputManager.extractItems(level, 1, 1);
if (extracted) {
this.setChanged();
this.notifyUpdate();
total = calculateProgress();

if (IHeat.HeatLevel.isNotDanger(heat)) {
//...
} else {
EventTriggerPacket packet = new EventTriggerPacket(600);
CreateNuclear.LOGGER.warn("hum EventTriggerBlock ? {}", packet);
CNPackets.sendToNear(level, getBlockPos(), 32, packet);
}
return;
}
}
// ready to run
this.setChanged();
this.notifyUpdate();

this.setChanged();
this.notifyUpdate();
}
} else {
configuredPattern.getOrCreateTag().putDouble("heat", heatManager.calculateHeat(bigFuelItem, bigCoolerItem, countGraphiteRod, countUraniumRod, inventory));
if (!this.outputManager.getBlocksPosition().isEmpty()) {
rotate(getBlockState(), getLevel(), 0);
}
configuredPattern.getOrCreateTag().putDouble("heat", heatService.calculateHeat(bigFuelItem, bigCoolerItem, countGraphiteRod, countUraniumRod, inventory));
if (!this.outputManager.getBlocksPosition().isEmpty()) {
rotate(getBlockState(), getLevel(), heat);
}

if (updateTimers()) {
boolean extracted = inputManager.extractItems(level, 1, 1);
if (extracted) {
this.setChanged();
this.notifyUpdate();
total = calculateProgress();

if (IHeat.HeatLevel.isNotDanger(heat)) {
// normal
} else {
EventTriggerPacket packet = new EventTriggerPacket(600);
CreateNuclear.LOGGER.warn("hum EventTriggerBlock ? {}", packet);
CNPackets.sendToNear(level, getBlockPos(), 32, packet);
}
}
}
}

private boolean isReadyToRun() {
return !isEmptyConfiguredPattern() && bigFuelItem.count > 0 && bigCoolerItem.count > 0 && this.inputManager.size() > 0;
}

private void updateHeatOnly() {
configuredPattern.getOrCreateTag().putDouble("heat", heatService.calculateHeat(bigFuelItem, bigCoolerItem, countGraphiteRod, countUraniumRod, inventory));
}

private boolean isEmptyConfiguredPattern() {
return configuredPattern.isEmpty() || configuredPattern.getOrCreateTag().isEmpty();
}
Expand Down Expand Up @@ -385,6 +404,7 @@ public void rotate(BlockState state, Level level, int rotation) {
}
}

@Deprecated
public int[] getStructureBounds(BlockPos startPos, int structureSize, String facing) {
int[] northOffsets5x5 = new int[] {-2, 2, -3, 3, 0, 4};
int[] northOffsets7x7 = new int[] {-3, 3, -4, 4, 0, 6};
Expand Down Expand Up @@ -431,6 +451,7 @@ public int[] getStructureBounds(BlockPos startPos, int structureSize, String fac
}
}

@Deprecated
private int[] applyOffset(BlockPos pos, int[] offset) {
int x = pos.getX();
int y = pos.getY();
Expand Down
Loading