Skip to content

Commit

Permalink
feat: refactor fluid tribute and nutrients api
Browse files Browse the repository at this point in the history
simplifies fluid nutrients handling
  • Loading branch information
Elenterius committed Nov 6, 2024
1 parent 205a59d commit ae5ebe4
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 100 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@
@ApiStatus.Experimental
public class FluidFuelConsumerHandler implements IFluidHandler, INBTSerializable<CompoundTag> {

public static final String FRACTIONAL_FUEL_BUFFER_KEY = "FractionalFuelBuffer";
private static final long SCALE_FACTOR = 1_000_000;
public static final String MILLI_FUEL_BUFFER_KEY = "MilliFuelBuffer";

private final FuelHandler fuelHandler;
private long fractionalFuelBuffer;
private long milliFuelBuffer;

public FluidFuelConsumerHandler(FuelHandler fuelHandler) {
this.fuelHandler = fuelHandler;
Expand All @@ -30,41 +29,34 @@ public int fill(FluidStack resource, FluidAction action) {
if (resource.isEmpty()) return 0;
if (fuelHandler.getFuelAmount() >= fuelHandler.getMaxFuelAmount()) return 0;

FluidToFuelConversion fuelConversion = FluidNutrients.getConversion(resource);
if (fuelConversion == null) return 0;
FluidToFuelConversion conversion = FluidNutrients.getConversion(resource);
if (conversion == null) return 0;

int fuelMultiplier = fuelConversion.getFuelMultiplier(resource);
int fluidToFuelRatio = fuelConversion.getFluidToFuelRatio(resource);
if (fuelMultiplier <= 0 || fluidToFuelRatio <= 0) return 0;
int milliFuel = conversion.getMilliFuelPerUnit(resource);
if (milliFuel <= 0) return 0;

int fuelYield = (resource.getAmount() / fluidToFuelRatio) * fuelMultiplier;
if (fuelYield <= 0) {
if (action.simulate()) return resource.getAmount();
long amountToConsume = resource.getAmount(); //8 of 120 --> 120/8 = 15
int fuelYield = (int) ((milliFuelBuffer + milliFuel * amountToConsume) / FluidToFuelConversion.MILLI_FUEL_SCALE); //1600 -> 1,6

fractionalFuelBuffer += (resource.getAmount() * SCALE_FACTOR / fluidToFuelRatio) * fuelMultiplier;
fuelYield = (int) (fractionalFuelBuffer / SCALE_FACTOR);
if (fuelYield <= 0) return resource.getAmount();
if (fuelYield > 0) {
int fuelToFill = Math.min(fuelHandler.getMaxFuelAmount() - fuelHandler.getFuelAmount(), fuelYield); //1
long fuelMissing = (long) fuelToFill * FluidToFuelConversion.MILLI_FUEL_SCALE - milliFuelBuffer; //1000 - 800 = 200

int fuelFilled = Math.min(fuelHandler.getMaxFuelAmount() - fuelHandler.getFuelAmount(), fuelYield);
fuelHandler.addFuelAmount(fuelFilled);
fractionalFuelBuffer -= fuelFilled * SCALE_FACTOR;
amountToConsume = (int) (fuelMissing / milliFuel); // 200/100 = 2

return resource.getAmount();
}
else {
int fuelToFill = Math.min(fuelHandler.getMaxFuelAmount() - fuelHandler.getFuelAmount(), fuelYield);

// calculate how much fluid this fuel corresponds to, based on the ratio
int fluidFilled = (fuelToFill * fluidToFuelRatio) / fuelMultiplier; //make sure we only take as much fluid actually "fits inside"

if (fluidFilled <= 0) return 0;
if (action.simulate()) return fluidFilled;
if (action.simulate()) return (int) amountToConsume;

int fuelFilled = (fluidFilled / fluidToFuelRatio) * fuelMultiplier;
fuelHandler.addFuelAmount(fuelFilled);
fuelHandler.addFuelAmount(fuelToFill);

return fluidFilled;
long remainder = (milliFuel * amountToConsume - fuelMissing); // 100 * 2 - 200
milliFuelBuffer = remainder;
}
else {
if (action.simulate()) return (int) amountToConsume;
milliFuelBuffer += milliFuel * amountToConsume;
}

return (int) amountToConsume;
}

@Override
Expand All @@ -85,7 +77,6 @@ public int getTanks() {
@Override
public int getTankCapacity(int tank) {
return fuelHandler.getMaxFuelAmount(); //misleading value as it does not represent the fluid volume but the amount of fuel stored in the machine
//could be Integer.MAX_VALUE instead
}

@Override
Expand All @@ -96,13 +87,13 @@ public FluidStack getFluidInTank(int tank) {
@Override
public CompoundTag serializeNBT() {
CompoundTag tag = new CompoundTag();
tag.putLong(FRACTIONAL_FUEL_BUFFER_KEY, fractionalFuelBuffer);
tag.putLong(MILLI_FUEL_BUFFER_KEY, milliFuelBuffer);
return tag;
}

@Override
public void deserializeNBT(CompoundTag tag) {
fractionalFuelBuffer = tag.getLong(FRACTIONAL_FUEL_BUFFER_KEY);
milliFuelBuffer = tag.getLong(MILLI_FUEL_BUFFER_KEY);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -5,31 +5,14 @@

@ApiStatus.Experimental
public interface FluidToFuelConversion {
FluidToFuelConversion IDENTITY = new FluidToFuelConversion() {
@Override
public int getFuelMultiplier(FluidStack resource) {
return 1;
}

@Override
public int getFluidToFuelRatio(FluidStack resource) {
return 1;
}
};
int MILLI_FUEL_SCALE = 1000;

/**
* Multiplier for increasing the yield of fuel <br>
* fuel_yield = raw_fuel * multiplier
* @return value > 0
*/
int getFuelMultiplier(FluidStack resource);
FluidToFuelConversion IDENTITY = resource -> MILLI_FUEL_SCALE;

/**
* Fluid-To-Fuel Ration <br>
* If fluidToFuelRatio = 10, then for every 10 units of fluid, 1 raw_fuel will be generated
*
* @return value > 0
* @return Fuel (in milli units) per 1 milli-bucket of fluid
*/
int getFluidToFuelRatio(FluidStack resource);
int getMilliFuelPerUnit(FluidStack resource);

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.github.elenterius.biomancy.api.tribute.fluid;

import com.github.elenterius.biomancy.api.tribute.MilliTribute;
import net.minecraftforge.fluids.FluidStack;
import org.jetbrains.annotations.ApiStatus;

Expand All @@ -10,6 +9,6 @@ public interface FluidToTributeConversion {
/**
* @return Tribute (in milli units) per 1 milli-bucket of fluid
*/
MilliTribute getTributePerUnit(FluidStack resource);
FluidTribute getTributePerUnit(FluidStack resource);

}
Original file line number Diff line number Diff line change
@@ -1,31 +1,32 @@
package com.github.elenterius.biomancy.api.tribute;
package com.github.elenterius.biomancy.api.tribute.fluid;

import com.github.elenterius.biomancy.api.tribute.Tribute;
import com.github.elenterius.biomancy.util.SaturatedMath;

/**
* Values are measured in milli units.<br>
* E.g. 1000 MilliBiomass = 1 Biomass
* E.g. 1000 Fluid-Biomass = 1 Biomass
*/
public record MilliTribute(int biomass, int lifeEnergy, int successModifier, int diseaseModifier, int hostileModifier, int anomalyModifier) implements Tribute {
public record FluidTribute(int biomass, int lifeEnergy, int successModifier, int diseaseModifier, int hostileModifier, int anomalyModifier) implements Tribute {

public static final long UNIT_SCALE = 1000;

public static MilliTribute convertToMilliUnit(Tribute tribute) {
return convertToMilliUnit(tribute, 1);
public static FluidTribute of(Tribute tribute) {
return of(tribute, 1);
}

public static MilliTribute convertToMilliUnit(Tribute tribute, int ratio) {
if (tribute instanceof MilliTribute milliTribute) {
return milliTribute;
public static FluidTribute of(Tribute tribute, int ratio) {
if (tribute instanceof FluidTribute fluidTribute) {
return fluidTribute;
}

return new MilliTribute(
SaturatedMath.castToInteger(tribute.biomass() * MilliTribute.UNIT_SCALE / ratio),
SaturatedMath.castToInteger(tribute.lifeEnergy() * MilliTribute.UNIT_SCALE / ratio),
SaturatedMath.castToInteger(tribute.successModifier() * MilliTribute.UNIT_SCALE / ratio),
SaturatedMath.castToInteger(tribute.diseaseModifier() * MilliTribute.UNIT_SCALE / ratio),
SaturatedMath.castToInteger(tribute.hostileModifier() * MilliTribute.UNIT_SCALE / ratio),
SaturatedMath.castToInteger(tribute.anomalyModifier() * MilliTribute.UNIT_SCALE / ratio)
return new FluidTribute(
SaturatedMath.castToInteger(tribute.biomass() * FluidTribute.UNIT_SCALE / ratio),
SaturatedMath.castToInteger(tribute.lifeEnergy() * FluidTribute.UNIT_SCALE / ratio),
SaturatedMath.castToInteger(tribute.successModifier() * FluidTribute.UNIT_SCALE / ratio),
SaturatedMath.castToInteger(tribute.diseaseModifier() * FluidTribute.UNIT_SCALE / ratio),
SaturatedMath.castToInteger(tribute.hostileModifier() * FluidTribute.UNIT_SCALE / ratio),
SaturatedMath.castToInteger(tribute.anomalyModifier() * FluidTribute.UNIT_SCALE / ratio)
);
}

Expand Down Expand Up @@ -76,8 +77,8 @@ public Builder anomalyModifier(int anomalyModifier) {
return this;
}

public MilliTribute build() {
return new MilliTribute(biomass, lifeEnergy, successModifier, diseaseModifier, hostileModifier, anomalyModifier);
public FluidTribute build() {
return new FluidTribute(biomass, lifeEnergy, successModifier, diseaseModifier, hostileModifier, anomalyModifier);
}

}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.github.elenterius.biomancy.api.tribute.fluid;

import com.github.elenterius.biomancy.api.tribute.MilliTribute;
import com.github.elenterius.biomancy.api.tribute.SacrificeHandler;
import com.github.elenterius.biomancy.inventory.Notify;
import net.minecraft.nbt.CompoundTag;
Expand All @@ -11,6 +10,8 @@

public class FluidTributeConsumerHandler implements IFluidHandler, INBTSerializable<CompoundTag> {

public static final String MILLI_TRIBUTE_BUFFER_KEY = "MilliTributeBuffer";

private final SacrificeHandler sacrificeHandler;
private final Notify onChange;
private final long[] milliTributeBuffer = new long[6];
Expand All @@ -33,55 +34,55 @@ public int fill(FluidStack resource, FluidAction action) {
FluidToTributeConversion conversion = FluidTributes.getConversion(resource);
if (conversion == null) return 0;

MilliTribute milliTribute = conversion.getTributePerUnit(resource);
if (milliTribute.isEmpty()) return 0;
if (milliTribute.biomass() > 0 && sacrificeHandler.isBiomassFull()) return 0;
FluidTribute fluidTribute = conversion.getTributePerUnit(resource);
if (fluidTribute.isEmpty()) return 0;
if (fluidTribute.biomass() > 0 && sacrificeHandler.isBiomassFull()) return 0;

long amountToConsume = resource.getAmount();

int biomassYield = (int) ((milliTributeBuffer[0] + milliTribute.biomass() * amountToConsume) / MilliTribute.UNIT_SCALE);
int biomassYield = (int) ((milliTributeBuffer[0] + fluidTribute.biomass() * amountToConsume) / FluidTribute.UNIT_SCALE);
int biomassToFill = Math.min(sacrificeHandler.getMaxBiomass() - sacrificeHandler.getBiomassAmount(), biomassYield);

if (biomassToFill > 0) {
long biomassMissing = biomassToFill * MilliTribute.UNIT_SCALE - milliTributeBuffer[0];
amountToConsume = Mth.ceil((float) biomassMissing / milliTribute.biomass());
long biomassMissing = biomassToFill * FluidTribute.UNIT_SCALE - milliTributeBuffer[0];
amountToConsume = Mth.ceil((float) biomassMissing / fluidTribute.biomass());

if (action.simulate()) return (int) amountToConsume;

sacrificeHandler.addBiomass(biomassToFill);

long remainder = (milliTribute.biomass() * amountToConsume - biomassMissing);
long remainder = (fluidTribute.biomass() * amountToConsume - biomassMissing);
milliTributeBuffer[0] = remainder;
}

if (action.simulate()) return (int) amountToConsume;

int yield;

milliTributeBuffer[1] += milliTribute.lifeEnergy() * amountToConsume;
yield = (int) (milliTributeBuffer[1] / MilliTribute.UNIT_SCALE);
milliTributeBuffer[1] += fluidTribute.lifeEnergy() * amountToConsume;
yield = (int) (milliTributeBuffer[1] / FluidTribute.UNIT_SCALE);
sacrificeHandler.addLifeEnergy(yield);
milliTributeBuffer[1] -= yield * MilliTribute.UNIT_SCALE;
milliTributeBuffer[1] -= yield * FluidTribute.UNIT_SCALE;

milliTributeBuffer[2] += milliTribute.successModifier() * amountToConsume;
yield = (int) (milliTributeBuffer[2] / MilliTribute.UNIT_SCALE);
milliTributeBuffer[2] += fluidTribute.successModifier() * amountToConsume;
yield = (int) (milliTributeBuffer[2] / FluidTribute.UNIT_SCALE);
sacrificeHandler.addSuccess(yield);
milliTributeBuffer[2] -= yield * MilliTribute.UNIT_SCALE;
milliTributeBuffer[2] -= yield * FluidTribute.UNIT_SCALE;

milliTributeBuffer[3] += milliTribute.hostileModifier() * amountToConsume;
yield = (int) (milliTributeBuffer[3] / MilliTribute.UNIT_SCALE);
milliTributeBuffer[3] += fluidTribute.hostileModifier() * amountToConsume;
yield = (int) (milliTributeBuffer[3] / FluidTribute.UNIT_SCALE);
sacrificeHandler.addHostile(yield);
milliTributeBuffer[3] -= yield * MilliTribute.UNIT_SCALE;
milliTributeBuffer[3] -= yield * FluidTribute.UNIT_SCALE;

milliTributeBuffer[4] += milliTribute.diseaseModifier() * amountToConsume;
yield = (int) (milliTributeBuffer[4] / MilliTribute.UNIT_SCALE);
milliTributeBuffer[4] += fluidTribute.diseaseModifier() * amountToConsume;
yield = (int) (milliTributeBuffer[4] / FluidTribute.UNIT_SCALE);
sacrificeHandler.addDisease(yield);
milliTributeBuffer[4] -= yield * MilliTribute.UNIT_SCALE;
milliTributeBuffer[4] -= yield * FluidTribute.UNIT_SCALE;

milliTributeBuffer[5] += milliTribute.anomalyModifier() * amountToConsume;
yield = (int) (milliTributeBuffer[5] / MilliTribute.UNIT_SCALE);
milliTributeBuffer[5] += fluidTribute.anomalyModifier() * amountToConsume;
yield = (int) (milliTributeBuffer[5] / FluidTribute.UNIT_SCALE);
sacrificeHandler.addAnomaly(yield);
milliTributeBuffer[5] -= yield * MilliTribute.UNIT_SCALE;
milliTributeBuffer[5] -= yield * FluidTribute.UNIT_SCALE;

if (sacrificeHandler.isDirty()) {
onChange.invoke();
Expand Down Expand Up @@ -119,13 +120,13 @@ public FluidStack drain(int maxDrain, FluidAction action) {
@Override
public CompoundTag serializeNBT() {
CompoundTag tag = new CompoundTag();
tag.putLongArray("MilliTributeBuffer", milliTributeBuffer);
tag.putLongArray(MILLI_TRIBUTE_BUFFER_KEY, milliTributeBuffer);
return tag;
}

@Override
public void deserializeNBT(CompoundTag tag) {
long[] buffer = tag.getLongArray("MilliTributeBuffer");
long[] buffer = tag.getLongArray(MILLI_TRIBUTE_BUFFER_KEY);
System.arraycopy(buffer, 0, milliTributeBuffer, 0, milliTributeBuffer.length);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.github.elenterius.biomancy.api.tribute.fluid;

import com.github.elenterius.biomancy.api.tribute.MilliTribute;
import com.github.elenterius.biomancy.api.tribute.Tributes;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Items;
Expand All @@ -21,7 +20,7 @@ public final class FluidTributes {

private static final Map<ResourceLocation, FluidToTributeConversion> FLUIDS = new HashMap<>();

private static final MilliTribute MILK_MILLI_TRIBUTE = MilliTribute.convertToMilliUnit(Tributes.getTribute(Items.MILK_BUCKET.getDefaultInstance()), 1000);
private static final FluidTribute MILK_MILLI_TRIBUTE = FluidTribute.of(Tributes.getTribute(Items.MILK_BUCKET.getDefaultInstance()), 1000);

static {
register(ForgeMod.MILK.get(), resource -> MILK_MILLI_TRIBUTE);
Expand Down

0 comments on commit ae5ebe4

Please sign in to comment.