mirror of
https://github.com/HbmMods/Hbm-s-Nuclear-Tech-GIT.git
synced 2026-01-25 10:32:49 +00:00
481 lines
16 KiB
Java
481 lines
16 KiB
Java
package com.hbm.items.machine;
|
|
|
|
import java.util.List;
|
|
|
|
import com.hbm.interfaces.IItemHazard;
|
|
import com.hbm.items.ModItems;
|
|
import com.hbm.main.MainRegistry;
|
|
import com.hbm.modules.ItemHazardModule;
|
|
import com.hbm.tileentity.machine.rbmk.IRBMKFluxReceiver.NType;
|
|
import com.hbm.tileentity.machine.rbmk.RBMKDials;
|
|
import com.hbm.util.I18nUtil;
|
|
|
|
import net.minecraft.entity.Entity;
|
|
import net.minecraft.entity.EntityLivingBase;
|
|
import net.minecraft.entity.item.EntityItem;
|
|
import net.minecraft.entity.player.EntityPlayer;
|
|
import net.minecraft.item.Item;
|
|
import net.minecraft.item.ItemStack;
|
|
import net.minecraft.nbt.NBTTagCompound;
|
|
import net.minecraft.util.EnumChatFormatting;
|
|
import net.minecraft.world.World;
|
|
|
|
public class ItemRBMKRod extends Item implements IItemHazard {
|
|
|
|
public ItemRBMKPellet pellet;
|
|
public String fullName = ""; //full name of the fuel rod
|
|
public double reactivity; //endpoint of the function
|
|
public double selfRate; //self-inflicted flux from self-igniting fuels
|
|
public EnumBurnFunc function = EnumBurnFunc.LOG_TEN;
|
|
public double xGen = 0.5D; //multiplier for xenon production
|
|
public double xBurn = 50D; //divider for xenon burnup
|
|
public double heat = 1D; //heat produced per outFlux
|
|
public double yield; //total potential inFlux the rod can take in its lifetime
|
|
public double meltingPoint = 1000D; //the maximum heat of the rod's hull before shit hits the fan. the core can be as hot as it wants to be
|
|
public double diffusion = 0.02D; //the speed at which the core heats the hull
|
|
public NType nType = NType.SLOW; //neutronType, the most efficient neutron type for fission
|
|
public NType rType = NType.FAST; //releaseType, the type of neutrons released by this fuel
|
|
|
|
/* _____
|
|
* ,I I I I,
|
|
* |'-----'|
|
|
* | |
|
|
* '-----'
|
|
* I I I I
|
|
* I I I I
|
|
* I I I I
|
|
* I I I I
|
|
* I I I I
|
|
* I I I I
|
|
* ,I I I I,
|
|
* |'-----'|
|
|
* | |
|
|
* '-----'
|
|
* I I I I
|
|
*
|
|
* i drew a fuel rod yay
|
|
*/
|
|
|
|
public ItemRBMKRod(ItemRBMKPellet pellet) {
|
|
this(pellet.fullName);
|
|
this.pellet = pellet;
|
|
}
|
|
|
|
public ItemRBMKRod(String fullName) {
|
|
this.module = new ItemHazardModule();
|
|
|
|
this.fullName = fullName;
|
|
|
|
this.setContainerItem(ModItems.rbmk_fuel_empty);
|
|
this.setMaxStackSize(1);
|
|
this.setCreativeTab(MainRegistry.controlTab);
|
|
}
|
|
|
|
public ItemRBMKRod setYield(double yield) {
|
|
this.yield = yield;
|
|
return this;
|
|
}
|
|
|
|
public ItemRBMKRod setStats(double funcEnd) {
|
|
return setStats(funcEnd, 0);
|
|
}
|
|
|
|
public ItemRBMKRod setStats(double funcEnd, double selfRate) {
|
|
this.reactivity = funcEnd;
|
|
this.selfRate = selfRate;
|
|
return this;
|
|
}
|
|
|
|
public ItemRBMKRod setFunction(EnumBurnFunc func) {
|
|
this.function = func;
|
|
return this;
|
|
}
|
|
|
|
public ItemRBMKRod setHeat(double heat) {
|
|
this.heat = heat;
|
|
return this;
|
|
}
|
|
|
|
public ItemRBMKRod setDiffusion(double diffusion) {
|
|
this.diffusion = diffusion;
|
|
return this;
|
|
}
|
|
|
|
public ItemRBMKRod setMeltingPoint(double meltingPoint) {
|
|
this.meltingPoint = meltingPoint;
|
|
return this;
|
|
}
|
|
|
|
public ItemRBMKRod setNeutronTypes(NType nType, NType rType) {
|
|
this.nType = nType;
|
|
this.rType = rType;
|
|
return this;
|
|
}
|
|
|
|
/**
|
|
* Adjusts the input flux using the poison level
|
|
* Generates, then burns poison
|
|
* Calculates the outflux based on influx, enrichment and poison
|
|
* Depletes the yield, then returns the outflux
|
|
* @param stack
|
|
* @param inFlux
|
|
* @return outFlux
|
|
*/
|
|
public double burn(World world, ItemStack stack, double inFlux) {
|
|
|
|
inFlux += selfRate;
|
|
|
|
double xenon = getPoison(stack);
|
|
xenon -= xenonBurnFunc(inFlux);
|
|
|
|
inFlux *= (1D - getPoisonLevel(stack));
|
|
|
|
xenon += xenonGenFunc(inFlux);
|
|
|
|
if(xenon < 0D) xenon = 0D;
|
|
if(xenon > 100D) xenon = 100D;
|
|
|
|
setPoison(stack, xenon);
|
|
|
|
double outFlux = reactivityFunc(inFlux, getEnrichment(stack)) * RBMKDials.getReactivityMod(world);
|
|
|
|
double y = getYield(stack);
|
|
y -= inFlux;
|
|
|
|
if(y < 0D) y = 0D;
|
|
|
|
setYield(stack, y);
|
|
|
|
double coreHeat = this.getCoreHeat(stack);
|
|
coreHeat += outFlux * heat;
|
|
this.setCoreHeat(stack, coreHeat);
|
|
|
|
return outFlux;
|
|
}
|
|
|
|
/**
|
|
* Heat up the core based on the outFlux, then move some heat to the hull
|
|
* @param stack
|
|
*/
|
|
public void updateHeat(World world, ItemStack stack, double mod) {
|
|
|
|
double coreHeat = this.getCoreHeat(stack);
|
|
double hullHeat = this.getHullHeat(stack);
|
|
|
|
if(coreHeat > hullHeat) {
|
|
|
|
double mid = (coreHeat - hullHeat) / 2D;
|
|
|
|
coreHeat -= mid * this.diffusion * RBMKDials.getFuelDiffusionMod(world) * mod;
|
|
hullHeat += mid * this.diffusion * RBMKDials.getFuelDiffusionMod(world) * mod;
|
|
|
|
this.setCoreHeat(stack, coreHeat);
|
|
this.setHullHeat(stack, hullHeat);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* return one tick's worth of heat and cool the hull of the fuel rod, this heat goes into the fuel rod assembly block
|
|
* @param stack
|
|
* @return
|
|
*/
|
|
public double provideHeat(World world, ItemStack stack, double heat, double mod) {
|
|
|
|
double hullHeat = this.getHullHeat(stack);
|
|
|
|
//metldown! the hull melts so the entire structure stops making sense
|
|
//hull and core heats are instantly equalized into 33% of their sum each,
|
|
//the rest is sent to the component which is always fatal
|
|
if(hullHeat > this.meltingPoint) {
|
|
double coreHeat = this.getCoreHeat(stack);
|
|
double avg = (heat + hullHeat + coreHeat) / 3D;
|
|
this.setCoreHeat(stack, avg);
|
|
this.setHullHeat(stack, avg);
|
|
return avg;
|
|
}
|
|
|
|
if(hullHeat <= heat)
|
|
return 0;
|
|
|
|
double ret = (hullHeat - heat) / 2;
|
|
|
|
ret *= RBMKDials.getFuelHeatProvision(world) * mod;
|
|
|
|
hullHeat -= ret;
|
|
this.setHullHeat(stack, hullHeat);
|
|
|
|
return ret;
|
|
}
|
|
|
|
public static enum EnumBurnFunc {
|
|
PASSIVE(EnumChatFormatting.DARK_GREEN + "SAFE / PASSIVE"), //const, no reactivity
|
|
LOG_TEN(EnumChatFormatting.YELLOW + "MEDIUM / LOGARITHMIC"), //log10(x + 1) * reactivity * 50
|
|
PLATEU(EnumChatFormatting.GREEN + "SAFE / EULER"), //(1 - e^(-x/25)) * reactivity * 100
|
|
ARCH(EnumChatFormatting.YELLOW + "MEDIUM / NEGATIVE-QUADRATIC"), //x-(x²/1000) * reactivity
|
|
SIGMOID(EnumChatFormatting.GREEN + "SAFE / SIGMOID"), //100 / (1 + e^(-(x - 50) / 10)) <- tiny amount of reactivity at x=0 !
|
|
SQUARE_ROOT(EnumChatFormatting.YELLOW + "MEDIUM / SQUARE ROOT"), //sqrt(x) * 10 * reactivity
|
|
LINEAR(EnumChatFormatting.RED + "DANGEROUS / LINEAR"), //x * reactivity
|
|
QUADRATIC(EnumChatFormatting.RED + "DANGEROUS / QUADRATIC"); //x^2 / 100 * reactivity
|
|
|
|
public String title = "";
|
|
|
|
private EnumBurnFunc(String title) {
|
|
this.title = title;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param flux [0;100] ...or at least those are sane levels
|
|
* @return the amount of reactivity yielded, unmodified by xenon
|
|
*/
|
|
public double reactivityFunc(double in, double enrichment) {
|
|
|
|
double flux = in * enrichment;
|
|
|
|
switch(this.function) {
|
|
case PASSIVE: return selfRate * enrichment;
|
|
case LOG_TEN: return Math.log10(flux + 1) * 0.1D * reactivity;
|
|
case PLATEU: return (1 - Math.pow(Math.E, -flux / 25D)) * 100D * reactivity;
|
|
case ARCH: return flux - (flux * flux / 1000D) * reactivity;
|
|
case SIGMOID: return 100D / (1 + Math.pow(Math.E, -(flux - 50D) / 10D)) * reactivity;
|
|
case SQUARE_ROOT: return Math.sqrt(flux) * reactivity;
|
|
case LINEAR: return flux / 100D * reactivity;
|
|
case QUADRATIC: return flux * flux / 100D * reactivity;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
public String getFuncDescription() {
|
|
|
|
String x = "x";
|
|
|
|
if(selfRate > 0)
|
|
x = "(x" + EnumChatFormatting.RED + " + " + selfRate + "" + EnumChatFormatting.WHITE + ")";
|
|
|
|
switch(this.function) {
|
|
case PASSIVE: return EnumChatFormatting.RED + "" + selfRate;
|
|
case LOG_TEN: return "log10(x + 1" + (selfRate > 0 ? (EnumChatFormatting.RED + " + " + selfRate) : "") + EnumChatFormatting.WHITE + ") * " + reactivity;
|
|
case PLATEU: return "(1 - e^-" + x + " / 25)) * 100 * " + reactivity;
|
|
case ARCH: return "(" + x + " - " + x + "² / 1000) * " + reactivity;
|
|
case SIGMOID: return "100 / (1 + e^(-(" + x + " - 50) / 10) * " + reactivity;
|
|
case SQUARE_ROOT: return "sqrt(" + x + ") * " + reactivity;
|
|
case LINEAR: return x + " / 100 * " + reactivity;
|
|
case QUADRATIC: return x + "² / 100 * " + reactivity;
|
|
}
|
|
|
|
return "ERROR";
|
|
}
|
|
|
|
/**
|
|
* Xenon generated per tick, linear function
|
|
* @param flux
|
|
* @return
|
|
*/
|
|
public double xenonGenFunc(double flux) {
|
|
return flux * xGen;
|
|
}
|
|
|
|
/**
|
|
* Xenon burned away per tick, quadratic function
|
|
* @param flux
|
|
* @return
|
|
*/
|
|
public double xenonBurnFunc(double flux) {
|
|
return (flux * flux) / xBurn;
|
|
}
|
|
|
|
/**
|
|
* @param stack
|
|
* @return enrichment [0;1]
|
|
*/
|
|
public static double getEnrichment(ItemStack stack) {
|
|
return getYield(stack) / ((ItemRBMKRod) stack.getItem()).yield;
|
|
}
|
|
|
|
/**
|
|
* @param stack
|
|
* @return poison [0;1]
|
|
*/
|
|
public static double getPoisonLevel(ItemStack stack) {
|
|
return getPoison(stack) / 100D;
|
|
}
|
|
|
|
@Override
|
|
public void addInformation(ItemStack stack, EntityPlayer player, List list, boolean bool) {
|
|
|
|
list.add(EnumChatFormatting.ITALIC + this.fullName);
|
|
|
|
if(this == ModItems.rbmk_fuel_drx) {
|
|
|
|
if(selfRate > 0) {
|
|
list.add(EnumChatFormatting.RED + I18nUtil.resolveKey("trait.rbmx.source"));
|
|
}
|
|
|
|
list.add(EnumChatFormatting.GREEN + I18nUtil.resolveKey("trait.rbmx.depletion", ((int)(((yield - getYield(stack)) / yield) * 100000)) / 1000D + "%"));
|
|
list.add(EnumChatFormatting.DARK_PURPLE + I18nUtil.resolveKey("trait.rbmx.xenon", ((int)(getPoison(stack) * 1000D) / 1000D) + "%"));
|
|
list.add(EnumChatFormatting.BLUE + I18nUtil.resolveKey("trait.rbmx.splitsWith", I18nUtil.resolveKey(nType.unlocalized + ".x")));
|
|
list.add(EnumChatFormatting.BLUE + I18nUtil.resolveKey("trait.rbmx.splitsInto", I18nUtil.resolveKey(rType.unlocalized + ".x")));
|
|
list.add(EnumChatFormatting.YELLOW + I18nUtil.resolveKey("trait.rbmx.fluxFunc", EnumChatFormatting.WHITE + getFuncDescription()));
|
|
list.add(EnumChatFormatting.YELLOW + I18nUtil.resolveKey("trait.rbmx.funcType", this.function.title));
|
|
list.add(EnumChatFormatting.YELLOW + I18nUtil.resolveKey("trait.rbmx.xenonGen", EnumChatFormatting.WHITE + "x * " + xGen));
|
|
list.add(EnumChatFormatting.YELLOW + I18nUtil.resolveKey("trait.rbmx.xenonBurn", EnumChatFormatting.WHITE + "x² * " + xBurn));
|
|
list.add(EnumChatFormatting.GOLD + I18nUtil.resolveKey("trait.rbmx.heat", heat + "°C"));
|
|
list.add(EnumChatFormatting.GOLD + I18nUtil.resolveKey("trait.rbmx.diffusion", diffusion + "¹/²"));
|
|
list.add(EnumChatFormatting.RED + I18nUtil.resolveKey("trait.rbmx.skinTemp", ((int)(getHullHeat(stack) * 10D) / 10D) + "m"));
|
|
list.add(EnumChatFormatting.RED + I18nUtil.resolveKey("trait.rbmx.coreTemp", ((int)(getCoreHeat(stack) * 10D) / 10D) + "m"));
|
|
list.add(EnumChatFormatting.DARK_RED + I18nUtil.resolveKey("trait.rbmx.melt", meltingPoint + "m"));
|
|
|
|
} else {
|
|
|
|
if(selfRate > 0) {
|
|
list.add(EnumChatFormatting.RED + I18nUtil.resolveKey("trait.rbmk.source"));
|
|
}
|
|
|
|
list.add(EnumChatFormatting.GREEN + I18nUtil.resolveKey("trait.rbmk.depletion", ((int)(((yield - getYield(stack)) / yield) * 100000D)) / 1000D + "%"));
|
|
list.add(EnumChatFormatting.DARK_PURPLE + I18nUtil.resolveKey("trait.rbmk.xenon", ((int)(getPoison(stack) * 1000D) / 1000D) + "%"));
|
|
list.add(EnumChatFormatting.BLUE + I18nUtil.resolveKey("trait.rbmk.splitsWith", I18nUtil.resolveKey(nType.unlocalized)));
|
|
list.add(EnumChatFormatting.BLUE + I18nUtil.resolveKey("trait.rbmk.splitsInto", I18nUtil.resolveKey(rType.unlocalized)));
|
|
list.add(EnumChatFormatting.YELLOW + I18nUtil.resolveKey("trait.rbmk.fluxFunc", EnumChatFormatting.WHITE + getFuncDescription()));
|
|
list.add(EnumChatFormatting.YELLOW + I18nUtil.resolveKey("trait.rbmk.funcType", this.function.title));
|
|
list.add(EnumChatFormatting.YELLOW + I18nUtil.resolveKey("trait.rbmk.xenonGen", EnumChatFormatting.WHITE + "x * " + xGen));
|
|
list.add(EnumChatFormatting.YELLOW + I18nUtil.resolveKey("trait.rbmk.xenonBurn", EnumChatFormatting.WHITE + "x² * " + xBurn));
|
|
list.add(EnumChatFormatting.GOLD + I18nUtil.resolveKey("trait.rbmk.heat", heat + "°C"));
|
|
list.add(EnumChatFormatting.GOLD + I18nUtil.resolveKey("trait.rbmk.diffusion", diffusion + "¹/²"));
|
|
list.add(EnumChatFormatting.RED + I18nUtil.resolveKey("trait.rbmk.skinTemp", ((int)(getHullHeat(stack) * 10D) / 10D) + "°C"));
|
|
list.add(EnumChatFormatting.RED + I18nUtil.resolveKey("trait.rbmk.coreTemp", ((int)(getCoreHeat(stack) * 10D) / 10D) + "°C"));
|
|
list.add(EnumChatFormatting.DARK_RED + I18nUtil.resolveKey("trait.rbmk.melt", meltingPoint + "°C"));
|
|
}
|
|
|
|
/*list.add(EnumChatFormatting.GREEN + "Depletion: " + ((int)(((yield - getYield(stack)) / yield) * 10000)) / 10000D + "%");
|
|
list.add(EnumChatFormatting.DARK_PURPLE + "Xenon poison: " + ((getPoison(stack) * 100D) / 100D) + "%");
|
|
list.add(EnumChatFormatting.BLUE + "Splits with: " + nType.unlocalized);
|
|
list.add(EnumChatFormatting.BLUE + "Splits into: " + rType.unlocalized);
|
|
list.add(EnumChatFormatting.YELLOW + "Flux function: " + EnumChatFormatting.WHITE + "" + funcEnd + " * x" + (selfRate > 0 ? (EnumChatFormatting.RED + " + " + selfRate) : ""));
|
|
list.add(EnumChatFormatting.YELLOW + "Xenon gen function: " + EnumChatFormatting.WHITE + "x * " + xGen);
|
|
list.add(EnumChatFormatting.YELLOW + "Xenon burn function: " + EnumChatFormatting.WHITE + "x² * " + xBurn);
|
|
list.add(EnumChatFormatting.GOLD + "Heat per tick at full power: " + heat + "°C");
|
|
list.add(EnumChatFormatting.GOLD + "Diffusion: " + diffusion + "°C/t");
|
|
list.add(EnumChatFormatting.RED + "Skin temp: " + ((int)(getHullHeat(stack) * 10D) / 10D) + "°C");
|
|
list.add(EnumChatFormatting.RED + "Core temp: " + ((int)(getCoreHeat(stack) * 10D) / 10D) + "°C");
|
|
list.add(EnumChatFormatting.DARK_RED + "Melting point: " + meltingPoint + "°C");*/
|
|
|
|
super.addInformation(stack, player, list, bool);
|
|
updateModule(stack);
|
|
this.module.addInformation(stack, player, list, bool);
|
|
}
|
|
|
|
@Override
|
|
public void onUpdate(ItemStack stack, World world, Entity entity, int i, boolean b) {
|
|
|
|
if(entity instanceof EntityLivingBase) {
|
|
updateModule(stack);
|
|
this.module.applyEffects((EntityLivingBase) entity, stack.stackSize, i, b);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean onEntityItemUpdate(EntityItem item) {
|
|
|
|
super.onEntityItemUpdate(item);
|
|
updateModule(item.getEntityItem());
|
|
return this.module.onEntityItemUpdate(item);
|
|
}
|
|
|
|
ItemHazardModule module;
|
|
|
|
@Override
|
|
public ItemHazardModule getModule() {
|
|
return this.module;
|
|
}
|
|
|
|
private void updateModule(ItemStack stack) {
|
|
|
|
float mod = (float)(1 + (1 - this.getEnrichment(stack)) * 24 + this.getPoisonLevel(stack) * 100);
|
|
this.module.setMod(mod);
|
|
}
|
|
|
|
/* __ __ ____ ________
|
|
* | \ | | | __ \ |__ __|
|
|
* | \ | | | |__| | | |
|
|
* | |\\| | | __ < | |
|
|
* | | \ | | |__| | | |
|
|
* |__| \__| |_____/ |__|
|
|
*/
|
|
|
|
public static void setYield(ItemStack stack, double yield) {
|
|
setDouble(stack, "yield", yield);
|
|
}
|
|
|
|
public static double getYield(ItemStack stack) {
|
|
|
|
if(stack.getItem() instanceof ItemRBMKRod) {
|
|
return getDouble(stack, "yield");
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
public static void setPoison(ItemStack stack, double xenon) {
|
|
setDouble(stack, "xenon", xenon);
|
|
}
|
|
|
|
public static double getPoison(ItemStack stack) {
|
|
return getDouble(stack, "xenon");
|
|
}
|
|
|
|
public static void setCoreHeat(ItemStack stack, double heat) {
|
|
setDouble(stack, "core", heat);
|
|
}
|
|
|
|
public static double getCoreHeat(ItemStack stack) {
|
|
return getDouble(stack, "core");
|
|
}
|
|
|
|
public static void setHullHeat(ItemStack stack, double heat) {
|
|
setDouble(stack, "hull", heat);
|
|
}
|
|
|
|
public static double getHullHeat(ItemStack stack) {
|
|
return getDouble(stack, "hull");
|
|
}
|
|
|
|
@Override
|
|
public boolean showDurabilityBar(ItemStack stack) {
|
|
return getDurabilityForDisplay(stack) > 0D;
|
|
}
|
|
|
|
@Override
|
|
public double getDurabilityForDisplay(ItemStack stack) {
|
|
return 1D - getEnrichment(stack);
|
|
}
|
|
|
|
public static void setDouble(ItemStack stack, String key, double yield) {
|
|
|
|
if(!stack.hasTagCompound())
|
|
setNBTDefaults(stack);
|
|
|
|
stack.stackTagCompound.setDouble(key, yield);
|
|
}
|
|
|
|
public static double getDouble(ItemStack stack, String key) {
|
|
|
|
if(!stack.hasTagCompound())
|
|
setNBTDefaults(stack);
|
|
|
|
return stack.stackTagCompound.getDouble(key);
|
|
}
|
|
|
|
/**
|
|
* Sets up the default values for all NBT data because doing it one-by-one will only correctly set the first called value and the rest stays 0 which is very not good
|
|
* @param stack
|
|
*/
|
|
private static void setNBTDefaults(ItemStack stack) {
|
|
|
|
stack.stackTagCompound = new NBTTagCompound();
|
|
setYield(stack, ((ItemRBMKRod)stack.getItem()).yield);
|
|
setCoreHeat(stack, 20.0D);
|
|
setHullHeat(stack, 20.0D);
|
|
}
|
|
}
|