Skip to content

Commit

Permalink
Refactor how containers are implemented and exposed as capabilities o…
Browse files Browse the repository at this point in the history
…n itemstacks to properly use the data component system
  • Loading branch information
pupnewfster committed Apr 28, 2024
1 parent a4697f7 commit 2a8eb84
Show file tree
Hide file tree
Showing 137 changed files with 4,761 additions and 1,919 deletions.
10 changes: 10 additions & 0 deletions src/api/java/mekanism/api/chemical/ChemicalStack.java
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,16 @@ public void encode(RegistryFriendlyByteBuf buf, STACK stack) {
case PIGMENT -> PigmentStack.MAP_CODEC;
case SLURRY -> SlurryStack.MAP_CODEC;
});
/**
* Codec to get any kind of chemical stack, based on a "chemicalType" field.
*
* @see ChemicalType
* @see mekanism.api.chemical.merged.BoxedChemicalStack
* @since 10.6.0
*/
//TODO - 1.20.5: Re-evaluate if we wan this defaulting to an empty gas stack or to try and get the same stack type as it was?
public static final Codec<ChemicalStack<?>> BOXED_OPTIONAL_CODEC = ExtraCodecs.optionalEmptyMap(BOXED_CODEC).xmap(optional -> optional.orElse(GasStack.EMPTY),
stack -> stack.isEmpty() ? Optional.empty() : Optional.of(stack));
/**
* StreamCodec to get any kind of chemical stack (that does not accept empty stacks), based on a "chemicalType" field.
*
Expand Down
2 changes: 1 addition & 1 deletion src/api/java/mekanism/api/energy/IEnergyContainer.java
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ default void setEmpty() {
* @return Amount of energy needed
*/
default FloatingLong getNeeded() {
return FloatingLong.ZERO.max(getMaxEnergy().subtract(getEnergy()));
return getMaxEnergy().subtract(getEnergy());
}

@Override
Expand Down
5 changes: 5 additions & 0 deletions src/api/java/mekanism/api/fluid/IExtendedFluidTank.java
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,11 @@ default int getNeeded() {
return Math.max(0, getCapacity() - getFluidAmount());
}

@Override
default int getFluidAmount() {
return getFluid().getAmount();
}

