Merge branch '1.21' of https://git.dbotthepony.ru/DBot/overdrive_that_matters into world-structures
@ -130,13 +130,17 @@ fun addItemModels(provider: MatteryItemModelProvider) {
|
|||||||
provider.generated(MItems.CLEANER_DRONE_KIT, modLocation("item/egg/cleaner"))
|
provider.generated(MItems.CLEANER_DRONE_KIT, modLocation("item/egg/cleaner"))
|
||||||
provider.generated(MItems.ANDROID_MELEE_SPAWN_EGG, modLocation("item/egg/android_melee"))
|
provider.generated(MItems.ANDROID_MELEE_SPAWN_EGG, modLocation("item/egg/android_melee"))
|
||||||
|
|
||||||
provider.generatedTiered(MItems.BATTERIES, "battery_tier")
|
provider.capacitorWithGauge(MItems.BATTERY_CRUDE, 10, "battery_gauge_", modLocation("item/battery_tier0"))
|
||||||
|
provider.capacitorWithGauge(MItems.BATTERY_BASIC, 10, "battery_gauge_", modLocation("item/battery_tier1"))
|
||||||
|
provider.capacitorWithGauge(MItems.BATTERY_NORMAL, 10, "battery_gauge_", modLocation("item/battery_tier2"))
|
||||||
|
provider.capacitorWithGauge(MItems.BATTERY_DENSE, 10, "battery_gauge_", modLocation("item/battery_tier3"))
|
||||||
|
provider.capacitorWithGauge(MItems.BATTERY_CAPACITOR, 10, "battery_gauge_", modLocation("item/battery_tier4"))
|
||||||
provider.generated(MItems.BATTERY_CREATIVE)
|
provider.generated(MItems.BATTERY_CREATIVE)
|
||||||
provider.generated(MItems.PROCEDURAL_BATTERY, modLocation("item/battery_procedural"))
|
provider.capacitorWithGauge(MItems.PROCEDURAL_BATTERY, 9, "battery_procedural_gauge_", modLocation("item/battery_procedural"))
|
||||||
|
|
||||||
provider.generated(MItems.MATTER_CAPACITOR_BASIC, modLocation("item/matter_capacitor_tier1"))
|
provider.capacitorWithGauge(MItems.MATTER_CAPACITOR_BASIC, 8, "matter_capacitor_gauge_", modLocation("item/matter_capacitor_tier1"))
|
||||||
provider.generated(MItems.MATTER_CAPACITOR_NORMAL, modLocation("item/matter_capacitor_tier2"))
|
provider.capacitorWithGauge(MItems.MATTER_CAPACITOR_NORMAL, 8, "matter_capacitor_gauge_", modLocation("item/matter_capacitor_tier2"))
|
||||||
provider.generated(MItems.MATTER_CAPACITOR_DENSE, modLocation("item/matter_capacitor_tier3"))
|
provider.capacitorWithGauge(MItems.MATTER_CAPACITOR_DENSE, 8, "matter_capacitor_gauge_", modLocation("item/matter_capacitor_tier3"))
|
||||||
provider.generated(MItems.MATTER_CAPACITOR_CREATIVE)
|
provider.generated(MItems.MATTER_CAPACITOR_CREATIVE)
|
||||||
|
|
||||||
provider.generated(MItems.MachineUpgrades.Basic.BLANK, modLocation("item/machine_upgrade_tier1"))
|
provider.generated(MItems.MachineUpgrades.Basic.BLANK, modLocation("item/machine_upgrade_tier1"))
|
||||||
@ -184,8 +188,8 @@ fun addItemModels(provider: MatteryItemModelProvider) {
|
|||||||
provider.upgrade(MItems.MachineUpgrades.Creative.MATTER_STORAGE_FLAT_SMALL, "matter", "creative")
|
provider.upgrade(MItems.MachineUpgrades.Creative.MATTER_STORAGE_FLAT_SMALL, "matter", "creative")
|
||||||
|
|
||||||
|
|
||||||
provider.generated(MItems.QUANTUM_BATTERY)
|
provider.capacitorWithGauge(MItems.QUANTUM_BATTERY, 10, "battery_gauge_")
|
||||||
provider.generated(MItems.QUANTUM_CAPACITOR)
|
provider.capacitorWithGauge(MItems.QUANTUM_CAPACITOR, 10, "battery_gauge_")
|
||||||
provider.generated(MItems.QUANTUM_BATTERY_CREATIVE)
|
provider.generated(MItems.QUANTUM_BATTERY_CREATIVE)
|
||||||
|
|
||||||
provider.generated(MItems.PATTERN_DRIVE_NORMAL, modLocation("item/pattern_drive_tier1"))
|
provider.generated(MItems.PATTERN_DRIVE_NORMAL, modLocation("item/pattern_drive_tier1"))
|
||||||
|
@ -143,6 +143,33 @@ class MatteryItemModelProvider(event: GatherDataEvent) : ItemModelProvider(event
|
|||||||
.texture("layer1", modLocation("item/machine_upgrade_icon_$upgradeType"))
|
.texture("layer1", modLocation("item/machine_upgrade_icon_$upgradeType"))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun capacitorWithGauge(item: Item, fillTextures: Int, gaugePrefix: String, baseTexture: ResourceLocation? = null) = exec {
|
||||||
|
val path = item.registryName!!.path
|
||||||
|
val texture = baseTexture ?: modLocation("item/$path")
|
||||||
|
|
||||||
|
val empty = withExistingParent("${path}_empty", GENERATED)
|
||||||
|
.texture("layer0", texture)
|
||||||
|
|
||||||
|
val basic = withExistingParent(path, GENERATED)
|
||||||
|
.texture("layer0", texture)
|
||||||
|
.texture("layer1", modLocation("item/${gaugePrefix}$fillTextures"))
|
||||||
|
.override()
|
||||||
|
.predicate(modLocation("capacitor_gauge"), 0f)
|
||||||
|
.model(empty)
|
||||||
|
.end()
|
||||||
|
|
||||||
|
for (i in 1 .. fillTextures) {
|
||||||
|
val model = withExistingParent("${path}_fill_$i", GENERATED)
|
||||||
|
.texture("layer0", texture)
|
||||||
|
.texture("layer1", modLocation("item/${gaugePrefix}$i"))
|
||||||
|
|
||||||
|
basic.override()
|
||||||
|
.predicate(modLocation("capacitor_gauge"), i.toFloat() / fillTextures.toFloat())
|
||||||
|
.model(model)
|
||||||
|
.end()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
val ARMOR_TRIM_MATERIALS = listOf("quartz", "iron", "netherite", "redstone", "copper", "gold", "emerald", "diamond", "lapis", "amethyst")
|
val ARMOR_TRIM_MATERIALS = listOf("quartz", "iron", "netherite", "redstone", "copper", "gold", "emerald", "diamond", "lapis", "amethyst")
|
||||||
val GENERATED = ResourceLocation("minecraft", "item/generated")
|
val GENERATED = ResourceLocation("minecraft", "item/generated")
|
||||||
|
@ -348,6 +348,17 @@ abstract class MatteryBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state
|
|||||||
private var cache: BlockCapabilityCache<T, in Direction?>? = null
|
private var cache: BlockCapabilityCache<T, in Direction?>? = null
|
||||||
private val listeners = Listenable.Impl<T?>()
|
private val listeners = Listenable.Impl<T?>()
|
||||||
|
|
||||||
|
private val lookupProvider = Supplier<T?> {
|
||||||
|
if (isRemoved)
|
||||||
|
return@Supplier null
|
||||||
|
|
||||||
|
val get = cache?.capability
|
||||||
|
provider = Supplier { get }
|
||||||
|
return@Supplier get
|
||||||
|
}
|
||||||
|
|
||||||
|
private var provider: Supplier<T?> = lookupProvider
|
||||||
|
|
||||||
override fun addListener(listener: Consumer<T?>): Listenable.L {
|
override fun addListener(listener: Consumer<T?>): Listenable.L {
|
||||||
return listeners.addListener(listener)
|
return listeners.addListener(listener)
|
||||||
}
|
}
|
||||||
@ -358,23 +369,21 @@ abstract class MatteryBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun get(): T? {
|
override fun get(): T? {
|
||||||
if (isRemoved)
|
return provider.get()
|
||||||
return null
|
|
||||||
|
|
||||||
return cache?.capability
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val isPresent: Boolean
|
val isPresent: Boolean
|
||||||
get() = cache?.capability != null
|
get() = get() != null
|
||||||
|
|
||||||
val isEmpty: Boolean
|
val isEmpty: Boolean
|
||||||
get() = cache?.capability == null
|
get() = get() == null
|
||||||
|
|
||||||
fun rebuildCache() {
|
fun rebuildCache() {
|
||||||
if (!SERVER_IS_LIVE) return
|
if (!SERVER_IS_LIVE) return
|
||||||
val level = level as? ServerLevel
|
val level = level as? ServerLevel
|
||||||
|
|
||||||
val creationVersion = ++currentVersion
|
val creationVersion = ++currentVersion
|
||||||
|
provider = lookupProvider
|
||||||
|
|
||||||
if (level == null) {
|
if (level == null) {
|
||||||
cache = null
|
cache = null
|
||||||
@ -388,12 +397,21 @@ abstract class MatteryBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state
|
|||||||
{ !isRemoved || creationVersion != currentVersion },
|
{ !isRemoved || creationVersion != currentVersion },
|
||||||
// IllegalStateException("Do not call getCapability on an invalid cache or from the invalidation listener!")
|
// IllegalStateException("Do not call getCapability on an invalid cache or from the invalidation listener!")
|
||||||
// what a shame.
|
// what a shame.
|
||||||
{ if (SERVER_IS_LIVE) onceServer { if (!isRemoved && creationVersion == currentVersion) listeners.accept(cache?.capability) } })
|
{
|
||||||
|
provider = lookupProvider
|
||||||
|
if (SERVER_IS_LIVE) onceServer { if (!isRemoved && creationVersion == currentVersion) listeners.accept(get()) }
|
||||||
|
})
|
||||||
|
|
||||||
onceServer {
|
onceServer {
|
||||||
if (!isRemoved && creationVersion == currentVersion) listeners.accept(cache?.capability)
|
if (!isRemoved && creationVersion == currentVersion) listeners.accept(get())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun removeCache() {
|
||||||
|
cache = null
|
||||||
|
currentVersion++
|
||||||
|
provider = Supplier { null }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val syncher = SynchableGroup()
|
val syncher = SynchableGroup()
|
||||||
@ -424,6 +442,7 @@ abstract class MatteryBlockEntity(type: BlockEntityType<*>, pos: BlockPos, state
|
|||||||
|
|
||||||
override fun setRemoved() {
|
override fun setRemoved() {
|
||||||
super.setRemoved()
|
super.setRemoved()
|
||||||
|
capabilityCaches.forEach { it.removeCache() }
|
||||||
unsubscribe()
|
unsubscribe()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ abstract class EnergyCableBlockEntity(type: BlockEntityType<*>, blockPos: BlockP
|
|||||||
|
|
||||||
val sides get() = energySides
|
val sides get() = energySides
|
||||||
|
|
||||||
val currentlyTransferringTo = ObjectArraySet<Pair<Node, RelativeSide>>()
|
val currentlyTransferringTo = ObjectArraySet<Pair<Node, CableSide>>()
|
||||||
|
|
||||||
override fun onNeighbour(link: Link) {
|
override fun onNeighbour(link: Link) {
|
||||||
if (link is DirectionLink) {
|
if (link is DirectionLink) {
|
||||||
|
@ -74,8 +74,8 @@ private class LinkedPriorityQueue<T : Comparable<T>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableGraph>() {
|
class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableGraph>() {
|
||||||
private val livelyNodes = HashSet<Pair<EnergyCableBlockEntity.Node, RelativeSide>>()
|
private val livelyNodes = HashSet<Pair<EnergyCableBlockEntity.Node, EnergyCableBlockEntity.CableSide>>()
|
||||||
private val livelyNodesList = ArrayList<Pair<EnergyCableBlockEntity.Node, RelativeSide>>()
|
private val livelyNodesList = ArrayList<Pair<EnergyCableBlockEntity.Node, EnergyCableBlockEntity.CableSide>>()
|
||||||
|
|
||||||
fun addLivelyNode(node: EnergyCableBlockEntity.Node) {
|
fun addLivelyNode(node: EnergyCableBlockEntity.Node) {
|
||||||
when (contains(node)) {
|
when (contains(node)) {
|
||||||
@ -83,7 +83,7 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
|
|||||||
ContainsStatus.DOES_NOT_BELONG -> throw IllegalArgumentException("$node does not belong to $this")
|
ContainsStatus.DOES_NOT_BELONG -> throw IllegalArgumentException("$node does not belong to $this")
|
||||||
ContainsStatus.CONTAINS -> {
|
ContainsStatus.CONTAINS -> {
|
||||||
for (dir in RelativeSide.entries) {
|
for (dir in RelativeSide.entries) {
|
||||||
val pair = node to dir
|
val pair = node to node.sides[dir]!!
|
||||||
|
|
||||||
if (livelyNodes.add(pair)) {
|
if (livelyNodes.add(pair)) {
|
||||||
livelyNodesList.add(pair)
|
livelyNodesList.add(pair)
|
||||||
@ -589,7 +589,7 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
|
|||||||
|
|
||||||
override fun onNodeRemoved(node: EnergyCableBlockEntity.Node) {
|
override fun onNodeRemoved(node: EnergyCableBlockEntity.Node) {
|
||||||
for (dir in RelativeSide.entries) {
|
for (dir in RelativeSide.entries) {
|
||||||
val pair = node to dir
|
val pair = node to node.sides[dir]!!
|
||||||
|
|
||||||
if (livelyNodes.remove(pair)) {
|
if (livelyNodes.remove(pair)) {
|
||||||
check(livelyNodesList.remove(pair))
|
check(livelyNodesList.remove(pair))
|
||||||
@ -617,7 +617,7 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
|
|||||||
|
|
||||||
override fun onNodeAdded(node: EnergyCableBlockEntity.Node) {
|
override fun onNodeAdded(node: EnergyCableBlockEntity.Node) {
|
||||||
for (dir in RelativeSide.entries) {
|
for (dir in RelativeSide.entries) {
|
||||||
val pair = node to dir
|
val pair = node to node.sides[dir]!!
|
||||||
check(livelyNodes.add(pair))
|
check(livelyNodes.add(pair))
|
||||||
livelyNodesList.add(pair)
|
livelyNodesList.add(pair)
|
||||||
}
|
}
|
||||||
@ -649,8 +649,7 @@ class EnergyCableGraph : GraphNodeList<EnergyCableBlockEntity.Node, EnergyCableG
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val (node, relSide) = pair
|
val (node, side) = pair
|
||||||
val side = node.sides[relSide]!!
|
|
||||||
|
|
||||||
if (!side.isEnabled) {
|
if (!side.isEnabled) {
|
||||||
indicesToRemove.add(i)
|
indicesToRemove.add(i)
|
||||||
|
@ -29,6 +29,7 @@ import ru.dbotthepony.mc.otm.registry.game.MBlockEntities
|
|||||||
import ru.dbotthepony.mc.otm.util.math.Decimal
|
import ru.dbotthepony.mc.otm.util.math.Decimal
|
||||||
import ru.dbotthepony.mc.otm.util.countingLazy
|
import ru.dbotthepony.mc.otm.util.countingLazy
|
||||||
import ru.dbotthepony.mc.otm.graph.matter.SimpleMatterNode
|
import ru.dbotthepony.mc.otm.graph.matter.SimpleMatterNode
|
||||||
|
import ru.dbotthepony.mc.otm.util.math.toDecimal
|
||||||
import java.util.function.BooleanSupplier
|
import java.util.function.BooleanSupplier
|
||||||
|
|
||||||
class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
||||||
@ -197,16 +198,25 @@ class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
|||||||
|
|
||||||
if (matter.storedMatter.isPositive) {
|
if (matter.storedMatter.isPositive) {
|
||||||
val energyRatio = if (energyRate <= Decimal.ZERO) Decimal.ONE else energy.extractEnergy(energyRate, true) / energyRate
|
val energyRatio = if (energyRate <= Decimal.ZERO) Decimal.ONE else energy.extractEnergy(energyRate, true) / energyRate
|
||||||
val matterRatio = matter.extractMatter(capability.receiveMatter(rate.coerceAtMost(matter.storedMatter), true), true) / rate
|
val matterTransferred = matter.extractMatter(capability.receiveMatter(rate.coerceAtMost(matter.storedMatter), true), true)
|
||||||
|
val matterRatio = matterTransferred / rate
|
||||||
|
|
||||||
val minRatio = minOf(matterRatio, energyRatio)
|
if (matterRatio == Decimal.ZERO && matterTransferred > Decimal.ZERO) {
|
||||||
|
// transferring very little matter, transfer this time for free
|
||||||
if (minRatio > Decimal.ZERO) {
|
|
||||||
isWorking = true
|
isWorking = true
|
||||||
energy.extractEnergy(energyRate * minRatio, false)
|
matter.extractMatter(capability.receiveMatter(matter.storedMatter, false), false)
|
||||||
matter.extractMatter(capability.receiveMatter(rate * minRatio, false), false)
|
|
||||||
workProgress = ((capability.storedMatter - initialCapacity!!) / capability.maxStoredMatter).toFloat()
|
workProgress = ((capability.storedMatter - initialCapacity!!) / capability.maxStoredMatter).toFloat()
|
||||||
slot.setChanged()
|
slot.setChanged()
|
||||||
|
} else {
|
||||||
|
val minRatio = minOf(matterRatio, energyRatio)
|
||||||
|
|
||||||
|
if (minRatio > Decimal.ZERO) {
|
||||||
|
isWorking = true
|
||||||
|
energy.extractEnergy(energyRate * minRatio, false)
|
||||||
|
matter.extractMatter(capability.receiveMatter(rate * minRatio, false), false)
|
||||||
|
workProgress = ((capability.storedMatter - initialCapacity!!) / capability.maxStoredMatter).toFloat()
|
||||||
|
slot.setChanged()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (spitItemsWhenCantWork) {
|
if (spitItemsWhenCantWork) {
|
||||||
@ -262,20 +272,28 @@ class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
|||||||
initialCapacity = initialCapacity ?: it.storedMatter
|
initialCapacity = initialCapacity ?: it.storedMatter
|
||||||
|
|
||||||
hasCapacitors = true
|
hasCapacitors = true
|
||||||
val rate = MachinesConfig.MatterBottler.RATE * (1.0 + upgrades.speedBonus)
|
val rate = MachinesConfig.MatterBottler.RATE * (Decimal.ONE + upgrades.speedBonus.toDecimal())
|
||||||
val energyRate = MachinesConfig.MatterBottler.VALUES.energyConsumption * (1.0 + upgrades.speedBonus)
|
val energyRate = MachinesConfig.MatterBottler.VALUES.energyConsumption * (Decimal.ONE + upgrades.speedBonus.toDecimal())
|
||||||
|
|
||||||
val energyRatio = if (energyRate <= Decimal.ZERO) Decimal.ONE else energy.extractEnergy(energyRate, true) / energyRate
|
val energyRatio = if (energyRate <= Decimal.ZERO) Decimal.ONE else energy.extractEnergy(energyRate, true) / energyRate
|
||||||
val matterRatio = matter.receiveMatter(it.extractMatterChecked(rate, true), true) / rate
|
val matterExtracted = matter.receiveMatter(it.extractMatterChecked(rate, true), true)
|
||||||
|
val matterRatio = matterExtracted / rate
|
||||||
|
|
||||||
val minRatio = minOf(energyRatio, matterRatio)
|
if (matterRatio == Decimal.ZERO && matterExtracted > Decimal.ZERO) {
|
||||||
|
// very little matter extracted, extract this one for free
|
||||||
if (minRatio > Decimal.ZERO) {
|
|
||||||
any = true
|
any = true
|
||||||
energy.extractEnergy(energyRate * energyRatio, false)
|
matter.receiveMatter(it.extractMatterChecked(matterExtracted, false), false)
|
||||||
matter.receiveMatter(it.extractMatterChecked(rate * minRatio, false), false)
|
|
||||||
|
|
||||||
workProgress = 1f - (it.storedMatter / initialCapacity!!).toFloat()
|
workProgress = 1f - (it.storedMatter / initialCapacity!!).toFloat()
|
||||||
|
} else {
|
||||||
|
val minRatio = minOf(energyRatio, matterRatio)
|
||||||
|
|
||||||
|
if (minRatio > Decimal.ZERO) {
|
||||||
|
any = true
|
||||||
|
energy.extractEnergy(energyRate * energyRatio, false)
|
||||||
|
matter.receiveMatter(it.extractMatterChecked(rate * minRatio, false), false)
|
||||||
|
|
||||||
|
workProgress = 1f - (it.storedMatter / initialCapacity!!).toFloat()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
break
|
break
|
||||||
|
@ -163,6 +163,13 @@ class MatterDustItem : Item(Properties().stacksTo(64)), IMatterItem {
|
|||||||
return matter(stack) >= ItemsConfig.MATTER_DUST_CAPACITY
|
return matter(stack) >= ItemsConfig.MATTER_DUST_CAPACITY
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun makeStack(matterValue: Decimal = Decimal.ONE, count: Int = 1): ItemStack {
|
||||||
|
val stack = ItemStack(this, count)
|
||||||
|
matter(stack, matterValue)
|
||||||
|
|
||||||
|
return stack
|
||||||
|
}
|
||||||
|
|
||||||
override fun overrideStackedOnOther(
|
override fun overrideStackedOnOther(
|
||||||
pStack: ItemStack,
|
pStack: ItemStack,
|
||||||
pSlot: Slot,
|
pSlot: Slot,
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package ru.dbotthepony.mc.otm.network
|
package ru.dbotthepony.mc.otm.network
|
||||||
|
|
||||||
import io.netty.buffer.ByteBuf
|
import io.netty.buffer.ByteBuf
|
||||||
|
import net.minecraft.core.Direction
|
||||||
import net.minecraft.core.UUIDUtil
|
import net.minecraft.core.UUIDUtil
|
||||||
import net.minecraft.network.FriendlyByteBuf
|
import net.minecraft.network.FriendlyByteBuf
|
||||||
import net.minecraft.network.codec.ByteBufCodecs
|
import net.minecraft.network.codec.ByteBufCodecs
|
||||||
@ -10,6 +11,7 @@ import net.minecraft.world.level.block.Block
|
|||||||
import net.minecraft.world.level.block.state.BlockState
|
import net.minecraft.world.level.block.state.BlockState
|
||||||
import ru.dbotthepony.kommons.math.RGBAColor
|
import ru.dbotthepony.kommons.math.RGBAColor
|
||||||
import ru.dbotthepony.mc.otm.container.ItemFilter
|
import ru.dbotthepony.mc.otm.container.ItemFilter
|
||||||
|
import ru.dbotthepony.mc.otm.util.math.RelativeSide
|
||||||
import ru.dbotthepony.mc.otm.util.readDecimal
|
import ru.dbotthepony.mc.otm.util.readDecimal
|
||||||
import ru.dbotthepony.mc.otm.util.writeDecimal
|
import ru.dbotthepony.mc.otm.util.writeDecimal
|
||||||
import ru.dbotthepony.mc.otm.util.readBlockType
|
import ru.dbotthepony.mc.otm.util.readBlockType
|
||||||
@ -35,6 +37,8 @@ object StreamCodecs {
|
|||||||
val RESOURCE_LOCATION = ResourceLocation.STREAM_CODEC.wrap()
|
val RESOURCE_LOCATION = ResourceLocation.STREAM_CODEC.wrap()
|
||||||
val BLOCK_STATE: MatteryStreamCodec<ByteBuf, BlockState> = ByteBufCodecs.idMapper(Block.BLOCK_STATE_REGISTRY).wrap()
|
val BLOCK_STATE: MatteryStreamCodec<ByteBuf, BlockState> = ByteBufCodecs.idMapper(Block.BLOCK_STATE_REGISTRY).wrap()
|
||||||
val BLOCK_TYPE = MatteryStreamCodec.Of(FriendlyByteBuf::writeBlockType, FriendlyByteBuf::readBlockType)
|
val BLOCK_TYPE = MatteryStreamCodec.Of(FriendlyByteBuf::writeBlockType, FriendlyByteBuf::readBlockType)
|
||||||
|
val RELATIVE_SIDE = MatteryStreamCodec.Enum<FriendlyByteBuf, RelativeSide>(RelativeSide::class.java)
|
||||||
|
val DIRECTION = MatteryStreamCodec.Enum<FriendlyByteBuf, Direction>(Direction::class.java)
|
||||||
|
|
||||||
val RGBA: MatteryStreamCodec<ByteBuf, RGBAColor> = StreamCodec.of<ByteBuf, RGBAColor>(
|
val RGBA: MatteryStreamCodec<ByteBuf, RGBAColor> = StreamCodec.of<ByteBuf, RGBAColor>(
|
||||||
{ s, v -> s.writeFloat(v.red); s.writeFloat(v.green); s.writeFloat(v.blue); s.writeFloat(v.alpha) },
|
{ s, v -> s.writeFloat(v.red); s.writeFloat(v.green); s.writeFloat(v.blue); s.writeFloat(v.alpha) },
|
||||||
|
@ -10,29 +10,39 @@ import java.io.Closeable
|
|||||||
import java.util.concurrent.ConcurrentLinkedQueue
|
import java.util.concurrent.ConcurrentLinkedQueue
|
||||||
import java.util.concurrent.atomic.AtomicBoolean
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a new [DynamicSynchableGroup] where [T] is itself an [ISynchable]
|
||||||
|
*/
|
||||||
|
fun <T : ISynchable> DynamicSynchableGroup(reader: RegistryFriendlyByteBuf.() -> T, writer: T.(RegistryFriendlyByteBuf) -> Unit): DynamicSynchableGroup<T> {
|
||||||
|
return DynamicSynchableGroup(reader, { this }, writer)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Syncher group/set, which deals with synchables of only one type, and which are created and removed
|
* Syncher group/set, which deals with synchables of only one type, and which are created and removed
|
||||||
* on remote (e.g. server adding and removing synchables at will), which makes it distinct from
|
* on remote (e.g. server adding and removing synchables at will), which makes it distinct from
|
||||||
* [SynchableGroup], in which attached synchables are created/removed manually on both sides.
|
* [SynchableGroup], in which attached synchables are created/removed manually on both sides.
|
||||||
*/
|
*/
|
||||||
class DynamicSynchableGroup<T : ISynchable>(
|
class DynamicSynchableGroup<T : Any>(
|
||||||
/**
|
/**
|
||||||
* Constructs new [T] instance locally, when remote created one.
|
* Constructs new [T] instance locally, when remote created one.
|
||||||
* Data written by [writer] must be read here, if there is any.
|
* Data written by [writer] must be read here, if there is any.
|
||||||
*/
|
*/
|
||||||
private val reader: RegistryFriendlyByteBuf.() -> T,
|
private val reader: RegistryFriendlyByteBuf.() -> T,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an [ISynchable] out of value [T] for synching state
|
||||||
|
*/
|
||||||
|
private val synchable: T.() -> ISynchable,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows to write additional data to network stream during
|
* Allows to write additional data to network stream during
|
||||||
* first-time networking of [T] to remote
|
* first-time networking of [T] to remote
|
||||||
*/
|
*/
|
||||||
private val writer: T.(RegistryFriendlyByteBuf) -> Unit = {}
|
private val writer: T.(RegistryFriendlyByteBuf) -> Unit = {},
|
||||||
) : ISynchable, MutableSet<T> {
|
) : ISynchable, MutableSet<T> {
|
||||||
constructor(factory: () -> T) : this({ factory() }, {})
|
|
||||||
|
|
||||||
private inner class RemoteState(val listener: Runnable) : IRemoteState {
|
private inner class RemoteState(val listener: Runnable) : IRemoteState {
|
||||||
private inner class RemoteSlot(val slot: Slot<T>, fromConstructor: Boolean) : Runnable, Closeable {
|
private inner class RemoteSlot(val slot: Slot<T>, fromConstructor: Boolean) : Runnable, Closeable {
|
||||||
val remoteState = slot.synchable.createRemoteState(this)
|
val remoteState = synchable(slot.value).createRemoteState(this)
|
||||||
val isDirty = AtomicBoolean(true)
|
val isDirty = AtomicBoolean(true)
|
||||||
var isRemoved = false
|
var isRemoved = false
|
||||||
private set
|
private set
|
||||||
@ -114,7 +124,7 @@ class DynamicSynchableGroup<T : ISynchable>(
|
|||||||
firstTime.forEach {
|
firstTime.forEach {
|
||||||
stream.writeByte(ADD_ENTRY)
|
stream.writeByte(ADD_ENTRY)
|
||||||
stream.writeVarInt(it.slot.id)
|
stream.writeVarInt(it.slot.id)
|
||||||
writer(it.slot.synchable, stream)
|
writer(it.slot.value, stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
firstTime.clear()
|
firstTime.clear()
|
||||||
@ -177,10 +187,10 @@ class DynamicSynchableGroup<T : ISynchable>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private data class Slot<T : Any>(val synchable: T, val id: Int)
|
private data class Slot<T : Any>(val value: T, val id: Int)
|
||||||
|
|
||||||
private val remoteStates = ArrayList<RemoteState>()
|
private val remoteStates = ArrayList<RemoteState>()
|
||||||
private val value2slot = HashMap<T, Slot<T>>()
|
private val value2slot = LinkedHashMap<T, Slot<T>>()
|
||||||
private val id2slot = Int2ObjectOpenHashMap<Slot<T>>()
|
private val id2slot = Int2ObjectOpenHashMap<Slot<T>>()
|
||||||
private val idAllocator = IDAllocator()
|
private val idAllocator = IDAllocator()
|
||||||
|
|
||||||
@ -199,7 +209,7 @@ class DynamicSynchableGroup<T : ISynchable>(
|
|||||||
REMOVE_ENTRY -> {
|
REMOVE_ENTRY -> {
|
||||||
val id = stream.readVarInt()
|
val id = stream.readVarInt()
|
||||||
val slot = checkNotNull(id2slot.remove(id)) { "No such slot with ID: $id" }
|
val slot = checkNotNull(id2slot.remove(id)) { "No such slot with ID: $id" }
|
||||||
check(value2slot.remove(slot.synchable) == value2slot)
|
check(value2slot.remove(slot.value) == value2slot)
|
||||||
remoteStates.forEach { it.remove(slot) }
|
remoteStates.forEach { it.remove(slot) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -212,7 +222,7 @@ class DynamicSynchableGroup<T : ISynchable>(
|
|||||||
|
|
||||||
if (id2slot.containsKey(id)) {
|
if (id2slot.containsKey(id)) {
|
||||||
val slot = id2slot.remove(id)!!
|
val slot = id2slot.remove(id)!!
|
||||||
check(value2slot.remove(slot.synchable) == value2slot)
|
check(value2slot.remove(slot.value) == value2slot)
|
||||||
remoteStates.forEach { it.remove(slot) }
|
remoteStates.forEach { it.remove(slot) }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -225,7 +235,7 @@ class DynamicSynchableGroup<T : ISynchable>(
|
|||||||
SYNC_ENTRY -> {
|
SYNC_ENTRY -> {
|
||||||
val id = stream.readVarInt()
|
val id = stream.readVarInt()
|
||||||
val slot = checkNotNull(id2slot.get(id)) { "No such slot with ID: $id" }
|
val slot = checkNotNull(id2slot.get(id)) { "No such slot with ID: $id" }
|
||||||
slot.synchable.read(stream)
|
synchable(slot.value).read(stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
CLEAR -> {
|
CLEAR -> {
|
||||||
@ -299,7 +309,7 @@ class DynamicSynchableGroup<T : ISynchable>(
|
|||||||
override fun next(): T {
|
override fun next(): T {
|
||||||
val slot = parent.next()
|
val slot = parent.next()
|
||||||
last = KOptional(slot)
|
last = KOptional(slot)
|
||||||
return slot.synchable
|
return slot.value
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun remove() {
|
override fun remove() {
|
||||||
@ -313,11 +323,7 @@ class DynamicSynchableGroup<T : ISynchable>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun remove(element: T): Boolean {
|
override fun remove(element: T): Boolean {
|
||||||
if (element !in value2slot) {
|
val slot = value2slot.remove(element) ?: return false
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
val slot = value2slot.remove(element)!!
|
|
||||||
checkNotNull(id2slot.remove(slot.id))
|
checkNotNull(id2slot.remove(slot.id))
|
||||||
remoteStates.forEach { it.remove(slot) }
|
remoteStates.forEach { it.remove(slot) }
|
||||||
idAllocator.release(slot.id)
|
idAllocator.release(slot.id)
|
||||||
|
@ -36,6 +36,7 @@ import ru.dbotthepony.mc.otm.block.decorative.CargoCrateBlock
|
|||||||
import ru.dbotthepony.mc.otm.block.decorative.ComputerTerminalBlock
|
import ru.dbotthepony.mc.otm.block.decorative.ComputerTerminalBlock
|
||||||
import ru.dbotthepony.mc.otm.block.decorative.StarChairBlock
|
import ru.dbotthepony.mc.otm.block.decorative.StarChairBlock
|
||||||
import ru.dbotthepony.mc.otm.block.decorative.TritaniumPressurePlate
|
import ru.dbotthepony.mc.otm.block.decorative.TritaniumPressurePlate
|
||||||
|
import ru.dbotthepony.mc.otm.capability.MatteryCapability
|
||||||
import ru.dbotthepony.mc.otm.capability.matteryEnergy
|
import ru.dbotthepony.mc.otm.capability.matteryEnergy
|
||||||
import ru.dbotthepony.mc.otm.client.MatteryGUI
|
import ru.dbotthepony.mc.otm.client.MatteryGUI
|
||||||
import ru.dbotthepony.mc.otm.util.ResourceLocation
|
import ru.dbotthepony.mc.otm.util.ResourceLocation
|
||||||
@ -319,6 +320,21 @@ object MRegistry : IBlockItemRegistryAcceptor {
|
|||||||
val tag = stack.getOrDefault(MDataComponentTypes.Configurator.CONFIGURATION, CompoundTag())
|
val tag = stack.getOrDefault(MDataComponentTypes.Configurator.CONFIGURATION, CompoundTag())
|
||||||
if (tag.isEmpty) 0f else 1f
|
if (tag.isEmpty) 0f else 1f
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (item in MItems.MATTER_CAPACITORS) {
|
||||||
|
ItemProperties.register(item, ResourceLocation(OverdriveThatMatters.MOD_ID, "capacitor_gauge")) { stack, _, _, _ ->
|
||||||
|
val cap = stack.getCapability(MatteryCapability.MATTER_ITEM) ?: return@register 1f
|
||||||
|
(cap.storedMatter / cap.maxStoredMatter).toFloat()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (item in MItems.ALL_BATTERIES) {
|
||||||
|
ItemProperties.register(item, ResourceLocation(OverdriveThatMatters.MOD_ID, "capacitor_gauge")) { stack, _, _, _ ->
|
||||||
|
val energy = stack.matteryEnergy ?: return@register 1f
|
||||||
|
|
||||||
|
(energy.batteryLevel / energy.maxBatteryLevel).toFloat()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,7 +223,7 @@ private fun addMainCreativeTabItems(consumer: CreativeModeTab.Output) {
|
|||||||
|
|
||||||
accept(MItems.GRILL.values)
|
accept(MItems.GRILL.values)
|
||||||
|
|
||||||
// accept(MItems.MATTER_DUST)
|
accept(MItems.MATTER_DUST.makeStack())
|
||||||
|
|
||||||
accept(MItems.TRITANIUM_ORE)
|
accept(MItems.TRITANIUM_ORE)
|
||||||
accept(MItems.DEEPSLATE_TRITANIUM_ORE)
|
accept(MItems.DEEPSLATE_TRITANIUM_ORE)
|
||||||
|
@ -78,6 +78,17 @@ fun IntArray.shuffle(random: RandomSource): IntArray {
|
|||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun <T> Array<T>.shuffle(random: RandomSource): Array<T> {
|
||||||
|
for (i in lastIndex downTo 1) {
|
||||||
|
val j = random.nextInt(i + 1)
|
||||||
|
val copy = this[i]
|
||||||
|
this[i] = this[j]
|
||||||
|
this[j] = copy
|
||||||
|
}
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
fun <L : IntList> L.shuffle(random: RandomSource): L {
|
fun <L : IntList> L.shuffle(random: RandomSource): L {
|
||||||
for (i in lastIndex downTo 1) {
|
for (i in lastIndex downTo 1) {
|
||||||
val j = random.nextInt(i + 1)
|
val j = random.nextInt(i + 1)
|
||||||
|
@ -20,7 +20,21 @@ operator fun BlockPos.plus(other: BlockRotation): BlockPos {
|
|||||||
}
|
}
|
||||||
|
|
||||||
enum class RelativeSide(val default: Direction) {
|
enum class RelativeSide(val default: Direction) {
|
||||||
FRONT(Direction.NORTH), BACK(Direction.SOUTH), LEFT(Direction.WEST), RIGHT(Direction.EAST), TOP(Direction.UP), BOTTOM(Direction.DOWN)
|
FRONT(Direction.NORTH), BACK(Direction.SOUTH), LEFT(Direction.WEST), RIGHT(Direction.EAST), TOP(Direction.UP), BOTTOM(Direction.DOWN);
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
fun defaultOf(direction: Direction): RelativeSide {
|
||||||
|
return when (direction) {
|
||||||
|
Direction.DOWN -> BOTTOM
|
||||||
|
Direction.UP -> TOP
|
||||||
|
Direction.NORTH -> FRONT
|
||||||
|
Direction.SOUTH -> BACK
|
||||||
|
Direction.WEST -> LEFT
|
||||||
|
Direction.EAST -> RIGHT
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
After Width: | Height: | Size: 368 B |
After Width: | Height: | Size: 376 B |
After Width: | Height: | Size: 372 B |
After Width: | Height: | Size: 377 B |
After Width: | Height: | Size: 374 B |
After Width: | Height: | Size: 374 B |
After Width: | Height: | Size: 374 B |
After Width: | Height: | Size: 374 B |
After Width: | Height: | Size: 377 B |
After Width: | Height: | Size: 373 B |
Before Width: | Height: | Size: 262 B After Width: | Height: | Size: 486 B |
After Width: | Height: | Size: 366 B |
After Width: | Height: | Size: 376 B |
After Width: | Height: | Size: 386 B |
After Width: | Height: | Size: 379 B |
After Width: | Height: | Size: 388 B |
After Width: | Height: | Size: 378 B |
After Width: | Height: | Size: 388 B |
After Width: | Height: | Size: 380 B |
After Width: | Height: | Size: 389 B |
Before Width: | Height: | Size: 484 B After Width: | Height: | Size: 471 B |
Before Width: | Height: | Size: 505 B After Width: | Height: | Size: 489 B |
Before Width: | Height: | Size: 505 B After Width: | Height: | Size: 489 B |
Before Width: | Height: | Size: 505 B After Width: | Height: | Size: 489 B |
Before Width: | Height: | Size: 508 B After Width: | Height: | Size: 494 B |
After Width: | Height: | Size: 371 B |
After Width: | Height: | Size: 384 B |
After Width: | Height: | Size: 385 B |
After Width: | Height: | Size: 398 B |
After Width: | Height: | Size: 384 B |
After Width: | Height: | Size: 397 B |
After Width: | Height: | Size: 386 B |
After Width: | Height: | Size: 397 B |
Before Width: | Height: | Size: 480 B After Width: | Height: | Size: 466 B |
Before Width: | Height: | Size: 491 B After Width: | Height: | Size: 480 B |
Before Width: | Height: | Size: 491 B After Width: | Height: | Size: 480 B |
Before Width: | Height: | Size: 491 B After Width: | Height: | Size: 480 B |
Before Width: | Height: | Size: 493 B After Width: | Height: | Size: 483 B |
Before Width: | Height: | Size: 494 B After Width: | Height: | Size: 484 B |
Before Width: | Height: | Size: 498 B After Width: | Height: | Size: 488 B |