Compare commits
10 Commits
cc7fe1ea2f
...
822ab97066
Author | SHA1 | Date | |
---|---|---|---|
822ab97066 | |||
43c02b37a8 | |||
8f9103ca48 | |||
9a6cc53189 | |||
2453c60d76 | |||
a54382b74e | |||
d35da8c7f4 | |||
afb6cd5907 | |||
578d86410b | |||
9e1ae327ea |
@ -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)
|
||||||
|
@ -198,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) {
|
||||||
@ -267,16 +276,24 @@ class MatterBottlerBlockEntity(blockPos: BlockPos, blockState: BlockState) :
|
|||||||
val energyRate = MachinesConfig.MatterBottler.VALUES.energyConsumption * (Decimal.ONE + upgrades.speedBonus.toDecimal())
|
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
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Loading…
Reference in New Issue
Block a user