aboutsummaryrefslogtreecommitdiff
path: root/src/main/java/Ic2ExpReactorPlanner/components
diff options
context:
space:
mode:
authorAlkalus <3060479+draknyte1@users.noreply.github.com>2022-01-29 19:15:48 +0000
committerAlkalus <3060479+draknyte1@users.noreply.github.com>2022-01-29 19:15:48 +0000
commitc0da5cc4ea19dfb2a05e64ce09d808b4efdc95b1 (patch)
tree2b549b5dfe3f80421ae2d45e041f929ea46d59aa /src/main/java/Ic2ExpReactorPlanner/components
parentb926dfb3bc67b74b53749a3e420a8a6ce0fba6a7 (diff)
parent0de849179b344dfddc68393aaa23b3b75b307670 (diff)
downloadGT5-Unofficial-c0da5cc4ea19dfb2a05e64ce09d808b4efdc95b1.tar.gz
GT5-Unofficial-c0da5cc4ea19dfb2a05e64ce09d808b4efdc95b1.tar.bz2
GT5-Unofficial-c0da5cc4ea19dfb2a05e64ce09d808b4efdc95b1.zip
Merge branch 'master' of https://github.com/GTNewHorizons/GTplusplus into St00f
# Conflicts: # .gitignore # dependencies.gradle # src/main/java/gtPlusPlus/core/config/ConfigHandler.java # src/main/java/gtPlusPlus/core/item/base/BaseItemComponent.java # src/main/java/gtPlusPlus/xmod/gregtech/common/tileentities/machines/basic/GregtechMetaWirelessCharger.java # src/main/java/gtPlusPlus/xmod/gregtech/common/tileentities/machines/multi/production/GregtechMetaTileEntity_MassFabricator.java # src/main/resources/assets/miscutils/lang/en_US.lang
Diffstat (limited to 'src/main/java/Ic2ExpReactorPlanner/components')
-rw-r--r--src/main/java/Ic2ExpReactorPlanner/components/Condensator.java48
-rw-r--r--src/main/java/Ic2ExpReactorPlanner/components/CoolantCell.java31
-rw-r--r--src/main/java/Ic2ExpReactorPlanner/components/Exchanger.java130
-rw-r--r--src/main/java/Ic2ExpReactorPlanner/components/FuelRod.java166
-rw-r--r--src/main/java/Ic2ExpReactorPlanner/components/Plating.java49
-rw-r--r--src/main/java/Ic2ExpReactorPlanner/components/ReactorItem.java531
-rw-r--r--src/main/java/Ic2ExpReactorPlanner/components/Reflector.java63
-rw-r--r--src/main/java/Ic2ExpReactorPlanner/components/Vent.java110
8 files changed, 1128 insertions, 0 deletions
diff --git a/src/main/java/Ic2ExpReactorPlanner/components/Condensator.java b/src/main/java/Ic2ExpReactorPlanner/components/Condensator.java
new file mode 100644
index 0000000000..d38db4c704
--- /dev/null
+++ b/src/main/java/Ic2ExpReactorPlanner/components/Condensator.java
@@ -0,0 +1,48 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package Ic2ExpReactorPlanner.components;
+
+import gregtech.api.objects.GT_ItemStack;
+
+/**
+ * Represents a condensator in a reactor, either RSH or LZH.
+ * @author Brian McCloud
+ */
+public class Condensator extends ReactorItem {
+
+ public Condensator(final int id, final String baseName, GT_ItemStack aItem, final double maxDamage, final double maxHeat, final String sourceMod) {
+ super(id, baseName, aItem, maxDamage, maxHeat, sourceMod);
+ }
+
+ public Condensator(final Condensator other) {
+ super(other);
+ }
+
+ @Override
+ public double adjustCurrentHeat(final double heat) {
+ if (heat < 0.0) {
+ return heat;
+ }
+ currentCondensatorCooling += heat;
+ bestCondensatorCooling = Math.max(currentCondensatorCooling, bestCondensatorCooling);
+ double acceptedHeat = Math.min(heat, getMaxHeat() - heat);
+ double result = heat - acceptedHeat;
+ currentHeat += acceptedHeat;
+ maxReachedHeat = Math.max(maxReachedHeat, currentHeat);
+ return result;
+ }
+
+ @Override
+ public boolean needsCoolantInjected() {
+ return currentHeat > 0.85 * getMaxHeat();
+ }
+
+ @Override
+ public void injectCoolant() {
+ currentHeat = 0;
+ }
+
+}
diff --git a/src/main/java/Ic2ExpReactorPlanner/components/CoolantCell.java b/src/main/java/Ic2ExpReactorPlanner/components/CoolantCell.java
new file mode 100644
index 0000000000..f152b49985
--- /dev/null
+++ b/src/main/java/Ic2ExpReactorPlanner/components/CoolantCell.java
@@ -0,0 +1,31 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package Ic2ExpReactorPlanner.components;
+
+import gregtech.api.objects.GT_ItemStack;
+
+/**
+ * Represents a coolant cell in a reactor.
+ * @author Brian McCloud
+ */
+public class CoolantCell extends ReactorItem {
+
+ public CoolantCell(final int id, final String baseName, GT_ItemStack aItem, final double maxDamage, final double maxHeat, final String sourceMod) {
+ super(id, baseName, aItem, maxDamage, maxHeat, sourceMod);
+ }
+
+ public CoolantCell(final CoolantCell other) {
+ super(other);
+ }
+
+ @Override
+ public double adjustCurrentHeat(final double heat) {
+ currentCellCooling += heat;
+ bestCellCooling = Math.max(currentCellCooling, bestCellCooling);
+ return super.adjustCurrentHeat(heat);
+ }
+
+}
diff --git a/src/main/java/Ic2ExpReactorPlanner/components/Exchanger.java b/src/main/java/Ic2ExpReactorPlanner/components/Exchanger.java
new file mode 100644
index 0000000000..efb9a826e2
--- /dev/null
+++ b/src/main/java/Ic2ExpReactorPlanner/components/Exchanger.java
@@ -0,0 +1,130 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package Ic2ExpReactorPlanner.components;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import gregtech.api.objects.GT_ItemStack;
+
+/**
+ * Represents a heat exchanger of some sort in a reactor.
+ * @author Brian McCloud
+ */
+public class Exchanger extends ReactorItem {
+
+ private final int switchSide;
+ private final int switchReactor;
+
+ public Exchanger(final int id, final String baseName, GT_ItemStack aItem, final double maxDamage, final double maxHeat, final String sourceMod, final int switchSide, final int switchReactor) {
+ super(id, baseName, aItem, maxDamage, maxHeat, sourceMod);
+ this.switchSide = switchSide;
+ this.switchReactor = switchReactor;
+ }
+
+ public Exchanger(final Exchanger other) {
+ super(other);
+ this.switchSide = other.switchSide;
+ this.switchReactor = other.switchReactor;
+ }
+
+ @Override
+ public void transfer() {
+ List<ReactorItem> heatableNeighbors = new ArrayList<>(4);
+ ReactorItem component = parent.getComponentAt(row, col - 1);
+ if (component != null && component.isHeatAcceptor()) {
+ heatableNeighbors.add(component);
+ }
+ component = parent.getComponentAt(row, col + 1);
+ if (component != null && component.isHeatAcceptor()) {
+ heatableNeighbors.add(component);
+ }
+ component = parent.getComponentAt(row - 1, col);
+ if (component != null && component.isHeatAcceptor()) {
+ heatableNeighbors.add(component);
+ }
+ component = parent.getComponentAt(row + 1, col);
+ if (component != null && component.isHeatAcceptor()) {
+ heatableNeighbors.add(component);
+ }
+ // Code adapted from decompiled IC2 code, class ItemReactorHeatSwitch, with permission from Thunderdark.
+ double myHeat = 0;
+ if (switchSide > 0) {
+ for (ReactorItem heatableNeighbor : heatableNeighbors) {
+ double mymed = getCurrentHeat() * 100.0 / getMaxHeat();
+ double heatablemed = heatableNeighbor.getCurrentHeat() * 100.0 / heatableNeighbor.getMaxHeat();
+
+ double add = (int) (heatableNeighbor.getMaxHeat() / 100.0 * (heatablemed + mymed / 2.0));
+ if (add > switchSide) {
+ add = switchSide;
+ }
+ if (heatablemed + mymed / 2.0 < 1.0) {
+ add = switchSide / 2;
+ }
+ if (heatablemed + mymed / 2.0 < 0.75) {
+ add = switchSide / 4;
+ }
+ if (heatablemed + mymed / 2.0 < 0.5) {
+ add = switchSide / 8;
+ }
+ if (heatablemed + mymed / 2.0 < 0.25) {
+ add = 1;
+ }
+ if (Math.round(heatablemed * 10.0) / 10.0 > Math.round(mymed * 10.0) / 10.0) {
+ add -= 2 * add;
+ } else if (Math.round(heatablemed * 10.0) / 10.0 == Math.round(mymed * 10.0) / 10.0) {
+ add = 0;
+ }
+ myHeat -= add;
+ if (add > 0) {
+ currentComponentHeating += add;
+ }
+ add = heatableNeighbor.adjustCurrentHeat(add);
+ myHeat += add;
+ }
+ }
+ if (switchReactor > 0) {
+ double mymed = getCurrentHeat() * 100.0 / getMaxHeat();
+ double Reactormed = parent.getCurrentHeat() * 100.0 / parent.getMaxHeat();
+
+ int add = (int) Math.round(parent.getMaxHeat() / 100.0 * (Reactormed + mymed / 2.0));
+ if (add > switchReactor) {
+ add = switchReactor;
+ }
+ if (Reactormed + mymed / 2.0 < 1.0) {
+ add = switchSide / 2;
+ }
+ if (Reactormed + mymed / 2.0 < 0.75) {
+ add = switchSide / 4;
+ }
+ if (Reactormed + mymed / 2.0 < 0.5) {
+ add = switchSide / 8;
+ }
+ if (Reactormed + mymed / 2.0 < 0.25) {
+ add = 1;
+ }
+ if (Math.round(Reactormed * 10.0) / 10.0 > Math.round(mymed * 10.0) / 10.0) {
+ add -= 2 * add;
+ } else if (Math.round(Reactormed * 10.0) / 10.0 == Math.round(mymed * 10.0) / 10.0) {
+ add = 0;
+ }
+ myHeat -= add;
+ parent.adjustCurrentHeat(add);
+ if (add > 0) {
+ currentHullHeating = add;
+ } else {
+ currentHullCooling = -add;
+ }
+ }
+ adjustCurrentHeat(myHeat);
+ }
+
+ @Override
+ public double getHullCoolingCapacity() {
+ return switchReactor;
+ }
+
+}
diff --git a/src/main/java/Ic2ExpReactorPlanner/components/FuelRod.java b/src/main/java/Ic2ExpReactorPlanner/components/FuelRod.java
new file mode 100644
index 0000000000..588e221424
--- /dev/null
+++ b/src/main/java/Ic2ExpReactorPlanner/components/FuelRod.java
@@ -0,0 +1,166 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package Ic2ExpReactorPlanner.components;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import gregtech.api.objects.GT_ItemStack;
+
+/**
+ * Represents some form of fuel rod (may be single, dual, or quad).
+ * @author Brian McCloud
+ */
+public class FuelRod extends ReactorItem {
+
+ private final int energyMult;
+ private final double heatMult;
+ private final int rodCount;
+ private final boolean moxStyle;
+
+ private static boolean GT509behavior = false;
+ private static boolean GTNHbehavior = false;
+
+ public static void setGT509Behavior(boolean value) {
+ GT509behavior = value;
+ }
+
+ public static void setGTNHBehavior(boolean value) {
+ GTNHbehavior = value;
+ }
+
+ public FuelRod(final int id, final String baseName, GT_ItemStack aItem, final double maxDamage, final double maxHeat, final String sourceMod,
+ final int energyMult, final double heatMult, final int rodCount, final boolean moxStyle) {
+ super(id, baseName, aItem, maxDamage, maxHeat, sourceMod);
+ this.energyMult = energyMult;
+ this.heatMult = heatMult;
+ this.rodCount = rodCount;
+ this.moxStyle = moxStyle;
+ }
+
+ public FuelRod(final FuelRod other) {
+ super(other);
+ this.energyMult = other.energyMult;
+ this.heatMult = other.heatMult;
+ this.rodCount = other.rodCount;
+ this.moxStyle = other.moxStyle;
+ }
+
+ @Override
+ public boolean isNeutronReflector() {
+ return !isBroken();
+ }
+
+ private int countNeutronNeighbors() {
+ int neutronNeighbors = 0;
+ ReactorItem component = parent.getComponentAt(row + 1, col);
+ if (component != null && component.isNeutronReflector()) {
+ neutronNeighbors++;
+ }
+ component = parent.getComponentAt(row - 1, col);
+ if (component != null && component.isNeutronReflector()) {
+ neutronNeighbors++;
+ }
+ component = parent.getComponentAt(row, col - 1);
+ if (component != null && component.isNeutronReflector()) {
+ neutronNeighbors++;
+ }
+ component = parent.getComponentAt(row, col + 1);
+ if (component != null && component.isNeutronReflector()) {
+ neutronNeighbors++;
+ }
+ return neutronNeighbors;
+ }
+
+ protected void handleHeat(final int heat) {
+ List<ReactorItem> heatableNeighbors = new ArrayList<>(4);
+ ReactorItem component = parent.getComponentAt(row + 1, col);
+ if (component != null && component.isHeatAcceptor()) {
+ heatableNeighbors.add(component);
+ }
+ component = parent.getComponentAt(row - 1, col);
+ if (component != null && component.isHeatAcceptor()) {
+ heatableNeighbors.add(component);
+ }
+ component = parent.getComponentAt(row, col - 1);
+ if (component != null && component.isHeatAcceptor()) {
+ heatableNeighbors.add(component);
+ }
+ component = parent.getComponentAt(row, col + 1);
+ if (component != null && component.isHeatAcceptor()) {
+ heatableNeighbors.add(component);
+ }
+ if (heatableNeighbors.isEmpty()) {
+ parent.adjustCurrentHeat(heat);
+ currentHullHeating = heat;
+ } else {
+ currentComponentHeating = heat;
+ for (ReactorItem heatableNeighbor : heatableNeighbors) {
+ heatableNeighbor.adjustCurrentHeat(heat / heatableNeighbors.size());
+ }
+ int remainderHeat = heat % heatableNeighbors.size();
+ heatableNeighbors.get(0).adjustCurrentHeat(remainderHeat);
+ }
+ }
+
+ @Override
+ public double generateHeat() {
+ int pulses = countNeutronNeighbors() + (rodCount == 1 ? 1 : (rodCount == 2) ? 2 : 3);
+ int heat = (int)(heatMult * pulses * (pulses + 1));
+ if (moxStyle && parent.isFluid() && (parent.getCurrentHeat() / parent.getMaxHeat()) > 0.5) {
+ heat *= 2;
+ }
+ currentHeatGenerated = heat;
+ minHeatGenerated = Math.min(minHeatGenerated, heat);
+ maxHeatGenerated = Math.max(maxHeatGenerated, heat);
+ handleHeat(heat);
+ return currentHeatGenerated;
+ }
+
+ @Override
+ public double generateEnergy() {
+ int pulses = countNeutronNeighbors() + (rodCount == 1 ? 1 : (rodCount == 2) ? 2 : 3);
+ double energy = energyMult * pulses;
+ if (GT509behavior || "GT5".equals(sourceMod)) {
+ energy *= 2;//EUx2 if from GT5.09 or in GT5.09 mode
+ if (moxStyle) {
+ energy *= (1 + 1.5 * parent.getCurrentHeat() / parent.getMaxHeat());
+ }
+ }
+ else if (GTNHbehavior || "GTNH".equals(sourceMod)) {
+ energy *= 10;//EUx10 if from GTNH or in GTNH mode
+ if (moxStyle) {
+ energy *= (1 + 1.5 * parent.getCurrentHeat() / parent.getMaxHeat());
+ }
+ } else if (moxStyle) {
+ energy *= (1 + 4.0 * parent.getCurrentHeat() / parent.getMaxHeat());
+ }
+ minEUGenerated = Math.min(minEUGenerated, energy);
+ maxEUGenerated = Math.max(maxEUGenerated, energy);
+ currentEUGenerated = energy;
+ parent.addEUOutput(energy);
+ applyDamage(1.0);
+ return energy;
+ }
+
+ @Override
+ public int getRodCount() {
+ return rodCount;
+ }
+
+ @Override
+ public double getCurrentOutput() {
+ if (parent != null) {
+ if (parent.isFluid()) {
+ return currentHeatGenerated;
+ } else {
+ return currentEUGenerated;
+ }
+ }
+ return 0;
+ }
+
+}
diff --git a/src/main/java/Ic2ExpReactorPlanner/components/Plating.java b/src/main/java/Ic2ExpReactorPlanner/components/Plating.java
new file mode 100644
index 0000000000..d792e06035
--- /dev/null
+++ b/src/main/java/Ic2ExpReactorPlanner/components/Plating.java
@@ -0,0 +1,49 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package Ic2ExpReactorPlanner.components;
+
+import Ic2ExpReactorPlanner.Reactor;
+import gregtech.api.objects.GT_ItemStack;
+
+/**
+ * Represents some form of plating, which changes how much heat the reactor can
+ * hold before causing external effects (up to and including explosion), as well
+ * as somewhat reducing explosion power.
+ * @author Brian McCloud
+ */
+public class Plating extends ReactorItem {
+
+ private final int heatAdjustment;
+
+ public Plating(final int id, final String baseName, GT_ItemStack aItem, final double maxDamage, final double maxHeat, final String sourceMod, final int heatAdjustment, final double explosionPowerMultiplier) {
+ super(id, baseName, aItem, maxDamage, maxHeat, sourceMod);
+ this.heatAdjustment = heatAdjustment;
+ this.explosionPowerMultiplier = explosionPowerMultiplier;
+ }
+
+ public Plating(Plating other) {
+ super(other);
+ this.heatAdjustment = other.heatAdjustment;
+ this.explosionPowerMultiplier = other.explosionPowerMultiplier;
+ }
+
+ @Override
+ public void addToReactor(final Reactor parent, final int row, final int col) {
+ super.addToReactor(parent, row, col);
+ if (parent != null) {
+ parent.adjustMaxHeat(heatAdjustment);
+ }
+ }
+
+ @Override
+ public void removeFromReactor() {
+ if (parent != null) {
+ parent.adjustMaxHeat(-heatAdjustment);
+ }
+ super.removeFromReactor();
+ }
+
+}
diff --git a/src/main/java/Ic2ExpReactorPlanner/components/ReactorItem.java b/src/main/java/Ic2ExpReactorPlanner/components/ReactorItem.java
new file mode 100644
index 0000000000..9a9b1ce341
--- /dev/null
+++ b/src/main/java/Ic2ExpReactorPlanner/components/ReactorItem.java
@@ -0,0 +1,531 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package Ic2ExpReactorPlanner.components;
+
+import java.util.HashMap;
+import java.util.ResourceBundle;
+
+import Ic2ExpReactorPlanner.Reactor;
+import gregtech.api.objects.GT_ItemStack;
+
+/**
+ * Represents an item (component) in an IndustrialCraft2 Experimental Nuclear
+ * Reactor.
+ *
+ * @author Brian McCloud
+ */
+public class ReactorItem {
+
+ public static HashMap<String, ReactorItem> sComponentMap = new HashMap<String, ReactorItem>();
+ // Fundamental values, set at object instantiation, should never need to be
+ // changed.
+ public final int id;
+ public final String baseName; // this is the non-localized version, for
+ // internal program use
+ public final String name; // this is expected to be localized, for display
+ // usage.
+ protected double maxDamage;
+
+ public double getMaxDamage() {
+ return maxDamage;
+ }
+
+ protected double maxHeat;
+
+ public double getMaxHeat() {
+ return maxHeat;
+ }
+
+ public final String sourceMod; // for potentially adjusting controls based
+ // on whether the mod is in use, will be
+ // null to indicate the item is part of base
+ // IC2.
+ public final GT_ItemStack mItem;
+
+ // Simulation setting values
+ private double initialHeat = 0;
+
+ public double getInitialHeat() {
+ return initialHeat;
+ }
+
+ public void setInitialHeat(final double value) {
+ if (this.isHeatAcceptor() && value >= 0 && value < this.maxHeat) {
+ initialHeat = value;
+ }
+ }
+ private int automationThreshold = 9000;
+
+ public int getAutomationThreshold() {
+ return automationThreshold;
+ }
+
+ public void setAutomationThreshold(final int value) {
+ if (maxHeat > 1 || maxDamage > 1) {
+ automationThreshold = value;
+ }
+ }
+ private int reactorPause = 0;
+
+ public int getReactorPause() {
+ return reactorPause;
+ }
+
+ public void setReactorPause(final int value) {
+ if (maxHeat > 1 || maxDamage > 1) {
+ reactorPause = value;
+ }
+ }
+
+ // fields below here are not to be copied by the copy constructor.
+
+ // Parent reactor and position
+ protected Reactor parent = null;
+ protected int row = -10;
+ protected int col = -10;
+
+ // Special variable for holding information about this item from last
+ // simulation.
+ // Usage of StringBuffer instead of StringBuilder is deliberate - this may
+ // be accessed by
+ // both the simulation worker thread and the event dispatch thread.
+ public final StringBuffer info = new StringBuffer(1000);
+
+ // Calculated values - readable from outside, but only writable by
+ // subclasses.
+ protected double currentDamage = 0;
+ public double getCurrentDamage() {
+ return currentDamage;
+ }
+ protected double currentHeat = 0;
+ public double getCurrentHeat() {
+ return currentHeat;
+ }
+ protected double maxReachedHeat = 0;
+ public double getMaxReachedHeat() {
+ return maxReachedHeat;
+ }
+
+ protected double currentEUGenerated = 0;
+ public double getCurrentEUGenerated() {
+ return currentEUGenerated;
+ }
+ protected double minEUGenerated = Double.MAX_VALUE;
+ public double getMinEUGenerated() {
+ return minEUGenerated;
+ }
+ protected double maxEUGenerated = 0;
+ public double getMaxEUGenerated() {
+ return maxEUGenerated;
+ }
+
+ protected double currentHeatGenerated = 0;
+ public double getCurrentHeatGenerated() {
+ return currentHeatGenerated;
+ }
+ protected double minHeatGenerated = Double.MAX_VALUE;
+ public double getMinHeatGenerated() {
+ return minHeatGenerated;
+ }
+ protected double maxHeatGenerated = 0;
+ public double getMaxHeatGenerated() {
+ return maxHeatGenerated;
+ }
+
+ protected double currentHullHeating = 0;
+ public double getCurrentHullHeating() {
+ return currentHullHeating;
+ }
+ protected double currentComponentHeating = 0;
+ public double getCurrentComponentHeating() {
+ return currentComponentHeating;
+ }
+ protected double currentHullCooling = 0;
+ public double getCurrentHullCooling() {
+ return currentHullCooling;
+ }
+ protected double currentVentCooling = 0;
+ public double getCurrentVentCooling() {
+ return currentVentCooling;
+ }
+ protected double bestVentCooling = 0;
+ public double getBestVentCooling() {
+ return bestVentCooling;
+ }
+
+ protected double currentCellCooling = 0;
+ public double getCurrentCellCooling() {
+ return currentCellCooling;
+ }
+ protected double bestCellCooling = 0;
+ public double getBestCellCooling() {
+ return bestCellCooling;
+ }
+
+ protected double currentCondensatorCooling = 0;
+ public double getCurrentCondensatorCooling() {
+ return currentCondensatorCooling;
+ }
+ protected double bestCondensatorCooling = 0;
+ public double getBestCondensatorCooling() {
+ return bestCondensatorCooling;
+ }
+
+ protected double explosionPowerMultiplier = 1;
+
+ protected ReactorItem(final int id, final String baseName, GT_ItemStack aItem, final double maxDamage, final double maxHeat, String sourceMod) {
+ this.id = id;
+ this.baseName = baseName;
+ this.name = aItem.mItem.getItemStackDisplayName(aItem.toStack());
+ this.mItem = aItem;
+ this.maxDamage = maxDamage;
+ this.maxHeat = maxHeat;
+ if (maxHeat > 1) {
+ automationThreshold = (int) (maxHeat * 0.9);
+ }
+ else if (maxDamage > 1) {
+ automationThreshold = (int) (maxDamage * 1.1);
+ }
+ if (sourceMod == null) {
+ sourceMod = "IC2";
+ }
+ this.sourceMod = sourceMod;
+ sComponentMap.put(sourceMod+"."+aItem.mItem.getUnlocalizedName()+"."+aItem.mMetaData, this);
+ }
+
+ // Protected copy constructor for use by subclasses. Generalized copying
+ // should be done with a method in ComponentFactory (which can check which
+ // subclass copy constructor to use).
+ protected ReactorItem(final ReactorItem other) {
+ this.id = other.id;
+ this.baseName = other.baseName;
+ this.name = other.name;
+ this.mItem = other.mItem;
+ this.maxDamage = other.maxDamage;
+ this.maxHeat = other.maxHeat;
+ this.initialHeat = other.initialHeat;
+ this.automationThreshold = other.automationThreshold;
+ this.reactorPause = other.reactorPause;
+ this.sourceMod = other.sourceMod;
+ }
+
+ /**
+ * Gets the name of the component, and the initial heat (if applicable).
+ *
+ * @return the name of this component, and potentially initial heat.
+ */
+ @Override
+ public String toString() {
+ String result = name;
+ if (initialHeat > 0) {
+ result += String.format("\u0020(initial heat: %,d)", (int) initialHeat);
+ }
+ return result;
+ }
+
+ /**
+ * Checks if this component can accept heat. (e.g. from adjacent fuel rods,
+ * or from an exchanger)
+ *
+ * @return true if this component can accept heat, false otherwise.
+ */
+ public boolean isHeatAcceptor() {
+ // maxHeat of 1 means this component never accepts heat (though it might
+ // take damage instead)
+ return maxHeat > 1 && !isBroken();
+ }
+
+ /**
+ * Determines if this component can be cooled down, such as by a component
+ * heat vent.
+ *
+ * @return true if this component can be cooled down, false otherwise.
+ */
+ public boolean isCoolable() {
+ return maxHeat > 1 && !(this instanceof Condensator);
+ }
+
+ /**
+ * Checks if this component acts as a neutron reflector, and boosts
+ * performance of adjacent fuel rods, either by being a "neutron reflector"
+ * item or by being a fuel rod.
+ *
+ * @return true if this component reflects neutrons, false otherwise.
+ */
+ public boolean isNeutronReflector() {
+ return false;
+ }
+
+ /**
+ * Prepare for a new reactor tick.
+ */
+ public void preReactorTick() {
+ currentHullHeating = 0.0;
+ currentComponentHeating = 0.0;
+ currentHullCooling = 0.0;
+ currentVentCooling = 0.0;
+ currentCellCooling = 0.0;
+ currentCondensatorCooling = 0.0;
+ currentEUGenerated = 0;
+ currentHeatGenerated = 0;
+ }
+
+ /**
+ * Generate heat if appropriate for component type, and spread to reactor or
+ * adjacent cells.
+ *
+ * @return the amount of heat generated by this component.
+ */
+ public double generateHeat() {
+ return 0.0;
+ }
+
+ /**
+ * Generate energy if appropriate for component type.
+ *
+ * @return the number of EU generated by this component during the current
+ * reactor tick.
+ */
+ public double generateEnergy() {
+ return 0.0;
+ }
+
+ /**
+ * Dissipate (aka vent) heat if appropriate for component type.
+ *
+ * @return the amount of heat successfully vented during the current reactor
+ * tick.
+ */
+ public double dissipate() {
+ return 0.0;
+ }
+
+ /**
+ * Transfer heat between component, neighbors, and/or reactor, if
+ * appropriate for component type.
+ */
+ public void transfer() {
+ // do nothing by default.
+ }
+
+ /**
+ * Adds this component to a new reactor, and applies changes to the reactor
+ * when adding this component if appropriate, such as for reactor plating.
+ *
+ * @param parent
+ * the reactor to add this component to.
+ * @param row
+ * the row this component will be in.
+ * @param col
+ * the column this component will be in.
+ */
+ public void addToReactor(final Reactor parent, final int row, final int col) {
+ // call removeFromReactor first, in case it had previously been added to
+ // a different reactor (unlikely)
+ removeFromReactor();
+ this.parent = parent;
+ this.row = row;
+ this.col = col;
+ }
+
+ /**
+ * Removes this component from its reactor (if any), and applies changes to
+ * the reactor when removing this component if appropriate, such as for
+ * reactor plating.
+ */
+ public void removeFromReactor() {
+ parent = null;
+ this.row = -10;
+ this.col = -10;
+ }
+
+ /**
+ * Resets heat to 0 (used when resetting simulation).
+ */
+ public final void clearCurrentHeat() {
+ currentHeat = initialHeat;
+ bestVentCooling = 0.0;
+ bestCondensatorCooling = 0.0;
+ bestCellCooling = 0.0;
+ minEUGenerated = Double.MAX_VALUE;
+ maxEUGenerated = 0.0;
+ minHeatGenerated = Double.MAX_VALUE;
+ maxHeatGenerated = 0.0;
+ maxReachedHeat = initialHeat;
+ }
+
+ /**
+ * Adjusts the component heat up or down
+ *
+ * @param heat
+ * the amount of heat to adjust by (positive to add heat,
+ * negative to remove heat).
+ * @return the amount of heat adjustment refused. (e.g. due to going below
+ * minimum heat, breaking due to excessive heat, or attempting to
+ * remove heat from a condensator)
+ */
+ public double adjustCurrentHeat(final double heat) {
+ if (isHeatAcceptor()) {
+ double result = 0.0;
+ double tempHeat = getCurrentHeat();
+ tempHeat += heat;
+ if (tempHeat > getMaxHeat()) {
+ result = getMaxHeat() - tempHeat + 1;
+ tempHeat = getMaxHeat();
+ }
+ else if (tempHeat < 0.0) {
+ result = tempHeat;
+ tempHeat = 0.0;
+ }
+ currentHeat = tempHeat;
+ maxReachedHeat = Math.max(maxReachedHeat, currentHeat);
+ return result;
+ }
+ return heat;
+ }
+
+ /**
+ * Clears the damage back to 0 (used when resetting simulation, or replacing
+ * the component in an automation simulation).
+ */
+ public final void clearDamage() {
+ currentDamage = 0.0;
+ }
+
+ /**
+ * Applies damage to the component, as opposed to heat. Mainly used for fuel
+ * rods and neutron reflectors that lose durability as the reactor runs, but
+ * can't recover it via cooling.
+ *
+ * @param damage
+ * the damage to apply (only used if positive).
+ */
+ public final void applyDamage(final double damage) {
+ // maxDamage of 1 is treated as meaning the component doesn't accept
+ // damage (though it might accept heat instead)
+ // if someone actually writes a mod with such a flimsy component, I
+ // might have to rethink this.
+ if (maxDamage > 1 && damage > 0.0) {
+ currentDamage += damage;
+ }
+ }
+
+ /**
+ * Determines if this component is broken in the current tick of the
+ * simulation
+ *
+ * @return true if the component has broken either from damage (e.g. neutron
+ * reflectors, fuel rods) or from heat (e.g. heat vents, coolant
+ * cells), false otherwise.
+ */
+ public boolean isBroken() {
+ return currentHeat >= getMaxHeat() || currentDamage >= getMaxDamage();
+ }
+
+ /**
+ * The number of fuel rods in this component (0 for non-fuel-rod
+ * components).
+ *
+ * @return The number of fuel rods in this component, or 0 if this component
+ * has no fuel rods.
+ */
+ public int getRodCount() {
+ return 0;
+ }
+
+ /**
+ * Gets a value added in the formula for calculating explosion power.
+ *
+ * @return the additive value for explosion power caused by this component,
+ * or 0 if this component doesn't affect the addition part of the
+ * explosion calculation.
+ */
+ public double getExplosionPowerOffset() {
+ if (!isBroken()) {
+ if (getRodCount() == 0 && isNeutronReflector()) {
+ return -1;
+ }
+ return 2 * getRodCount(); // all known fuel rods (including those
+ // from GT) use this formula, and
+ // non-rod components return 0 for
+ // getRodCount
+ }
+ return 0;
+ }
+
+ /**
+ * Gets a value multiplied in the formula for calculating explosion power.
+ *
+ * @return the multiplier value for explosion power caused by this
+ * component, or 1 if this component doesn't affect the
+ * multiplication part of the explosion calculation.
+ */
+ public double getExplosionPowerMultiplier() {
+ return explosionPowerMultiplier;
+ }
+
+ /**
+ * Finds the theoretical maximum venting of this component, regardless of
+ * whether this venting is from itself, directly from the reactor, or from
+ * adjacent components.
+ *
+ * @return the capacity of this component to vent heat.
+ */
+ public double getVentCoolingCapacity() {
+ return 0;
+ }
+
+ /**
+ * Finds the theoretical maximum hull cooling of this component.
+ *
+ * @return the capacity of this component to remove heat from the reactor
+ * hull.
+ */
+ public double getHullCoolingCapacity() {
+ return 0;
+ }
+
+ /**
+ * Gets the current "output" of this component, presumably for writing to
+ * CSV data. What this "output" means may vary by component type or reactor
+ * type.
+ *
+ * @return the output of this component for the current reactor tick.
+ */
+ public double getCurrentOutput() {
+ return 0;
+ }
+
+ /**
+ * Determines whether this component expects to produces some sort of output
+ * each reactor tick, e.g. for purposes of tracking in a CSV file.
+ *
+ * @return true if this component produces output (such as EU or vented
+ * heat), false otherwise.
+ */
+ public boolean producesOutput() {
+ return getVentCoolingCapacity() > 0 || getRodCount() > 0;
+ }
+
+ /**
+ * Determines if this component needs input from a Reactor Coolant Injector.
+ * Simply returns false for non-condensator items.
+ *
+ * @return true if this is a condensator that has absorbed enough heat to
+ * require the appropriate item added to repair it, false otherwise.
+ */
+ public boolean needsCoolantInjected() {
+ return false;
+ }
+
+ /**
+ * Simulates having a coolant item added by a Reactor Coolant Injector.
+ */
+ public void injectCoolant() {
+ // do nothing by default.
+ }
+
+}
diff --git a/src/main/java/Ic2ExpReactorPlanner/components/Reflector.java b/src/main/java/Ic2ExpReactorPlanner/components/Reflector.java
new file mode 100644
index 0000000000..7851a62804
--- /dev/null
+++ b/src/main/java/Ic2ExpReactorPlanner/components/Reflector.java
@@ -0,0 +1,63 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package Ic2ExpReactorPlanner.components;
+
+import gregtech.api.objects.GT_ItemStack;
+
+/**
+ * Represents a neutron reflector in a reactor.
+ * @author Brian McCloud
+ */
+public class Reflector extends ReactorItem {
+
+ private static String mcVersion = "1.12.2";
+
+ public Reflector(final int id, final String baseName, final GT_ItemStack aStack, final double maxDamage, final double maxHeat, final String sourceMod) {
+ super(id, baseName, aStack, maxDamage, maxHeat, sourceMod);
+ }
+
+ public Reflector(final Reflector other) {
+ super(other);
+ }
+
+ @Override
+ public boolean isNeutronReflector() {
+ return !isBroken();
+ }
+
+ @Override
+ public double generateHeat() {
+ ReactorItem component = parent.getComponentAt(row - 1, col);
+ if (component != null) {
+ applyDamage(component.getRodCount());
+ }
+ component = parent.getComponentAt(row, col + 1);
+ if (component != null) {
+ applyDamage(component.getRodCount());
+ }
+ component = parent.getComponentAt(row + 1, col);
+ if (component != null) {
+ applyDamage(component.getRodCount());
+ }
+ component = parent.getComponentAt(row, col - 1);
+ if (component != null) {
+ applyDamage(component.getRodCount());
+ }
+ return 0;
+ }
+
+ @Override
+ public double getMaxDamage() {
+ if (maxDamage > 1 && "1.7.10".equals(mcVersion)) {
+ return maxDamage / 3;
+ }
+ return maxDamage;
+ }
+
+ public static void setMcVersion(String newVersion) {
+ mcVersion = newVersion;
+ }
+}
diff --git a/src/main/java/Ic2ExpReactorPlanner/components/Vent.java b/src/main/java/Ic2ExpReactorPlanner/components/Vent.java
new file mode 100644
index 0000000000..a43383f694
--- /dev/null
+++ b/src/main/java/Ic2ExpReactorPlanner/components/Vent.java
@@ -0,0 +1,110 @@
+/*
+ * To change this license header, choose License Headers in Project Properties.
+ * To change this template file, choose Tools | Templates
+ * and open the template in the editor.
+ */
+package Ic2ExpReactorPlanner.components;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import gregtech.api.objects.GT_ItemStack;
+
+/**
+ * Represents some kind of vent in a reactor.
+ * @author Brian McCloud
+ */
+public class Vent extends ReactorItem {
+
+ private final int selfVent;
+ private final int hullDraw;
+ private final int sideVent;
+
+ public Vent(final int id, final String baseName, GT_ItemStack aItem, final double maxDamage, final double maxHeat, final String sourceMod,
+ final int selfVent, final int hullDraw, final int sideVent) {
+ super(id, baseName, aItem, maxDamage, maxHeat, sourceMod);
+ this.selfVent = selfVent;
+ this.hullDraw = hullDraw;
+ this.sideVent = sideVent;
+ }
+
+ public Vent(final Vent other) {
+ super(other);
+ this.selfVent = other.selfVent;
+ this.hullDraw = other.hullDraw;
+ this.sideVent = other.sideVent;
+ }
+
+ @Override
+ public double dissipate() {
+ double deltaHeat = Math.min(hullDraw, parent.getCurrentHeat());
+ currentHullCooling = deltaHeat;
+ parent.adjustCurrentHeat(-deltaHeat);
+ this.adjustCurrentHeat(deltaHeat);
+ final double currentDissipation = Math.min(selfVent, getCurrentHeat());
+ currentVentCooling = currentDissipation;
+ parent.ventHeat(currentDissipation);
+ adjustCurrentHeat(-currentDissipation);
+ if (sideVent > 0) {
+ List<ReactorItem> coolableNeighbors = new ArrayList<>(4);
+ ReactorItem component = parent.getComponentAt(row - 1, col);
+ if (component != null && component.isCoolable()) {
+ coolableNeighbors.add(component);
+ }
+ component = parent.getComponentAt(row, col + 1);
+ if (component != null && component.isCoolable()) {
+ coolableNeighbors.add(component);
+ }
+ component = parent.getComponentAt(row + 1, col);
+ if (component != null && component.isCoolable()) {
+ coolableNeighbors.add(component);
+ }
+ component = parent.getComponentAt(row, col - 1);
+ if (component != null && component.isCoolable()) {
+ coolableNeighbors.add(component);
+ }
+ for (ReactorItem coolableNeighbor : coolableNeighbors) {
+ double rejectedCooling = coolableNeighbor.adjustCurrentHeat(-sideVent);
+ double tempDissipatedHeat = sideVent + rejectedCooling;
+ parent.ventHeat(tempDissipatedHeat);
+ currentVentCooling += tempDissipatedHeat;
+ }
+ }
+ bestVentCooling = Math.max(bestVentCooling, currentVentCooling);
+ return currentDissipation;
+ }
+
+ @Override
+ public double getVentCoolingCapacity() {
+ double result = selfVent;
+ if (sideVent > 0) {
+ ReactorItem component = parent.getComponentAt(row - 1, col);
+ if (component != null && component.isCoolable()) {
+ result += sideVent;
+ }
+ component = parent.getComponentAt(row, col + 1);
+ if (component != null && component.isCoolable()) {
+ result += sideVent;
+ }
+ component = parent.getComponentAt(row + 1, col);
+ if (component != null && component.isCoolable()) {
+ result += sideVent;
+ }
+ component = parent.getComponentAt(row, col - 1);
+ if (component != null && component.isCoolable()) {
+ result += sideVent;
+ }
+ }
+ return result;
+ }
+
+ @Override
+ public double getHullCoolingCapacity() {
+ return hullDraw;
+ }
+
+ @Override
+ public double getCurrentOutput() {
+ return currentVentCooling;
+ }
+ }