Heimdall: Keep track of block data.

This commit is contained in:
Alex Zenla 2023-02-07 20:36:30 -05:00
parent 760b77364a
commit 688106a6e6
Signed by: alex
GPG Key ID: C0780728420EBFE5
13 changed files with 46 additions and 45 deletions

View File

@ -4,5 +4,6 @@ import kotlinx.serialization.Serializable
@Serializable
data class ExportedBlock(
val type: String
val type: String,
val data: String? = null
)

View File

@ -2,4 +2,5 @@ package gay.pizza.foundation.heimdall.table
object BlockBreakTable : PlayerTimedLocalEventTable("block_breaks") {
val block = text("block")
val blockData = text("block_data").nullable()
}

View File

@ -2,4 +2,5 @@ package gay.pizza.foundation.heimdall.table
object BlockPlaceTable : PlayerTimedLocalEventTable("block_places") {
val block = text("block")
val blockData = text("block_data").nullable()
}

View File

@ -5,4 +5,5 @@ import gay.pizza.foundation.heimdall.table.PlayerTimedLocalEventTable
object BlockChangeView : PlayerTimedLocalEventTable("block_changes") {
val isBreak = bool("break")
val block = text("block")
val blockData = text("block_data").nullable()
}

View File

@ -16,12 +16,14 @@ class BlockBreak(
val playerUniqueIdentity: UUID,
val location: Location,
val material: Material,
val blockData: String? = null,
val timestamp: Instant = Instant.now()
) : HeimdallEvent() {
constructor(event: BlockBreakEvent) : this(
event.player.uniqueId,
event.block.location,
event.block.type
event.block.type,
event.block.blockData.asString
)
override fun store(transaction: Transaction) {
@ -29,6 +31,7 @@ class BlockBreak(
BlockBreakTable.insert {
putPlayerTimedLocalEvent(it, timestamp, location, playerUniqueIdentity)
it[block] = material.key.toString()
it[blockData] = this@BlockBreak.blockData
}
}
}

View File

@ -16,12 +16,14 @@ class BlockPlace(
val playerUniqueIdentity: UUID,
val location: Location,
val material: Material,
val blockData: String? = null,
val timestamp: Instant = Instant.now()
) : HeimdallEvent() {
constructor(event: BlockPlaceEvent) : this(
event.player.uniqueId,
event.block.location,
event.block.type
event.block.type,
event.block.blockData.asString
)
override fun store(transaction: Transaction) {
@ -29,6 +31,7 @@ class BlockPlace(
BlockPlaceTable.insert {
putPlayerTimedLocalEvent(it, timestamp, location, playerUniqueIdentity)
it[block] = material.key.toString()
it[blockData] = this@BlockPlace.blockData
}
}
}

View File

@ -1,5 +1,6 @@
package gay.pizza.foundation.heimdall.plugin.load
import gay.pizza.foundation.heimdall.export.ExportedBlock
import gay.pizza.foundation.heimdall.load.WorldLoadFormat
import gay.pizza.foundation.heimdall.load.WorldLoadWorld
import org.bukkit.Location
@ -24,7 +25,7 @@ class WorldReassembler(val plugin: Plugin, val server: Server, val format: World
continue
}
val blocksToMake = mutableListOf<Pair<Location, Material>>()
val blocksToMake = mutableListOf<Pair<Location, ExportedBlock>>()
for ((x, zBlocks) in load.blocks) {
for ((z, yBlocks) in zBlocks) {
@ -36,7 +37,7 @@ class WorldReassembler(val plugin: Plugin, val server: Server, val format: World
continue
}
blocksToMake.add(Location(world, x.toDouble(), y.toDouble(), z.toDouble()) to material)
blocksToMake.add(Location(world, x.toDouble(), y.toDouble(), z.toDouble()) to block)
}
}
}
@ -50,9 +51,15 @@ class WorldReassembler(val plugin: Plugin, val server: Server, val format: World
val copy = section.toList()
val runnable = object : BukkitRunnable() {
override fun run() {
for ((location, material) in copy) {
for ((location, blk) in copy) {
val block = world.getBlockAt(location)
block.type = material
val blockData = if (blk.data != null) server.createBlockData(blk.data!!) else null
if (blockData != null) {
block.blockData = blockData
} else {
val material = Material.matchMaterial(blk.type)!!
block.type = material
}
count.incrementAndGet()
}
feedback("Placed ${count.get()} blocks in ${world.name}")

View File

@ -126,12 +126,6 @@ create table if not exists entity_kills (
--
select create_hypertable('entity_kills', 'time', 'player', 4, if_not_exists => TRUE);
--
create or replace view block_changes as
select true as break, *
from block_breaks
union all
select false as break, * from block_places;
--
create or replace view player_names as
with unique_player_ids as (
select distinct player
@ -145,3 +139,14 @@ create or replace view player_names as
limit 1
) as name
from unique_player_ids;
--
alter table block_places add column if not exists block_data text null;
--
alter table block_breaks add column if not exists block_data text null;
--
create or replace view block_changes as
select true as break, *
from block_breaks
union all
select false as break, * from block_places;
--

View File

@ -33,7 +33,7 @@ class GenerateWorldLoadFile : CliktCommand(name = "generate-world-load", help =
for ((id, changelog) in worldChangelogs) {
val tracker = BlockLogTracker()
tracker.replay(changelog)
val sparse = tracker.buildBlockMap { ExportedBlock(it.type) }
val sparse = tracker.buildBlockMap { ExportedBlock(it.type, it.data) }
val blocks = sparse.blocks
worlds[id.toString().lowercase()] = WorldLoadWorld(
worldNames[id] ?: "unknown_$id",

View File

@ -47,7 +47,7 @@ class ChunkExportLoader(
}
val coordinate = BlockCoordinate(x.toLong(), y.toLong(), z.toLong())
val state = BlockState.cached(block.type)
val state = BlockState(block.type, block.data)
map?.put(coordinate, state)
if (allBlocks != null) {
allBlocks[coordinate] = state

View File

@ -68,10 +68,11 @@ class BlockChangelog(
val y = row[BlockChangeView.y]
val z = row[BlockChangeView.z]
val block = row[BlockChangeView.block]
val blockData = row[BlockChangeView.blockData]
val location = BlockCoordinate(x.toLong(), y.toLong(), z.toLong())
val fromBlock = if (changeIsBreak) {
BlockState.cached(block)
BlockState(block, blockData)
} else {
BlockState.AirBlock
}
@ -79,7 +80,7 @@ class BlockChangelog(
val toBlock = if (changeIsBreak) {
BlockState.AirBlock
} else {
BlockState.cached(block)
BlockState(block, blockData)
}
BlockChange(

View File

@ -1,15 +1,13 @@
package gay.pizza.foundation.heimdall.tool.state
import java.util.concurrent.ConcurrentHashMap
import kotlinx.serialization.Serializable
@Serializable(BlockStateSerializer::class)
data class BlockState(val type: String) {
@Serializable
data class BlockState(
val type: String,
val data: String? = null
) {
companion object {
private val cache = ConcurrentHashMap<String, BlockState>()
val AirBlock: BlockState = cached("minecraft:air")
fun cached(type: String): BlockState = cache.computeIfAbsent(type) { BlockState(type) }
val AirBlock: BlockState = BlockState("minecraft:air")
}
}

View File

@ -1,20 +0,0 @@
package gay.pizza.foundation.heimdall.tool.state
import kotlinx.serialization.KSerializer
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
class BlockStateSerializer : KSerializer<BlockState> {
override val descriptor: SerialDescriptor
get() = String.serializer().descriptor
override fun deserialize(decoder: Decoder): BlockState {
return BlockState.cached(decoder.decodeString())
}
override fun serialize(encoder: Encoder, value: BlockState) {
encoder.encodeString(value.type)
}
}