loading connections
This commit is contained in:
parent
1bd84780b7
commit
97d2ea5cdf
4 changed files with 154 additions and 35 deletions
|
|
@ -6,6 +6,7 @@ import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientLifecycleEvents
|
|||
import net.liquidev.d3r.D3r
|
||||
import net.liquidev.dawd3.audio.Audio
|
||||
import net.liquidev.dawd3.block.Blocks
|
||||
import net.liquidev.dawd3.block.device.WorldDeviceLoading
|
||||
import net.liquidev.dawd3.block.entity.registerClientBlockEntityEvents
|
||||
import net.liquidev.dawd3.item.Items
|
||||
import net.liquidev.dawd3.net.Packets
|
||||
|
|
@ -37,6 +38,7 @@ object Mod : ModInitializer, ClientModInitializer {
|
|||
}
|
||||
|
||||
registerClientBlockEntityEvents()
|
||||
WorldDeviceLoading.registerClientTickEvent()
|
||||
Textures.initializeClient()
|
||||
Blocks.initializeClient()
|
||||
Packets.registerClientReceivers()
|
||||
|
|
|
|||
|
|
@ -37,52 +37,111 @@ class DeviceBlockEntity(
|
|||
|
||||
internal val inputConnections = hashMapOf<InputPortName, InputConnection>()
|
||||
|
||||
/**
|
||||
* This field is mostly used for tracing back connections from outputs of this block to inputs
|
||||
* of another block, to know which blocks' connections to sever when this one's destroyed.
|
||||
*/
|
||||
internal val outputConnections = hashMapOf<OutputPortName, BlockPos>()
|
||||
|
||||
/** NBT compound keys. */
|
||||
private object Nbt {
|
||||
const val inputConnections = "inputConnections"
|
||||
|
||||
object InputConnection {
|
||||
const val input = "input"
|
||||
const val output = "output"
|
||||
const val position = "position"
|
||||
const val color = "color"
|
||||
}
|
||||
|
||||
const val outputConnections = "outputConnections"
|
||||
|
||||
object OutputConnection {
|
||||
const val port = "port"
|
||||
const val block = "block"
|
||||
}
|
||||
}
|
||||
|
||||
override fun readNbt(nbt: NbtCompound) {
|
||||
super.readNbt(nbt)
|
||||
|
||||
val nbtConnections = nbt.getList("connections", NbtElement.COMPOUND_TYPE.toInt())
|
||||
val inputConnectionsNbt =
|
||||
nbt.getList(Nbt.inputConnections, NbtElement.COMPOUND_TYPE.toInt())
|
||||
for (i in 0 until inputConnectionsNbt.size) {
|
||||
val connectionNbt = inputConnectionsNbt.getCompound(i)
|
||||
|
||||
for (i in 0 until nbtConnections.size) {
|
||||
val connectionNbt = nbtConnections.getCompound(i)
|
||||
|
||||
val outputString = connectionNbt.getString("output")
|
||||
val outputString = connectionNbt.getString(Nbt.InputConnection.output)
|
||||
val output = PortName.fromString(outputString) ?: continue
|
||||
if (output !is OutputPortName) {
|
||||
logger.error("NBT declares 'output' field that refers to an input port")
|
||||
logger.error("NBT declares 'inputConnections.output' field that refers to an input port")
|
||||
continue
|
||||
}
|
||||
|
||||
val inputString = connectionNbt.getString("input")
|
||||
val inputString = connectionNbt.getString(Nbt.InputConnection.input)
|
||||
val input = PortName.fromString(inputString) ?: continue
|
||||
if (input !is InputPortName) {
|
||||
logger.error("NBT declares 'input' field that refers to an output port")
|
||||
logger.error("NBT declares 'inputConnections.input' field that refers to an output port")
|
||||
continue
|
||||
}
|
||||
|
||||
val blockPosition = NbtHelper.toBlockPos(connectionNbt.getCompound("position"))
|
||||
val color = connectionNbt.getByte("color")
|
||||
val blockPosition =
|
||||
NbtHelper.toBlockPos(connectionNbt.getCompound(Nbt.InputConnection.position))
|
||||
val color = connectionNbt.getByte(Nbt.InputConnection.color)
|
||||
|
||||
inputConnections[input] = InputConnection(blockPosition, outputPortName = output, color)
|
||||
}
|
||||
|
||||
val outputConnectionsNbt =
|
||||
nbt.getList(Nbt.outputConnections, NbtElement.COMPOUND_TYPE.toInt())
|
||||
for (i in 0 until outputConnectionsNbt.size) {
|
||||
val connectionNbt = outputConnectionsNbt.getCompound(i)
|
||||
|
||||
val portString = connectionNbt.getString(Nbt.OutputConnection.port)
|
||||
val port = PortName.fromString(portString) ?: continue
|
||||
if (port !is OutputPortName) {
|
||||
logger.error("NBT declares 'outputConnections.port' field that refers to an input port")
|
||||
continue
|
||||
}
|
||||
val blockPosition =
|
||||
NbtHelper.toBlockPos(connectionNbt.getCompound(Nbt.OutputConnection.block))
|
||||
|
||||
outputConnections[port] = blockPosition
|
||||
}
|
||||
}
|
||||
|
||||
override fun writeNbt(nbt: NbtCompound) {
|
||||
super.writeNbt(nbt)
|
||||
|
||||
val connectionsNbt = NbtList()
|
||||
val inputConnectionsNbt = NbtList()
|
||||
for ((inputPortName, connection) in inputConnections) {
|
||||
val connectionNbt = NbtCompound()
|
||||
connectionNbt.putString("output", connection.outputPortName.toString())
|
||||
connectionNbt.putString("input", inputPortName.toString())
|
||||
connectionNbt.put("position", NbtHelper.fromBlockPos(connection.blockPosition))
|
||||
connectionNbt.putByte("color", connection.color)
|
||||
connectionsNbt.add(connectionNbt)
|
||||
connectionNbt.putString(
|
||||
Nbt.InputConnection.output,
|
||||
connection.outputPortName.toString()
|
||||
)
|
||||
connectionNbt.putString(Nbt.InputConnection.input, inputPortName.toString())
|
||||
connectionNbt.put(
|
||||
Nbt.InputConnection.position,
|
||||
NbtHelper.fromBlockPos(connection.blockPosition)
|
||||
)
|
||||
connectionNbt.putByte(Nbt.InputConnection.color, connection.color)
|
||||
inputConnectionsNbt.add(connectionNbt)
|
||||
}
|
||||
nbt.put("connections", connectionsNbt)
|
||||
nbt.put(Nbt.inputConnections, inputConnectionsNbt)
|
||||
|
||||
val outputConnectionsNbt = NbtList()
|
||||
for ((outputPortName, blockPosition) in outputConnections) {
|
||||
val connectionNbt = NbtCompound()
|
||||
connectionNbt.putString(Nbt.OutputConnection.port, outputPortName.toString())
|
||||
connectionNbt.put(Nbt.OutputConnection.block, NbtHelper.fromBlockPos(blockPosition))
|
||||
outputConnectionsNbt.add(connectionNbt)
|
||||
}
|
||||
nbt.put(Nbt.outputConnections, outputConnectionsNbt)
|
||||
}
|
||||
|
||||
override fun onClientLoad(world: ClientWorld) {
|
||||
clientState = descriptor.onClientLoad(world)
|
||||
WorldDeviceLoading.enqueueDeviceForRebuild(this)
|
||||
}
|
||||
|
||||
override fun onClientUnload(world: ClientWorld) {
|
||||
|
|
@ -105,6 +164,11 @@ class DeviceBlockEntity(
|
|||
}
|
||||
}
|
||||
|
||||
internal fun reapAllConnections() {
|
||||
// TODO: This should be triggered whenever a device block's destroyed and reap all
|
||||
// existing connections to the device.
|
||||
}
|
||||
|
||||
companion object {
|
||||
val logger = Mod.logger<DeviceBlockEntity>()
|
||||
|
||||
|
|
@ -131,6 +195,7 @@ class DeviceBlockEntity(
|
|||
val inputDevice = inputBlockEntity.clientState?.logicalDevice ?: return
|
||||
inputBlockEntity.inputConnections[inputPort] =
|
||||
InputConnection(outputBlockEntity.pos, outputPort, cableColor)
|
||||
outputBlockEntity.outputConnections[outputPort] = inputBlockEntity.pos
|
||||
Devices.makeConnection(
|
||||
outputDevice,
|
||||
outputPort.resolveInstance(),
|
||||
|
|
@ -154,6 +219,7 @@ class DeviceBlockEntity(
|
|||
) ?: throw PortDirectionException("connected ports must be of opposing directions")
|
||||
inputBlockEntity.inputConnections[inputPort] =
|
||||
InputConnection(outputBlockEntity.pos, outputPort, cableColor)
|
||||
outputBlockEntity.outputConnections[outputPort] = inputBlockEntity.pos
|
||||
outputBlockEntity.markDirty()
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -140,24 +140,26 @@ class DeviceBlockEntityRenderer(context: BlockEntityRendererFactory.Context) : B
|
|||
|
||||
for ((_, connection) in blockEntity.inputConnections) {
|
||||
val outputBlockEntity =
|
||||
world.getBlockEntity(connection.blockPosition) as DeviceBlockEntity
|
||||
val outputBlockState = world.getBlockState(connection.blockPosition)
|
||||
val outputPort = outputBlockEntity.descriptor.portLayout[connection.outputPortName]
|
||||
if (outputPort != null) {
|
||||
val delta = (outputBlockEntity.pos - blockEntity.pos).toVec3d()
|
||||
matrixStack.push()
|
||||
matrixStack.translate(delta.x, delta.y, delta.z)
|
||||
rotateToFaceFront(outputBlockState, matrixStack)
|
||||
renderPlugInsidePort(
|
||||
world,
|
||||
outputBlockEntity,
|
||||
facing,
|
||||
outputPort,
|
||||
matrixStack,
|
||||
vertexConsumers,
|
||||
overlay
|
||||
)
|
||||
matrixStack.pop()
|
||||
world.getBlockEntity(connection.blockPosition)
|
||||
if (outputBlockEntity is DeviceBlockEntity) {
|
||||
val outputBlockState = world.getBlockState(connection.blockPosition)
|
||||
val outputPort = outputBlockEntity.descriptor.portLayout[connection.outputPortName]
|
||||
if (outputPort != null) {
|
||||
val delta = (outputBlockEntity.pos - blockEntity.pos).toVec3d()
|
||||
matrixStack.push()
|
||||
matrixStack.translate(delta.x, delta.y, delta.z)
|
||||
rotateToFaceFront(outputBlockState, matrixStack)
|
||||
renderPlugInsidePort(
|
||||
world,
|
||||
outputBlockEntity,
|
||||
facing,
|
||||
outputPort,
|
||||
matrixStack,
|
||||
vertexConsumers,
|
||||
overlay
|
||||
)
|
||||
matrixStack.pop()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
package net.liquidev.dawd3.block.device
|
||||
|
||||
import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents
|
||||
import net.minecraft.client.world.ClientWorld
|
||||
import net.minecraft.util.math.BlockPos
|
||||
|
||||
/**
|
||||
* Logic that needs to run to rebuild the logical device graph upon world loading.
|
||||
*/
|
||||
object WorldDeviceLoading {
|
||||
private val pendingDevicesToRebuild = arrayListOf<BlockPos>()
|
||||
|
||||
fun enqueueDeviceForRebuild(blockEntity: DeviceBlockEntity) {
|
||||
pendingDevicesToRebuild.add(blockEntity.pos)
|
||||
}
|
||||
|
||||
private fun rebuildPendingDevices(world: ClientWorld) {
|
||||
for (blockPosition in pendingDevicesToRebuild) {
|
||||
val inputBlockEntity = world.getBlockEntity(blockPosition) as DeviceBlockEntity
|
||||
for ((inputPortName, inputConnection) in inputBlockEntity.inputConnections) {
|
||||
val outputBlockEntity = world.getBlockEntity(inputConnection.blockPosition)
|
||||
if (outputBlockEntity is DeviceBlockEntity) {
|
||||
DeviceBlockEntity.connectLogicalDevices(
|
||||
inputBlockEntity,
|
||||
inputPortName,
|
||||
outputBlockEntity,
|
||||
inputConnection.outputPortName,
|
||||
inputConnection.color
|
||||
)
|
||||
// Reconcile the physical connection, just in case it goes only to one side.
|
||||
DeviceBlockEntity.connectPhysicalDevices(
|
||||
inputBlockEntity,
|
||||
inputPortName,
|
||||
outputBlockEntity,
|
||||
inputConnection.outputPortName,
|
||||
inputConnection.color
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
pendingDevicesToRebuild.clear()
|
||||
}
|
||||
|
||||
fun registerClientTickEvent() {
|
||||
ClientTickEvents.START_WORLD_TICK.register { clientWorld ->
|
||||
rebuildPendingDevices(clientWorld)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in a new issue