custom fluid traits fix

Fixed some custom fluid traits buds, like the JSON output error of the polluting trait and the java.lang.InstantiationException issue of the PWRModerator and Pheromone traits. Mean while, the hot reload function of hbmFluidTypes.json and hbmFluidTraits.json has been added.
This commit is contained in:
FOlkvangrField 2024-11-14 21:13:13 +08:00
parent e95123c359
commit 146e19d463
6 changed files with 134 additions and 102 deletions

View File

@ -1,7 +1,9 @@
package com.hbm.commands;
import com.hbm.config.ItemPoolConfigJSON;
import com.hbm.inventory.fluid.Fluids;
import com.hbm.inventory.recipes.loader.SerializableRecipe;
import com.hbm.main.MainRegistry;
import com.hbm.util.ChatBuilder;
import net.minecraft.command.CommandBase;
@ -9,6 +11,10 @@ import net.minecraft.command.ICommandSender;
import net.minecraft.util.ChatComponentText;
import net.minecraft.util.EnumChatFormatting;
import java.io.File;
public class CommandReloadRecipes extends CommandBase {
@Override
@ -26,6 +32,7 @@ public class CommandReloadRecipes extends CommandBase {
try {
SerializableRecipe.initialize();
ItemPoolConfigJSON.initialize();
Fluids.reloadFluids();
sender.addChatMessage(new ChatComponentText(EnumChatFormatting.YELLOW + "Reload complete :)"));
} catch(Exception ex) {
sender.addChatMessage(ChatBuilder.start("----------------------------------").color(EnumChatFormatting.GRAY).flush());

View File

@ -20,27 +20,28 @@ public class BoilingHandler extends NEIUniversalHandler {
public String getKey() {
return "ntmBoiling";
}
public static HashMap<Object, Object> cache;
public static boolean isReload=false;
public static HashMap<Object, Object> generateRecipes() {
if(cache != null) return cache;
if(cache != null && !isReload) return cache;
cache = new HashMap();
for(FluidType type : Fluids.getInNiceOrder()) {
if(type.hasTrait(FT_Heatable.class)) {
FT_Heatable trait = type.getTrait(FT_Heatable.class);
if(trait.getEfficiency(HeatingType.BOILER) > 0) {
HeatingStep step = trait.getFirstStep();
cache.put(ItemFluidIcon.make(type, step.amountReq), ItemFluidIcon.make(step.typeProduced, step.amountProduced));
}
}
}
isReload=false;
return cache;
}
}

View File

@ -14,6 +14,7 @@ import com.google.gson.Gson;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.stream.JsonWriter;
import com.hbm.handler.nei.BoilingHandler;
import com.hbm.handler.pollution.PollutionHandler;
import com.hbm.handler.pollution.PollutionHandler.PollutionType;
import com.hbm.inventory.fluid.trait.*;
@ -179,12 +180,12 @@ public class Fluids {
public static FluidType STELLAR_FLUX;
public static FluidType VITRIOL;
public static FluidType SLOP;
/* Lagacy names for compatibility purposes */
@Deprecated public static FluidType ACID; //JAOPCA uses this, apparently
public static final HashBiMap<String, FluidType> renameMapping = HashBiMap.create();
public static List<FluidType> customFluids = new ArrayList();
private static final HashMap<Integer, FluidType> idMapping = new HashMap();
@ -226,20 +227,20 @@ public class Fluids {
public static final FT_Polluting P_LIQUID_GAS = new FT_Polluting().burn(PollutionType.SOOT, SOOT_GAS * 2F);
public static void init() {
// ##### ##### ##### ##### ## # ##### # # ##### ## # #####
// # # # # # ## # # # # # # ## # #
// ##### # # ### # # # ##### ##### # # # # # ###
// # # # # # # ## # # # # # # ## #
// # # # # ##### # ## ##### # # ##### # ## #####
/*
* The mapping ID is set in the CTOR, which is the static, never shifting ID that is used to save the fluid type.
* Therefore, ALWAYS append new fluid entries AT THE BOTTOM to avoid unnecessary ID shifting.
* In addition, you have to add your fluid to 'metaOrder' which is what is used to sort fluid identifiers and whatnot in the inventory.
* You may screw with metaOrder as much as you like, as long as you keep all fluids in the list exactly once.
*/
NONE = new FluidType("NONE", 0x888888, 0, 0, 0, EnumSymbol.NONE);
WATER = new FluidType("WATER", 0x3333FF, 0, 0, 0, EnumSymbol.NONE).addTraits(LIQUID, UNSIPHONABLE);
STEAM = new FluidType("STEAM", 0xe5e5e5, 3, 0, 0, EnumSymbol.NONE).setTemp(100).addTraits(GASEOUS, UNSIPHONABLE);
@ -384,18 +385,18 @@ public class Fluids {
SLOP = new FluidType("SLOP", 0x929D45, 0, 0, 0, EnumSymbol.NONE).addTraits(LIQUID, VISCOUS);
LEAD = new FluidType("LEAD", 0x666672, 4, 0, 0, EnumSymbol.NONE).setTemp(350).addTraits(LIQUID, VISCOUS);
LEAD_HOT = new FluidType(143, "LEAD_HOT", 0x776563, 4, 0, 0, EnumSymbol.NONE).setTemp(1500).addTraits(LIQUID, VISCOUS);
// ^ ^ ^ ^ ^ ^ ^ ^
//ADD NEW FLUIDS HERE
File folder = MainRegistry.configHbmDir;
File customTypes = new File(folder.getAbsolutePath() + File.separatorChar + "hbmFluidTypes.json");
if(!customTypes.exists()) initDefaultFluids(customTypes);
readCustomFluids(customTypes);
//AND DON'T FORGET THE META DOWN HERE
// V V V V V V V V
//null
metaOrder.add(NONE);
//vanilla
@ -556,15 +557,15 @@ public class Fluids {
//bug meth
metaOrder.add(PHEROMONE);
metaOrder.add(PHEROMONE_M);
//ANY INTERNAL RENAMING MUST BE REFLECTED HERE - DON'T FORGET TO CHANGE: LANG FILES + TYPE'S STRING ID + NAME OF TANK/GUI TEXTURE FILES!
// V
renameMapping.put("ACID", PEROXIDE);
// LEGACY
ACID = PEROXIDE;
for(FluidType custom : customFluids) metaOrder.add(custom);
CHLORINE.addTraits(new FT_Toxin().addEntry(new ToxinDirectDamage(ModDamageSource.cloud, 2F, 20, HazardClass.GAS_LUNG, false)));
@ -576,7 +577,7 @@ public class Fluids {
double eff_steam_boil = 1.0D;
double eff_steam_heatex = 0.25D;
WATER.addTraits(new FT_Heatable().setEff(HeatingType.BOILER, eff_steam_boil).setEff(HeatingType.HEATEXCHANGER, eff_steam_heatex)
.addStep(200, 1, STEAM, 100)
.addStep(220, 1, HOTSTEAM, 10)
@ -606,13 +607,13 @@ public class Fluids {
COOLANT.addTraits(new FT_Heatable().setEff(HeatingType.HEATEXCHANGER, 1.0D).setEff(HeatingType.PWR, 1.0D).setEff(HeatingType.ICF, 1.0D).addStep(300, 1, COOLANT_HOT, 1));
COOLANT_HOT.addTraits(new FT_Coolable(COOLANT, 1, 1, 300).setEff(CoolingType.HEATEXCHANGER, 1.0D));
MUG.addTraits(new FT_Heatable().setEff(HeatingType.HEATEXCHANGER, 1.0D).setEff(HeatingType.PWR, 1.0D).setEff(HeatingType.ICF, 1.25D).addStep(400, 1, MUG_HOT, 1), new FT_PWRModerator(1.15D));
MUG_HOT.addTraits(new FT_Coolable(MUG, 1, 1, 400).setEff(CoolingType.HEATEXCHANGER, 1.0D));
BLOOD.addTraits(new FT_Heatable().setEff(HeatingType.HEATEXCHANGER, 1.0D).setEff(HeatingType.ICF, 1.25D).addStep(500, 1, BLOOD_HOT, 1));
BLOOD_HOT.addTraits(new FT_Coolable(BLOOD, 1, 1, 500).setEff(CoolingType.HEATEXCHANGER, 1.0D));
HEAVYWATER.addTraits(new FT_Heatable().setEff(HeatingType.PWR, 1.0D).addStep(300, 1, HEAVYWATER_HOT, 1), new FT_PWRModerator(1.25D));
HEAVYWATER_HOT.addTraits(new FT_Coolable(HEAVYWATER, 1, 1, 300).setEff(CoolingType.HEATEXCHANGER, 1.0D));
@ -623,17 +624,17 @@ public class Fluids {
/* Or maybe not, because I blocked your sorry ass. Guess why that is? */
LEAD_HOT.addTraits(new FT_Coolable(LEAD, 1, 1, 680).setEff(CoolingType.HEATEXCHANGER, 1.0D));
/* Maybe shittalking me in some corner where you thought I wouldn't listen was not that bright of an idea afterall? */
THORIUM_SALT.addTraits(new FT_Heatable().setEff(HeatingType.PWR, 1.0D).addStep(400, 1, THORIUM_SALT_HOT, 1), new FT_PWRModerator(2.5D));
THORIUM_SALT_HOT.addTraits(new FT_Coolable(THORIUM_SALT_DEPLETED, 1, 1, 400).setEff(CoolingType.HEATEXCHANGER, 1.0D));
if(idMapping.size() != metaOrder.size()) {
throw new IllegalStateException("A severe error has occoured during NTM's fluid registering process! The MetaOrder and Mappings are inconsistent! Mapping size: " + idMapping.size()+ " / MetaOrder size: " + metaOrder.size());
}
/// FINAL ///
long baseline = 100_000L; //we do not know
double demandVeryLow = 0.5D; //for waste gasses
double demandLow = 1.0D; //for fuel oils
@ -695,11 +696,11 @@ public class Fluids {
registerCalculatedFuel(DIESEL_CRACK_REFORM, DIESEL_CRACK.getTrait(FT_Flammable.class).getHeatEnergy() * complexityReform, 2.5D, FuelGrade.HIGH);
registerCalculatedFuel(KEROSENE_REFORM, KEROSENE.getTrait(FT_Flammable.class).getHeatEnergy() * complexityReform, 1.5D, FuelGrade.AERO);
registerCalculatedFuel(REFORMGAS, (baseline / 0.06 * flammabilityHigh * demandLow * complexityVacuum * complexityFraction), 1.5D, FuelGrade.GAS);
//all hail the spreadsheet
//the spreadsheet must not be questioned
//none may enter the orb- i mean the spreadsheet
int coalHeat = 400_000; // 200TU/t for 2000 ticks
registerCalculatedFuel(COALOIL, (coalHeat * (1000 /* bucket */ / 100 /* mB per coal */) * flammabilityLow * demandLow * complexityChemplant), 0, null);
long coaloil = COALOIL.getTrait(FT_Flammable.class).getHeatEnergy();
@ -721,24 +722,24 @@ public class Fluids {
registerCalculatedFuel(SYNGAS, (coalHeat * (1000 /* bucket */ / 100 /* mB per coal */) * flammabilityLow * demandLow * complexityChemplant) * 1.5, 1.25, FuelGrade.GAS); //same as coal oil, +50% bonus
registerCalculatedFuel(OXYHYDROGEN, 5_000, 3, FuelGrade.GAS); // whatever
File config = new File(folder.getAbsolutePath() + File.separatorChar + "hbmFluidTraits.json");
File template = new File(folder.getAbsolutePath() + File.separatorChar + "_hbmFluidTraits.json");
if(!config.exists()) {
writeDefaultTraits(template);
} else {
readTraits(config);
}
}
private static void initDefaultFluids(File file) {
try {
JsonWriter writer = new JsonWriter(new FileWriter(file));
writer.setIndent(" ");
writer.beginObject();
writer.name("CUSTOM_DEMO").beginObject();
writer.name("name").value("Custom Fluid Demo");
writer.name("id").value(1000);
@ -749,21 +750,21 @@ public class Fluids {
writer.name("texture").value("custom_water");
writer.name("temperature").value(20);
writer.endObject();
writer.endObject();
writer.close();
} catch(IOException e) {
e.printStackTrace();
}
}
private static void readCustomFluids(File file) {
try {
JsonObject json = gson.fromJson(new FileReader(file), JsonObject.class);
for(Entry<String, JsonElement> entry : json.entrySet()) {
JsonObject obj = (JsonObject) entry.getValue();
String name = entry.getKey();
@ -777,54 +778,54 @@ public class Fluids {
EnumSymbol symbol = EnumSymbol.valueOf(obj.get("symbol").getAsString());
String texture = obj.get("texture").getAsString();
int temperature = obj.get("temperature").getAsInt();
FluidType type = new FluidType(name, color, p, f, r, symbol, texture, tint, id, displayName).setTemp(temperature);
customFluids.add(type);
}
} catch(Exception ex) {
ex.printStackTrace();
}
}
private static void writeDefaultTraits(File file) {
try {
JsonWriter writer = new JsonWriter(new FileWriter(file));
writer.setIndent(" ");
writer.beginObject();
for(FluidType type : metaOrder) {
writer.name(type.getName()).beginObject();
for(Entry<Class<? extends FluidTrait>, FluidTrait> entry : type.traits.entrySet()) {
writer.name(FluidTrait.traitNameMap.inverse().get(entry.getKey())).beginObject();
entry.getValue().serializeJSON(writer);
writer.endObject();
}
writer.endObject();
}
writer.endObject();
writer.close();
} catch(IOException e) {
e.printStackTrace();
}
}
private static void readTraits(File config) {
try {
JsonObject json = gson.fromJson(new FileReader(config), JsonObject.class);
for(FluidType type : metaOrder) {
JsonElement element = json.get(type.getName());
if(element != null) {
type.traits.clear();
JsonObject obj = element.getAsJsonObject();
for(Entry<String, JsonElement> entry : obj.entrySet()) {
Class<? extends FluidTrait> traitClass = FluidTrait.traitNameMap.get(entry.getKey());
try {
@ -837,14 +838,36 @@ public class Fluids {
}
}
}
} catch(Exception ex) {
ex.printStackTrace();
}
}
public static void reloadFluids(){
File folder = MainRegistry.configHbmDir;
File customTypes = new File(folder.getAbsolutePath() + File.separatorChar + "hbmFluidTypes.json");
if(!customTypes.exists()) initDefaultFluids(customTypes);
for(FluidType type : customFluids){
idMapping.remove(type.getID());
registerOrder.remove(type);
nameMapping.remove(type.getName());
metaOrder.remove(type);
}
customFluids.clear();
readCustomFluids(customTypes);
for(FluidType custom : customFluids) metaOrder.add(custom);
File config = new File(MainRegistry.configHbmDir.getAbsolutePath() + File.separatorChar + "hbmFluidTraits.json");
File template = new File(MainRegistry.configHbmDir.getAbsolutePath() + File.separatorChar + "_hbmFluidTraits.json");
if(!config.exists()) {
writeDefaultTraits(template);
} else {
readTraits(config);
}
BoilingHandler.isReload=true;
}
private static void registerCalculatedFuel(FluidType type, double base, double combustMult, FuelGrade grade) {
long flammable = (long) base;
long combustible = (long) (base * combustMult);
@ -852,11 +875,11 @@ public class Fluids {
combustible = round(combustible);
type.addTraits(new FT_Flammable(flammable));
if(combustible > 0 && grade != null)
type.addTraits(new FT_Combustible(grade, combustible));
}
/** ugly but it does the thing well enough */
private static long round(long l) {
if(l > 10_000_000L) return l - (l % 100_000L);
@ -864,10 +887,10 @@ public class Fluids {
if(l > 100_000L) return l - (l % 1_000L);
if(l > 10_000L) return l - (l % 100L);
if(l > 1_000L) return l - (l % 10L);
return l;
}
protected static int registerSelf(FluidType fluid) {
int id = idMapping.size();
idMapping.put(id, fluid);
@ -875,90 +898,90 @@ public class Fluids {
nameMapping.put(fluid.getName(), fluid);
return id;
}
protected static void register(FluidType fluid, int id) {
idMapping.put(id, fluid);
registerOrder.add(fluid);
nameMapping.put(fluid.getName(), fluid);
}
public static FluidType fromID(int id) {
FluidType fluid = idMapping.get(id);
if(fluid == null)
fluid = Fluids.NONE;
return fluid;
}
public static FluidType fromName(String name) {
FluidType fluid = nameMapping.get(name);
if(fluid == null)
fluid = Fluids.NONE;
return fluid;
}
/** for old worlds with types saved as name, do not use otherwise */
public static FluidType fromNameCompat(String name) {
if(renameMapping.containsKey(name)) {
FluidType fluid = renameMapping.get(name);
if(fluid == null) //null safety never killed nobody
fluid = Fluids.NONE;
return fluid;
}
return fromName(name);
}
/** basically the inverse of the above method */
public static String toNameCompat(FluidType type) {
if(renameMapping.containsValue(type)) {
String name = renameMapping.inverse().get(type);
if(name == null) //ditto
name = Fluids.NONE.getName();
return name;
}
return type.getName();
}
public static FluidType[] getAll() {
return getInOrder(false);
}
public static FluidType[] getInNiceOrder() {
return getInOrder(true);
}
private static FluidType[] getInOrder(final boolean nice) {
FluidType[] all = new FluidType[idMapping.size()];
for(int i = 0; i < all.length; i++) {
FluidType type = nice ? metaOrder.get(i) : registerOrder.get(i);
if(type == null) {
throw new IllegalStateException("A severe error has occoured with NTM's fluid system! Fluid of the ID " + i + " has returned NULL in the registry!");
}
all[i] = type;
}
return all;
}
public static class CD_Canister {
public int color;
public CD_Canister(int color) { this.color = color; }
}
public static class CD_Gastank {
public int bottleColor, labelColor;
public CD_Gastank(int color1, int color2) { this.bottleColor = color1; this.labelColor = color2; }
}
}
}

View File

@ -11,15 +11,15 @@ import net.minecraft.util.EnumChatFormatting;
public class FT_PWRModerator extends FluidTrait {
private double multiplier;
public FT_PWRModerator(){}
public FT_PWRModerator(double mulitplier) {
this.multiplier = mulitplier;
}
public double getMultiplier() {
return multiplier;
}
@Override
public void addInfo(List<String> info) {
info.add(EnumChatFormatting.BLUE + "[PWR Flux Multiplier]");
@ -35,7 +35,7 @@ public class FT_PWRModerator extends FluidTrait {
public void serializeJSON(JsonWriter writer) throws IOException {
writer.name("multiplier").value(multiplier);
}
@Override
public void deserializeJSON(JsonObject obj) {
this.multiplier = obj.get("multiplier").getAsDouble();

View File

@ -11,6 +11,7 @@ import java.util.List;
public class FT_Pheromone extends FluidTrait{
public int type;
public FT_Pheromone() {}
public FT_Pheromone(int type) {
this.type = type;

View File

@ -20,12 +20,12 @@ public class FT_Polluting extends FluidTrait {
//original draft had both of them inside a hashmap for the release type but honestly handling hash maps in hash maps adds more complexity than it removes
public HashMap<PollutionType, Float> releaseMap = new HashMap();
public HashMap<PollutionType, Float> burnMap = new HashMap();
public FT_Polluting release(PollutionType type, float amount) {
releaseMap.put(type, amount);
return this;
}
public FT_Polluting burn(PollutionType type, float amount) {
burnMap.put(type, amount);
return this;
@ -38,12 +38,12 @@ public class FT_Polluting extends FluidTrait {
@Override
public void addInfoHidden(List<String> info) {
if(!this.releaseMap.isEmpty()) {
info.add(EnumChatFormatting.GREEN + "When spilled:");
for(Entry<PollutionType, Float> entry : releaseMap.entrySet()) info.add(EnumChatFormatting.GREEN + " - " + entry.getValue() + " " + entry.getKey() + " per mB");
}
if(!this.burnMap.isEmpty()) {
info.add(EnumChatFormatting.RED + "When burned:");
for(Entry<PollutionType, Float> entry : burnMap.entrySet()) info.add(EnumChatFormatting.RED + " - " + entry.getValue() + " " + entry.getKey() + " per mB");
@ -60,16 +60,16 @@ public class FT_Polluting extends FluidTrait {
public void serializeJSON(JsonWriter writer) throws IOException {
writer.name("release").beginObject();
for(Entry<PollutionType, Float> entry : releaseMap.entrySet()) {
writer.name(entry.toString()).value(entry.getValue());
writer.name(entry.getKey().name()).value(entry.getValue());
}
writer.endObject();
writer.name("burn").beginObject();
for(Entry<PollutionType, Float> entry : burnMap.entrySet()) {
writer.name(entry.toString()).value(entry.getValue());
writer.name(entry.getKey().name()).value(entry.getValue());
}
writer.endObject();
}
@Override
public void deserializeJSON(JsonObject obj) {
if(obj.has("release")) {
@ -89,14 +89,14 @@ public class FT_Polluting extends FluidTrait {
}
}
}
public static void pollute(World world, int x, int y, int z, FluidType type, FluidReleaseType release, float mB) {
FT_Polluting trait = type.getTrait(FT_Polluting.class);
if(trait == null) return;
if(release == FluidReleaseType.VOID) return;
HashMap<PollutionType, Float> map = release == FluidReleaseType.BURN ? trait.burnMap : trait.releaseMap;
for(Entry<PollutionType, Float> entry : map.entrySet()) {
PollutionHandler.incrementPollution(world, x, y, z, entry.getKey(), entry.getValue() * mB);
}