@Override
default CompoundTag serializeNBT(HolderLookup.Provider provider) {
CompoundTag nbt = new CompoundTag();
Expand Down
7 changes: 5 additions & 2 deletions src/api/java/mekanism/api/inventory/IInventorySlot.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ default ItemStack extractItem(int amount, Action action, AutomationType automati
ItemStack current = getStack();
//Ensure that if this slot allows going past the max stack size of an item, that when extracting we don't act as if we have more than
// the max stack size, as the JavaDoc for IItemHandler requires that the returned stack is not larger than its stack size
int currentAmount = Math.min(getCount(), current.getMaxStackSize());
int currentAmount = Math.min(current.getCount(), current.getMaxStackSize());
if (currentAmount < amount) {
//If we are trying to extract more than we have, just change it so that we are extracting it all
amount = currentAmount;
Expand Down Expand Up @@ -179,7 +179,9 @@ default ItemStack extractItem(int amount, Action action, AutomationType automati
* @return A slot for use in a container that represents this {@link IInventorySlot}, or null if this slot should not be added.
*/
@Nullable
Slot createContainerSlot();
default Slot createContainerSlot() {
return null;
}

/**
* Convenience method for modifying the size of the stored stack.
Expand Down Expand Up @@ -312,6 +314,7 @@ default CompoundTag serializeNBT(HolderLookup.Provider provider) {
* @since 10.5.0
*/
default boolean isCompatible(IInventorySlot other) {
//TODO - 1.20.5: Remove this? I don't think it is necessary anymore
return getClass() == other.getClass() && ItemStack.matches(getStack(), other.getStack());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import mekanism.api.annotations.NothingNullByDefault;
import mekanism.api.providers.IBlockProvider;
import mekanism.common.Mekanism;
import mekanism.common.attachments.containers.AttachedContainers;
import mekanism.common.attachments.containers.ContainerType;
import mekanism.common.block.BlockRadioactiveWasteBarrel;
import mekanism.common.block.attribute.Attribute;
Expand Down Expand Up @@ -183,29 +182,28 @@ protected void dropSelfWithContents(Collection<? extends Holder<Block>> blockPro
boolean hasContainers = false;
CopyContainersLootFunction.Builder containerBuilder = CopyContainersLootFunction.builder();
for (ContainerType<?, ?, ?> type : ContainerType.TYPES) {
AttachedContainers<?> attachment = type.getAttachment(stack);
List<?> containers = tileEntity.persists(type) ? type.getContainers(tileEntity) : Collections.emptyList();
List<?> attachmentContainers = attachment == null ? Collections.emptyList() : attachment.getContainers();
if (containers.size() == attachmentContainers.size()) {
int attachmentContainers = type.getContainerCount(stack);
if (containers.size() == attachmentContainers) {
if (!containers.isEmpty()) {
containerBuilder.copy(type);
hasContainers = true;
if (type != ContainerType.ENERGY && type != ContainerType.HEAT) {
hasContents = true;
}
}
} else if (attachmentContainers.isEmpty()) {
} else if (attachmentContainers == 0) {
//TODO: Improve how we handle skipping warnings for known missing types
if (type == ContainerType.ITEM && block.asItem() instanceof ItemBlockPersonalStorage) {
//We don't want explosions causing personal storage items to be directly destroyed. It is also known that the attachment is missing
hasContents = true;
} else if (type != ContainerType.GAS || !(block instanceof BlockRadioactiveWasteBarrel)) {
Mekanism.logger.warn("Container type: {}, item missing attachments: {}", type.getAttachmentName(), RegistryUtils.getName(block));
Mekanism.logger.warn("Container type: {}, item missing attachments: {}", type.getComponentName(), RegistryUtils.getName(block));
}
} else if (containers.isEmpty()) {
Mekanism.logger.warn("Container type: {}, item has attachments but block doesn't have containers: {}", type.getAttachmentName(), RegistryUtils.getName(block));
Mekanism.logger.warn("Container type: {}, item has attachments but block doesn't have containers: {}", type.getComponentName(), RegistryUtils.getName(block));
} else {
Mekanism.logger.warn("Container type: {}, has {} item attachments and block has {} containers: {}", type.getAttachmentName(), attachmentContainers.size(),
Mekanism.logger.warn("Container type: {}, has {} item attachments and block has {} containers: {}", type.getComponentName(), attachmentContainers,
containers.size(), RegistryUtils.getName(block));
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
package mekanism.generators.common.registries;

import java.util.function.Supplier;
import mekanism.api.chemical.ChemicalTankBuilder;
import mekanism.api.chemical.gas.attribute.GasAttributes.Fuel;
import mekanism.common.attachments.containers.ContainerType;
import mekanism.common.attachments.containers.chemical.gas.GasTanksBuilder;
import mekanism.common.attachments.containers.fluid.FluidTanksBuilder;
import mekanism.common.attachments.containers.heat.HeatCapacitorsBuilder;
import mekanism.common.attachments.containers.item.ItemSlotsBuilder;
import mekanism.common.block.basic.BlockStructuralGlass;
import mekanism.common.block.interfaces.IHasDescription;
import mekanism.common.block.prefab.BlockBasicMultiblock;
import mekanism.common.block.prefab.BlockTile;
import mekanism.common.block.prefab.BlockTile.BlockTileModel;
import mekanism.common.capabilities.chemical.variable.RateLimitGasTank;
import mekanism.common.capabilities.fluid.BasicFluidTank;
import mekanism.common.capabilities.fluid.item.RateLimitFluidTank;
import mekanism.common.capabilities.heat.BasicHeatCapacitor;
import mekanism.common.content.blocktype.BlockTypeTile;
import mekanism.common.inventory.slot.ItemSlotsBuilder;
import mekanism.common.inventory.slot.chemical.GasInventorySlot;
import mekanism.common.item.block.ItemBlockTooltip;
import mekanism.common.registration.impl.BlockDeferredRegister;
import mekanism.common.registration.impl.BlockRegistryObject;
Expand All @@ -30,7 +27,6 @@
import mekanism.generators.common.item.ItemBlockFissionLogicAdapter;
import mekanism.generators.common.item.ItemBlockFusionLogicAdapter;
import mekanism.generators.common.item.generator.ItemBlockWindGenerator;
import mekanism.generators.common.slot.FluidFuelInventorySlot;
import mekanism.generators.common.tile.TileEntityAdvancedSolarGenerator;
import mekanism.generators.common.tile.TileEntityBioGenerator;
import mekanism.generators.common.tile.TileEntityGasGenerator;
Expand All @@ -55,9 +51,7 @@
import mekanism.generators.common.tile.turbine.TileEntityTurbineVent;
import net.minecraft.tags.FluidTags;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.material.Fluids;
import net.minecraft.world.level.material.MapColor;
import net.neoforged.neoforge.fluids.FluidStack;

public class GeneratorsBlocks {

Expand All @@ -69,54 +63,50 @@ private GeneratorsBlocks() {
public static final BlockRegistryObject<BlockTileModel<TileEntityHeatGenerator, Generator<TileEntityHeatGenerator>>, ItemBlockTooltip<BlockTileModel<TileEntityHeatGenerator, Generator<TileEntityHeatGenerator>>>> HEAT_GENERATOR =
BLOCKS.register("heat_generator", () -> new BlockTileModel<>(GeneratorsBlockTypes.HEAT_GENERATOR, properties -> properties.mapColor(MapColor.METAL)), ItemBlockTooltip::new)
.forItemHolder(holder -> holder
.addAttachmentOnlyContainer(ContainerType.FLUID, stack -> RateLimitFluidTank.createBasicItem(MekanismGeneratorsConfig.generators.heatTankCapacity,
BasicFluidTank.manualOnly, BasicFluidTank.alwaysTrueBi,
fluidStack -> fluidStack.is(FluidTags.LAVA)
)).addAttachmentOnlyContainer(ContainerType.HEAT, stack -> BasicHeatCapacitor.createBasicItem(TileEntityHeatGenerator.HEAT_CAPACITY,
TileEntityHeatGenerator.INVERSE_CONDUCTION_COEFFICIENT, TileEntityHeatGenerator.INVERSE_INSULATION_COEFFICIENT
)).addAttachmentOnlyContainers(ContainerType.ITEM, stack -> ItemSlotsBuilder.builder(stack)
.addFluidSlot(0, (tank, listener, x, y) -> FluidFuelInventorySlot.forFuel(tank,
s -> s.getBurnTime(null) / 20,
size -> new FluidStack(Fluids.LAVA, size),
listener, x, y)
).addEnergy()
.addAttachmentOnlyContainers(ContainerType.FLUID, () -> FluidTanksBuilder.builder()
.addBasic(MekanismGeneratorsConfig.generators.heatTankCapacity, fluid -> fluid.is(FluidTags.LAVA))
.build()
).addAttachmentOnlyContainers(ContainerType.HEAT, () -> HeatCapacitorsBuilder.builder()
.addBasic(TileEntityHeatGenerator.HEAT_CAPACITY, TileEntityHeatGenerator.INVERSE_CONDUCTION_COEFFICIENT, TileEntityHeatGenerator.INVERSE_INSULATION_COEFFICIENT)
.build()
).addAttachmentOnlyContainers(ContainerType.ITEM, () -> ItemSlotsBuilder.builder()
.addFluidFuelSlot(0, s -> s.getBurnTime(null) > 0)
.addEnergy()
.build()
)
);
public static final BlockRegistryObject<BlockTileModel<TileEntitySolarGenerator, Generator<TileEntitySolarGenerator>>, ItemBlockTooltip<BlockTileModel<TileEntitySolarGenerator, Generator<TileEntitySolarGenerator>>>> SOLAR_GENERATOR =
BLOCKS.register("solar_generator", () -> new BlockTileModel<>(GeneratorsBlockTypes.SOLAR_GENERATOR, properties -> properties.mapColor(MapColor.COLOR_BLUE)), ItemBlockTooltip::new)
.forItemHolder(holder -> holder.addAttachmentOnlyContainers(ContainerType.ITEM, stack -> ItemSlotsBuilder.builder(stack).addEnergy().build()));
.forItemHolder(holder -> holder.addAttachmentOnlyContainers(ContainerType.ITEM, () -> ItemSlotsBuilder.builder().addEnergy().build()));
public static final BlockRegistryObject<BlockTileModel<TileEntityGasGenerator, Generator<TileEntityGasGenerator>>, ItemBlockTooltip<BlockTileModel<TileEntityGasGenerator, Generator<TileEntityGasGenerator>>>> GAS_BURNING_GENERATOR =
BLOCKS.register("gas_burning_generator", () -> new BlockTileModel<>(GeneratorsBlockTypes.GAS_BURNING_GENERATOR, properties -> properties.mapColor(BlockResourceInfo.STEEL.getMapColor())), ItemBlockTooltip::new)
.forItemHolder(holder -> holder
.addAttachmentOnlyContainer(ContainerType.GAS, stack -> RateLimitGasTank.createBasicItem(MekanismGeneratorsConfig.generators.gbgTankCapacity,
ChemicalTankBuilder.GAS.manualOnly, ChemicalTankBuilder.GAS.alwaysTrueBi,
gas -> gas.has(Fuel.class)
)).addAttachmentOnlyContainers(ContainerType.ITEM, stack -> ItemSlotsBuilder.builder(stack)
.addGasSlot(0, GasInventorySlot::fill)
.addAttachmentOnlyContainers(ContainerType.GAS, () -> GasTanksBuilder.builder()
.addBasic(MekanismGeneratorsConfig.generators.gbgTankCapacity, gas -> gas.has(Fuel.class))
.build()
).addAttachmentOnlyContainers(ContainerType.ITEM, () -> ItemSlotsBuilder.builder()
.addGasFillSlot(0)
.addEnergy()
.build()
)
);
public static final BlockRegistryObject<BlockTileModel<TileEntityBioGenerator, Generator<TileEntityBioGenerator>>, ItemBlockTooltip<BlockTileModel<TileEntityBioGenerator, Generator<TileEntityBioGenerator>>>> BIO_GENERATOR =
BLOCKS.register("bio_generator", () -> new BlockTileModel<>(GeneratorsBlockTypes.BIO_GENERATOR, properties -> properties.mapColor(BlockResourceInfo.STEEL.getMapColor())), ItemBlockTooltip::new)
.forItemHolder(holder -> holder
.addAttachmentOnlyContainer(ContainerType.FLUID, stack -> RateLimitFluidTank.createBasicItem(MekanismGeneratorsConfig.generators.bioTankCapacity,
BasicFluidTank.manualOnly, BasicFluidTank.alwaysTrueBi,
fluidStack -> fluidStack.is(GeneratorTags.Fluids.BIOETHANOL)
)).addAttachmentOnlyContainers(ContainerType.ITEM, stack -> ItemSlotsBuilder.builder(stack)
.addFluidSlot(0, (tank, listener, x, y) -> FluidFuelInventorySlot.forFuel(tank, s -> s.is(MekanismTags.Items.FUELS_BIO) ? 200 : s.is(MekanismTags.Items.FUELS_BLOCK_BIO) ? 200 * 9 : 0,
GeneratorsFluids.BIOETHANOL::getFluidStack,
listener, x, y)
).addEnergy()
.addAttachmentOnlyContainers(ContainerType.FLUID, () -> FluidTanksBuilder.builder()
.addBasic(MekanismGeneratorsConfig.generators.bioTankCapacity, fluid -> fluid.is(GeneratorTags.Fluids.BIOETHANOL))
.build()
).addAttachmentOnlyContainers(ContainerType.ITEM, () -> ItemSlotsBuilder.builder()
.addFluidFuelSlot(0, s -> s.is(MekanismTags.Items.FUELS_BIO) || s.is(MekanismTags.Items.FUELS_BLOCK_BIO))
.addEnergy()
.build()
)
);
public static final BlockRegistryObject<BlockTileModel<TileEntityAdvancedSolarGenerator, Generator<TileEntityAdvancedSolarGenerator>>, ItemBlockTooltip<BlockTileModel<TileEntityAdvancedSolarGenerator, Generator<TileEntityAdvancedSolarGenerator>>>> ADVANCED_SOLAR_GENERATOR =
BLOCKS.register("advanced_solar_generator", () -> new BlockTileModel<>(GeneratorsBlockTypes.ADVANCED_SOLAR_GENERATOR, properties -> properties.mapColor(MapColor.COLOR_BLUE)), ItemBlockTooltip::new)
.forItemHolder(holder -> holder.addAttachmentOnlyContainers(ContainerType.ITEM, stack -> ItemSlotsBuilder.builder(stack).addEnergy().build()));
.forItemHolder(holder -> holder.addAttachmentOnlyContainers(ContainerType.ITEM, () -> ItemSlotsBuilder.builder().addEnergy().build()));
public static final BlockRegistryObject<BlockTileModel<TileEntityWindGenerator, Generator<TileEntityWindGenerator>>, ItemBlockWindGenerator> WIND_GENERATOR = BLOCKS.register("wind_generator", () -> new BlockTileModel<>(GeneratorsBlockTypes.WIND_GENERATOR, properties -> properties.mapColor(MapColor.METAL)), ItemBlockWindGenerator::new)
.forItemHolder(holder -> holder.addAttachmentOnlyContainers(ContainerType.ITEM, stack -> ItemSlotsBuilder.builder(stack).addEnergy().build()));
.forItemHolder(holder -> holder.addAttachmentOnlyContainers(ContainerType.ITEM, () -> ItemSlotsBuilder.builder().addEnergy().build()));

public static final BlockRegistryObject<BlockTurbineRotor, ItemBlockTooltip<BlockTurbineRotor>> TURBINE_ROTOR = registerTooltipBlock("turbine_rotor", BlockTurbineRotor::new);
public static final BlockRegistryObject<BlockTile<TileEntityRotationalComplex, BlockTypeTile<TileEntityRotationalComplex>>, ItemBlockTooltip<BlockTile<TileEntityRotationalComplex, BlockTypeTile<TileEntityRotationalComplex>>>> ROTATIONAL_COMPLEX = registerTooltipBlock("rotational_complex", () -> new BlockTile<>(GeneratorsBlockTypes.ROTATIONAL_COMPLEX, properties -> properties.mapColor(BlockResourceInfo.STEEL.getMapColor())));
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package mekanism.generators.common.registries;

import mekanism.common.attachments.containers.ContainerType;
import mekanism.common.capabilities.chemical.variable.RateLimitGasTank;
import mekanism.common.attachments.containers.chemical.gas.GasTanksBuilder;
import mekanism.common.item.ItemModule;
import mekanism.common.registration.impl.ItemDeferredRegister;
import mekanism.common.registration.impl.ItemRegistryObject;
Expand All @@ -22,11 +22,10 @@ private GeneratorsItems() {

public static final ItemRegistryObject<Item> SOLAR_PANEL = ITEMS.register("solar_panel");
public static final ItemRegistryObject<ItemHohlraum> HOHLRAUM = ITEMS.registerItem("hohlraum", ItemHohlraum::new)
.addAttachedContainerCapability(ContainerType.GAS, stack -> RateLimitGasTank.createInternalStorage(
MekanismGeneratorsConfig.generators.hohlraumFillRate,
MekanismGeneratorsConfig.generators.hohlraumMaxGas,
gas -> gas.is(GeneratorTags.Gases.FUSION_FUEL)
), MekanismGeneratorsConfig.generators);
.addAttachedContainerCapabilities(ContainerType.GAS, () -> GasTanksBuilder.builder()
.addInternalStorage(MekanismGeneratorsConfig.generators.hohlraumFillRate, MekanismGeneratorsConfig.generators.hohlraumMaxGas,
gas -> gas.is(GeneratorTags.Gases.FUSION_FUEL)
).build(), MekanismGeneratorsConfig.generators);
public static final ItemRegistryObject<ItemTurbineBlade> TURBINE_BLADE = ITEMS.registerItem("turbine_blade", ItemTurbineBlade::new);

public static final ItemRegistryObject<ItemModule> MODULE_SOLAR_RECHARGING = ITEMS.registerModule(GeneratorsModules.SOLAR_RECHARGING_UNIT, Rarity.RARE);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public static FluidFuelInventorySlot forFuel(IExtendedFluidTank fluidTank, ToInt
//Always allow extraction if something went horribly wrong, and we are not a fluid item AND we can't provide a valid type of chemical
// This might happen after a reload for example
return fuelValue.applyAsInt(stack) == 0;
}, fillPredicate.or(stack -> fuelValue.applyAsInt(stack) > 0), listener, x, y);
}, stack -> fuelValue.applyAsInt(stack) > 0 || fillPredicate.test(stack), listener, x, y);
}

private final IntFunction<@NotNull FluidStack> fuelCreator;
Expand Down
Loading

0 comments on commit 2a8eb84

Please sign in to comment.