From 60cd9d5bef9cfda1f881608ed05aa3837568127e Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Thu, 29 Sep 2022 20:38:08 +0700 Subject: [PATCH] Move black hole block entity to field synchronizer --- .../mc/otm/block/entity/MatteryBlockEntity.kt | 48 +----- .../block/entity/SynchronizedBlockEntity.kt | 62 ++++++++ .../entity/blackhole/BlackHoleBlockEntity.kt | 140 +++++++----------- .../mc/otm/network/WorldNetworkChannel.kt | 4 +- 4 files changed, 115 insertions(+), 139 deletions(-) create mode 100644 src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/SynchronizedBlockEntity.kt diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt index b19b59f3d..aef25351a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/MatteryBlockEntity.kt @@ -34,7 +34,7 @@ import ru.dbotthepony.mc.otm.network.FieldSynchronizer import ru.dbotthepony.mc.otm.network.WorldNetworkChannel import ru.dbotthepony.mc.otm.oncePre -abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) : BlockEntity(p_155228_, p_155229_, p_155230_), MenuProvider { +abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) : SynchronizedBlockEntity(p_155228_, p_155229_, p_155230_), MenuProvider { var customDisplayName: Component? = null var redstoneSignal = 0 set(level) { @@ -74,52 +74,6 @@ abstract class MatteryBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: Bloc } } - val synchronizer = FieldSynchronizer() - - init { - synchronizer.defaultEndpoint.markUnused() - } - - open val synchronizationRadius: Double = 32.0 - - // TODO: Optimize, if required - fun synchronizeToPlayers() { - if (synchronizationRadius <= 0.0 || synchronizer.isEmpty) { - return - } - - val server = level?.server ?: return - - if (server.playerCount <= 0) { - return - } - - val (xi, yi, zi) = blockPos - val bx = xi + 0.5 - val by = yi + 0.5 - val bz = zi + 0.5 - - val double = synchronizationRadius * synchronizationRadius - - server.playerList.players.stream().filter { - if (!it.isAlive || it.level != level) { - return@filter false - } - - val (x, y, z) = it.position - - (x - bx) * (x - bx) + - (y - by) * (y - by) + - (z - bz) * (z - bz) <= double - }.forEach { - val payload = synchronizer.computeEndpointFor(it).collectNetworkPayload() - - if (payload != null) { - WorldNetworkChannel.send(it, BlockEntitySyncPacket(blockPos, payload.array, payload.length)) - } - } - } - protected open val defaultDisplayName: Component get() = level?.getBlockState(blockPos)?.block?.name ?: TextComponent("null at $blockPos") diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/SynchronizedBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/SynchronizedBlockEntity.kt new file mode 100644 index 000000000..8952d4c64 --- /dev/null +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/SynchronizedBlockEntity.kt @@ -0,0 +1,62 @@ +package ru.dbotthepony.mc.otm.block.entity + +import net.minecraft.core.BlockPos +import net.minecraft.world.level.block.entity.BlockEntity +import net.minecraft.world.level.block.entity.BlockEntityType +import net.minecraft.world.level.block.state.BlockState +import ru.dbotthepony.mc.otm.core.component1 +import ru.dbotthepony.mc.otm.core.component2 +import ru.dbotthepony.mc.otm.core.component3 +import ru.dbotthepony.mc.otm.core.position +import ru.dbotthepony.mc.otm.network.BlockEntitySyncPacket +import ru.dbotthepony.mc.otm.network.FieldSynchronizer +import ru.dbotthepony.mc.otm.network.WorldNetworkChannel + +abstract class SynchronizedBlockEntity(p_155228_: BlockEntityType<*>, p_155229_: BlockPos, p_155230_: BlockState) : BlockEntity(p_155228_, p_155229_, p_155230_) { + val synchronizer = FieldSynchronizer() + + init { + synchronizer.defaultEndpoint.markUnused() + } + + open val synchronizationRadius: Double = 32.0 + + // TODO: Optimize, if required + fun synchronizeToPlayers() { + if (synchronizationRadius <= 0.0 || synchronizer.isEmpty) { + return + } + + val server = level?.server ?: return + + if (server.playerCount <= 0) { + return + } + + val (xi, yi, zi) = blockPos + val bx = xi + 0.5 + val by = yi + 0.5 + val bz = zi + 0.5 + + val double = synchronizationRadius * synchronizationRadius + + server.playerList.players.stream().filter { + if (!it.isAlive || it.level != level) { + return@filter false + } + + val (x, y, z) = it.position + + (x - bx) * (x - bx) + + (y - by) * (y - by) + + (z - bz) * (z - bz) <= double + }.forEach { + val payload = synchronizer.computeEndpointFor(it).collectNetworkPayload() + + if (payload != null) { + WorldNetworkChannel.send(it, BlockEntitySyncPacket(blockPos, payload.array, payload.length)) + } + } + } + +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/blackhole/BlackHoleBlockEntity.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/blackhole/BlackHoleBlockEntity.kt index c027d455f..4c95bd092 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/blackhole/BlackHoleBlockEntity.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/block/entity/blackhole/BlackHoleBlockEntity.kt @@ -24,6 +24,7 @@ import net.minecraft.world.phys.AABB import net.minecraft.world.phys.Vec3 import ru.dbotthepony.mc.otm.block.BlackHoleBlock import ru.dbotthepony.mc.otm.block.entity.GravitationStabilizerBlockEntity +import ru.dbotthepony.mc.otm.block.entity.SynchronizedBlockEntity import ru.dbotthepony.mc.otm.block.entity.blackhole.ExplosionQueue.Companion.queueForLevel import ru.dbotthepony.mc.otm.core.ImpreciseFraction import ru.dbotthepony.mc.otm.core.plus @@ -32,55 +33,53 @@ import ru.dbotthepony.mc.otm.registry.MBlockEntities import ru.dbotthepony.mc.otm.registry.MItems import ru.dbotthepony.mc.otm.registry.MRegistry import ru.dbotthepony.mc.otm.core.getSphericalBlockPositions +import ru.dbotthepony.mc.otm.core.mapIf import ru.dbotthepony.mc.otm.core.set import kotlin.math.pow import kotlin.math.roundToInt import kotlin.math.sqrt -class BlackHoleBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : BlockEntity(MBlockEntities.BLACK_HOLE, p_155229_, p_155230_) { - var mass = BASELINE_MASS - set(mass) { - if (mass <= ImpreciseFraction.ZERO) { - collapse() - return - } - - field = mass - - setChanged() - - var massForDiv = mass - - when (if (level?.isClientSide == false) stabilizers.size else stabilizerClientCount) { - 1 -> {massForDiv /= 4} - 2 -> {massForDiv /= 16} - 3 -> {massForDiv /= 64} - 4 -> {massForDiv /= 512} - 5 -> {massForDiv /= 2048} - 6 -> {massForDiv /= 16384} - } - - gravitationStrength = sqrt(massForDiv.div(BASELINE_MASS).toDouble()).coerceAtMost(20.0).coerceAtLeast(0.2) - - val level = level - - if (level != null && !level.isClientSide && !suppressUpdates) - level.sendBlockUpdated(blockPos, blockState, blockState, Block.UPDATE_CLIENTS) - - affectedBounds = BoundingBox( - (-30 * gravitationStrength).toInt(), - (-30 * gravitationStrength).toInt(), - (-30 * gravitationStrength).toInt(), - (30 * gravitationStrength).toInt(), - (30 * gravitationStrength).toInt(), - (30 * gravitationStrength).toInt() - ).move( - blockPos - ) - - affectedBoundsAABB = AABB.of(affectedBounds) +class BlackHoleBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : SynchronizedBlockEntity(MBlockEntities.BLACK_HOLE, p_155229_, p_155230_) { + var mass by synchronizer.fraction(BASELINE_MASS, setter = setter@{ mass, field, setByRemote -> + if (mass <= ImpreciseFraction.ZERO) { + collapse() + return@setter } + field.write(mass) + setChanged() + var massForDiv = mass + + when (if (level?.isClientSide == false) stabilizers.size else stabilizerClientCount) { + 1 -> {massForDiv /= 4} + 2 -> {massForDiv /= 16} + 3 -> {massForDiv /= 64} + 4 -> {massForDiv /= 512} + 5 -> {massForDiv /= 2048} + 6 -> {massForDiv /= 16384} + } + + gravitationStrength = sqrt(massForDiv.div(BASELINE_MASS).toDouble()).coerceAtMost(20.0).coerceAtLeast(0.2) + + val level = level + + if (level != null && !level.isClientSide && !suppressUpdates) + level.sendBlockUpdated(blockPos, blockState, blockState, Block.UPDATE_CLIENTS) + + affectedBounds = BoundingBox( + (-30 * gravitationStrength).toInt(), + (-30 * gravitationStrength).toInt(), + (-30 * gravitationStrength).toInt(), + (30 * gravitationStrength).toInt(), + (30 * gravitationStrength).toInt(), + (30 * gravitationStrength).toInt() + ).moved( + blockPos.x, blockPos.y, blockPos.z + ) + + affectedBoundsAABB = AABB.of(affectedBounds) + }) + override fun getRenderBoundingBox(): AABB { return AABB(blockPos.offset(-GravitationStabilizerBlockEntity.RANGE, -GravitationStabilizerBlockEntity.RANGE, -GravitationStabilizerBlockEntity.RANGE), blockPos.offset(GravitationStabilizerBlockEntity.RANGE, GravitationStabilizerBlockEntity.RANGE, GravitationStabilizerBlockEntity.RANGE)) } @@ -152,59 +151,18 @@ class BlackHoleBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : BlockEn } } - // shared functions - fun writeBlackHoleData(tag: CompoundTag): CompoundTag { - tag["mass"] = mass.serializeNBT() - tag["spin_direction"] = spin_direction - return tag - } - - fun readBlackHoleData(tag: CompoundTag) { - tag["mass"]?.let { - mass = ImpreciseFraction.deserializeNBT(it) - } - - spin_direction = tag.getBoolean("spin_direction") - } - - // disk io public override fun saveAdditional(nbt: CompoundTag) { super.saveAdditional(nbt) - writeBlackHoleData(nbt) + nbt["mass"] = mass.serializeNBT() + nbt["spin_direction"] = spin_direction } + override val synchronizationRadius: Double = 256.0 + override fun load(tag: CompoundTag) { super.load(tag) - readBlackHoleData(tag) - } - - // received either by game engine (from getUpdateTag on ClientLevelPacket) - // or by onDataPacket - override fun handleUpdateTag(tag: CompoundTag) { - stabilizerClientCount = (tag["stabilizers"] as IntTag).asInt - super.handleUpdateTag(tag) - readBlackHoleData(tag) - } - - // called by game engine for ClientLevelPacket - override fun getUpdateTag(): CompoundTag { - return writeBlackHoleData(super.getUpdateTag()).also { - it["stabilizers"] = stabilizers.size - } - } - - // called by game engine on block updates - override fun getUpdatePacket(): ClientboundBlockEntityDataPacket? { - return ClientboundBlockEntityDataPacket.create(this) - } - - // called by game engine by forge patches when ClientboundBlockEntityDataPacket is received - override fun onDataPacket(net: Connection, pkt: ClientboundBlockEntityDataPacket) { - super.onDataPacket(net, pkt) - - if (net.receiving == PacketFlow.CLIENTBOUND) { - handleUpdateTag(pkt.tag!!) - } + mass = tag.mapIf("mass", ImpreciseFraction::deserializeNBT) ?: BASELINE_MASS + spin_direction = tag.getBoolean("spin_direction") } var affectedBounds = BoundingBox(0, 0, 0, 1, 1, 1) @@ -255,6 +213,8 @@ class BlackHoleBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : BlockEn } fun tick() { + synchronizeToPlayers() + sleepTicks-- if (sleepTicks > 0) return val level = level as? ServerLevel ?: return @@ -365,4 +325,4 @@ class BlackHoleBlockEntity(p_155229_: BlockPos, p_155230_: BlockState) : BlockEn val BASELINE_MASS = ImpreciseFraction(1_000) val HAWKING_MASS_LOSE_STEP = ImpreciseFraction("-0.1") } -} \ No newline at end of file +} diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/network/WorldNetworkChannel.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/network/WorldNetworkChannel.kt index eefe58861..6eac71721 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/network/WorldNetworkChannel.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/network/WorldNetworkChannel.kt @@ -6,7 +6,7 @@ import net.minecraft.network.FriendlyByteBuf import net.minecraftforge.network.NetworkDirection import net.minecraftforge.network.NetworkEvent import ru.dbotthepony.mc.otm.android.feature.ItemEntityDataPacket -import ru.dbotthepony.mc.otm.block.entity.MatteryBlockEntity +import ru.dbotthepony.mc.otm.block.entity.SynchronizedBlockEntity import ru.dbotthepony.mc.otm.client.minecraft import java.util.function.Supplier @@ -21,7 +21,7 @@ class BlockEntitySyncPacket(val position: BlockPos, val buffer: ByteArray, val v context.enqueueWork { val level = minecraft.player?.level ?: return@enqueueWork - val blockEntity = level.getBlockEntity(position) as? MatteryBlockEntity ?: return@enqueueWork + val blockEntity = level.getBlockEntity(position) as? SynchronizedBlockEntity ?: return@enqueueWork blockEntity.synchronizer.applyNetworkPayload(FastByteArrayInputStream(buffer, 0, validBytes)) } }