Move black hole block entity to field synchronizer

This commit is contained in:
DBotThePony 2022-09-29 20:38:08 +07:00
parent 284e4d404a
commit 60cd9d5bef
Signed by: DBot
GPG Key ID: DCC23B5715498507
4 changed files with 115 additions and 139 deletions

View File

@ -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")

View File

@ -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))
}
}
}
}

View File

@ -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")
}
}
}

View File

@ -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))
}
}