Documentation and some refactoring related to matter capability

This commit is contained in:
DBotThePony 2023-01-14 11:41:18 +07:00
parent 16ea829514
commit f68ce78bf9
Signed by: DBot
GPG Key ID: DCC23B5715498507
17 changed files with 133 additions and 56 deletions

View File

@ -7,7 +7,6 @@ import net.minecraftforge.event.entity.living.LivingHurtEvent
import ru.dbotthepony.mc.otm.capability.MatteryPlayerCapability
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.network.FieldSynchronizer
import java.io.DataInputStream
import java.io.InputStream
abstract class AndroidFeature(val type: AndroidFeatureType<*>, val android: MatteryPlayerCapability) : INBTSerializable<CompoundTag> {

View File

@ -22,11 +22,11 @@ import ru.dbotthepony.mc.otm.block.IDroppableContainer
import ru.dbotthepony.mc.otm.block.matter.MatterBottlerBlock
import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
import ru.dbotthepony.mc.otm.block.entity.WorkerState
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.energy.BlockEnergyStorageImpl
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler
import ru.dbotthepony.mc.otm.capability.matter.MatterDirection
import ru.dbotthepony.mc.otm.capability.matter.MatterHandlerImpl
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.MatteryContainerHooks
@ -114,9 +114,9 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
}
})
val matter: MatterHandlerImpl = object : MatterHandlerImpl(this::setChangedLight, MatterDirection.BIDIRECTIONAL, ::CAPACITY) {
override val direction: MatterDirection get() {
return if (this@MatterBottlerBlockEntity.isBottling) MatterDirection.RECEIVE else MatterDirection.EXTRACT
val matter: MatterHandlerImpl = object : MatterHandlerImpl(this::setChangedLight, FlowDirection.BI_DIRECTIONAL, ::CAPACITY) {
override val matterDirection: FlowDirection get() {
return if (this@MatterBottlerBlockEntity.isBottling) FlowDirection.INPUT else FlowDirection.OUTPUT
}
}
@ -233,7 +233,7 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
var capability: IMatterHandler? = null
val align = if (isBottling) 0 else 3
var work_slot = -1
val unexpectedDirection = if (isBottling) MatterDirection.EXTRACT else MatterDirection.RECEIVE
val unexpectedDirection = if (isBottling) FlowDirection.OUTPUT else FlowDirection.INPUT
for (i in align until align + 3) {
val itemStack = container.getItem(i)
@ -241,7 +241,7 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
if (!itemStack.isEmpty) {
val cap = itemStack.getCapability(MatteryCapability.MATTER).orNull() ?: continue
if (cap.direction !== unexpectedDirection) {
if (cap.matterDirection != unexpectedDirection) {
if (this.isBottling && cap.missingMatter > Decimal.ZERO || !this.isBottling && cap.storedMatter > Decimal.ZERO) {
work_stack = itemStack
capability = cap

View File

@ -19,9 +19,9 @@ import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.block.BatteryBankBlock
import ru.dbotthepony.mc.otm.block.IDroppableContainer
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler
import ru.dbotthepony.mc.otm.capability.matter.MatterDirection
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.core.Decimal
import ru.dbotthepony.mc.otm.core.ifPresentK
@ -136,9 +136,8 @@ class MatterCapacitorBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState)
return summ
}
override val direction: MatterDirection get() {
return MatterDirection.BIDIRECTIONAL
}
override val matterDirection: FlowDirection
get() = FlowDirection.BI_DIRECTIONAL
private var resolver = LazyOptional.of { this }

View File

@ -20,11 +20,11 @@ import net.minecraftforge.items.IItemHandler
import ru.dbotthepony.mc.otm.ConciseBalanceValues
import ru.dbotthepony.mc.otm.block.IDroppableContainer
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.energy.BlockEnergyStorageImpl
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler
import ru.dbotthepony.mc.otm.capability.matter.MatterDirection
import ru.dbotthepony.mc.otm.capability.matter.MatterHandlerImpl
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.MatteryContainerHooks
@ -128,7 +128,7 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState)
private var valid = true
override val matterNode = Graph6Node<IMatterGraphNode>(this)
val matter = MatterHandlerImpl(this::setChangedLight, MatterDirection.EXTRACT, ::CAPACITY)
val matter = MatterHandlerImpl(this::setChangedLight, FlowDirection.OUTPUT, ::CAPACITY)
private var resolverMatter = LazyOptional.of { matter }
private var resolverNode = LazyOptional.of { this }

View File

@ -20,11 +20,11 @@ import net.minecraftforge.common.util.LazyOptional
import ru.dbotthepony.mc.otm.ConciseBalanceValues
import ru.dbotthepony.mc.otm.block.IDroppableContainer
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.energy.BlockEnergyStorageImpl
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler
import ru.dbotthepony.mc.otm.capability.matter.MatterDirection
import ru.dbotthepony.mc.otm.capability.matter.MatterHandlerImpl
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.MatteryContainerHooks
@ -75,7 +75,7 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
val matter = MatterHandlerImpl(
this::matterLevelUpdated,
MatterDirection.EXTRACT,
FlowDirection.OUTPUT,
::CAPACITY
)

View File

@ -19,6 +19,7 @@ import net.minecraftforge.common.util.LazyOptional
import ru.dbotthepony.mc.otm.ConciseBalanceValues
import ru.dbotthepony.mc.otm.block.IDroppableContainer
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.energy.BlockEnergyStorageImpl
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.energy.WorkerEnergyStorage
@ -104,7 +105,7 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
val matter = MatterHandlerImpl(
this::matterLevelUpdated,
MatterDirection.RECEIVE,
FlowDirection.INPUT,
::MATTER_CAPACITY
)

View File

@ -1,5 +1,32 @@
package ru.dbotthepony.mc.otm.capability
enum class FlowDirection {
INPUT, OUTPUT, BI_DIRECTIONAL
import java.util.function.Predicate
/**
* Represents possible flow direction, both for matter and for energy
*/
enum class FlowDirection(val input: Boolean, val output: Boolean) : Predicate<FlowDirection> {
/**
* Can only be inputted (consumer)
*/
INPUT(true, false),
/**
* Can only be outputted/transmitted (producer)
*/
OUTPUT(false, true),
/**
* Can both consume and produce (capacitor)
*/
BI_DIRECTIONAL(true, true),
/**
* Why would you want to use this
*/
NONE(false, false);
override fun test(t: FlowDirection): Boolean {
return t === this || (!input || t.input) && (!output || t.output)
}
}

View File

@ -1,4 +1,4 @@
package ru.dbotthepony.mc.otm.capability.android
package ru.dbotthepony.mc.otm.capability
import it.unimi.dsi.fastutil.objects.Reference2ObjectOpenHashMap
import net.minecraft.ChatFormatting
@ -44,9 +44,7 @@ import ru.dbotthepony.mc.otm.android.AndroidResearch
import ru.dbotthepony.mc.otm.android.AndroidResearchManager
import ru.dbotthepony.mc.otm.android.AndroidResearchType
import ru.dbotthepony.mc.otm.android.AndroidSwitchableFeature
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.UUIDIntModifiersMap
import ru.dbotthepony.mc.otm.capability.matteryPlayer
import ru.dbotthepony.mc.otm.capability.energy.AndroidPowerSource
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.stream

View File

@ -1,4 +1,4 @@
package ru.dbotthepony.mc.otm.capability.android
package ru.dbotthepony.mc.otm.capability.energy
import net.minecraft.nbt.CompoundTag
import net.minecraft.server.level.ServerPlayer
@ -6,7 +6,6 @@ import net.minecraft.world.entity.player.Player
import net.minecraft.world.item.ItemStack
import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.common.util.INBTSerializable
import ru.dbotthepony.mc.otm.capability.energy.IMatteryEnergyStorage
import ru.dbotthepony.mc.otm.capability.extractEnergy
import ru.dbotthepony.mc.otm.capability.receiveEnergy
import ru.dbotthepony.mc.otm.core.Decimal

View File

@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.capability.matter
import net.minecraftforge.common.capabilities.ICapabilityProvider
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.core.Decimal
import ru.dbotthepony.mc.otm.core.RGBAColor
import ru.dbotthepony.mc.otm.core.orNull
@ -14,12 +15,20 @@ interface IMatterHandler {
val canSetMatterLevel: Boolean get() = true
/**
* How much matter (estimated) is stored in this object. Why estimated? Because some objects can be bottomless.
*
* Implementations are free to throw [UnsupportedOperationException] if setting battery level is not supported
* due to technical complications (in this case, [canSetMatterLevel] MUST be false)
*
* @throws [UnsupportedOperationException]
*/
var storedMatter: Decimal
/**
* How much matter (estimated) can this object hold. Why estimated? Because some objects can be bottomless.
*
* **DO NOT use this to determine "how much stuff is missing", use [missingMatter] instead!**
*/
val maxStoredMatter: Decimal
/**
@ -42,22 +51,71 @@ interface IMatterHandler {
storedMatter = maxStoredMatter
}
/**
* Make this object receive matter, from outside world.
*
* Call this if you don't own the object in question.
*
* @return matter accepted
*/
fun receiveMatterOuter(howMuch: Decimal, simulate: Boolean): Decimal
/**
* Make this object receive matter, from inside world.
*
* Call this if you DO own the object in question.
*
* Nothing stops you from calling this from outside world, however, this will most likely
* lead to bugs, use [receiveMatterOuter] in this case instead. Methods were separated (and inside interface) for ease of use.
*
* Don't try to hammer nails with a screwdriver.
*
* @return matter accepted
*/
fun receiveMatterInner(howMuch: Decimal, simulate: Boolean): Decimal
/**
* Make this object extract matter from itself, from outside world.
*
* Call this if you don't own the object in question.
*
* @return matter extracted
*/
fun extractMatterOuter(howMuch: Decimal, simulate: Boolean): Decimal
/**
* Make this object extract matter from itself, from inside world.
*
* Call this if you DO own the object in question.
*
* Nothing stops you from calling this from outside world, however, this will most likely
* lead to bugs, use [extractMatterOuter] in this case instead. Methods were separated (and inside interface) for ease of use.
*
* Don't try to hammer nails with a screwdriver.
*
* @return matter extracted
*/
fun extractMatterInner(howMuch: Decimal, simulate: Boolean): Decimal
val direction: MatterDirection
/**
* How much matter (estimated) is missing in this object. Why estimated? Because some objects can be bottomless.
*
* Use this to determine whenever you need an estimate on how much matter this object can accept, **and do not implement [maxStoredMatter] - [storedMatter] logic by yourself**.
*/
val missingMatter: Decimal
get() = maxStoredMatter.minus(storedMatter).moreThanZero()
val allowsExtract: Boolean
get() = direction != MatterDirection.RECEIVE
val allowsReceive: Boolean
get() = direction != MatterDirection.EXTRACT
/**
* Which direction does matter flows
*/
val matterDirection: FlowDirection
}
inline val IMatterHandler.canExtractMatter: Boolean
get() = matterDirection.output
inline val IMatterHandler.canReceiveMatter: Boolean
get() = matterDirection.input
fun IMatterHandler.getBarWidth(): Int {
return ((storedMatter / maxStoredMatter).toFloat().coerceAtLeast(0f).coerceAtMost(1f) * 13f).roundToInt()
}

View File

@ -1,3 +0,0 @@
package ru.dbotthepony.mc.otm.capability.matter
enum class MatterDirection { RECEIVE, EXTRACT, BIDIRECTIONAL }

View File

@ -5,19 +5,20 @@ import net.minecraftforge.common.util.INBTSerializable
import net.minecraftforge.common.util.LazyOptional
import ru.dbotthepony.mc.otm.ConciseBalanceValues
import ru.dbotthepony.mc.otm.VerboseBalanceValues
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.core.Decimal
import ru.dbotthepony.mc.otm.core.set
open class MatterHandlerImpl @JvmOverloads constructor(
protected val listener: Runnable?,
override val direction: MatterDirection,
override val matterDirection: FlowDirection,
protected val maxStoredMatterSupplier: () -> Decimal,
protected val maxReceiveSupplier: () -> Decimal? = { null },
protected val maxExtractSupplier: () -> Decimal? = maxReceiveSupplier
) : IMatterHandler, INBTSerializable<CompoundTag> {
constructor(
listener: Runnable?,
direction: MatterDirection,
direction: FlowDirection,
maxStoredMatter: Decimal,
maxReceive: Decimal? = null,
maxExtract: Decimal? = null,
@ -25,13 +26,13 @@ open class MatterHandlerImpl @JvmOverloads constructor(
constructor(
listener: Runnable?,
direction: MatterDirection,
direction: FlowDirection,
values: ConciseBalanceValues
) : this(listener, direction, values::capacity, values::throughput, values::throughput)
constructor(
listener: Runnable?,
direction: MatterDirection,
direction: FlowDirection,
values: VerboseBalanceValues
) : this(listener, direction, values::capacity, values::receive, values::extract)
@ -62,7 +63,7 @@ open class MatterHandlerImpl @JvmOverloads constructor(
}
override fun receiveMatterOuter(howMuch: Decimal, simulate: Boolean): Decimal {
if (direction === MatterDirection.EXTRACT)
if (!canReceiveMatter)
return Decimal.ZERO
return receiveMatterInner(howMuch, simulate)
@ -88,7 +89,7 @@ open class MatterHandlerImpl @JvmOverloads constructor(
}
override fun extractMatterOuter(howMuch: Decimal, simulate: Boolean): Decimal {
if (direction === MatterDirection.RECEIVE)
if (canExtractMatter)
return Decimal.ZERO
return extractMatterInner(howMuch, simulate)

View File

@ -1,10 +1,8 @@
package ru.dbotthepony.mc.otm.capability
package ru.dbotthepony.mc.otm.core
import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.ListTag
import net.minecraft.nbt.Tag
import net.minecraftforge.common.util.INBTSerializable
import ru.dbotthepony.mc.otm.core.contains
import java.util.UUID
/**

View File

@ -4,6 +4,7 @@ import com.google.common.collect.Streams
import net.minecraft.server.level.ServerLevel
import net.minecraft.world.item.Item
import net.minecraft.world.level.block.entity.BlockEntity
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.matter.*
import ru.dbotthepony.mc.otm.core.Decimal
@ -79,7 +80,7 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
for (node in nodes) {
val matter = node.value.getMatterHandler()
if (matter != null && matter.direction == MatterDirection.BIDIRECTIONAL) {
if (matter != null && matter.matterDirection == FlowDirection.BI_DIRECTIONAL) {
level += matter.storedMatter
}
}
@ -93,7 +94,7 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
for (node in nodes) {
val matter = node.value.getMatterHandler()
if (matter != null && matter.direction == MatterDirection.BIDIRECTIONAL) {
if (matter != null && matter.matterDirection == FlowDirection.BI_DIRECTIONAL) {
level += matter.maxStoredMatter
}
}
@ -136,7 +137,7 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
for (node in nodes) {
val matter = node.value.getMatterHandler()
if (matter != null && matter.direction == MatterDirection.BIDIRECTIONAL) {
if (matter != null && matter.matterDirection == FlowDirection.BI_DIRECTIONAL) {
val value = matter.receiveMatterOuter(howMuch, simulate)
howMuch -= value
received += value
@ -160,7 +161,7 @@ class MatterNetworkGraph : Abstract6Graph<IMatterGraphNode>(), IMatterGraphListe
for (node in nodes) {
val matter = node.value.getMatterHandler()
if (matter != null && matter.direction != MatterDirection.EXTRACT) {
if (matter != null && matter.matterDirection != FlowDirection.OUTPUT) {
val value = matter.receiveMatterOuter(howMuch, simulate)
howMuch -= value
received += value

View File

@ -3,10 +3,8 @@ package ru.dbotthepony.mc.otm.item
import net.minecraft.ChatFormatting
import net.minecraft.MethodsReturnNonnullByDefault
import net.minecraft.core.Direction
import net.minecraft.core.NonNullList
import net.minecraft.nbt.CompoundTag
import net.minecraft.network.chat.Component
import net.minecraft.world.item.CreativeModeTab
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Rarity
@ -15,7 +13,7 @@ import net.minecraft.world.level.Level
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ICapabilityProvider
import net.minecraftforge.common.util.LazyOptional
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.matter.*
@ -86,7 +84,7 @@ class MatterCapacitorItem : Item {
return diff
}
override val direction = MatterDirection.BIDIRECTIONAL
override val matterDirection = FlowDirection.BI_DIRECTIONAL
}
private val _capacity: () -> Decimal

View File

@ -6,6 +6,8 @@ import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.core.ImmutableList
import ru.dbotthepony.mc.otm.block.entity.matter.MatterBottlerBlockEntity
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.matter.canExtractMatter
import ru.dbotthepony.mc.otm.capability.matter.canReceiveMatter
import ru.dbotthepony.mc.otm.menu.widget.BooleanPlayerInputWidget
import ru.dbotthepony.mc.otm.menu.widget.LevelGaugeWidget
import ru.dbotthepony.mc.otm.menu.widget.ProgressGaugeWidget
@ -45,9 +47,9 @@ class MatterBottlerMenu @JvmOverloads constructor(
val cap = p_40231_.getCapability(MatteryCapability.MATTER).orNull() ?: return false
if (workFlow.value) {
return index < 3 && cap.allowsReceive
return index < 3 && cap.canReceiveMatter
} else {
return index >= 3 && cap.allowsExtract
return index >= 3 && cap.canExtractMatter
}
}
}

View File

@ -4,9 +4,9 @@ import net.minecraft.world.Container
import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.Slot
import net.minecraft.world.item.ItemStack
import ru.dbotthepony.mc.otm.capability.FlowDirection
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.energy
import ru.dbotthepony.mc.otm.capability.matter.MatterDirection
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.runOnClient
@ -43,13 +43,12 @@ open class MatterContainerInputSlot @JvmOverloads constructor(
index: Int,
x: Int = 0,
y: Int = 0,
val direction: MatterDirection = MatterDirection.BIDIRECTIONAL
val direction: FlowDirection = FlowDirection.BI_DIRECTIONAL
) : MatterySlot(container, index, x, y) {
override fun mayPlace(itemStack: ItemStack): Boolean {
val handler = itemStack.getCapability(MatteryCapability.MATTER).resolve()
if (handler.isEmpty) return false
val direction = handler.get().direction
return super.mayPlace(itemStack) && (direction == MatterDirection.BIDIRECTIONAL || this.direction == direction)
return super.mayPlace(itemStack) && this.direction.test(handler.get().matterDirection)
}
}