Serverside Config

Fixes #88
This commit is contained in:
DBotThePony 2022-09-17 13:59:48 +07:00
parent 5275a9494c
commit 0fff4c003b
Signed by: DBot
GPG Key ID: DCC23B5715498507
35 changed files with 881 additions and 199 deletions

View File

@ -89,6 +89,7 @@ public final class OverdriveThatMatters {
modBus.addListener(EventPriority.NORMAL, MatteryCapability::register);
ClientConfig.INSTANCE.register();
ServerConfig.INSTANCE.register();
}
private void setup(final FMLCommonSetupEvent event) {

View File

@ -3,8 +3,6 @@ package ru.dbotthepony.mc.otm
import net.minecraftforge.common.ForgeConfigSpec
import net.minecraftforge.fml.ModLoadingContext
import net.minecraftforge.fml.config.ModConfig
import ru.dbotthepony.mc.otm.core.getValue
import ru.dbotthepony.mc.otm.core.setValue
object ClientConfig {
private val spec: ForgeConfigSpec

View File

@ -0,0 +1,42 @@
package ru.dbotthepony.mc.otm
import net.minecraftforge.common.ForgeConfigSpec
import kotlin.reflect.KProperty
operator fun <T> ForgeConfigSpec.ConfigValue<T>.setValue(config: Any, property: KProperty<*>, value: T) {
set(value)
}
operator fun <T : Any> ForgeConfigSpec.ConfigValue<T>.getValue(config: Any, property: KProperty<*>): T {
return get()
}
private val builderField by lazy {
val field = ForgeConfigSpec.Builder::class.java.getDeclaredField("context")
field.isAccessible = true
field
}
private val builderContextField by lazy {
val clazz = ForgeConfigSpec::class.java.declaredClasses.firstOrNull { it.name == "net.minecraftforge.common.ForgeConfigSpec\$BuilderContext" } ?: throw NoSuchElementException("Unable to find ForgeConfigSpec.BuilderContext")
val field = clazz.getDeclaredField("comment")
field.isAccessible = true
field
}
fun ForgeConfigSpec.Builder.appendComment(vararg comments: String): ForgeConfigSpec.Builder {
val context = builderField.get(this) ?: throw NullPointerException("No builder context!")
val commentList = builderContextField.get(context) as? Array<String> ?: throw NullPointerException("BuilderContext.comment is null or not of right type!")
val reconstruct = Array(commentList.size + comments.size) {
if (it in commentList.indices) {
commentList[it]
} else {
comments[it - commentList.size]
}
}
builderContextField.set(context, reconstruct)
return this
}

View File

@ -0,0 +1,74 @@
package ru.dbotthepony.mc.otm
import net.minecraftforge.common.ForgeConfigSpec.ConfigValue
import org.apache.logging.log4j.LogManager
import java.util.function.Consumer
import java.util.function.Supplier
import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty
abstract class ObservedConfigValue<V : Any>(val parent: ConfigValue<String>) : ReadWriteProperty<Any, V>, Supplier<V>, Consumer<V> {
var rawValue: String by parent
private var observedValue: String? = null
private var cachedValue: V? = null
protected abstract fun fromValue(value: String): V?
/**
* value [V] -> newRawValue [String], newValue [V]
*/
protected abstract fun toValue(value: V): Pair<String, V>
override fun get(): V {
if (cachedValue == null || rawValue != observedValue) {
var deserialized = fromValue(rawValue)
if (deserialized == null) {
val default = parent.default
deserialized = fromValue(default)
if (deserialized == null) {
throw RuntimeException("Deserializer did not accept default value: $default")
} else {
LOGGER.error("Config value of <${parent.path.joinToString(".")}>: $rawValue is invalid, replacing with default $default")
}
rawValue = default
}
cachedValue = deserialized
observedValue = rawValue
}
return cachedValue ?: throw ConcurrentModificationException()
}
override fun getValue(thisRef: Any, property: KProperty<*>): V {
return get()
}
override fun accept(value: V) {
if (cachedValue == null || rawValue != observedValue) {
cachedValue = fromValue(rawValue)
observedValue = rawValue
}
if (cachedValue != value) {
val (newRaw, newValue) = toValue(value)
if (cachedValue != newValue) {
rawValue = newRaw
observedValue = rawValue
cachedValue = newValue
}
}
}
override fun setValue(thisRef: Any, property: KProperty<*>, value: V) {
accept(value)
}
companion object {
private val LOGGER = LogManager.getLogger()
}
}

View File

@ -0,0 +1,142 @@
package ru.dbotthepony.mc.otm
import net.minecraftforge.common.ForgeConfigSpec
import net.minecraftforge.fml.ModLoadingContext
import net.minecraftforge.fml.config.ModConfig
import ru.dbotthepony.mc.otm.block.entity.AndroidStationBlockEntity
import ru.dbotthepony.mc.otm.block.entity.ChemicalGeneratorBlockEntity
import ru.dbotthepony.mc.otm.block.entity.matter.MatterBottlerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.matter.MatterRecyclerBlockEntity
import ru.dbotthepony.mc.otm.block.entity.matter.MatterReplicatorBlockEntity
import ru.dbotthepony.mc.otm.block.entity.matter.MatterScannerBlockEntity
import ru.dbotthepony.mc.otm.capability.BlockEnergyStorageImpl
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.core.defineImpreciseFraction
import ru.dbotthepony.mc.otm.registry.MNames
interface VerboseBalanceValues {
val capacity: ImpreciseFraction
val receive: ImpreciseFraction
val extract: ImpreciseFraction
}
interface BatteryBalanceValues : VerboseBalanceValues {
val initialBatteryLevel: ImpreciseFraction
}
interface ConciseBalanceValues {
val capacity: ImpreciseFraction
val throughput: ImpreciseFraction
}
object ServerConfig {
private val specBuilder = ForgeConfigSpec.Builder()
private val spec: ForgeConfigSpec
private var registered = false
private fun verboseValues(name: String, storage: ImpreciseFraction, receive: ImpreciseFraction, extract: ImpreciseFraction = receive, initialBatteryLevel: ImpreciseFraction = ImpreciseFraction.ZERO): VerboseBalanceValues {
specBuilder.push(name)
val obj = object : VerboseBalanceValues {
override val capacity: ImpreciseFraction by specBuilder.defineImpreciseFraction("capacity", storage, minimum = ImpreciseFraction.ONE)
override val receive: ImpreciseFraction by specBuilder.defineImpreciseFraction("receive", receive, minimum = ImpreciseFraction.ONE)
override val extract: ImpreciseFraction by specBuilder.defineImpreciseFraction("extract", extract, minimum = ImpreciseFraction.ONE)
}
specBuilder.pop()
return obj
}
private fun batteryValues(name: String, storage: ImpreciseFraction, receive: ImpreciseFraction, extract: ImpreciseFraction = receive, initialBatteryLevel: ImpreciseFraction = ImpreciseFraction.ZERO): BatteryBalanceValues {
specBuilder.push(name)
val obj = object : BatteryBalanceValues {
override val capacity: ImpreciseFraction by specBuilder.defineImpreciseFraction("capacity", storage, minimum = ImpreciseFraction.ONE)
override val receive: ImpreciseFraction by specBuilder.defineImpreciseFraction("receive", receive, minimum = ImpreciseFraction.ONE)
override val extract: ImpreciseFraction by specBuilder.defineImpreciseFraction("extract", extract, minimum = ImpreciseFraction.ONE)
override val initialBatteryLevel: ImpreciseFraction by specBuilder.defineImpreciseFraction("initialBatteryLevel", initialBatteryLevel, minimum = ImpreciseFraction.ZERO)
}
specBuilder.pop()
return obj
}
private fun conciseValues(name: String, storage: ImpreciseFraction, throughput: ImpreciseFraction): ConciseBalanceValues {
specBuilder.push(name)
val obj = object : ConciseBalanceValues {
override val capacity: ImpreciseFraction by specBuilder.defineImpreciseFraction("capacity", storage, minimum = ImpreciseFraction.ONE)
override val throughput: ImpreciseFraction by specBuilder.defineImpreciseFraction("throughput", throughput, minimum = ImpreciseFraction.ONE)
}
specBuilder.pop()
return obj
}
init {
specBuilder.comment("Serverside config, holds shared values that are required to be read by both client and server.").push("server")
specBuilder.comment("Energy batteries balance values").push("energy_batteries")
}
val BATTERY_CRUDE = batteryValues(MNames.BATTERY_CRUDE, ImpreciseFraction(100_000), ImpreciseFraction(160), ImpreciseFraction(40), ImpreciseFraction(80_000))
val BATTERY_BASIC = batteryValues(MNames.BATTERY_BASIC, ImpreciseFraction(400_000), ImpreciseFraction(600))
val BATTERY_NORMAL = batteryValues(MNames.BATTERY_NORMAL, ImpreciseFraction(2_000_000), ImpreciseFraction(1_000))
val BATTERY_DENSE = batteryValues(MNames.BATTERY_DENSE, ImpreciseFraction(10_000_000), ImpreciseFraction(2_000))
val BATTERY_CAPACITOR = batteryValues(MNames.BATTERY_CAPACITOR, ImpreciseFraction(500_000), ImpreciseFraction(50_000))
val QUANTUM_BATTERY = conciseValues(MNames.QUANTUM_BATTERY, ImpreciseFraction(40_000_000), ImpreciseFraction(10_000))
val QUANTUM_CAPACITOR = conciseValues(MNames.QUANTUM_CAPACITOR, ImpreciseFraction(1_000_000), ImpreciseFraction(200_000))
val ZPM_BATTERY = conciseValues(MNames.ZPM_BATTERY, ImpreciseFraction(200_000_000_000_000L), ImpreciseFraction(200_000_000L))
init {
specBuilder.pop()
specBuilder.comment("Matter capacitors and pattern drives balance values").push("matter_capacitors_and_drives")
}
val MATTER_CAPACITOR_BASIC by specBuilder.defineImpreciseFraction(MNames.MATTER_CAPACITOR_BASIC, ImpreciseFraction(2), minimum = ImpreciseFraction.ONE_TENTH)
val MATTER_CAPACITOR_NORMAL by specBuilder.defineImpreciseFraction(MNames.MATTER_CAPACITOR_NORMAL, ImpreciseFraction(10), minimum = ImpreciseFraction.ONE_TENTH)
val MATTER_CAPACITOR_DENSE by specBuilder.defineImpreciseFraction(MNames.MATTER_CAPACITOR_DENSE, ImpreciseFraction(40), minimum = ImpreciseFraction.ONE_TENTH)
val PATTERN_DRIVE_NORMAL: Int by specBuilder.defineInRange(MNames.PATTERN_DRIVE_NORMAL, 4, 1, Int.MAX_VALUE)
init {
specBuilder.pop()
specBuilder.comment("Balance values of machinery").push("machines")
AndroidStationBlockEntity.registerConfig(specBuilder)
ChemicalGeneratorBlockEntity.registerConfig(specBuilder)
MatterRecyclerBlockEntity.registerConfig(specBuilder)
MatterBottlerBlockEntity.registerConfig(specBuilder)
MatterReplicatorBlockEntity.registerConfig(specBuilder)
MatterScannerBlockEntity.registerConfig(specBuilder)
}
val PLATE_PRESS = BlockEnergyStorageImpl.makeConfigEntry(specBuilder, MNames.PLATE_PRESS)
val STORAGE_POWER_SUPPLIER = BlockEnergyStorageImpl.makeConfigEntry(specBuilder, MNames.STORAGE_POWER_SUPPLIER, capacity = ImpreciseFraction(100_000), throughput = ImpreciseFraction(320))
val STORAGE_INTERFACES = BlockEnergyStorageImpl.makeConfigEntry(specBuilder, "storage_interfaces", capacity = ImpreciseFraction(10_000))
val ITEM_MONITOR = BlockEnergyStorageImpl.makeConfigEntry(specBuilder, MNames.ITEM_MONITOR)
val DRIVE_VIEWER = BlockEnergyStorageImpl.makeConfigEntry(specBuilder, MNames.DRIVE_VIEWER)
val DRIVE_RACK = BlockEnergyStorageImpl.makeConfigEntry(specBuilder, MNames.DRIVE_RACK, capacity = ImpreciseFraction(80_000))
init {
specBuilder.pop()
}
init {
specBuilder.pop()
spec = specBuilder.build()
}
fun register() {
check(!registered) { "Already registered config" }
registered = true
ModLoadingContext.get().registerConfig(ModConfig.Type.SERVER, spec)
}
}

View File

@ -4,20 +4,24 @@ import net.minecraft.core.BlockPos
import net.minecraft.network.chat.Component
import net.minecraft.server.level.ServerPlayer
import net.minecraft.world.MenuProvider
import net.minecraft.world.entity.LivingEntity
import net.minecraft.world.entity.player.Inventory
import net.minecraft.world.entity.player.Player
import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.state.BlockState
import net.minecraft.world.phys.AABB
import net.minecraftforge.common.ForgeConfigSpec
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.core.ImpreciseFractionConfigValue
import ru.dbotthepony.mc.otm.core.defineImpreciseFraction
import ru.dbotthepony.mc.otm.core.ifPresentK
import ru.dbotthepony.mc.otm.menu.AndroidStationMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.registry.WriteOnce
class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryPoweredBlockEntity(MBlockEntities.ANDROID_STATION, p_155229_, p_155230_), MenuProvider {
@ -29,7 +33,7 @@ class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
override val defaultDisplayName: Component
get() = MACHINE_NAME
override val energy = object : WorkerEnergyStorage(this@AndroidStationBlockEntity, STORAGE, MAX_IO, null) {
override val energy = object : WorkerEnergyStorage(this@AndroidStationBlockEntity::setChangedLight, ::CAPACITY, ::MAX_IO, { null }) {
override fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
return super.extractEnergyInner(howMuch, simulate).also {
if (!simulate && this.batteryLevel.isZero) {
@ -93,9 +97,26 @@ class AndroidStationBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
companion object {
private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.android_station")
val STORAGE = ImpreciseFraction(100_000)
val MAX_IO = ImpreciseFraction.valueOf(2048)
val ENERGY_PER_OPERATION = ImpreciseFraction.valueOf(2048)
val ENERGY_PER_RESEARCH = ImpreciseFraction.valueOf(16384)
private var _CAPACITY: ImpreciseFractionConfigValue by WriteOnce()
private var _MAX_IO: ImpreciseFractionConfigValue by WriteOnce()
private var _ENERGY_PER_OPERATION: ImpreciseFractionConfigValue by WriteOnce()
private var _ENERGY_PER_RESEARCH: ImpreciseFractionConfigValue by WriteOnce()
val CAPACITY get() = _CAPACITY.get()
val MAX_IO get() = _MAX_IO.get()
val ENERGY_PER_OPERATION get() = _ENERGY_PER_OPERATION.get()
val ENERGY_PER_RESEARCH get() = _ENERGY_PER_RESEARCH.get()
fun registerConfig(builder: ForgeConfigSpec.Builder) {
builder.push(MNames.ANDROID_STATION)
_CAPACITY = builder.defineImpreciseFraction("capacity", ImpreciseFraction(100_000), ImpreciseFraction.ONE)
_MAX_IO = builder.defineImpreciseFraction("throughput", ImpreciseFraction.valueOf(2048), ImpreciseFraction.ONE)
_ENERGY_PER_OPERATION = builder.comment("Swapping parts, etc").defineImpreciseFraction("energyPerOperation", ImpreciseFraction.valueOf(2048), ImpreciseFraction.ONE)
_ENERGY_PER_RESEARCH = builder.defineImpreciseFraction("energyPerResearch", ImpreciseFraction.valueOf(16384), ImpreciseFraction.ONE)
builder.pop()
}
}
}

View File

@ -340,4 +340,4 @@ class BatteryBankBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
const val CAPACITY = 6 * 2
private val LOGGER = LogManager.getLogger()
}
}
}

View File

@ -12,6 +12,7 @@ import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.ForgeConfigSpec
import net.minecraftforge.common.ForgeHooks
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ForgeCapabilities
@ -26,6 +27,8 @@ import ru.dbotthepony.mc.otm.container.MatteryContainerFilter
import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.menu.ChemicalGeneratorMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.registry.WriteOnce
import java.lang.ref.WeakReference
class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryBlockEntity(MBlockEntities.CHEMICAL_GENERATOR, pos, state), IDroppableContainer {
@ -40,7 +43,7 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryBl
val container = MatteryContainer(this::setChangedLight, SLOTS)
override val droppableContainer: Container
get() = container
val energy = GeneratorEnergyStorage(this::setChangedLight, MAX_ENERGY, THROUGHPUT)
val energy = GeneratorEnergyStorage(this::setChangedLight, CAPACITY, THROUGHPUT)
private val consumers = ArrayList<LazyOptional<out IEnergyStorage>>()
@ -227,17 +230,30 @@ class ChemicalGeneratorBlockEntity(pos: BlockPos, state: BlockState) : MatteryBl
}
companion object {
private val THROUGHPUT = ImpreciseFraction(160)
private const val THROUGHPUT_INT = 160
private val GENERATION_SPEED = ImpreciseFraction(40)
private val MAX_ENERGY = ImpreciseFraction(24_000)
private val THROUGHPUT get() = _THROUGHPUT.get()
private val GENERATION_SPEED get() = _GENERATION_SPEED.get()
private val CAPACITY get() = _CAPACITY.get()
private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.chemical_generator")
private var _THROUGHPUT: ImpreciseFractionConfigValue by WriteOnce()
private var _GENERATION_SPEED: ImpreciseFractionConfigValue by WriteOnce()
private var _CAPACITY: ImpreciseFractionConfigValue by WriteOnce()
const val SLOT_INPUT = 0
const val SLOT_BATTERY = 1
const val SLOT_RESIDUE = 2
const val SLOTS = 3
fun registerConfig(builder: ForgeConfigSpec.Builder) {
builder.push(MNames.CHEMICAL_GENERATOR)
_THROUGHPUT = builder.defineImpreciseFraction("throughput", ImpreciseFraction(160), ImpreciseFraction.ONE)
_GENERATION_SPEED = builder.defineImpreciseFraction("generationSpeed", ImpreciseFraction(40), ImpreciseFraction.ONE)
_CAPACITY = builder.defineImpreciseFraction("capacity", ImpreciseFraction(24_000), ImpreciseFraction.ONE)
builder.pop()
}
const val WORK_TICKS_KEY = "workTicks"
const val WORK_TICKS_TOTAL_KEY = "workTicksTotal"
}

View File

@ -21,6 +21,8 @@ import net.minecraft.nbt.StringTag
import net.minecraft.network.chat.Component
import net.minecraft.world.level.Level
import net.minecraftforge.common.capabilities.Capability
import ru.dbotthepony.mc.otm.core.TextComponent
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.ifHas
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.oncePre
@ -65,7 +67,9 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc
}
}
protected abstract val defaultDisplayName: Component
protected open val defaultDisplayName: Component
get() = level?.getBlockState(blockPos)?.block?.name ?: TextComponent("null at $blockPos")
abstract override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu?
protected fun tickOnce(func: Runnable) {

View File

@ -13,6 +13,7 @@ import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.common.util.LazyOptional
import ru.dbotthepony.mc.otm.ServerConfig
import ru.dbotthepony.mc.otm.block.IDroppableContainer
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage
@ -31,7 +32,7 @@ class PlatePressBlockEntity(
p_155230_: BlockState
) : MatteryWorkerBlockEntity<MatteryWorkerBlockEntity.ItemJob>(MBlockEntities.PLATE_PRESS, p_155229_, p_155230_, ::ItemJob), IDroppableContainer {
val container = MatteryContainer(this::setChangedLight, 2)
override val energy = WorkerEnergyStorage(this::setChangedLight)
override val energy = WorkerEnergyStorage(this::setChangedLight, ServerConfig.PLATE_PRESS)
override val droppableContainer: Container
get() = container

View File

@ -13,14 +13,18 @@ import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.ForgeConfigSpec
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.items.CapabilityItemHandler
import ru.dbotthepony.mc.otm.ConciseBalanceValues
import ru.dbotthepony.mc.otm.ServerConfig
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.BlockEnergyStorageImpl
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler
@ -34,13 +38,16 @@ import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
import ru.dbotthepony.mc.otm.menu.MatterBottlerMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.registry.MBlocks
import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.registry.WriteOnce
class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryPoweredBlockEntity(MBlockEntities.MATTER_BOTTLER, p_155229_, p_155230_), IMatterGraphNode, IDroppableContainer {
override val matterNode = Graph6Node<IMatterGraphNode>(this)
private val resolverNode = LazyOptional.of { this }
override val energy = WorkerEnergyStorage(this)
override val energy = WorkerEnergyStorage(this, ENERGY_VALUES)
var isBottling: Boolean = true
set(value) {
@ -109,7 +116,7 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
}
})
val matter: MatterHandlerImpl = object : MatterHandlerImpl(this::setChangedLight, MatterDirection.BIDIRECTIONAL, CAPACITY) {
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
}
@ -164,7 +171,7 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
}
override val defaultDisplayName: Component
get() = MACHINE_NAME
get() = MBlocks.MATTER_BOTTLER.name
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return MatterBottlerMenu(containerID, inventory, this)
@ -335,11 +342,31 @@ class MatterBottlerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
}
companion object {
private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.matter_bottler")
private val MATTER_EXCHANGE_RATE = ImpreciseFraction("0.04")
private val ENERGY_CONSUMPTION = ImpreciseFraction(20)
private val EXTRACTION_TICKS = ImpreciseFraction(200)
private val CAPACITY = ImpreciseFraction(4)
val MATTER_EXCHANGE_RATE get() = _MATTER_EXCHANGE_RATE.get()
val ENERGY_CONSUMPTION get() = _ENERGY_CONSUMPTION.get()
val EXTRACTION_TICKS get() = _EXTRACTION_TICKS.get()
val CAPACITY get() = _CAPACITY.get()
private var _MATTER_EXCHANGE_RATE: ImpreciseFractionConfigValue by WriteOnce()
private var _ENERGY_CONSUMPTION: ImpreciseFractionConfigValue by WriteOnce()
private var _EXTRACTION_TICKS: ImpreciseFractionConfigValue by WriteOnce()
private var _CAPACITY: ImpreciseFractionConfigValue by WriteOnce()
var ENERGY_VALUES: ConciseBalanceValues by WriteOnce()
private set
fun registerConfig(builder: ForgeConfigSpec.Builder) {
builder.push(MNames.MATTER_BOTTLER)
ENERGY_VALUES = BlockEnergyStorageImpl.makeConfigEntry(builder)
_MATTER_EXCHANGE_RATE = builder.defineImpreciseFraction("matterExchangeRate", ImpreciseFraction("0.04"), ImpreciseFraction("0.0001"))
_ENERGY_CONSUMPTION = builder.defineImpreciseFraction("energyConsumption", ImpreciseFraction(20), ImpreciseFraction.ONE)
_EXTRACTION_TICKS = builder.defineImpreciseFraction("extractionTicks", ImpreciseFraction(200), ImpreciseFraction.ONE)
_CAPACITY = builder.defineImpreciseFraction("matterCapacity", ImpreciseFraction(4), ImpreciseFraction.ONE_TENTH)
builder.pop()
}
const val IS_BOTTLING_KEY = "isBottling"
}

