Skip to content

Commit

Permalink
Cleanup tool tanks taking advantage of tool stats and modifier traits
Browse files Browse the repository at this point in the history
Instead of shuffling the owner with every modifier implementing tanks, we have a single modifier that implements the tank, and other modifiers just add it as a trait
Modifiers using tanks can use the new helper to get and modify the fluid, instead of needing to talk to the module directly
Tank capacity has been moved from a volatile integer to a tool stat, reducing the need to have specialized modules for it. Custom tanks will just want to add their own custom stats or can handle capacity in another way if they prefer
Repackaged a few capability stuff as part of this commit
This refactor notably fixes fluid overflowing when tank capacity changes (#5190)
  • Loading branch information
KnightMiner committed May 20, 2024
1 parent 36eece4 commit 988d846
Show file tree
Hide file tree
Showing 33 changed files with 450 additions and 448 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,16 @@
"level_display": "tconstruct:default",
"modules": [
{
"type": "tconstruct:tank",
"capacity": 1000,
"scale_capacity": true
"type": "tconstruct:stat_boost",
"each_level": 1000.0,
"operation": "add",
"stat": "tconstruct:tank_capacity"
},
{
"type": "tconstruct:trait",
"fixed_level": true,
"level": 1,
"name": "tconstruct:tank_handler"
}
],
"tooltip_display": "always"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,7 @@
import slimeknights.tconstruct.library.client.model.FluidContainerModel;
import slimeknights.tconstruct.library.modifiers.Modifier;
import slimeknights.tconstruct.library.modifiers.ModifierEntry;
import slimeknights.tconstruct.library.tools.capability.ToolFluidCapability;
import slimeknights.tconstruct.library.tools.capability.ToolFluidCapability.FluidModifierHook;
import slimeknights.tconstruct.library.tools.capability.fluid.ToolTankHelper;
import slimeknights.tconstruct.library.tools.nbt.IToolStackView;

import javax.annotation.Nullable;
Expand All @@ -44,34 +43,28 @@ public class FluidModifierModel extends NormalModifierModel {
private static final Vector3f ORIGIN = new Vector3f(-0.5f, -0.5f, -0.5f);

/** Constant unbaked model instance, as they are all the same */
public static final IUnbakedModifierModel UNBAKED_INSTANCE = (smallGetter, largeGetter) -> {
Material smallTexture = smallGetter.apply("");
Material largeTexture = largeGetter.apply("");
Material smallFull = smallGetter.apply("_full");
Material largeFull = largeGetter.apply("_full");
if (smallTexture != null || largeTexture != null) {
return new FluidModifierModel(smallTexture, largeTexture, smallFull, largeFull);
}
return null;
};
public static final IUnbakedModifierModel UNBAKED_INSTANCE = new Unbaked(ToolTankHelper.TANK_HELPER);

/** Logic for fetching the fluid */
protected final ToolTankHelper helper;
/** Textures to show */
protected final Material[] fluidTextures;

protected FluidModifierModel(@Nullable Material smallTexture, @Nullable Material largeTexture, Material[] fluidTextures) {
protected FluidModifierModel(ToolTankHelper helper, @Nullable Material smallTexture, @Nullable Material largeTexture, Material[] fluidTextures) {
super(smallTexture, largeTexture);
this.helper = helper;
this.fluidTextures = fluidTextures;
}

public FluidModifierModel(@Nullable Material smallTexture, @Nullable Material largeTexture,
@Nullable Material smallFull, @Nullable Material largeFull) {
this(smallTexture, largeTexture, new Material[] { smallFull, largeFull });
public FluidModifierModel(ToolTankHelper helper, @Nullable Material smallTexture, @Nullable Material largeTexture,
@Nullable Material smallFull, @Nullable Material largeFull) {
this(helper, smallTexture, largeTexture, new Material[] { smallFull, largeFull });
}

@Nullable
@Override
public Object getCacheKey(IToolStackView tool, ModifierEntry entry) {
FluidStack fluid = entry.getHook(ToolFluidCapability.HOOK).getFluidInTank(tool, entry, 0);
FluidStack fluid = helper.getFluid(tool);
if (!fluid.isEmpty()) {
// cache by modifier and fluid
return new FluidModifierCacheKey(entry.getModifier(), fluid.getFluid());
Expand All @@ -80,20 +73,19 @@ public Object getCacheKey(IToolStackView tool, ModifierEntry entry) {
}

@Nullable
protected Material getTemplate(FluidModifierHook tank, IToolStackView tool, ModifierEntry entry, FluidStack fluid, boolean isLarge) {
protected Material getTemplate(IToolStackView tool, ModifierEntry entry, FluidStack fluid, boolean isLarge) {
return fluidTextures[(isLarge ? 1 : 0)];
}

@Override
public void addQuads(IToolStackView tool, ModifierEntry entry, Function<Material,TextureAtlasSprite> spriteGetter, Transformation transforms, boolean isLarge, int startTintIndex, Consumer<Collection<BakedQuad>> quadConsumer, @Nullable ItemLayerPixels pixels) {
// first, determine stored fluid
// modifier must be tank
FluidModifierHook tank = entry.getHook(ToolFluidCapability.HOOK);
FluidStack fluid = tank.getFluidInTank(tool, entry, 0);
FluidStack fluid = helper.getFluid(tool);
// must have fluid
if (!fluid.isEmpty()) {
// must have texture for the proper state
Material template = getTemplate(tank, tool, entry, fluid, isLarge);
Material template = getTemplate(tool, entry, fluid, isLarge);
if (template != null) {
// fluid properties
IClientFluidTypeExtensions attributes = IClientFluidTypeExtensions.of(fluid.getFluid());
Expand Down Expand Up @@ -122,4 +114,17 @@ public void addQuads(IToolStackView tool, ModifierEntry entry, Function<Material

/** Cache key for the model */
private record FluidModifierCacheKey(Modifier modifier, Fluid fluid) {}

public record Unbaked(ToolTankHelper helper) implements IUnbakedModifierModel {
@Nullable
@Override
public IBakedModifierModel forTool(Function<String,Material> smallGetter, Function<String,Material> largeGetter) {
Material smallTexture = smallGetter.apply("");
Material largeTexture = largeGetter.apply("");
if (smallTexture != null || largeTexture != null) {
return new FluidModifierModel(helper, smallTexture, largeTexture, smallGetter.apply("_full"), largeGetter.apply("_full"));
}
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,57 +5,61 @@
import net.minecraftforge.fluids.FluidStack;
import slimeknights.tconstruct.library.modifiers.Modifier;
import slimeknights.tconstruct.library.modifiers.ModifierEntry;
import slimeknights.tconstruct.library.tools.capability.ToolFluidCapability;
import slimeknights.tconstruct.library.tools.capability.ToolFluidCapability.FluidModifierHook;
import slimeknights.tconstruct.library.tools.capability.fluid.ToolTankHelper;
import slimeknights.tconstruct.library.tools.nbt.IToolStackView;

import javax.annotation.Nullable;
import java.util.function.Function;

/**
* Model for tank modifiers, also displays the fluid
*/
public class TankModifierModel extends FluidModifierModel {
/** Constant unbaked model instance, as they are all the same */
public static final IUnbakedModifierModel UNBAKED_INSTANCE = (smallGetter, largeGetter) -> {
Material smallTexture = smallGetter.apply("");
Material largeTexture = largeGetter.apply("");
Material smallPartial = smallGetter.apply("_partial");
Material largePartial = largeGetter.apply("_partial");
Material smallFull = smallGetter.apply("_full");
Material largeFull = largeGetter.apply("_full");
if (smallTexture != null || largeTexture != null) {
return new TankModifierModel(smallTexture, largeTexture, smallPartial, largePartial, smallFull, largeFull);
}
return null;
};
public static final IUnbakedModifierModel UNBAKED_INSTANCE = new Unbaked(ToolTankHelper.TANK_HELPER);

public TankModifierModel(@Nullable Material smallTexture, @Nullable Material largeTexture,
public TankModifierModel(ToolTankHelper helper,
@Nullable Material smallTexture, @Nullable Material largeTexture,
@Nullable Material smallPartial, @Nullable Material largePartial,
@Nullable Material smallFull, @Nullable Material largeFull) {
super(smallTexture, largeTexture, new Material[] { smallPartial, largePartial, smallFull, largeFull });
super(helper, smallTexture, largeTexture, new Material[] { smallPartial, largePartial, smallFull, largeFull });
}

@Nullable
@Override
public Object getCacheKey(IToolStackView tool, ModifierEntry entry) {
FluidModifierHook tank = entry.getHook(ToolFluidCapability.HOOK);
FluidStack fluid = tank.getFluidInTank(tool, entry, 0);
FluidStack fluid = helper.getFluid(tool);
if (!fluid.isEmpty()) {
// cache by modifier, fluid, and not being full
return new TankModifierCacheKey(entry.getModifier(), fluid.getFluid(), fluid.getAmount() < tank.getTankCapacity(tool, entry, 0));
return new TankModifierCacheKey(entry.getModifier(), fluid.getFluid(), fluid.getAmount() < helper.getCapacity(tool));
}
return entry.getModifier();
}

@Override
@Nullable
protected Material getTemplate(FluidModifierHook tank, IToolStackView tool, ModifierEntry entry, FluidStack fluid, boolean isLarge) {
boolean isFull = fluid.getAmount() == tank.getTankCapacity(tool, entry, 0);
protected Material getTemplate(IToolStackView tool, ModifierEntry entry, FluidStack fluid, boolean isLarge) {
boolean isFull = fluid.getAmount() == helper.getCapacity(tool);
return fluidTextures[(isFull ? 2 : 0) | (isLarge ? 1 : 0)];
}

/**
* Cache key for the model
*/
private record TankModifierCacheKey(Modifier modifier, Fluid fluid, boolean isPartial) {}

public record Unbaked(ToolTankHelper helper) implements IUnbakedModifierModel {
@Nullable
@Override
public IBakedModifierModel forTool(Function<String,Material> smallGetter, Function<String,Material> largeGetter) {
Material smallTexture = smallGetter.apply("");
Material largeTexture = largeGetter.apply("");
if (smallTexture != null || largeTexture != null) {
return new TankModifierModel(helper, smallTexture, largeTexture,
smallGetter.apply("_partial"), largeGetter.apply("_partial"),
smallGetter.apply("_full"), largeGetter.apply("_full"));
}
return null;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
import slimeknights.tconstruct.library.modifiers.hook.interaction.KeybindInteractModifierHook;
import slimeknights.tconstruct.library.modifiers.impl.InventoryModifier;
import slimeknights.tconstruct.library.module.ModuleHookMap.Builder;
import slimeknights.tconstruct.library.tools.capability.ToolInventoryCapability;
import slimeknights.tconstruct.library.tools.capability.inventory.ToolInventoryCapability;
import slimeknights.tconstruct.library.tools.definition.module.ToolHooks;
import slimeknights.tconstruct.library.tools.definition.module.interaction.DualOptionInteraction;
import slimeknights.tconstruct.library.tools.nbt.IToolStackView;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@
import slimeknights.tconstruct.library.modifiers.hook.build.ValidateModifierHook;
import slimeknights.tconstruct.library.modifiers.hook.build.VolatileDataModifierHook;
import slimeknights.tconstruct.library.module.ModuleHookMap.Builder;
import slimeknights.tconstruct.library.tools.capability.ToolInventoryCapability;
import slimeknights.tconstruct.library.tools.capability.ToolInventoryCapability.InventoryModifierHook;
import slimeknights.tconstruct.library.tools.capability.inventory.ToolInventoryCapability;
import slimeknights.tconstruct.library.tools.capability.inventory.ToolInventoryCapability.InventoryModifierHook;
import slimeknights.tconstruct.library.tools.nbt.IModDataView;
import slimeknights.tconstruct.library.tools.nbt.INamespacedNBTView;
import slimeknights.tconstruct.library.tools.nbt.IToolContext;
Expand Down

This file was deleted.

Loading

0 comments on commit 988d846

Please sign in to comment.