Holders
Holders are used to store/handle specific data like energy amount or side config data and provide an interface for networks.
Every NetworkedTileEntity
has an energyHolder
, an itemHolder
and a fluidHolder
property. To make them functional,
you need to override them in your TileEntity implementation. All 3 holders have a common property: The connectionConfig
which is used to determine what NetworkConnectionType
each BlockFace
has. The connection types NONE
, INSERT
,
EXTRACT
and BUFFER
are available. The BUFFER
connection type is used for faces that have both an insert and
extract connection. All holder constructors take a lambda to configure the default connection/side config.
EnergyHolder
Before overriding the energyHolder
property, you need to choose the best implementation for your TileEntity.
- ConsumerEnergyHolder: Used for TileEntities that need and consume energy to operate.
- ProviderEnergyHolder: Used for TileEntities that generate energy.
- BufferEnergyHolder: Used for TileEntities that store energy and transfer it to other tileEntities when needed. E.g. power cells.
These all have different constructors. You can open the example box below to see how each one is implemented.
EnergyHolder implementations
override val energyHolder = ConsumerEnergyHolder(
this, // (1)!
MAX_ENERGY, // (2)!
ENERGY_PER_TICK, // (3)!
null, // (4)!
upgradeHolder // (5)!
) { createSideConfig(NetworkConnectionType.INSERT, BlockSide.FRONT) } // (6)!
- The parent TileEntity that the holder is attached to.
- A config reloadable value of the maximum amount of energy that can be stored (See Config for more info). The actual maximum amount is calculated with upgrades.
- (optional) Another config reloadable value that stores the amount of energy that is consumed per tick. While this value is not required, it is still recommended to set it since it will automatically calculate the actual energy consumption with upgrades.
- (optional) A second energy consumption rate if needed.
- (optional) A
UpgradeHolder
instance. See UpgradeHolder for more info. - A lambda that creates a default side config for the holder. You can use
createSideConfig
orcreateExclusiveSideConfig
if you have a simple default config. In this case, a config with insert on all sides except the front will be created.
override val energyHolder = ProviderEnergyHolder(
this, // (1)!
MAX_ENERGY, // (2)!
ENERGY_PER_TICK, // (3)!
upgradeHolder // (4)!
) { createSideConfig(NetworkConnectionType.EXTRACT, FRONT) } // (5)!
- The parent TileEntity that the holder is attached to.
- A config reloadable value that stores the maximum amount of energy that can be stored (See Config for more info). The actual maximum amount is calculated with upgrades.
- (optional) Another config reloadable value that stores the amount of energy that is generated per tick. While this value is not required, it is still recommended to set it since it will automatically calculate the actual energy generation with upgrades.
- (optional) A
UpgradeHolder
instance. See UpgradeHolder for more info. - A lambda that creates a default side config for the holder. You can use
createSideConfig
orcreateExclusiveSideConfig
if you have a simple default config. In this case, a config with extract on all sides except the front will be created.
override val energyHolder = BufferEnergyHolder(
this, // (1)!
MAX_ENERGY, // (2)!
false // (3)!
) { createSideConfig(BUFFER) } // (4)!
- The parent TileEntity that the holder is attached to.
- A config reloadable value that stores the maximum amount of energy that can be stored (See Config for more info). The actual maximum amount is calculated with upgrades.
- (optional) A boolean value that determines if the holder should provide an infinite amount of energy. Can be used for creative blocks (E.g. a creative power cell).
- A lambda that creates a default side config for the holder. You can use
createSideConfig
orcreateExclusiveSideConfig
if you have a simple default config. In this case, a config with buffer on all sides will be created.
ItemHolder
VirtualInventory
Make sure to read the VirtualInventory page on the InvUI wiki before proceeding!
ItemHolders
are used to provide an interface for networks to interact with your TileEntity's inventories. Depending on
what your TileEntity does, you may need more than one inventory (For example, a pulverizer with an input and output inventory).
Unlike EnergyHolders
, ItemHolders
only have one default implementation called NovaItemHolder
. To create a
VirtualInventory
use the getInventory
functions. For this example, let's create an input and output inventory.
If you want to handle inventory changes, you can pass a lambda or method reference to the getInventory
function.
private val inputInv = getInventory("input", 1, ::handleInputUpdate)
// ...
private fun handleInputUpdate(event: ItemUpdateEvent) {
// ...
}
Now we can override the itemHolder
property.
override val itemHolder = NovaItemHolder(
this, // (1)!
inputInv to NetworkConnectionType.BUFFER, // (2)!
outputInv to NetworkConnectionType.EXTRACT // (3)!
) { createSideConfig(NetworkConnectionType.INSERT, BlockSide.FRONT) } // (4)!
- The parent TileEntity that the holder is attached to.
- The default inventory. A pair of
VirtualInventory
andNetworkConnectionType
. The first element is the input inventory and the second element is the default connection type. - Vararg of additional inventories.
- A lambda that creates a default side config for the holder. You can use
createSideConfig
orcreateExclusiveSideConfig
if you have a simple default config. In this case, a config with insert on all sides except the front will be created.
FluidHolder
Similar to ItemHolders
, FluidHolders
are used provide an interface for networks to interact with your TileEntity's tanks.
But instead of VirtualInventories
, they use FluidTanks
which you can get from the getFluidContainer
function:
private val waterTank = getFluidContainer(
"water", // (1)!
setOf(FluidType.WATER), // (2)!
WATER_CAPACITY, // (3)!
0 // (4)!
)
- The name of the tank.
- The fluid types that can be stored in the tank.
- A config reloadable value that stores the maximum amount of fluid that can be stored (See Config for more info).
- (optional) The amount of fluid that is initially stored in the tank. Defaults to 0 if omitted.
Again, you can handle changes in the tank by passing a lambda or method reference to the getFluidContainer
function.
But unlike The ItemHolder
you can also pass a UpgradeHolder
to the getFluidContainer
function.
private val waterTank = getFluidContainer(
"water",
setOf(FluidType.WATER),
WATER_CAPACITY,
0,
::updateWaterLevel,
upgradeHolder
)
// ...
private fun updateWaterLevel() {
// ...
}
Now we can override the fluidHolder
property.
override val fluidHolder = NovaFluidHolder(
this, // (1)!
waterTank to NetworkConnectionType.BUFFER// (2)!
// You can add additional tanks here // (3) !
) { createSideConfig(NetworkConnectionType.INSERT, BlockSide.FRONT) } // (4)!
- The parent TileEntity that the holder is attached to.
- The default tank. A pair of
FluidTank
andNetworkConnectionType
. The first element is the input tank and the second element is the default connection type. - Vararg of additional tanks.
- A lambda that creates a default side config for the holder. You can use
createSideConfig
orcreateExclusiveSideConfig
if you have a simple default config. In this case, a config with insert on all sides except the front will be created.
Back to the original Solar Panel
For our solar panel, we only have to override the energyHolder
property.
override val energyHolder = ProviderEnergyHolder(this, MAX_ENERGY, ENERGY_PER_TICK, null) {
createExclusiveSideConfig(NetworkConnectionType.EXTRACT, BlockSide.BOTTOM)
}
Now that we've got our energyHolder set up, we can start giving it energy. To do that, we just override the handleTick
method
and check if it's still day time.
override fun handleTick() {
if(world.time < 13000)
energyHolder.energy += ENERGY_PER_TICK
}
And that's it! We now have a working solar panel.