View File

@ -12,12 +12,15 @@ import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.ForgeConfigSpec
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.common.util.LazyOptional
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.BlockEnergyStorageImpl
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler
@ -36,7 +39,10 @@ import ru.dbotthepony.mc.otm.matter.canDecompose
import ru.dbotthepony.mc.otm.matter.getMatterValue
import ru.dbotthepony.mc.otm.menu.MatterDecomposerMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.registry.MBlocks
import ru.dbotthepony.mc.otm.registry.MItems
import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.registry.WriteOnce
fun moveMatterAsDustIntoContainer(_matterValue: ImpreciseFraction, container: MatteryContainer, OUTPUT_DUST_MAIN: Int, OUTPUT_DUST_STACKING: Int): ImpreciseFraction {
var matterValue = _matterValue
@ -121,11 +127,11 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState)
}
}
override val energy = WorkerEnergyStorage(this, ENERGY_STORAGE, MAX_IO)
override val energy = WorkerEnergyStorage(this, ENERGY_VALUES)
private var valid = true
override val matterNode = Graph6Node<IMatterGraphNode>(this)
val matter = MatterHandlerImpl(this::setChangedLight, MatterDirection.EXTRACT, CAPACITY)
val matter = MatterHandlerImpl(this::setChangedLight, MatterDirection.EXTRACT, ::CAPACITY)
private var resolverMatter = LazyOptional.of { matter }
private var resolverNode = LazyOptional.of { this }
@ -149,7 +155,7 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState)
}
override val defaultDisplayName: Component
get() = MACHINE_NAME
get() = MBlocks.MATTER_DECOMPOSER.name
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return MatterDecomposerMenu(containerID, inventory, this)
@ -263,11 +269,24 @@ class MatterDecomposerBlockEntity(pos: BlockPos, state: BlockState)
const val OUTPUT_DUST_MAIN = 1
const val OUTPUT_DUST_STACKING = 2
private val CAPACITY = ImpreciseFraction("20")
private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.matter_decomposer")
private val BASE_CONSUMPTION = ImpreciseFraction(240)
val CAPACITY get() = _CAPACITY.get()
val BASE_CONSUMPTION get() = _BASE_CONSUMPTION.get()
private val ENERGY_STORAGE = ImpreciseFraction(400_000)
private val MAX_IO = ImpreciseFraction(2_000)
private var _CAPACITY: ImpreciseFractionConfigValue by WriteOnce()
private var _BASE_CONSUMPTION: ImpreciseFractionConfigValue by WriteOnce()
var ENERGY_VALUES: ConciseBalanceValues by WriteOnce()
private set
fun registerConfig(builder: ForgeConfigSpec.Builder) {
builder.push(MNames.MATTER_DECOMPOSER)
ENERGY_VALUES = BlockEnergyStorageImpl.makeConfigEntry(builder, capacity = ImpreciseFraction(400_000), throughput = ImpreciseFraction(2_000))
_CAPACITY = builder.defineImpreciseFraction("matterCapacity", ImpreciseFraction(20), ImpreciseFraction.ONE_TENTH)
_BASE_CONSUMPTION = builder.defineImpreciseFraction("baseConsumption", ImpreciseFraction(240), ImpreciseFraction.ONE)
builder.pop()
}
}
}

