mirror of
https://github.com/GayPizzaSpecifications/foundation.git
synced 2025-08-03 05:30:55 +00:00
Heimdall: Keep track of block data.
This commit is contained in:
@ -4,5 +4,6 @@ import kotlinx.serialization.Serializable
|
|||||||
|
|
||||||
@Serializable
|
@Serializable
|
||||||
data class ExportedBlock(
|
data class ExportedBlock(
|
||||||
val type: String
|
val type: String,
|
||||||
|
val data: String? = null
|
||||||
)
|
)
|
||||||
|
@ -2,4 +2,5 @@ package gay.pizza.foundation.heimdall.table
|
|||||||
|
|
||||||
object BlockBreakTable : PlayerTimedLocalEventTable("block_breaks") {
|
object BlockBreakTable : PlayerTimedLocalEventTable("block_breaks") {
|
||||||
val block = text("block")
|
val block = text("block")
|
||||||
|
val blockData = text("block_data").nullable()
|
||||||
}
|
}
|
||||||
|
@ -2,4 +2,5 @@ package gay.pizza.foundation.heimdall.table
|
|||||||
|
|
||||||
object BlockPlaceTable : PlayerTimedLocalEventTable("block_places") {
|
object BlockPlaceTable : PlayerTimedLocalEventTable("block_places") {
|
||||||
val block = text("block")
|
val block = text("block")
|
||||||
|
val blockData = text("block_data").nullable()
|
||||||
}
|
}
|
||||||
|
@ -5,4 +5,5 @@ import gay.pizza.foundation.heimdall.table.PlayerTimedLocalEventTable
|
|||||||
object BlockChangeView : PlayerTimedLocalEventTable("block_changes") {
|
object BlockChangeView : PlayerTimedLocalEventTable("block_changes") {
|
||||||
val isBreak = bool("break")
|
val isBreak = bool("break")
|
||||||
val block = text("block")
|
val block = text("block")
|
||||||
|
val blockData = text("block_data").nullable()
|
||||||
}
|
}
|
||||||
|
@ -16,12 +16,14 @@ class BlockBreak(
|
|||||||
val playerUniqueIdentity: UUID,
|
val playerUniqueIdentity: UUID,
|
||||||
val location: Location,
|
val location: Location,
|
||||||
val material: Material,
|
val material: Material,
|
||||||
|
val blockData: String? = null,
|
||||||
val timestamp: Instant = Instant.now()
|
val timestamp: Instant = Instant.now()
|
||||||
) : HeimdallEvent() {
|
) : HeimdallEvent() {
|
||||||
constructor(event: BlockBreakEvent) : this(
|
constructor(event: BlockBreakEvent) : this(
|
||||||
event.player.uniqueId,
|
event.player.uniqueId,
|
||||||
event.block.location,
|
event.block.location,
|
||||||
event.block.type
|
event.block.type,
|
||||||
|
event.block.blockData.asString
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun store(transaction: Transaction) {
|
override fun store(transaction: Transaction) {
|
||||||
@ -29,6 +31,7 @@ class BlockBreak(
|
|||||||
BlockBreakTable.insert {
|
BlockBreakTable.insert {
|
||||||
putPlayerTimedLocalEvent(it, timestamp, location, playerUniqueIdentity)
|
putPlayerTimedLocalEvent(it, timestamp, location, playerUniqueIdentity)
|
||||||
it[block] = material.key.toString()
|
it[block] = material.key.toString()
|
||||||
|
it[blockData] = this@BlockBreak.blockData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,12 +16,14 @@ class BlockPlace(
|
|||||||
val playerUniqueIdentity: UUID,
|
val playerUniqueIdentity: UUID,
|
||||||
val location: Location,
|
val location: Location,
|
||||||
val material: Material,
|
val material: Material,
|
||||||
|
val blockData: String? = null,
|
||||||
val timestamp: Instant = Instant.now()
|
val timestamp: Instant = Instant.now()
|
||||||
) : HeimdallEvent() {
|
) : HeimdallEvent() {
|
||||||
constructor(event: BlockPlaceEvent) : this(
|
constructor(event: BlockPlaceEvent) : this(
|
||||||
event.player.uniqueId,
|
event.player.uniqueId,
|
||||||
event.block.location,
|
event.block.location,
|
||||||
event.block.type
|
event.block.type,
|
||||||
|
event.block.blockData.asString
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun store(transaction: Transaction) {
|
override fun store(transaction: Transaction) {
|
||||||
@ -29,6 +31,7 @@ class BlockPlace(
|
|||||||
BlockPlaceTable.insert {
|
BlockPlaceTable.insert {
|
||||||
putPlayerTimedLocalEvent(it, timestamp, location, playerUniqueIdentity)
|
putPlayerTimedLocalEvent(it, timestamp, location, playerUniqueIdentity)
|
||||||
it[block] = material.key.toString()
|
it[block] = material.key.toString()
|
||||||
|
it[blockData] = this@BlockPlace.blockData
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
package gay.pizza.foundation.heimdall.plugin.load
|
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.WorldLoadFormat
|
||||||
import gay.pizza.foundation.heimdall.load.WorldLoadWorld
|
import gay.pizza.foundation.heimdall.load.WorldLoadWorld
|
||||||
import org.bukkit.Location
|
import org.bukkit.Location
|
||||||
@ -24,7 +25,7 @@ class WorldReassembler(val plugin: Plugin, val server: Server, val format: World
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
val blocksToMake = mutableListOf<Pair<Location, Material>>()
|
val blocksToMake = mutableListOf<Pair<Location, ExportedBlock>>()
|
||||||
|
|
||||||
for ((x, zBlocks) in load.blocks) {
|
for ((x, zBlocks) in load.blocks) {
|
||||||
for ((z, yBlocks) in zBlocks) {
|
for ((z, yBlocks) in zBlocks) {
|
||||||
@ -36,7 +37,7 @@ class WorldReassembler(val plugin: Plugin, val server: Server, val format: World
|
|||||||
continue
|
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 copy = section.toList()
|
||||||
val runnable = object : BukkitRunnable() {
|
val runnable = object : BukkitRunnable() {
|
||||||
override fun run() {
|
override fun run() {
|
||||||
for ((location, material) in copy) {
|
for ((location, blk) in copy) {
|
||||||
val block = world.getBlockAt(location)
|
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()
|
count.incrementAndGet()
|
||||||
}
|
}
|
||||||
feedback("Placed ${count.get()} blocks in ${world.name}")
|
feedback("Placed ${count.get()} blocks in ${world.name}")
|
||||||
|
@ -126,12 +126,6 @@ create table if not exists entity_kills (
|
|||||||
--
|
--
|
||||||
select create_hypertable('entity_kills', 'time', 'player', 4, if_not_exists => TRUE);
|
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
|
create or replace view player_names as
|
||||||
with unique_player_ids as (
|
with unique_player_ids as (
|
||||||
select distinct player
|
select distinct player
|
||||||
@ -145,3 +139,14 @@ create or replace view player_names as
|
|||||||
limit 1
|
limit 1
|
||||||
) as name
|
) as name
|
||||||
from unique_player_ids;
|
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;
|
||||||
|
--
|
||||||
|
@ -33,7 +33,7 @@ class GenerateWorldLoadFile : CliktCommand(name = "generate-world-load", help =
|
|||||||
for ((id, changelog) in worldChangelogs) {
|
for ((id, changelog) in worldChangelogs) {
|
||||||
val tracker = BlockLogTracker()
|
val tracker = BlockLogTracker()
|
||||||
tracker.replay(changelog)
|
tracker.replay(changelog)
|
||||||
val sparse = tracker.buildBlockMap { ExportedBlock(it.type) }
|
val sparse = tracker.buildBlockMap { ExportedBlock(it.type, it.data) }
|
||||||
val blocks = sparse.blocks
|
val blocks = sparse.blocks
|
||||||
worlds[id.toString().lowercase()] = WorldLoadWorld(
|
worlds[id.toString().lowercase()] = WorldLoadWorld(
|
||||||
worldNames[id] ?: "unknown_$id",
|
worldNames[id] ?: "unknown_$id",
|
||||||
|
@ -47,7 +47,7 @@ class ChunkExportLoader(
|
|||||||
}
|
}
|
||||||
|
|
||||||
val coordinate = BlockCoordinate(x.toLong(), y.toLong(), z.toLong())
|
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)
|
map?.put(coordinate, state)
|
||||||
if (allBlocks != null) {
|
if (allBlocks != null) {
|
||||||
allBlocks[coordinate] = state
|
allBlocks[coordinate] = state
|
||||||
|
@ -68,10 +68,11 @@ class BlockChangelog(
|
|||||||
val y = row[BlockChangeView.y]
|
val y = row[BlockChangeView.y]
|
||||||
val z = row[BlockChangeView.z]
|
val z = row[BlockChangeView.z]
|
||||||
val block = row[BlockChangeView.block]
|
val block = row[BlockChangeView.block]
|
||||||
|
val blockData = row[BlockChangeView.blockData]
|
||||||
val location = BlockCoordinate(x.toLong(), y.toLong(), z.toLong())
|
val location = BlockCoordinate(x.toLong(), y.toLong(), z.toLong())
|
||||||
|
|
||||||
val fromBlock = if (changeIsBreak) {
|
val fromBlock = if (changeIsBreak) {
|
||||||
BlockState.cached(block)
|
BlockState(block, blockData)
|
||||||
} else {
|
} else {
|
||||||
BlockState.AirBlock
|
BlockState.AirBlock
|
||||||
}
|
}
|
||||||
@ -79,7 +80,7 @@ class BlockChangelog(
|
|||||||
val toBlock = if (changeIsBreak) {
|
val toBlock = if (changeIsBreak) {
|
||||||
BlockState.AirBlock
|
BlockState.AirBlock
|
||||||
} else {
|
} else {
|
||||||
BlockState.cached(block)
|
BlockState(block, blockData)
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockChange(
|
BlockChange(
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
package gay.pizza.foundation.heimdall.tool.state
|
package gay.pizza.foundation.heimdall.tool.state
|
||||||
|
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
|
||||||
import kotlinx.serialization.Serializable
|
import kotlinx.serialization.Serializable
|
||||||
|
|
||||||
@Serializable(BlockStateSerializer::class)
|
@Serializable
|
||||||
data class BlockState(val type: String) {
|
data class BlockState(
|
||||||
|
val type: String,
|
||||||
|
val data: String? = null
|
||||||
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
private val cache = ConcurrentHashMap<String, BlockState>()
|
val AirBlock: BlockState = BlockState("minecraft:air")
|
||||||
|
|
||||||
val AirBlock: BlockState = cached("minecraft:air")
|
|
||||||
|
|
||||||
fun cached(type: String): BlockState = cache.computeIfAbsent(type) { BlockState(type) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
|
||||||
}
|
|
||||||
}
|
|
Reference in New Issue
Block a user