mirror of
https://github.com/GayPizzaSpecifications/foundation.git
synced 2025-08-03 21:41:32 +00:00
Rewrite Heimdall block handling to support more event types and non-player block changes.
This commit is contained in:
@ -8,11 +8,11 @@ import com.github.ajalt.clikt.parameters.options.option
|
||||
import com.github.ajalt.clikt.parameters.options.required
|
||||
import com.github.ajalt.clikt.parameters.types.enum
|
||||
import com.github.ajalt.clikt.parameters.types.int
|
||||
import gay.pizza.foundation.heimdall.table.BlockChangeTable
|
||||
import gay.pizza.foundation.heimdall.table.WorldChangeTable
|
||||
import gay.pizza.foundation.heimdall.tool.render.*
|
||||
import gay.pizza.foundation.heimdall.tool.state.*
|
||||
import gay.pizza.foundation.heimdall.tool.util.compose
|
||||
import gay.pizza.foundation.heimdall.view.BlockChangeView
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.greaterEq
|
||||
@ -49,8 +49,6 @@ class BlockChangeTimelapseCommand : CliktCommand("Block Change Timelapse", name
|
||||
.enum<ImageFormatType> { it.id }
|
||||
.default(ImageFormatType.Png)
|
||||
|
||||
private val considerAirBlocks by option("--consider-air-blocks", help = "Enable Air Block Consideration").flag()
|
||||
|
||||
private val fromCoordinate by option("--trim-from", help = "Trim From Coordinate")
|
||||
private val toCoordinate by option("--trim-to", help = "Trim To Coordinate")
|
||||
|
||||
@ -100,11 +98,11 @@ class BlockChangeTimelapseCommand : CliktCommand("Block Change Timelapse", name
|
||||
|
||||
val filter = compose(
|
||||
combine = { a, b -> a and b },
|
||||
{ trim?.first?.x != null } to { BlockChangeView.x greaterEq trim!!.first.x.toDouble() },
|
||||
{ trim?.first?.z != null } to { BlockChangeView.z greaterEq trim!!.first.z.toDouble() },
|
||||
{ trim?.second?.x != null } to { BlockChangeView.x lessEq trim!!.second.x.toDouble() },
|
||||
{ trim?.second?.z != null } to { BlockChangeView.z lessEq trim!!.second.z.toDouble() },
|
||||
{ true } to { BlockChangeView.world eq world }
|
||||
{ trim?.first?.x != null } to { BlockChangeTable.x greaterEq trim!!.first.x.toDouble() },
|
||||
{ trim?.first?.z != null } to { BlockChangeTable.z greaterEq trim!!.first.z.toDouble() },
|
||||
{ trim?.second?.x != null } to { BlockChangeTable.x lessEq trim!!.second.x.toDouble() },
|
||||
{ trim?.second?.z != null } to { BlockChangeTable.z lessEq trim!!.second.z.toDouble() },
|
||||
{ true } to { BlockChangeTable.world eq world }
|
||||
)
|
||||
|
||||
val changelog = BlockChangelog.query(db, filter)
|
||||
@ -131,7 +129,6 @@ class BlockChangeTimelapseCommand : CliktCommand("Block Change Timelapse", name
|
||||
|
||||
val pool = BlockMapRenderPool(
|
||||
changelog = changelog,
|
||||
blockTrackMode = if (considerAirBlocks) BlockTrackMode.AirOnDelete else BlockTrackMode.RemoveOnDelete,
|
||||
delegate = timelapse,
|
||||
createRendererFunction = { expanse -> render.createNewRenderer(expanse, db) },
|
||||
threadPoolExecutor = threadPoolExecutor
|
||||
|
@ -36,9 +36,9 @@ class PlayerLocationShareRenderer(
|
||||
val player = it[PlayerPositionTable.player]
|
||||
playerSparseMap.createOrModify(
|
||||
coordinate,
|
||||
create = { mutableListOf(player) },
|
||||
modify = { players -> players.add(player) })
|
||||
allPlayerIds.add(player)
|
||||
create = { mutableListOf(player!!) },
|
||||
modify = { players -> players.add(player!!) })
|
||||
allPlayerIds.add(player!!)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,9 +0,0 @@
|
||||
package gay.pizza.foundation.heimdall.tool.state
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
@Serializable
|
||||
enum class BlockChangeType {
|
||||
Place,
|
||||
Break
|
||||
}
|
@ -1,6 +1,6 @@
|
||||
package gay.pizza.foundation.heimdall.tool.state
|
||||
|
||||
import gay.pizza.foundation.heimdall.view.BlockChangeView
|
||||
import gay.pizza.foundation.heimdall.table.BlockChangeTable
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
import org.jetbrains.exposed.sql.Op
|
||||
import org.jetbrains.exposed.sql.select
|
||||
@ -10,7 +10,7 @@ import java.time.Instant
|
||||
import java.util.stream.Stream
|
||||
|
||||
class BlockChangelog(
|
||||
val changes: List<BlockChange>
|
||||
val changes: List<RecordedBlockChange>
|
||||
) {
|
||||
fun slice(slice: ChangelogSlice): BlockChangelog = BlockChangelog(changes.filter {
|
||||
slice.isTimeWithinFullRange(it.time)
|
||||
@ -60,43 +60,30 @@ class BlockChangelog(
|
||||
|
||||
companion object {
|
||||
fun query(db: Database, filter: Op<Boolean> = Op.TRUE): BlockChangelog = transaction(db) {
|
||||
BlockChangelog(BlockChangeView.select(filter).orderBy(BlockChangeView.time).map { row ->
|
||||
val time = row[BlockChangeView.time]
|
||||
val changeIsBreak = row[BlockChangeView.isBreak]
|
||||
val world = row[BlockChangeView.world]
|
||||
val x = row[BlockChangeView.x]
|
||||
val y = row[BlockChangeView.y]
|
||||
val z = row[BlockChangeView.z]
|
||||
val block = row[BlockChangeView.block]
|
||||
val blockData = row[BlockChangeView.blockData]
|
||||
BlockChangelog(BlockChangeTable.select(filter).orderBy(BlockChangeTable.time).map { row ->
|
||||
val time = row[BlockChangeTable.time]
|
||||
val world = row[BlockChangeTable.world]
|
||||
val x = row[BlockChangeTable.x]
|
||||
val y = row[BlockChangeTable.y]
|
||||
val z = row[BlockChangeTable.z]
|
||||
val blockMaterial = row[BlockChangeTable.block]
|
||||
val blockData = row[BlockChangeTable.data]
|
||||
val location = BlockCoordinate(x.toLong(), y.toLong(), z.toLong())
|
||||
|
||||
val fromBlock = if (changeIsBreak) {
|
||||
BlockState(block, blockData)
|
||||
} else {
|
||||
BlockState.AirBlock
|
||||
}
|
||||
val block = BlockState(blockMaterial, blockData)
|
||||
|
||||
val toBlock = if (changeIsBreak) {
|
||||
BlockState.AirBlock
|
||||
} else {
|
||||
BlockState(block, blockData)
|
||||
}
|
||||
|
||||
BlockChange(
|
||||
RecordedBlockChange(
|
||||
time,
|
||||
world,
|
||||
if (changeIsBreak) BlockChangeType.Break else BlockChangeType.Place,
|
||||
location,
|
||||
fromBlock,
|
||||
toBlock
|
||||
block
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fun <T> splitBy(key: (BlockChange) -> T): Map<T, BlockChangelog> {
|
||||
val logs = mutableMapOf<T, MutableList<BlockChange>>()
|
||||
fun <T> splitBy(key: (RecordedBlockChange) -> T): Map<T, BlockChangelog> {
|
||||
val logs = mutableMapOf<T, MutableList<RecordedBlockChange>>()
|
||||
for (change in changes) {
|
||||
val k = key(change)
|
||||
var log = logs[k]
|
||||
|
@ -5,7 +5,7 @@ import gay.pizza.foundation.heimdall.tool.util.minOfAll
|
||||
import java.util.concurrent.ConcurrentHashMap
|
||||
import kotlin.math.absoluteValue
|
||||
|
||||
class BlockLogTracker(private val mode: BlockTrackMode = BlockTrackMode.RemoveOnDelete, isConcurrent: Boolean = false) {
|
||||
class BlockLogTracker(isConcurrent: Boolean = false) {
|
||||
internal val blocks: MutableMap<BlockCoordinate, BlockState> = if (isConcurrent) ConcurrentHashMap() else mutableMapOf()
|
||||
|
||||
fun place(position: BlockCoordinate, state: BlockState) {
|
||||
@ -16,14 +16,6 @@ class BlockLogTracker(private val mode: BlockTrackMode = BlockTrackMode.RemoveOn
|
||||
blocks.putAll(map)
|
||||
}
|
||||
|
||||
fun delete(position: BlockCoordinate) {
|
||||
if (mode == BlockTrackMode.AirOnDelete) {
|
||||
blocks[position] = BlockState.AirBlock
|
||||
} else {
|
||||
blocks.remove(position)
|
||||
}
|
||||
}
|
||||
|
||||
fun calculateZeroBlockOffset(): BlockCoordinate {
|
||||
val (x, y, z) = blocks.keys.minOfAll(3) { listOf(it.x, it.y, it.z) }
|
||||
val xOffset = if (x < 0) x.absoluteValue else 0
|
||||
@ -60,11 +52,7 @@ class BlockLogTracker(private val mode: BlockTrackMode = BlockTrackMode.RemoveOn
|
||||
}
|
||||
|
||||
fun replay(changelog: BlockChangelog) = changelog.changes.forEach { change ->
|
||||
if (change.type == BlockChangeType.Break) {
|
||||
delete(change.location)
|
||||
} else {
|
||||
place(change.location, change.to)
|
||||
}
|
||||
place(change.location, change.state)
|
||||
}
|
||||
|
||||
fun get(position: BlockCoordinate): BlockState? = blocks[position]
|
||||
|
@ -8,7 +8,6 @@ import java.util.concurrent.ThreadPoolExecutor
|
||||
|
||||
class BlockMapRenderPool<T>(
|
||||
val changelog: BlockChangelog,
|
||||
val blockTrackMode: BlockTrackMode,
|
||||
val createRendererFunction: (BlockExpanse) -> BlockMapRenderer<T>,
|
||||
val delegate: BlockMapRenderPoolDelegate<T>,
|
||||
val threadPoolExecutor: ThreadPoolExecutor,
|
||||
@ -64,7 +63,7 @@ class BlockMapRenderPool<T>(
|
||||
private fun runPlaybackSlice(id: String, slice: ChangelogSlice) {
|
||||
val start = System.currentTimeMillis()
|
||||
val sliced = changelog.slice(slice)
|
||||
val tracker = BlockLogTracker(blockTrackMode)
|
||||
val tracker = BlockLogTracker()
|
||||
tracker.replay(sliced)
|
||||
if (tracker.isNotEmpty()) {
|
||||
trackers[slice] = tracker
|
||||
|
@ -21,7 +21,7 @@ class PlayerPositionChangelog(
|
||||
val pitch = row[PlayerPositionTable.z]
|
||||
val yaw = row[PlayerPositionTable.z]
|
||||
|
||||
PlayerPositionChange(time, player, world, x, y, z, pitch, yaw)
|
||||
PlayerPositionChange(time, player!!, world, x, y, z, pitch, yaw)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -3,11 +3,9 @@ package gay.pizza.foundation.heimdall.tool.state
|
||||
import java.time.Instant
|
||||
import java.util.UUID
|
||||
|
||||
data class BlockChange(
|
||||
data class RecordedBlockChange(
|
||||
val time: Instant,
|
||||
val world: UUID,
|
||||
val type: BlockChangeType,
|
||||
val location: BlockCoordinate,
|
||||
val from: BlockState,
|
||||
val to: BlockState
|
||||
val state: BlockState
|
||||
)
|
Reference in New Issue
Block a user