View File

@ -12,12 +12,14 @@ import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.ForgeConfigSpec
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.common.util.LazyOptional
import ru.dbotthepony.mc.otm.ConciseBalanceValues
import ru.dbotthepony.mc.otm.block.IDroppableContainer
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
import ru.dbotthepony.mc.otm.capability.BlockEnergyStorageImpl
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.capability.matter.IMatterHandler
@ -33,8 +35,12 @@ import ru.dbotthepony.mc.otm.item.MatterDustItem
import ru.dbotthepony.mc.otm.core.map
import ru.dbotthepony.mc.otm.menu.MatterRecyclerMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.ImpreciseFractionConfigValue
import ru.dbotthepony.mc.otm.core.defineImpreciseFraction
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.registry.MBlocks
import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.registry.WriteOnce
class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
: MatteryWorkerBlockEntity<MatteryWorkerBlockEntity.Job>(MBlockEntities.MATTER_RECYCLER, blockPos, blockState, ::Job), IMatterGraphNode, IDroppableContainer {
@ -42,7 +48,7 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
val matter = MatterHandlerImpl(
this::matterLevelUpdated,
MatterDirection.EXTRACT,
STORAGE
::CAPACITY
)
val container = MatteryContainer(this::itemContainerUpdated, 1)
@ -52,7 +58,7 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
override val matterNode = Graph6Node<IMatterGraphNode>(this)
private var resolverNode = LazyOptional.of { this }
private var valid = true
override val energy = WorkerEnergyStorage(this::powerLevelUpdated, MAX_POWER)
override val energy = WorkerEnergyStorage(this::powerLevelUpdated, ENERGY_CONFIG)
override fun getMatterHandler(): IMatterHandler {
return matter
@ -119,7 +125,7 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
}
override val defaultDisplayName: Component
get() = MACHINE_NAME
get() = MBlocks.MATTER_RECYCLER.name
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return MatterRecyclerMenu(containerID, inventory, this)
@ -172,10 +178,25 @@ class MatterRecyclerBlockEntity(blockPos: BlockPos, blockState: BlockState)
}
companion object {
private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.matter_recycler")
private val STORAGE = ImpreciseFraction(40)
private val POWER_CONSUMPTION = ImpreciseFraction(80)
private val MAX_POWER = ImpreciseFraction(80_000)
private var _CAPACITY: ImpreciseFractionConfigValue by WriteOnce()
private var _POWER_CONSUMPTION: ImpreciseFractionConfigValue by WriteOnce()
var ENERGY_CONFIG: ConciseBalanceValues by WriteOnce()
private set
private val CAPACITY get() = _CAPACITY.get()
private val POWER_CONSUMPTION get() = _POWER_CONSUMPTION.get()
fun registerConfig(builder: ForgeConfigSpec.Builder) {
builder.push(MNames.MATTER_RECYCLER)
ENERGY_CONFIG = BlockEnergyStorageImpl.makeConfigEntry(builder, capacity = ImpreciseFraction(80_000))
_CAPACITY = builder.defineImpreciseFraction("matterCapacity", ImpreciseFraction(40), ImpreciseFraction.ONE)
_POWER_CONSUMPTION = builder.defineImpreciseFraction("powerConsumption", ImpreciseFraction(80), ImpreciseFraction.ONE)
builder.pop()
}
private const val MATTER_TICKS = 200.0
private val MATTER_PER_TICK = ImpreciseFraction(1.0 / MATTER_TICKS)
}

View File

