diff --git a/src/main/java/gregtech/api/nuclear/fission/FissionReactor.java b/src/main/java/gregtech/api/nuclear/fission/FissionReactor.java index b150f939ca3..6e0a982000e 100644 --- a/src/main/java/gregtech/api/nuclear/fission/FissionReactor.java +++ b/src/main/java/gregtech/api/nuclear/fission/FissionReactor.java @@ -74,7 +74,7 @@ public class FissionReactor { public double coolantBoilingPointStandardPressure; public double coolantHeatOfVaporization; public double coolantBaseTemperature; - public double fuelDepletion; + public double fuelDepletion = 1; public double prevFuelDepletion; public double heatRemoved; public double neutronPoisonAmount; @@ -136,7 +136,11 @@ public void prepareThermalProperties() { for (int i = 0; i < reactorLayout.length; i++) { for (int j = 0; j < reactorLayout[i].length; j++) { - if (reactorLayout[i][j].isValid()) { + /* + * Check for null because the layout + * is in generally not a square + */ + if (reactorLayout[i][j] != null && reactorLayout[i][j].isValid()) { reactorLayout[i][j].setPos(i, j); numberOfComponents++; maxTemperature = Double.min(maxTemperature, reactorLayout[i][j].getMaxTemperature()); @@ -373,6 +377,7 @@ protected double coolantBoilingPoint() { public void updateTemperature() { this.temperature = responseFunctionTemperature(this.maxTemperature, this.temperature, this.power, this.heatRemoved, this.coolantBaseTemperature); + this.heatRemoved = 0; } public void updatePressure() { diff --git a/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java b/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java index 57b4c631dc7..9d2442e1cce 100644 --- a/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java +++ b/src/main/java/gregtech/api/unification/material/materials/FirstDegreeMaterials.java @@ -5,7 +5,6 @@ import gregtech.api.fluids.FluidState; import gregtech.api.fluids.attribute.FluidAttributes; import gregtech.api.fluids.store.FluidStorageKeys; -import gregtech.api.nuclear.fission.FissionReactor; import gregtech.api.unification.material.Material; import gregtech.api.unification.material.properties.BlastProperty.GasTier; import gregtech.api.unification.material.properties.PropertyKey; @@ -1286,7 +1285,6 @@ public static void register() { .liquid(new FluidBuilder().alternativeName("fluidDistWater")) .color(0x4A94FF) .flags(DISABLE_DECOMPOSITION) - .coolantProperty(Steam, HighPressureSteam, 1., 1., 373, 10., FissionReactor.standardPressure) .components(Hydrogen, 2, Oxygen, 1) .build(); diff --git a/src/main/java/gregtech/api/unification/material/materials/MaterialFlagAddition.java b/src/main/java/gregtech/api/unification/material/materials/MaterialFlagAddition.java index 8dbb3b48c6d..85ffd8ae12c 100644 --- a/src/main/java/gregtech/api/unification/material/materials/MaterialFlagAddition.java +++ b/src/main/java/gregtech/api/unification/material/materials/MaterialFlagAddition.java @@ -1,5 +1,7 @@ package gregtech.api.unification.material.materials; +import gregtech.api.nuclear.fission.FissionReactor; +import gregtech.api.unification.material.properties.CoolantProperty; import gregtech.api.unification.material.properties.OreProperty; import gregtech.api.unification.material.properties.PropertyKey; @@ -404,5 +406,13 @@ public static void register() { oreProp = Pyrochlore.getProperty(PropertyKey.ORE); oreProp.setOreByProducts(Apatite, Calcium, Niobium); + + /* + * Coolant property addition + * This sometimes cross-references materials + */ + DistilledWater.setProperty(PropertyKey.COOLANT, + new CoolantProperty(Steam, HighPressureSteam, 1., 1., + 373, 10., FissionReactor.standardPressure)); } } diff --git a/src/main/java/gregtech/common/metatileentities/multi/MetaTileEntityFissionReactor.java b/src/main/java/gregtech/common/metatileentities/multi/MetaTileEntityFissionReactor.java index 9a03dc3631c..783182542bc 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/MetaTileEntityFissionReactor.java +++ b/src/main/java/gregtech/common/metatileentities/multi/MetaTileEntityFissionReactor.java @@ -33,6 +33,7 @@ import gregtech.common.blocks.BlockFissionCasing; import gregtech.common.blocks.MetaBlocks; import gregtech.common.metatileentities.multi.multiblockpart.MetaTileEntityControlRodPort; +import gregtech.common.metatileentities.multi.multiblockpart.MetaTileEntityCoolantExportHatch; import gregtech.common.metatileentities.multi.multiblockpart.MetaTileEntityCoolantImportHatch; import gregtech.common.metatileentities.multi.multiblockpart.MetaTileEntityFuelRodImportHatch; @@ -64,7 +65,7 @@ public class MetaTileEntityFissionReactor extends MultiblockWithDisplayBase impl private int heightBottom; private int height; private int flowRate; - private boolean locked; + private LockingState lockingState = LockingState.UNLOCKED; public MetaTileEntityFissionReactor(ResourceLocation metaTileEntityId) { super(metaTileEntityId); @@ -113,27 +114,33 @@ public int findHeight(boolean top) { protected void updateFormedValid() { // Take in coolant, take in fuel, update reactor, output steam - if (this.locked) { + if (this.lockingState == LockingState.LOCKED) { // Coolant handling for (ICoolantHandler coolantImport : this.getAbilities(MultiblockAbility.IMPORT_COOLANT)) { + // TODO: Move into coolant import hatch this.fissionReactor.heatRemoved += coolantImport.getCoolant().getProperty(PropertyKey.COOLANT) .getCoolingFactor() * this.flowRate; coolantImport.getFluidTank().drain(this.flowRate, true); } for (ICoolantHandler coolantExport : this.getAbilities(MultiblockAbility.EXPORT_COOLANT)) { + // TODO: Move into coolant export hatch coolantExport.getFluidTank().fill(coolantExport.getCoolant().getProperty(PropertyKey.COOLANT) .getHotHPCoolant().getFluid(this.flowRate), true); } // Fuel handling if (this.fissionReactor.fuelDepletion == 1.) { - boolean gotFuel = true; + boolean hasEmpty = false; for (IFuelRodHandler fuelImport : this.getAbilities(MultiblockAbility.IMPORT_FUEL_ROD)) { - gotFuel = fuelImport.getStackHandler().extractItem(0, 1, false).isEmpty(); - if (!gotFuel) break; + if (fuelImport.getStackHandler().extractItem(0, 1, true).isEmpty()) hasEmpty = true; + } + if (!hasEmpty) { + for (IFuelRodHandler fuelImport : this.getAbilities(MultiblockAbility.IMPORT_FUEL_ROD)) { + fuelImport.getStackHandler().extractItem(0, 1, false); + } + this.fissionReactor.fuelDepletion = 0.; } - if (gotFuel) this.fissionReactor.fuelDepletion = 0.; } this.updateReactorState(); @@ -337,12 +344,20 @@ public void checkStructurePattern() { } } + @Override + public void invalidateStructure() { + if (lockingState == LockingState.LOCKED) { + this.unlockAll(); + } + super.invalidateStructure(); + } + @Override public NBTTagCompound writeToNBT(NBTTagCompound data) { data.setInteger("diameter", this.diameter); data.setInteger("heightTop", this.heightTop); data.setInteger("heightBottom", this.heightBottom); - data.setBoolean("locked", this.locked); + data.setBoolean("locked", this.lockingState == LockingState.LOCKED); return super.writeToNBT(data); } @@ -353,7 +368,9 @@ public void readFromNBT(NBTTagCompound data) { this.heightTop = data.getInteger("heightTop"); this.heightBottom = data.getInteger("heightBottom"); this.height = this.heightTop + this.heightBottom + 1; - this.locked = data.getBoolean("locked"); + if (data.getBoolean("locked")) { + this.lockingState = LockingState.SHOULD_LOCK; + } ; } @Override @@ -362,10 +379,10 @@ public void writeInitialSyncData(PacketBuffer buf) { buf.writeInt(this.diameter); buf.writeInt(this.heightTop); buf.writeInt(this.heightBottom); - buf.writeBoolean(this.locked); - if (this.locked) { + if (this.lockingState == LockingState.SHOULD_LOCK) { this.lockAndPrepareReactor(); } + buf.writeBoolean(this.lockingState == LockingState.LOCKED); } @Override @@ -374,16 +391,37 @@ public void receiveInitialSyncData(PacketBuffer buf) { this.diameter = buf.readInt(); this.heightTop = buf.readInt(); this.heightBottom = buf.readInt(); - this.locked = buf.readBoolean(); + if (buf.readBoolean()) { + this.lockingState = LockingState.LOCKED; + } } @Override protected void addDisplayText(List textList) { super.addDisplayText(textList); - ITextComponent toggleText = locked ? - new TextComponentTranslation("gregtech.multiblock.fission_reactor.turn_off") : - new TextComponentTranslation("gregtech.multiblock.fission_reactor.turn_on"); - toggleText.appendSibling(withButton(new TextComponentString(" [Toggle]"), "toggle")); + ITextComponent toggleText = null; + if (!this.isStructureFormed()) + toggleText = new TextComponentTranslation("gregtech.multiblock.fission_reactor.structure_incomplete"); + else { + switch (this.lockingState) { + case LOCKED: + toggleText = new TextComponentTranslation("gregtech.multiblock.fission_reactor.turn_off"); + toggleText.appendSibling(withButton(new TextComponentString(" [Toggle Off]"), "turn_off")); + break; + case UNLOCKED: + toggleText = new TextComponentTranslation("gregtech.multiblock.fission_reactor.turn_on"); + toggleText.appendSibling(withButton(new TextComponentString(" [Toggle On]"), "turn_on")); + break; + case INVALID_COMPONENT: + toggleText = new TextComponentTranslation("gregtech.multiblock.fission_reactor.invalid_component"); + toggleText.appendSibling(withButton(new TextComponentString(" [Retry]"), "turn_on")); + break; + case MISSING_INPUTS: + toggleText = new TextComponentTranslation("gregtech.multiblock.fission_reactor.missing_inputs"); + toggleText.appendSibling(withButton(new TextComponentString(" [Retry]"), "turn_on")); + break; + } + } textList.add(toggleText); } @@ -409,50 +447,59 @@ protected void unlockAll() { for (ILockableHandler handler : this.getAbilities(MultiblockAbility.IMPORT_FUEL_ROD)) { handler.setLock(false); } + this.fissionReactor = null; + this.lockingState = LockingState.UNLOCKED; } @Override protected void handleDisplayClick(String componentData, Widget.ClickData clickData) { super.handleDisplayClick(componentData, clickData); - if (componentData.equals("toggle")) { - this.locked = !this.locked; - if (this.locked) { - lockAndPrepareReactor(); - } else { - this.unlockAll(); - } - } + if (componentData.equals("turn_on")) lockAndPrepareReactor(); + else if (componentData.equals("turn_off")) unlockAll(); } private void lockAndPrepareReactor() { this.lockAll(); fissionReactor = new FissionReactor(this.diameter - 2); - int radius = this.diameter % 2 == 0 ? (int) Math.floor(this.diameter / 2.f) : - Math.round((this.diameter - 1) / 2.f); - radius--; + int radius = (int) this.diameter / 2; // This is the floor of the radius, the actual radius is 0.5 blocks + // larger BlockPos reactorOrigin = this.getPos().offset(this.frontFacing.getOpposite(), radius); - for (int i = -radius; i < radius; i++) { - for (int j = -radius; j < radius; j++) { - if (Math.pow(i, 2) + Math.pow(j, 2) > Math.pow(radius, 2)) + radius--; + for (int i = -radius; i <= radius; i++) { + for (int j = -radius; j <= radius; j++) { + if (Math.pow(i, 2) + Math.pow(j, 2) > Math.pow(radius, 2) + radius) // (radius + .5)^2 = + // radius^2 + radius + .25 continue; BlockPos currentPos = reactorOrigin.offset(this.frontFacing.rotateYCCW(), i) .offset(this.frontFacing.getOpposite(), j).offset(EnumFacing.UP, height - 2); if (getWorld().getTileEntity(currentPos) instanceof IGregTechTileEntity gtTe) { MetaTileEntity mte = gtTe.getMetaTileEntity(); ReactorComponent component = null; + boolean foundPort = true; if (mte instanceof MetaTileEntityCoolantImportHatch coolantIn) { FluidStack containedFluid = coolantIn.getImportFluids().getTankAt(0).getFluid(); if (containedFluid != null) { Material mat = GregTechAPI.materialManager.getMaterial( coolantIn.getImportFluids().getTankAt(0).getFluid().getFluid().getName()); - if (mat != null) component = new CoolantChannel(0, 0, mat); + if (mat != null && mat.hasProperty(PropertyKey.COOLANT)) { + component = new CoolantChannel(0, 0, mat); + coolantIn.setCoolant(mat); + BlockPos exportHatchPos = currentPos.offset(EnumFacing.DOWN, height - 1); + if (getWorld().getTileEntity( + exportHatchPos) instanceof IGregTechTileEntity coolantOutCandidate) { + MetaTileEntity coolantOutMTE = coolantOutCandidate.getMetaTileEntity(); + if (coolantOutMTE instanceof MetaTileEntityCoolantExportHatch coolantOut) { + coolantOut.setCoolant(mat); + } + } + } } } else if (mte instanceof MetaTileEntityFuelRodImportHatch fuelIn) { ItemStack lockedFuel = fuelIn.getImportItems().getStackInSlot(0); if (lockedFuel != null && !lockedFuel.isEmpty()) { MaterialStack mat = OreDictUnifier.getMaterial(lockedFuel); - if (mat != null && OreDictUnifier.getPrefix(lockedFuel) == OrePrefix.dust) { + if (mat != null && OreDictUnifier.getPrefix(lockedFuel) == OrePrefix.fuelRod) { FissionFuelProperty property = mat.material.getProperty(PropertyKey.FISSION_FUEL); if (property != null) component = new FuelRod(0, 1, property, 3); @@ -460,14 +507,32 @@ private void lockAndPrepareReactor() { } } else if (mte instanceof MetaTileEntityControlRodPort controlIn) { component = new ControlRod(0, true, 1, controlIn.getInsertionAmount()); + } else { + foundPort = false; + } + + if (component != null) { + if (component.isValid()) { + fissionReactor.addComponent(component, i + radius, j + radius); + } else { // Invalid component located + this.unlockAll(); + fissionReactor = null; + this.lockingState = LockingState.INVALID_COMPONENT; + return; + } + } else if (foundPort) { // This implies that a port was found, but it didn't generate + // a component because of mismatched inputs + this.unlockAll(); + fissionReactor = null; + this.lockingState = LockingState.MISSING_INPUTS; + return; } - if (component != null) - fissionReactor.addComponent(component, i, j); } } } fissionReactor.prepareThermalProperties(); fissionReactor.computeGeometry(); + this.lockingState = LockingState.LOCKED; } private void updateReactorState() { @@ -476,4 +541,17 @@ private void updateReactorState() { this.fissionReactor.updateNeutronPoisoning(); this.fissionReactor.updatePower(); } + + private enum LockingState { + // The reactor is locked + LOCKED, + // The reactor is unlocked + UNLOCKED, + // The reactor is supposed to be locked, but the locking logic is yet to run + SHOULD_LOCK, + // The reactor can't lock because it is missing inputs + MISSING_INPUTS, + // The reactor can't lock because components are flagged as invalid + INVALID_COMPONENT + } } diff --git a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityCoolantExportHatch.java b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityCoolantExportHatch.java index 23cb38521d9..eea32950feb 100644 --- a/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityCoolantExportHatch.java +++ b/src/main/java/gregtech/common/metatileentities/multi/multiblockpart/MetaTileEntityCoolantExportHatch.java @@ -3,6 +3,7 @@ import gregtech.api.capability.IControllable; import gregtech.api.capability.ICoolantHandler; import gregtech.api.capability.impl.FilteredItemHandler; +import gregtech.api.capability.impl.FluidTankList; import gregtech.api.capability.impl.LockableFluidTank; import gregtech.api.gui.GuiTextures; import gregtech.api.gui.ModularUI; @@ -166,6 +167,12 @@ protected IItemHandlerModifiable createExportItemHandler() { return new ItemStackHandler(1); } + @Override + protected FluidTankList createExportFluidHandler() { + this.fluidTank = new LockableFluidTank(16000, this, true); + return new FluidTankList(false, fluidTank); + } + @Override public void update() { super.update(); diff --git a/src/main/resources/assets/gregtech/lang/en_us.lang b/src/main/resources/assets/gregtech/lang/en_us.lang index 4ef9aeb612b..cf8bfa8749c 100644 --- a/src/main/resources/assets/gregtech/lang/en_us.lang +++ b/src/main/resources/assets/gregtech/lang/en_us.lang @@ -5711,6 +5711,9 @@ gregtech.multiblock.hpca.info_bridging_disabled=Bridging Disabled gregtech.multiblock.fission_reactor.turn_on=Turn on the reactor? (Locks all hatches) gregtech.multiblock.fission_reactor.turn_off=Turn off the reactor? +gregtech.multiblock.fission_reactor.structure_incomplete=Cannot toggle the reactor. The structure is incomplete. +gregtech.multiblock.fission_reactor.invalid_components=Reactor startup failed. Some of the inputs ports are invalid. Please check that channels are aligned with their respective ports. +gregtech.multiblock.fission_reactor.missing_inputs=Reactor startup failed. Some of the inputs ports are empty or have inappropriate contents. Please check the ports. gregtech.command.usage=Usage: /gregtech gregtech.command.worldgen.usage=Usage: /gregtech worldgen