@ -12,11 +12,14 @@ import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.ForgeConfigSpec
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ForgeCapabilities
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.BlockEnergyStorageImpl
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.capability.matter.*
@ -31,6 +34,9 @@ import ru.dbotthepony.mc.otm.menu.MatterReplicatorMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.*
import ru.dbotthepony.mc.otm.registry.MBlocks
import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.registry.WriteOnce
class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryWorkerBlockEntity<MatterReplicatorBlockEntity.ReplicatorJob>(MBlockEntities.MATTER_REPLICATOR, p_155229_, p_155230_, {
@ -94,21 +100,21 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
}
}
override val energy = WorkerEnergyStorage(this::powerLevelUpdated, STORAGE, MAX_IO)
override val energy = WorkerEnergyStorage(this::powerLevelUpdated, ENERGY_VALUES)
override val matterNode = Graph6Node<IMatterGraphNode>(this)
private val resolverNode = LazyOptional.of { this }
val matter = MatterHandlerImpl(
this::matterLevelUpdated,
MatterDirection.RECEIVE,
ImpreciseFraction(2)
::MATTER_CAPACITY
)
val container = MatteryContainer(this::itemContainerUpdated, 5)
private val itemHandler = container.handler(MatteryContainerFilterOnlyOut)
override val defaultDisplayName: Component
get() = MACHINE_NAME
get() = MBlocks.MATTER_REPLICATOR.name
override val droppableContainer: Container
get() = container
@ -279,11 +285,28 @@ class MatterReplicatorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
}
companion object {
private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.matter_replicator")
private val BASE_CONSUMPTION = ImpreciseFraction(400)
private val DRAIN_MULT = ImpreciseFraction(200)
private val STORAGE = ImpreciseFraction(200_000)
private val MAX_IO = ImpreciseFraction(4_000)
private val BASE_CONSUMPTION get() = _BASE_CONSUMPTION.get()
private val DRAIN_MULT get() = _DRAIN_MULT.get()
private val MATTER_CAPACITY get() = _MATTER_CAPACITY.get()
private var _BASE_CONSUMPTION: ImpreciseFractionConfigValue by WriteOnce()
private var _DRAIN_MULT: ImpreciseFractionConfigValue by WriteOnce()
private var _MATTER_CAPACITY: ImpreciseFractionConfigValue by WriteOnce()
var ENERGY_VALUES: ConciseBalanceValues by WriteOnce()
private set
fun registerConfig(builder: ForgeConfigSpec.Builder) {
builder.push(MNames.MATTER_REPLICATOR)
ENERGY_VALUES = BlockEnergyStorageImpl.makeConfigEntry(builder, capacity = ImpreciseFraction(200_000), throughput = ImpreciseFraction(4_000))
_BASE_CONSUMPTION = builder.defineImpreciseFraction("basePowerConsumption", ImpreciseFraction(400), ImpreciseFraction.ONE)
_DRAIN_MULT = builder.comment("How much 'ticks' of replication should replicator drain matter from network when running low on internal matter buffer. This is ultimately a performance value.").defineImpreciseFraction("drainMultiplier", ImpreciseFraction(200), ImpreciseFraction.ONE)
_MATTER_CAPACITY = builder.defineImpreciseFraction("matterCapacity", ImpreciseFraction(2), ImpreciseFraction.ONE_TENTH)
builder.pop()
}
const val FIRST_ACTUAL_OUTPUT_SLOT = 0
const val LAST_ACTUAL_OUTPUT_SLOT = 2

View File

@ -12,12 +12,15 @@ import net.minecraft.world.inventory.AbstractContainerMenu
import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.ForgeConfigSpec
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.common.util.LazyOptional
import ru.dbotthepony.mc.otm.ConciseBalanceValues
import ru.dbotthepony.mc.otm.block.IDroppableContainer
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.block.entity.MatteryWorkerBlockEntity
import ru.dbotthepony.mc.otm.capability.BlockEnergyStorageImpl
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.WorkerEnergyStorage
import ru.dbotthepony.mc.otm.capability.matter.IPatternState
@ -25,6 +28,8 @@ import ru.dbotthepony.mc.otm.capability.matter.PatternState
import ru.dbotthepony.mc.otm.container.MatteryContainer
import ru.dbotthepony.mc.otm.container.MatteryContainerFilter
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.core.ImpreciseFractionConfigValue
import ru.dbotthepony.mc.otm.core.defineImpreciseFraction
import ru.dbotthepony.mc.otm.core.map
import ru.dbotthepony.mc.otm.graph.Graph6Node
import ru.dbotthepony.mc.otm.graph.matter.IMatterGraphNode
@ -32,6 +37,9 @@ import ru.dbotthepony.mc.otm.graph.matter.MatterNetworkGraph
import ru.dbotthepony.mc.otm.matter.*
import ru.dbotthepony.mc.otm.menu.MatterScannerMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.registry.MBlocks
import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.registry.WriteOnce
import java.util.*
import kotlin.math.pow
@ -39,7 +47,7 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryWorkerBlockEntity<MatteryWorkerBlockEntity.ItemJob>(MBlockEntities.MATTER_SCANNER, p_155229_, p_155230_, ::ItemJob), IMatterGraphNode, IDroppableContainer {
val container = MatteryContainer(this::itemContainerUpdated, 1)
override val energy = WorkerEnergyStorage(this::powerLevelUpdated, STORAGE, MAX_IO)
override val energy = WorkerEnergyStorage(this::powerLevelUpdated, ENERGY_VALUES)
private val itemHandler = container.handler(object : MatteryContainerFilter {
override fun canInsert(slot: Int, stack: ItemStack): Boolean {
@ -108,7 +116,7 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
}
override val defaultDisplayName: Component
get() = MACHINE_NAME
get() = MBlocks.MATTER_SCANNER.name
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return MatterScannerMenu(containerID, inventory, this)
@ -207,9 +215,19 @@ class MatterScannerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
}
companion object {
private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.matter_scanner")
private val BASE_CONSUMPTION = ImpreciseFraction("40")
private val STORAGE = ImpreciseFraction(80_000)
private val MAX_IO = ImpreciseFraction(400)
private val BASE_CONSUMPTION get() = _BASE_CONSUMPTION.get()
private var _BASE_CONSUMPTION: ImpreciseFractionConfigValue by WriteOnce()
var ENERGY_VALUES: ConciseBalanceValues by WriteOnce()
private set
fun registerConfig(builder: ForgeConfigSpec.Builder) {
builder.push(MNames.MATTER_SCANNER)
ENERGY_VALUES = BlockEnergyStorageImpl.makeConfigEntry(builder, capacity = ImpreciseFraction(80_000), throughput = ImpreciseFraction(400))
_BASE_CONSUMPTION = builder.defineImpreciseFraction("baseConsumption", ImpreciseFraction(40), ImpreciseFraction.ONE)
builder.pop()
}
}
}
}

View File

@ -13,6 +13,7 @@ import net.minecraft.world.level.Level
import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.util.LazyOptional
import ru.dbotthepony.mc.otm.ServerConfig
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode
@ -25,11 +26,12 @@ import ru.dbotthepony.mc.otm.core.map
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.registry.MBlocks
import ru.dbotthepony.mc.otm.storage.*
class DriveRackBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryPoweredBlockEntity(MBlockEntities.DRIVE_RACK, p_155229_, p_155230_) {
override val energy = WorkerEnergyStorage(this, STORAGE)
override val energy = WorkerEnergyStorage(this, ServerConfig.DRIVE_RACK)
val container: MatteryContainer = object : MatteryContainer(this::setChanged, 4) {
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
@ -74,7 +76,7 @@ class DriveRackBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
}
override val defaultDisplayName: Component
get() = MACHINE_NAME
get() = MBlocks.DRIVE_RACK.name
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return DriveRackMenu(containerID, inventory, this)
@ -100,9 +102,4 @@ class DriveRackBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
super.setRemoved()
cell.destroy(level)
}
companion object {
private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.drive_rack")
private val STORAGE = ImpreciseFraction(80_000)
}
}

View File

@ -12,6 +12,7 @@ import net.minecraft.world.item.ItemStack
import net.minecraft.world.level.block.Block
import net.minecraft.world.level.block.state.BlockState
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.ServerConfig
import ru.dbotthepony.mc.otm.block.IDroppableContainer
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
@ -25,6 +26,7 @@ import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.map
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.registry.MBlocks
import javax.annotation.ParametersAreNonnullByDefault
class DriveViewerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : MatteryPoweredBlockEntity(MBlockEntities.DRIVE_VIEWER, p_155229_, p_155230_), IDroppableContainer {
@ -46,7 +48,7 @@ class DriveViewerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
}
}
override val energy = WorkerEnergyStorage(this)
override val energy = WorkerEnergyStorage(this, ServerConfig.DRIVE_VIEWER)
val container: MatteryContainer = object : MatteryContainer(this::setChanged, 1) {
override fun setChanged(slot: Int, new: ItemStack, old: ItemStack) {
@ -73,7 +75,7 @@ class DriveViewerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
override val droppableContainer: Container
get() = container
override val defaultDisplayName: Component
get() = MACHINE_NAME
get() = MBlocks.DRIVE_VIEWER.name
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu? {
return DriveViewerMenu(containerID, inventory, this)
@ -92,8 +94,4 @@ class DriveViewerBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : Matte
fun tick() {
batteryChargeLoop()
}
companion object {
private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.drive_viewer")
}
}

View File

@ -26,6 +26,7 @@ import net.minecraftforge.common.util.INBTSerializable
import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.network.NetworkEvent
import org.apache.logging.log4j.LogManager
import ru.dbotthepony.mc.otm.ServerConfig
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
import ru.dbotthepony.mc.otm.capability.MatteryCapability
@ -42,6 +43,7 @@ import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.getEnum
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.registry.MBlocks
import ru.dbotthepony.mc.otm.storage.*
import java.math.BigInteger
import java.util.*
@ -182,7 +184,7 @@ class ItemMonitorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
MatteryPoweredBlockEntity(MBlockEntities.ITEM_MONITOR, p_155229_, p_155230_),
IStorageEventConsumer<ItemStackWrapper> {
override val energy = WorkerEnergyStorage(this)
override val energy = WorkerEnergyStorage(this, ServerConfig.ITEM_MONITOR)
var poweredView: PoweredVirtualComponent<ItemStackWrapper>? = null
private set
@ -488,7 +490,7 @@ class ItemMonitorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
}
override val defaultDisplayName: Component
get() = MACHINE_NAME
get() = MBlocks.ITEM_MONITOR.name
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return ItemMonitorMenu(containerID, inventory, this)
@ -521,8 +523,4 @@ class ItemMonitorBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) :
super.setRemoved()
cell.destroy(level)
}
companion object {
private val MACHINE_NAME = TranslatableComponent("block.overdrive_that_matters.item_monitor")
}
}

View File

@ -33,6 +33,7 @@ import ru.dbotthepony.mc.otm.graph.storage.BasicStorageGraphNode
import ru.dbotthepony.mc.otm.graph.storage.StorageNetworkGraph
import ru.dbotthepony.mc.otm.menu.StorageBusMenu
import ru.dbotthepony.mc.otm.registry.MBlockEntities
import ru.dbotthepony.mc.otm.registry.MBlocks
import ru.dbotthepony.mc.otm.registry.MNames
import ru.dbotthepony.mc.otm.storage.*
import java.lang.ref.WeakReference
@ -62,13 +63,13 @@ private fun Long.clamp(): Int {
class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : MatteryPoweredBlockEntity(MBlockEntities.STORAGE_BUS, blockPos, blockState) {
override val defaultDisplayName: Component
get() = MACHINE_NAME
get() = MBlocks.STORAGE_BUS.name
override fun createMenu(containerID: Int, inventory: Inventory, ply: Player): AbstractContainerMenu {
return StorageBusMenu(containerID, inventory, this)
}
override val energy = WorkerEnergyStorage(this, maxBatteryLevel = MAX_POWER)
override val energy = WorkerEnergyStorage(this::setChangedLight, ServerConfig.STORAGE_INTERFACES)
val cell: BasicStorageGraphNode = object : BasicStorageGraphNode(energy), GraphNodeListener {
override fun onNeighbour(node: Graph6Node<*>, direction: Direction) {
@ -178,8 +179,6 @@ class StorageBusBlockEntity(blockPos: BlockPos, blockState: BlockState) : Matter
}
companion object {
private val MACHINE_NAME = TranslatableComponent("block.${OverdriveThatMatters.MOD_ID}.${MNames.STORAGE_BUS}")
private val MAX_POWER = ImpreciseFraction(10_000)
const val MAX_FILTERS = 6 * 3
}

View File

@ -42,11 +42,9 @@ abstract class AbstractStorageImportExport<T>(
blockType: BlockEntityType<*>,
blockPos: BlockPos,
blockState: BlockState,
maxBatteryLevel: ImpreciseFraction = MAX_POWER,
maxInput: ImpreciseFraction? = BlockEnergyStorageImpl.DEFAULT_MAX_IO,
maxOutput: ImpreciseFraction? = maxInput
energyValues: ConciseBalanceValues = ServerConfig.STORAGE_INTERFACES
) : MatteryPoweredBlockEntity(blockType, blockPos, blockState) {
final override val energy = WorkerEnergyStorage(this, maxBatteryLevel, maxInput, maxOutput)
final override val energy = WorkerEnergyStorage(this::setChangedLight, energyValues)
val cell: BasicStorageGraphNode = object : BasicStorageGraphNode(energy), GraphNodeListener {
override fun onNeighbour(node: Graph6Node<*>, direction: Direction) {

View File

@ -13,6 +13,7 @@ import net.minecraft.world.level.block.state.BlockState
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.util.LazyOptional
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.ServerConfig
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.block.entity.MatteryPoweredBlockEntity
import ru.dbotthepony.mc.otm.capability.MatteryCapability
@ -88,7 +89,7 @@ class StoragePowerSupplierBlockEntity(blockPos: BlockPos, blockState: BlockState
var demand = ImpreciseFraction.ZERO
var i = 0
val available = energy.batteryLevel.coerceAtMost(MAX_IO)
val available = energy.batteryLevel.coerceAtMost(ServerConfig.STORAGE_POWER_SUPPLIER.throughput)
for (demanding in graph.powerDemandingNodes) {
val received = demanding.receiveEnergyOuter(available, true)
@ -114,7 +115,7 @@ class StoragePowerSupplierBlockEntity(blockPos: BlockPos, blockState: BlockState
}
}
override val energy = WorkerEnergyStorage(this, MAX_POWER, MAX_IO)
override val energy = WorkerEnergyStorage(this, ServerConfig.STORAGE_POWER_SUPPLIER)
override fun saveAdditional(nbt: CompoundTag) {
super.saveAdditional(nbt)
@ -128,8 +129,6 @@ class StoragePowerSupplierBlockEntity(blockPos: BlockPos, blockState: BlockState
companion object {
private val MACHINE_NAME = TranslatableComponent("block.${OverdriveThatMatters.MOD_ID}.${MNames.STORAGE_POWER_SUPPLIER}")
private val MAX_POWER = ImpreciseFraction(100_000)
private val MAX_IO = ImpreciseFraction(320)
const val POWER_PASSED_KEY = "powerPassed"
}
}

View File

@ -13,19 +13,23 @@ import net.minecraft.world.item.TooltipFlag
import net.minecraft.world.level.BlockGetter
import net.minecraft.world.level.Level
import net.minecraft.world.level.block.entity.BlockEntity
import net.minecraftforge.common.ForgeConfigSpec
import net.minecraftforge.common.capabilities.Capability
import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.common.capabilities.ICapabilityProvider
import net.minecraftforge.common.util.INBTSerializable
import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.energy.IEnergyStorage
import ru.dbotthepony.mc.otm.ConciseBalanceValues
import ru.dbotthepony.mc.otm.VerboseBalanceValues
import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity
import ru.dbotthepony.mc.otm.compat.mekanism.Mattery2MekanismEnergyWrapper
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.defineImpreciseFraction
import ru.dbotthepony.mc.otm.core.formatPower
import ru.dbotthepony.mc.otm.core.ifPresentK
import ru.dbotthepony.mc.otm.core.map
import ru.dbotthepony.mc.otm.core.mapIf
import ru.dbotthepony.mc.otm.core.set
import ru.dbotthepony.mc.otm.core.tagNotNull
@ -250,22 +254,48 @@ open class EnergyCapacitorItem(
initialBatteryLevel: ImpreciseFraction = ImpreciseFraction.ZERO
) : ItemEnergyStorageImpl(FlowDirection.BI_DIRECTIONAL, stack, maxBatteryLevel, maxInput, maxOutput, initialBatteryLevel)
sealed class BlockEnergyStorageImpl constructor(
sealed class BlockEnergyStorageImpl(
protected val listener: () -> Unit,
final override val direction: FlowDirection,
maxBatteryLevel: ImpreciseFraction,
maxInput: ImpreciseFraction?,
maxOutput: ImpreciseFraction?,
private val maxBatteryLevelProvider: () -> ImpreciseFraction,
private val maxInputProvider: () -> ImpreciseFraction?,
private val maxOutputProvider: () -> ImpreciseFraction?,
) : IMatteryEnergyStorage, INBTSerializable<CompoundTag>, IEnergyStorageImpl {
final override var maxInput: ImpreciseFraction? = maxInput
protected set
final override var maxOutput: ImpreciseFraction? = maxOutput
protected set
constructor(
listener: () -> Unit,
direction: FlowDirection,
maxBatteryLevel: ImpreciseFraction,
maxInput: ImpreciseFraction?,
maxOutput: ImpreciseFraction?,
) : this(listener, direction, { maxBatteryLevel }, { maxInput }, { maxOutput })
override var maxBatteryLevel: ImpreciseFraction = maxBatteryLevel
private var maxInputStorage: ImpreciseFraction? = null
private var maxOutputStorage: ImpreciseFraction? = null
private var maxBatteryLevelStorage: ImpreciseFraction? = null
final override var maxInput: ImpreciseFraction?
get() = maxInputStorage ?: maxInputProvider.invoke()
protected set(value) {
if (value != field) {
field = value
if (value != maxInputStorage) {
maxInputStorage = value
listener.invoke()
}
}
final override var maxOutput: ImpreciseFraction?
get() = maxOutputStorage ?: maxOutputProvider.invoke()
protected set(value) {
if (value != maxOutputStorage) {
maxOutputStorage = value
listener.invoke()
}
}
override var maxBatteryLevel: ImpreciseFraction
get() = maxBatteryLevelStorage ?: maxBatteryLevelProvider.invoke()
protected set(value) {
if (value != maxBatteryLevelStorage) {
maxBatteryLevelStorage = value
listener.invoke()
}
}
@ -353,19 +383,19 @@ sealed class BlockEnergyStorageImpl constructor(
override fun serializeNBT(): CompoundTag {
val tag = CompoundTag()
tag[ENERGY_STORED_KEY] = batteryLevel.serializeNBT()
tag[ENERGY_STORED_MAX_KEY] = maxBatteryLevel.serializeNBT()
maxInput?.let { tag[MAX_INPUT_KEY] = it.serializeNBT() }
maxOutput?.let { tag[MAX_OUTPUT_KEY] = it.serializeNBT() }
maxBatteryLevelStorage?.let { tag[ENERGY_STORED_MAX_KEY] = it.serializeNBT() }
maxInputStorage?.let { tag[MAX_INPUT_KEY] = it.serializeNBT() }
maxOutputStorage?.let { tag[MAX_OUTPUT_KEY] = it.serializeNBT() }
return tag
}
override fun deserializeNBT(nbt: CompoundTag) {
batteryLevel = nbt.map(ENERGY_STORED_KEY, ImpreciseFraction.Companion::deserializeNBT) ?: ImpreciseFraction.ZERO
maxBatteryLevel = nbt.map(ENERGY_STORED_MAX_KEY, ImpreciseFraction.Companion::deserializeNBT) ?: ImpreciseFraction.ZERO
maxInput = nbt.map(MAX_INPUT_KEY, ImpreciseFraction.Companion::deserializeNBT)
maxOutput = nbt.map(MAX_OUTPUT_KEY, ImpreciseFraction.Companion::deserializeNBT)
maxBatteryLevelStorage = nbt.mapIf(ENERGY_STORED_MAX_KEY, ImpreciseFraction.Companion::deserializeNBT)
maxInputStorage = nbt.mapIf(MAX_INPUT_KEY, ImpreciseFraction.Companion::deserializeNBT)
maxOutputStorage = nbt.mapIf(MAX_OUTPUT_KEY, ImpreciseFraction.Companion::deserializeNBT)
}
var resolver: LazyOptional<IMatteryEnergyStorage> = LazyOptional.of { this }
@ -387,25 +417,62 @@ sealed class BlockEnergyStorageImpl constructor(
const val ENERGY_STORED_MAX_KEY = "energy_stored_max"
const val MAX_INPUT_KEY = "max_input"
const val MAX_OUTPUT_KEY = "max_output"
fun makeConfigEntry(builder: ForgeConfigSpec.Builder, name: String? = null, capacity: ImpreciseFraction = DEFAULT_MAX_CAPACITY, throughput: ImpreciseFraction = DEFAULT_MAX_IO): ConciseBalanceValues {
if (name != null)
builder.push(name)
val obj = object : ConciseBalanceValues {
override val capacity: ImpreciseFraction by builder.defineImpreciseFraction("capacity", capacity, ImpreciseFraction.ONE)
override val throughput: ImpreciseFraction by builder.defineImpreciseFraction("throughput", throughput, ImpreciseFraction.ONE)
}
if (name != null)
builder.pop()
return obj
}
}
}
open class WorkerEnergyStorage(
listener: () -> Unit,
maxBatteryLevel: ImpreciseFraction = DEFAULT_MAX_CAPACITY,
maxInput: ImpreciseFraction? = DEFAULT_MAX_IO,
maxOutput: ImpreciseFraction? = maxInput
maxBatteryLevel: () -> ImpreciseFraction = { DEFAULT_MAX_CAPACITY },
maxInput: () -> ImpreciseFraction? = { DEFAULT_MAX_IO },
maxOutput: () -> ImpreciseFraction? = maxInput
) : BlockEnergyStorageImpl(listener, FlowDirection.INPUT, maxBatteryLevel, maxInput, maxOutput) {
constructor(
listener: () -> Unit,
maxBatteryLevel: ImpreciseFraction = DEFAULT_MAX_CAPACITY,
maxInput: ImpreciseFraction? = DEFAULT_MAX_IO,
maxOutput: ImpreciseFraction? = maxInput) : this(listener, { maxBatteryLevel }, { maxInput }, { maxOutput })
constructor(
listener: () -> Unit,
values: ConciseBalanceValues) : this(listener, values::capacity, values::throughput, values::throughput)
constructor(
listener: BlockEntity,
values: ConciseBalanceValues) : this(listener::setChanged, values::capacity, values::throughput, values::throughput)
constructor(
listener: () -> Unit,
values: VerboseBalanceValues) : this(listener, values::capacity, values::receive, values::extract)
constructor(
listener: BlockEntity,
values: VerboseBalanceValues) : this(listener::setChanged, values::capacity, values::receive, values::extract)
constructor(
listener: BlockEntity,
maxBatteryLevel: ImpreciseFraction = DEFAULT_MAX_CAPACITY,
maxInput: ImpreciseFraction? = DEFAULT_MAX_IO,
maxOutput: ImpreciseFraction? = maxInput) : this({listener.setChanged()}, maxBatteryLevel, maxInput, maxOutput)
maxOutput: ImpreciseFraction? = maxInput) : this(listener::setChanged, maxBatteryLevel, maxInput, maxOutput)
companion object {
fun appendHoverText(itemStack: ItemStack, tooltips: MutableList<Component>) {
val tag = (itemStack.tag?.get(BlockItem.BLOCK_ENTITY_TAG) as? CompoundTag)?.get(MatteryBlockEntity.ENERGY_KEY) as? CompoundTag ?: return
val cap = WorkerEnergyStorage({})
val cap = WorkerEnergyStorage({}, DEFAULT_MAX_CAPACITY)
cap.deserializeNBT(tag)
batteryLevel(cap, tooltips)
}
@ -418,20 +485,42 @@ open class WorkerEnergyStorage(
open class GeneratorEnergyStorage(
listener: () -> Unit,
maxBatteryLevel: ImpreciseFraction = DEFAULT_MAX_CAPACITY,
maxInput: ImpreciseFraction? = DEFAULT_MAX_IO,
maxOutput: ImpreciseFraction? = maxInput
maxBatteryLevel: () -> ImpreciseFraction = { DEFAULT_MAX_CAPACITY },
maxInput: () -> ImpreciseFraction? = { DEFAULT_MAX_IO },
maxOutput: () -> ImpreciseFraction? = maxInput
) : BlockEnergyStorageImpl(listener, FlowDirection.OUTPUT, maxBatteryLevel, maxInput, maxOutput) {
constructor(
listener: () -> Unit,
maxBatteryLevel: ImpreciseFraction = DEFAULT_MAX_CAPACITY,
maxInput: ImpreciseFraction? = DEFAULT_MAX_IO,
maxOutput: ImpreciseFraction? = maxInput) : this(listener, { maxBatteryLevel }, { maxInput }, { maxOutput })
constructor(
listener: () -> Unit,
values: ConciseBalanceValues) : this(listener, values::capacity, values::throughput, values::throughput)
constructor(
listener: BlockEntity,
values: ConciseBalanceValues) : this(listener::setChanged, values::capacity, values::throughput, values::throughput)
constructor(
listener: () -> Unit,
values: VerboseBalanceValues) : this(listener, values::capacity, values::receive, values::extract)
constructor(
listener: BlockEntity,
values: VerboseBalanceValues) : this(listener::setChanged, values::capacity, values::receive, values::extract)
constructor(
listener: BlockEntity,
maxBatteryLevel: ImpreciseFraction = DEFAULT_MAX_CAPACITY,
maxInput: ImpreciseFraction? = DEFAULT_MAX_IO,
maxOutput: ImpreciseFraction? = maxInput) : this({listener.setChanged()}, maxBatteryLevel, maxInput, maxOutput)
maxOutput: ImpreciseFraction? = maxInput) : this(listener::setChanged, maxBatteryLevel, maxInput, maxOutput)
companion object {
fun appendHoverText(itemStack: ItemStack, tooltips: MutableList<Component>) {
val tag = (itemStack.tag?.get(BlockItem.BLOCK_ENTITY_TAG) as? CompoundTag)?.get(MatteryBlockEntity.ENERGY_KEY) as? CompoundTag ?: return
val cap = GeneratorEnergyStorage({})
val cap = GeneratorEnergyStorage({}, DEFAULT_MAX_CAPACITY)
cap.deserializeNBT(tag)
batteryLevel(cap, tooltips)
}
@ -444,20 +533,42 @@ open class GeneratorEnergyStorage(
open class CapacitorEnergyStorage(
listener: () -> Unit,
maxBatteryLevel: ImpreciseFraction = DEFAULT_MAX_CAPACITY,
maxInput: ImpreciseFraction? = DEFAULT_MAX_IO,
maxOutput: ImpreciseFraction? = maxInput
maxBatteryLevel: () -> ImpreciseFraction = { DEFAULT_MAX_CAPACITY },
maxInput: () -> ImpreciseFraction? = { DEFAULT_MAX_IO },
maxOutput: () -> ImpreciseFraction? = maxInput
) : BlockEnergyStorageImpl(listener, FlowDirection.BI_DIRECTIONAL, maxBatteryLevel, maxInput, maxOutput) {
constructor(
listener: () -> Unit,
maxBatteryLevel: ImpreciseFraction = DEFAULT_MAX_CAPACITY,
maxInput: ImpreciseFraction? = DEFAULT_MAX_IO,
maxOutput: ImpreciseFraction? = maxInput) : this(listener, { maxBatteryLevel }, { maxInput }, { maxOutput })
constructor(
listener: () -> Unit,
values: ConciseBalanceValues) : this(listener, values::capacity, values::throughput, values::throughput)
constructor(
listener: BlockEntity,
values: ConciseBalanceValues) : this(listener::setChanged, values::capacity, values::throughput, values::throughput)
constructor(
listener: () -> Unit,
values: VerboseBalanceValues) : this(listener, values::capacity, values::receive, values::extract)
constructor(
listener: BlockEntity,
values: VerboseBalanceValues) : this(listener::setChanged, values::capacity, values::receive, values::extract)
constructor(
listener: BlockEntity,
maxBatteryLevel: ImpreciseFraction = DEFAULT_MAX_CAPACITY,
maxInput: ImpreciseFraction? = DEFAULT_MAX_IO,
maxOutput: ImpreciseFraction? = maxInput) : this({listener.setChanged()}, maxBatteryLevel, maxInput, maxOutput)
maxOutput: ImpreciseFraction? = maxInput) : this(listener::setChanged, maxBatteryLevel, maxInput, maxOutput)
companion object {
fun appendHoverText(itemStack: ItemStack, tooltips: MutableList<Component>) {
val tag = (itemStack.tag?.get(BlockItem.BLOCK_ENTITY_TAG) as? CompoundTag)?.get(MatteryBlockEntity.ENERGY_KEY) as? CompoundTag ?: return
val cap = CapacitorEnergyStorage({})
val cap = CapacitorEnergyStorage({}, DEFAULT_MAX_CAPACITY)
cap.deserializeNBT(tag)
batteryLevel(cap, tooltips)
}

View File

@ -3,6 +3,8 @@ package ru.dbotthepony.mc.otm.capability.matter
import net.minecraft.nbt.CompoundTag
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.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.container.set
import ru.dbotthepony.mc.otm.core.set
@ -10,10 +12,36 @@ import ru.dbotthepony.mc.otm.core.set
open class MatterHandlerImpl @JvmOverloads constructor(
protected val listener: Runnable?,
override val direction: MatterDirection,
override val maxStoredMatter: ImpreciseFraction,
val maxReceive: ImpreciseFraction? = null,
val maxExtract: ImpreciseFraction? = maxReceive
protected val maxStoredMatterSupplier: () -> ImpreciseFraction,
protected val maxReceiveSupplier: () -> ImpreciseFraction? = { null },
protected val maxExtractSupplier: () -> ImpreciseFraction? = maxReceiveSupplier
) : IMatterHandler, INBTSerializable<CompoundTag> {
constructor(
listener: Runnable?,
direction: MatterDirection,
maxStoredMatter: ImpreciseFraction,
maxReceive: ImpreciseFraction? = null,
maxExtract: ImpreciseFraction? = null,
) : this(listener, direction, { maxStoredMatter }, { maxReceive }, { maxExtract })
constructor(
listener: Runnable?,
direction: MatterDirection,
values: ConciseBalanceValues
) : this(listener, direction, values::capacity, values::throughput, values::throughput)
constructor(
listener: Runnable?,
direction: MatterDirection,
values: VerboseBalanceValues
) : this(listener, direction, values::capacity, values::receive, values::extract)
val maxReceive get() = maxReceiveSupplier.invoke()
val maxExtract get() = maxExtractSupplier.invoke()
override val maxStoredMatter: ImpreciseFraction
get() = maxStoredMatterSupplier.invoke()
override var storedMatter = ImpreciseFraction.ZERO
protected set
@ -48,7 +76,7 @@ open class MatterHandlerImpl @JvmOverloads constructor(
if (maxReceive == null) {
new = (storedMatter + howMuch).coerceAtMost(maxStoredMatter)
} else {
new = (storedMatter + howMuch.coerceAtMost(maxReceive)).coerceAtMost(maxStoredMatter)
new = (storedMatter + howMuch.coerceAtMost(maxReceive!!)).coerceAtMost(maxStoredMatter)
}
val diff = new - storedMatter
@ -74,7 +102,7 @@ open class MatterHandlerImpl @JvmOverloads constructor(
if (maxExtract == null) {
new = (storedMatter - howMuch).moreThanZero()
} else {
new = (storedMatter - howMuch.coerceAtMost(maxExtract)).moreThanZero()
new = (storedMatter - howMuch.coerceAtMost(maxExtract!!)).moreThanZero()
}
val diff = storedMatter - new

View File

@ -51,6 +51,16 @@ inline fun <R, reified T : Tag?> CompoundTag.map(key: String, consumer: (T) -> R
return null
}
inline fun <R, reified T : Tag> CompoundTag.mapIf(key: String, consumer: (T) -> R): R? {
val tag = get(key)
if (tag is T) {
return consumer(tag)
}
return null
}
inline fun <reified R : Enum<R>> CompoundTag.getEnum(key: String): R {
val tag = get(key)

View File

@ -18,6 +18,7 @@ import net.minecraft.world.level.block.state.StateHolder
import net.minecraft.world.level.block.state.properties.Property
import net.minecraft.world.phys.Vec3
import net.minecraftforge.common.ForgeConfigSpec
import net.minecraftforge.common.ForgeConfigSpec.ConfigValue
import net.minecraftforge.common.util.LazyOptional
import net.minecraftforge.items.IItemHandler
import net.minecraftforge.registries.ForgeRegistries
@ -25,6 +26,7 @@ import net.minecraftforge.registries.ForgeRegistry
import net.minecraftforge.registries.IForgeRegistry
import net.minecraftforge.registries.RegistryManager
import ru.dbotthepony.mc.otm.ClientConfig
import ru.dbotthepony.mc.otm.item.BatteryItem
import java.math.BigInteger
import kotlin.reflect.KProperty
@ -339,10 +341,6 @@ fun <T> List<T>.toImmutableList(): ImmutableList<T> {
return ImmutableList.copyOf(this)
}
operator fun <T> ForgeConfigSpec.ConfigValue<T>.setValue(config: ClientConfig, property: KProperty<*>, value: T) {
set(value)
operator fun <R> (() -> R).getValue(thisRef: Any, property: KProperty<*>): R {
return invoke()
}
operator fun <T : Any> ForgeConfigSpec.ConfigValue<T>.getValue(config: Any, property: KProperty<*>): T {
return get()
}

View File

@ -5,6 +5,9 @@ import net.minecraft.nbt.CompoundTag
import net.minecraft.nbt.StringTag
import net.minecraft.nbt.Tag
import net.minecraft.network.FriendlyByteBuf
import net.minecraftforge.common.ForgeConfigSpec
import ru.dbotthepony.mc.otm.ObservedConfigValue
import ru.dbotthepony.mc.otm.appendComment
import java.io.InputStream
import java.io.OutputStream
import java.math.BigDecimal
@ -144,7 +147,7 @@ private val BI_MINUS_ONE = -BigInteger.ONE
*
*/
@Suppress("unused")
class ImpreciseFraction @JvmOverloads constructor(whole: BigInteger, decimal: Double = 0.0) : Number(), Comparable<ImpreciseFraction> {
class ImpreciseFraction @JvmOverloads constructor(whole: BigInteger, decimal: Double = 0.0) : Number(), Comparable<ImpreciseFraction>, java.io.Serializable {
@JvmOverloads constructor(whole: Byte, decimal: Double = 0.0) : this(BigInteger.valueOf(whole.toLong()), decimal)
@JvmOverloads constructor(whole: Short, decimal: Double = 0.0) : this(BigInteger.valueOf(whole.toLong()), decimal)
@JvmOverloads constructor(whole: Int, decimal: Double = 0.0) : this(BigInteger.valueOf(whole.toLong()), decimal)
@ -752,6 +755,9 @@ class ImpreciseFraction @JvmOverloads constructor(whole: BigInteger, decimal: Do
}
companion object {
@JvmStatic
val serialVersionUID: Long = 287354739494574838L
@JvmField val MINUS_ZERO = ImpreciseFraction(0, -0.0)
@JvmField val ZERO = ImpreciseFraction(BigInteger.ZERO)
@JvmField val ONE = ImpreciseFraction(BigInteger.ONE)
@ -769,6 +775,8 @@ class ImpreciseFraction @JvmOverloads constructor(whole: BigInteger, decimal: Do
@JvmField val DOUBLE_MAX_VALUE = ImpreciseFraction(BI_DOUBLE_MAX)
@JvmField val DOUBLE_MIN_VALUE = ImpreciseFraction(BI_DOUBLE_MIN)
@JvmField val ONE_TENTH = ImpreciseFraction("0.1")
private val cache = Array(2048) { ImpreciseFraction(it - 1024) }
/**
@ -860,3 +868,49 @@ fun Byte.toImpreciseFraction() = ImpreciseFraction(this)
fun Short.toImpreciseFraction() = ImpreciseFraction(this)
fun Long.toImpreciseFraction() = ImpreciseFraction(this)
fun ImpreciseFraction.toImpreciseFraction() = this
class ImpreciseFractionConfigValue(
parent: ForgeConfigSpec.ConfigValue<String>,
val minimum: ImpreciseFraction? = null,
val maximum: ImpreciseFraction? = null,
) : ObservedConfigValue<ImpreciseFraction>(parent) {
override fun fromValue(value: String): ImpreciseFraction? {
try {
val parsed = ImpreciseFraction(value)
if (minimum != null && minimum > parsed) {
return minimum
} else if (maximum != null && maximum < parsed) {
return maximum
}
return parsed
} catch (err: java.lang.NumberFormatException) {
return null
}
}
override fun toValue(value: ImpreciseFraction): Pair<String, ImpreciseFraction> {
return value.toString() to value
}
}
private fun ForgeConfigSpec.Builder.commentRange(minimum: ImpreciseFraction?, maximum: ImpreciseFraction?) {
if (minimum != null && maximum != null) {
appendComment("Range: $minimum ~ $maximum")
} else if (minimum != null) {
appendComment("Range: >= $minimum")
} else if (maximum != null) {
appendComment("Range: <= $maximum")
}
}
fun ForgeConfigSpec.Builder.defineImpreciseFraction(path: String, defaultValue: ImpreciseFraction, minimum: ImpreciseFraction? = null, maximum: ImpreciseFraction? = null): ImpreciseFractionConfigValue {
commentRange(minimum, maximum)
return ImpreciseFractionConfigValue(define(path, defaultValue.toString()), minimum, maximum)
}
fun ForgeConfigSpec.Builder.defineImpreciseFraction(path: List<String>, defaultValue: ImpreciseFraction, minimum: ImpreciseFraction? = null, maximum: ImpreciseFraction? = null): ImpreciseFractionConfigValue {
commentRange(minimum, maximum)
return ImpreciseFractionConfigValue(define(path, defaultValue.toString()), minimum, maximum)
}

View File

@ -14,7 +14,10 @@ import net.minecraft.world.item.*
import net.minecraft.world.level.Level
import net.minecraftforge.common.capabilities.ForgeCapabilities
import net.minecraftforge.common.capabilities.ICapabilityProvider
import ru.dbotthepony.mc.otm.BatteryBalanceValues
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.ServerConfig
import ru.dbotthepony.mc.otm.VerboseBalanceValues
import ru.dbotthepony.mc.otm.capability.*
import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.core.*
@ -23,7 +26,7 @@ import ru.dbotthepony.mc.otm.runIfClient
import kotlin.math.roundToInt
open class BatteryItem : Item {
private inner class Power(stack: ItemStack) : EnergyCapacitorItem(stack, this@BatteryItem.storage, this@BatteryItem.receive, this@BatteryItem.extract, initialBatteryLevel = this@BatteryItem.initialBatteryLevel) {
private inner class Power(stack: ItemStack) : EnergyCapacitorItem(stack, this@BatteryItem.capacity, this@BatteryItem.receive, this@BatteryItem.extract, initialBatteryLevel = this@BatteryItem.initialBatteryLevel) {
override fun extractEnergyInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (isCreative) return howMuch
return super.extractEnergyInner(howMuch, simulate)
@ -44,27 +47,61 @@ open class BatteryItem : Item {
}
private val isCreative: Boolean
val storage: ImpreciseFraction
val receive: ImpreciseFraction
val extract: ImpreciseFraction
val initialBatteryLevel: ImpreciseFraction
constructor(storage: ImpreciseFraction, receive: ImpreciseFraction, extract: ImpreciseFraction = receive, initialBatteryLevel: ImpreciseFraction = ImpreciseFraction.ZERO) : super(
Properties().stacksTo(1).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)
) {
val _capacity: () -> ImpreciseFraction
val _receive: () -> ImpreciseFraction
val _extract: () -> ImpreciseFraction
val _initialBatteryLevel: () -> ImpreciseFraction
val capacity: ImpreciseFraction
get() = _capacity.invoke()
val receive: ImpreciseFraction
get() = _receive.invoke()
val extract: ImpreciseFraction
get() = _extract.invoke()
val initialBatteryLevel: ImpreciseFraction
get() = _initialBatteryLevel.invoke()
constructor(
storage: ImpreciseFraction,
receive: ImpreciseFraction,
extract: ImpreciseFraction = receive,
initialBatteryLevel: ImpreciseFraction = ImpreciseFraction.ZERO
) : super(Properties().stacksTo(1).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) {
isCreative = false
this.storage = storage
this.receive = receive
this.extract = extract
this.initialBatteryLevel = initialBatteryLevel
this._capacity = { storage }
this._receive = { receive }
this._extract = { extract }
this._initialBatteryLevel = { initialBatteryLevel }
}
constructor(
storage: () -> ImpreciseFraction,
receive: () -> ImpreciseFraction,
extract: () -> ImpreciseFraction = receive,
initialBatteryLevel: () -> ImpreciseFraction = { ImpreciseFraction.ZERO }
) : super(Properties().stacksTo(1).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) {
isCreative = false
this._capacity = storage
this._receive = receive
this._extract = extract
this._initialBatteryLevel = initialBatteryLevel
}
constructor(values: BatteryBalanceValues) : super(Properties().stacksTo(1).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) {
isCreative = false
this._capacity = values::capacity
this._receive = values::receive
this._extract = values::extract
this._initialBatteryLevel = values::initialBatteryLevel
}
constructor() : super(Properties().stacksTo(1).rarity(Rarity.EPIC).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) {
isCreative = true
storage = ImpreciseFraction.LONG_MAX_VALUE
receive = ImpreciseFraction.LONG_MAX_VALUE
extract = ImpreciseFraction.LONG_MAX_VALUE
initialBatteryLevel = ImpreciseFraction.LONG_MAX_VALUE
_capacity = { ImpreciseFraction.LONG_MAX_VALUE }
_receive = { ImpreciseFraction.LONG_MAX_VALUE }
_extract = { ImpreciseFraction.LONG_MAX_VALUE }
_initialBatteryLevel = { ImpreciseFraction.LONG_MAX_VALUE }
}
override fun isBarVisible(p_150899_: ItemStack): Boolean {
@ -114,7 +151,7 @@ open class BatteryItem : Item {
}
}
class CrudeBatteryItem : BatteryItem(MAX_STORAGE, extract = MAX_EXTRACT, receive = MAX_RECEIVE, initialBatteryLevel = INITIAL_STORAGE) {
class CrudeBatteryItem : BatteryItem(ServerConfig.BATTERY_CRUDE) {
override fun appendHoverText(
stack: ItemStack,
p_41422_: Level?,
@ -183,11 +220,4 @@ class CrudeBatteryItem : BatteryItem(MAX_STORAGE, extract = MAX_EXTRACT, receive
return itemStack
}
companion object {
val MAX_STORAGE = ImpreciseFraction(100_000)
val MAX_EXTRACT = ImpreciseFraction(160)
val MAX_RECEIVE = ImpreciseFraction(40)
val INITIAL_STORAGE = MAX_STORAGE * .8f
}
}
}

View File

@ -5,7 +5,6 @@ import net.minecraft.MethodsReturnNonnullByDefault
import net.minecraft.core.Direction
import net.minecraft.nbt.CompoundTag
import net.minecraft.network.chat.Component
import net.minecraft.util.Mth
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Rarity
@ -17,10 +16,7 @@ import net.minecraftforge.common.util.LazyOptional
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.capability.MatteryCapability
import ru.dbotthepony.mc.otm.capability.getBarColor
import ru.dbotthepony.mc.otm.capability.getBarWidth
import ru.dbotthepony.mc.otm.capability.matter.*
import ru.dbotthepony.mc.otm.capability.matteryEnergy
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.core.formatMatter
import javax.annotation.ParametersAreNonnullByDefault
@ -51,7 +47,7 @@ class MatterCapacitorItem : Item {
}
override val maxStoredMatter: ImpreciseFraction get() {
return storage
return capacity
}
override val missingMatter: ImpreciseFraction get() {
@ -64,7 +60,7 @@ class MatterCapacitorItem : Item {
override fun receiveMatterInner(howMuch: ImpreciseFraction, simulate: Boolean): ImpreciseFraction {
if (isCreative) return howMuch
val new = matter().plus(howMuch.coerceAtMost(maxInput)).coerceAtMost(storage)
val new = matter().plus(howMuch.coerceAtMost(maxInput)).coerceAtMost(capacity)
val diff = new.minus(matter())
if (!simulate) {
@ -93,17 +89,24 @@ class MatterCapacitorItem : Item {
override val direction = MatterDirection.BIDIRECTIONAL
}
val storage: ImpreciseFraction
private val _capacity: () -> ImpreciseFraction
val capacity get() = _capacity.invoke()
private val isCreative: Boolean
constructor(storage: ImpreciseFraction) : super(Properties().stacksTo(1).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) {
isCreative = false
this.storage = storage
_capacity = { storage }
}
constructor(storage: () -> ImpreciseFraction) : super(Properties().stacksTo(1).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) {
isCreative = false
_capacity = storage
}
constructor() : super(Properties().stacksTo(1).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB).rarity(Rarity.EPIC)) {
isCreative = true
storage = ImpreciseFraction.LONG_MAX_VALUE
_capacity = { ImpreciseFraction.LONG_MAX_VALUE }
}
override fun isBarVisible(p_150899_: ItemStack): Boolean {
@ -142,7 +145,7 @@ class MatterCapacitorItem : Item {
TranslatableComponent(
"otm.item.matter.normal",
cap.storedMatter.formatMatter(),
storage.formatMatter()
capacity.formatMatter()
).withStyle(ChatFormatting.GRAY)
)
}

View File

@ -23,17 +23,23 @@ import java.util.*
import java.util.stream.Stream
class PatternStorageItem : Item {
val capacity: Int
private val _capacity: () -> Int
val capacity get() = _capacity.invoke()
var isCreative: Boolean
constructor(capacity: Int) : super(Properties().tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB).stacksTo(1)) {
this.capacity = capacity
_capacity = { capacity }
isCreative = false
}
constructor(capacity: () -> Int) : super(Properties().tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB).stacksTo(1)) {
_capacity = capacity
isCreative = false
}
constructor() : super(Properties().rarity(Rarity.EPIC).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB).stacksTo(1)) {
isCreative = true
capacity = Int.MAX_VALUE
_capacity = { Int.MAX_VALUE }
}
override fun initCapabilities(stack: ItemStack, nbt: CompoundTag?): ICapabilityProvider? {

View File

@ -155,7 +155,7 @@ class QuantumBatteryItem : Item {
return ImpreciseFraction.ZERO
}
val newEnergy = (data.energy + howMuch.coerceAtMost(throughput!!)).coerceAtMost(capacity)
val newEnergy = (data.energy + howMuch.coerceAtMost(throughput!!)).coerceAtMost(capacity!!)
val diff = newEnergy - data.energy
if (!simulate) {
@ -257,8 +257,12 @@ class QuantumBatteryItem : Item {
}
val isCreative: Boolean
val capacity: ImpreciseFraction?
val throughput: ImpreciseFraction?
private val _capacity: () -> ImpreciseFraction?
private val _throughput: () -> ImpreciseFraction?
val capacity get() = _capacity.invoke()
val throughput get() = _throughput.invoke()
val saveDataID: String
@ -287,15 +291,22 @@ class QuantumBatteryItem : Item {
constructor(saveDataID: String) : super(Properties().stacksTo(1).rarity(Rarity.EPIC).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) {
isCreative = true
capacity = null
throughput = null
_capacity = { null }
_throughput = { null }
this.saveDataID = "otm_$saveDataID".intern()
}
constructor(saveDataID: String, capacity: ImpreciseFraction, io: ImpreciseFraction) : super(Properties().stacksTo(1).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) {
isCreative = false
this.capacity = capacity
this.throughput = io
_capacity = { capacity }
_throughput = { io }
this.saveDataID = "otm_$saveDataID".intern()
}
constructor(saveDataID: String, values: ConciseBalanceValues) : super(Properties().stacksTo(1).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) {
isCreative = false
_capacity = values::capacity
_throughput = values::throughput
this.saveDataID = "otm_$saveDataID".intern()
}
@ -345,7 +356,7 @@ class QuantumBatteryItem : Item {
TranslatableComponent(
"otm.item.power.throughput",
throughput!!.formatPower(),
throughput.formatPower()
throughput!!.formatPower()
).withStyle(ChatFormatting.GRAY))
}

View File

@ -3,22 +3,29 @@ package ru.dbotthepony.mc.otm.item
import net.minecraft.ChatFormatting
import net.minecraft.nbt.CompoundTag
import net.minecraft.network.chat.Component
import net.minecraft.util.Mth
import net.minecraft.world.item.Item
import net.minecraft.world.item.ItemStack
import net.minecraft.world.item.Rarity
import net.minecraft.world.item.TooltipFlag
import net.minecraft.world.level.Level
import net.minecraftforge.common.capabilities.ICapabilityProvider
import ru.dbotthepony.mc.otm.ConciseBalanceValues
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.ServerConfig
import ru.dbotthepony.mc.otm.capability.*
import ru.dbotthepony.mc.otm.core.*
open class SingleUseBatteryItem(
val storage: ImpreciseFraction,
val throughput: ImpreciseFraction? = null,
private val _capacity: () -> ImpreciseFraction,
private val _throughput: () -> ImpreciseFraction? = { null },
properties: Properties = Properties().stacksTo(1).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)
) : Item(properties) {
constructor(values: ConciseBalanceValues, properties: Properties = Properties().stacksTo(1).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) : this(values::capacity, values::throughput, properties)
constructor(storage: ImpreciseFraction, throughput: ImpreciseFraction? = null, properties: Properties = Properties().stacksTo(1).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) : this({ storage }, { throughput }, properties)
val capacity get() = _capacity.invoke()
val throughput get() = _throughput.invoke()
override fun appendHoverText(
itemStack: ItemStack,
p_41422_: Level?,
@ -31,7 +38,7 @@ open class SingleUseBatteryItem(
}
override fun initCapabilities(stack: ItemStack, nbt: CompoundTag?): ICapabilityProvider {
return EnergyProducerItem(stack, storage, throughput, initialBatteryLevel = storage)
return EnergyProducerItem(stack, capacity, throughput, initialBatteryLevel = capacity)
}
override fun isBarVisible(p_150899_: ItemStack): Boolean {
@ -51,7 +58,7 @@ open class SingleUseBatteryItem(
}
}
class ZPMItem : SingleUseBatteryItem(MAX_STORAGE, THROUGHPUT, Properties().stacksTo(1).rarity(Rarity.EPIC).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) {
class ZPMItem : SingleUseBatteryItem(ServerConfig.ZPM_BATTERY, Properties().stacksTo(1).rarity(Rarity.EPIC).tab(OverdriveThatMatters.INSTANCE.CREATIVE_TAB)) {
override fun appendHoverText(
itemStack: ItemStack,
p_41422_: Level?,

View File

@ -130,9 +130,9 @@ private fun make(tag: TagKey<Item>, value: ImpreciseFraction, complexity: Double
}
private fun logResolutionError(text: String) {
LOGGER.debug("... Item chain: " + seenItems.joinToString(" -> "))
//LOGGER.debug("... Item chain: " + seenItems.joinToString(" -> "))
// LOGGER.error("Recipe chain: " + seenRecipes.joinToString(" -> "))
LOGGER.debug(text)
//LOGGER.debug(text)
}
private enum class ResultType {

View File

@ -14,6 +14,7 @@ import net.minecraftforge.eventbus.api.IEventBus
import net.minecraftforge.registries.DeferredRegister
import net.minecraftforge.registries.ForgeRegistries
import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.ServerConfig
import ru.dbotthepony.mc.otm.core.TranslatableComponent
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import ru.dbotthepony.mc.otm.item.*
@ -224,14 +225,14 @@ object MItems {
val PILL_HEAL: Item by registry.register(MNames.PILL_HEAL) { HealPillItem() }
val BATTERY_CRUDE: Item by registry.register(MNames.BATTERY_CRUDE) { CrudeBatteryItem() }
val BATTERY_BASIC: Item by registry.register(MNames.BATTERY_BASIC) { BatteryItem(ImpreciseFraction(400_000), ImpreciseFraction(600)) }
val BATTERY_NORMAL: Item by registry.register(MNames.BATTERY_NORMAL) { BatteryItem(ImpreciseFraction(2_000_000), ImpreciseFraction(1_000)) }
val BATTERY_DENSE: Item by registry.register(MNames.BATTERY_DENSE) { BatteryItem(ImpreciseFraction(10_000_000), ImpreciseFraction(2_000)) }
val BATTERY_CAPACITOR: Item by registry.register(MNames.BATTERY_CAPACITOR) { BatteryItem(ImpreciseFraction(500_000), ImpreciseFraction(50_000)) }
val BATTERY_BASIC: Item by registry.register(MNames.BATTERY_BASIC) { BatteryItem(ServerConfig.BATTERY_BASIC) }
val BATTERY_NORMAL: Item by registry.register(MNames.BATTERY_NORMAL) { BatteryItem(ServerConfig.BATTERY_NORMAL) }
val BATTERY_DENSE: Item by registry.register(MNames.BATTERY_DENSE) { BatteryItem(ServerConfig.BATTERY_DENSE) }
val BATTERY_CAPACITOR: Item by registry.register(MNames.BATTERY_CAPACITOR) { BatteryItem(ServerConfig.BATTERY_CAPACITOR) }
val BATTERY_CREATIVE: Item by registry.register(MNames.BATTERY_CREATIVE) { BatteryItem() }
val QUANTUM_BATTERY: Item by registry.register(MNames.QUANTUM_BATTERY) { QuantumBatteryItem(MNames.QUANTUM_BATTERY, ImpreciseFraction(40_000_000), ImpreciseFraction(10_000)) }
val QUANTUM_CAPACITOR: Item by registry.register(MNames.QUANTUM_CAPACITOR) { QuantumBatteryItem(MNames.QUANTUM_CAPACITOR, ImpreciseFraction(1_000_000), ImpreciseFraction(200_000)) }
val QUANTUM_BATTERY: Item by registry.register(MNames.QUANTUM_BATTERY) { QuantumBatteryItem(MNames.QUANTUM_BATTERY, ServerConfig.QUANTUM_BATTERY) }
val QUANTUM_CAPACITOR: Item by registry.register(MNames.QUANTUM_CAPACITOR) { QuantumBatteryItem(MNames.QUANTUM_CAPACITOR, ServerConfig.QUANTUM_CAPACITOR) }
val QUANTUM_BATTERY_CREATIVE: Item by registry.register(MNames.QUANTUM_BATTERY_CREATIVE) { QuantumBatteryItem(MNames.QUANTUM_BATTERY_CREATIVE) }
val ZPM_BATTERY: Item by registry.register(MNames.ZPM_BATTERY) { ZPMItem() }
@ -243,12 +244,12 @@ object MItems {
{ BATTERY_CAPACITOR },
)
val MATTER_CAPACITOR_BASIC: Item by registry.register(MNames.MATTER_CAPACITOR_BASIC) { MatterCapacitorItem(ImpreciseFraction("2")) }
val MATTER_CAPACITOR_NORMAL: Item by registry.register(MNames.MATTER_CAPACITOR_NORMAL) { MatterCapacitorItem(ImpreciseFraction("10")) }
val MATTER_CAPACITOR_DENSE: Item by registry.register(MNames.MATTER_CAPACITOR_DENSE) { MatterCapacitorItem(ImpreciseFraction("40")) }
val MATTER_CAPACITOR_BASIC: Item by registry.register(MNames.MATTER_CAPACITOR_BASIC) { MatterCapacitorItem(ServerConfig::MATTER_CAPACITOR_BASIC) }
val MATTER_CAPACITOR_NORMAL: Item by registry.register(MNames.MATTER_CAPACITOR_NORMAL) { MatterCapacitorItem(ServerConfig::MATTER_CAPACITOR_NORMAL) }
val MATTER_CAPACITOR_DENSE: Item by registry.register(MNames.MATTER_CAPACITOR_DENSE) { MatterCapacitorItem(ServerConfig::MATTER_CAPACITOR_DENSE) }
val MATTER_CAPACITOR_CREATIVE: Item by registry.register(MNames.MATTER_CAPACITOR_CREATIVE) { MatterCapacitorItem() }
val PATTERN_DRIVE_NORMAL: Item by registry.register(MNames.PATTERN_DRIVE_NORMAL) { PatternStorageItem(4) }
val PATTERN_DRIVE_NORMAL: Item by registry.register(MNames.PATTERN_DRIVE_NORMAL) { PatternStorageItem(ServerConfig::PATTERN_DRIVE_NORMAL) }
val PATTERN_DRIVE_CREATIVE: Item by registry.register(MNames.PATTERN_DRIVE_CREATIVE) { PatternStorageItem() }
val PATTERN_DRIVE_CREATIVE2: Item by registry.register(MNames.PATTERN_DRIVE_CREATIVE2) { CreativePatternItem() }

View File

@ -73,10 +73,7 @@ class WriteOnce<V> : ReadWriteProperty<Any?, V> {
}
override fun setValue(thisRef: Any?, property: KProperty<*>, value: V) {
if (this.value != null) {
throw IllegalStateException("Property ${property.name} already initialized")
}
check(this.value == null) { "Property ${property.name} is already initialized" }
this.value = value
}
}

View File

@ -1,9 +1,14 @@
package ru.dbotthepony.mc.otm.tests
import it.unimi.dsi.fastutil.io.FastByteArrayInputStream
import it.unimi.dsi.fastutil.io.FastByteArrayOutputStream
import org.junit.jupiter.api.Assertions.assertEquals
import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import ru.dbotthepony.mc.otm.core.ImpreciseFraction
import java.io.File
import java.io.ObjectInputStream
import java.io.ObjectOutputStream
object ImpreciseFractionTests {
@Test
@ -61,4 +66,29 @@ object ImpreciseFractionTests {
assertEquals(ImpreciseFraction(i.toLong()), ImpreciseFraction.valueOf(i.toLong()))
}
}
@Test
@DisplayName("ImpreciseFraction serialization")
fun serialization() {
val output = FastByteArrayOutputStream()
val outputStream = ObjectOutputStream(output)
val val1 = ImpreciseFraction("283")
val val2 = ImpreciseFraction("0")
val val3 = ImpreciseFraction("-4")
val val4 = ImpreciseFraction("25.225")
outputStream.writeObject(val1)
outputStream.writeObject(val2)
outputStream.writeObject(val3)
outputStream.writeObject(val4)
val input = FastByteArrayInputStream(output.array, 0, output.length)
val inputStream = ObjectInputStream(input)
assertEquals(val1, inputStream.readObject())
assertEquals(val2, inputStream.readObject())
assertEquals(val3, inputStream.readObject())
assertEquals(val4, inputStream.readObject())
}
}