mirror of
https://github.com/GayPizzaSpecifications/foundation.git
synced 2025-08-03 13:31:32 +00:00
Gjallarhorn: Timelapse Limiting and Coordinate Cropping
This commit is contained in:
@ -25,6 +25,7 @@ class GjallarhornCommand : CliktCommand(invokeWithoutSubcommand = true) {
|
|||||||
jdbcUrl = jdbcConnectionUrl
|
jdbcUrl = jdbcConnectionUrl
|
||||||
username = jdbcConnectionUsername
|
username = jdbcConnectionUsername
|
||||||
password = jdbcConnectionPassword
|
password = jdbcConnectionPassword
|
||||||
|
minimumIdle = dbPoolSize / 2
|
||||||
maximumPoolSize = dbPoolSize
|
maximumPoolSize = dbPoolSize
|
||||||
})
|
})
|
||||||
val db = Database.connect(pool)
|
val db = Database.connect(pool)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package cloud.kubelet.foundation.gjallarhorn.commands
|
package cloud.kubelet.foundation.gjallarhorn.commands
|
||||||
|
|
||||||
import cloud.kubelet.foundation.gjallarhorn.compose
|
import cloud.kubelet.foundation.gjallarhorn.util.compose
|
||||||
import cloud.kubelet.foundation.gjallarhorn.render.*
|
import cloud.kubelet.foundation.gjallarhorn.render.*
|
||||||
import cloud.kubelet.foundation.gjallarhorn.util.RandomColorKey
|
import cloud.kubelet.foundation.gjallarhorn.util.RandomColorKey
|
||||||
import cloud.kubelet.foundation.gjallarhorn.util.savePngFile
|
import cloud.kubelet.foundation.gjallarhorn.util.savePngFile
|
||||||
@ -11,6 +11,7 @@ import com.github.ajalt.clikt.parameters.options.flag
|
|||||||
import com.github.ajalt.clikt.parameters.options.option
|
import com.github.ajalt.clikt.parameters.options.option
|
||||||
import com.github.ajalt.clikt.parameters.options.required
|
import com.github.ajalt.clikt.parameters.options.required
|
||||||
import com.github.ajalt.clikt.parameters.types.enum
|
import com.github.ajalt.clikt.parameters.types.enum
|
||||||
|
import com.github.ajalt.clikt.parameters.types.int
|
||||||
import jetbrains.exodus.kotlin.notNull
|
import jetbrains.exodus.kotlin.notNull
|
||||||
import org.jetbrains.exposed.sql.*
|
import org.jetbrains.exposed.sql.*
|
||||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.lessEq
|
import org.jetbrains.exposed.sql.SqlExpressionBuilder.lessEq
|
||||||
@ -28,10 +29,14 @@ class BlockLogReplay : CliktCommand("Replay Block Logs", name = "replay-block-lo
|
|||||||
private val db by requireObject<Database>()
|
private val db by requireObject<Database>()
|
||||||
private val exactTimeAsString by option("--time", help = "Replay Time")
|
private val exactTimeAsString by option("--time", help = "Replay Time")
|
||||||
private val timelapseMode by option("--timelapse", help = "Timelapse Mode").enum<TimelapseMode> { it.id }
|
private val timelapseMode by option("--timelapse", help = "Timelapse Mode").enum<TimelapseMode> { it.id }
|
||||||
|
private val timelapseIntervalLimit by option("--timelapse-limit", help = "Timelapse Limit Intervals").int()
|
||||||
private val render by option("--render", help = "Render Top Down Image").enum<RenderType> { it.id }.required()
|
private val render by option("--render", help = "Render Top Down Image").enum<RenderType> { it.id }.required()
|
||||||
|
|
||||||
private val considerAirBlocks by option("--consider-air-blocks", help = "Enable Air Block Consideration").flag()
|
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")
|
||||||
|
|
||||||
private val logger = LoggerFactory.getLogger(BlockLogReplay::class.java)
|
private val logger = LoggerFactory.getLogger(BlockLogReplay::class.java)
|
||||||
|
|
||||||
override fun run() {
|
override fun run() {
|
||||||
@ -43,13 +48,17 @@ class BlockLogReplay : CliktCommand("Replay Block Logs", name = "replay-block-lo
|
|||||||
row[minTimeColumn]!! to row[maxTimeColumn]!!
|
row[minTimeColumn]!! to row[maxTimeColumn]!!
|
||||||
}
|
}
|
||||||
|
|
||||||
val intervals = mutableListOf<Instant>()
|
var intervals = mutableListOf<Instant>()
|
||||||
var current = start
|
var current = start
|
||||||
while (!current.isAfter(end)) {
|
while (!current.isAfter(end)) {
|
||||||
intervals.add(current)
|
intervals.add(current)
|
||||||
current = current.plus(timelapseMode!!.interval)
|
current = current.plus(timelapseMode!!.interval)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (timelapseIntervalLimit != null) {
|
||||||
|
intervals = intervals.takeLast(timelapseIntervalLimit!!).toMutableList()
|
||||||
|
}
|
||||||
|
|
||||||
val trackerPool = ScheduledThreadPoolExecutor(8)
|
val trackerPool = ScheduledThreadPoolExecutor(8)
|
||||||
val trackers = ConcurrentHashMap<Int, BlockStateTracker>()
|
val trackers = ConcurrentHashMap<Int, BlockStateTracker>()
|
||||||
for (time in intervals) {
|
for (time in intervals) {
|
||||||
@ -69,14 +78,14 @@ class BlockLogReplay : CliktCommand("Replay Block Logs", name = "replay-block-lo
|
|||||||
logger.info("State Tracking Completed")
|
logger.info("State Tracking Completed")
|
||||||
val allBlockOffsets = trackers.map { it.value.calculateZeroBlockOffset() }
|
val allBlockOffsets = trackers.map { it.value.calculateZeroBlockOffset() }
|
||||||
val globalBlockOffset = BlockPosition.maxOf(allBlockOffsets.asSequence())
|
val globalBlockOffset = BlockPosition.maxOf(allBlockOffsets.asSequence())
|
||||||
val allBlockMaxes = trackers.map { it.value.calculateZeroBlockOffset() }
|
val allBlockMaxes = trackers.map { it.value.calculateMaxBlock() }
|
||||||
val globalBlockMax = BlockPosition.maxOf(allBlockMaxes.asSequence())
|
val globalBlockMax = BlockPosition.maxOf(allBlockMaxes.asSequence())
|
||||||
val globalBlockExpanse = BlockExpanse.offsetAndMax(globalBlockOffset, globalBlockMax)
|
val globalBlockExpanse = BlockExpanse.offsetAndMax(globalBlockOffset, globalBlockMax)
|
||||||
|
|
||||||
logger.info("Calculations Completed")
|
logger.info("Calculations Completed")
|
||||||
|
|
||||||
val renderState = render.createState()
|
val renderState = render.createState()
|
||||||
val renderPool = ScheduledThreadPoolExecutor(8)
|
val renderPool = ScheduledThreadPoolExecutor(16)
|
||||||
for ((i, tracker) in trackers.entries) {
|
for ((i, tracker) in trackers.entries) {
|
||||||
renderPool.submit {
|
renderPool.submit {
|
||||||
val count = trackers.size.toString().length
|
val count = trackers.size.toString().length
|
||||||
@ -139,11 +148,30 @@ class BlockLogReplay : CliktCommand("Replay Block Logs", name = "replay-block-lo
|
|||||||
|
|
||||||
val uniqueBlockPositions = tracker.blocks.size
|
val uniqueBlockPositions = tracker.blocks.size
|
||||||
logger.info("Job $job Unique Block Positions... $uniqueBlockPositions")
|
logger.info("Job $job Unique Block Positions... $uniqueBlockPositions")
|
||||||
|
maybeTrimState(tracker)
|
||||||
return tracker
|
return tracker
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun maybeTrimState(tracker: BlockStateTracker) {
|
||||||
|
if (fromCoordinate == null || toCoordinate == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val from = fromCoordinate!!.split(",").map { it.toLong() }
|
||||||
|
val to = toCoordinate!!.split(",").map { it.toLong() }
|
||||||
|
|
||||||
|
val fromBlock = BlockPosition(from[0], 0, from[1])
|
||||||
|
val toBlock = BlockPosition(to[0], 0, to[1])
|
||||||
|
|
||||||
|
tracker.trimOutsideXAndZRange(fromBlock, toBlock)
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
enum class RenderType(val id: String, val createState: () -> Any, val renderBufferedImage: (Any, BlockStateImage, BlockExpanse) -> BufferedImage) {
|
enum class RenderType(
|
||||||
|
val id: String,
|
||||||
|
val createState: () -> Any,
|
||||||
|
val renderBufferedImage: (Any, BlockStateImage, BlockExpanse) -> BufferedImage
|
||||||
|
) {
|
||||||
TopDown("top-down",
|
TopDown("top-down",
|
||||||
{ TopDownState(RandomColorKey()) },
|
{ TopDownState(RandomColorKey()) },
|
||||||
{ state, image, expanse -> image.buildTopDownImage(expanse, (state as TopDownState).randomColorKey) }),
|
{ state, image, expanse -> image.buildTopDownImage(expanse, (state as TopDownState).randomColorKey) }),
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package cloud.kubelet.foundation.gjallarhorn.commands
|
package cloud.kubelet.foundation.gjallarhorn.commands
|
||||||
|
|
||||||
import cloud.kubelet.foundation.gjallarhorn.compose
|
import cloud.kubelet.foundation.gjallarhorn.util.compose
|
||||||
import cloud.kubelet.foundation.heimdall.table.PlayerPositionTable
|
import cloud.kubelet.foundation.heimdall.table.PlayerPositionTable
|
||||||
import com.github.ajalt.clikt.core.CliktCommand
|
import com.github.ajalt.clikt.core.CliktCommand
|
||||||
import com.github.ajalt.clikt.core.requireObject
|
import com.github.ajalt.clikt.core.requireObject
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package cloud.kubelet.foundation.gjallarhorn.commands
|
package cloud.kubelet.foundation.gjallarhorn.commands
|
||||||
|
|
||||||
import cloud.kubelet.foundation.gjallarhorn.compose
|
import cloud.kubelet.foundation.gjallarhorn.util.compose
|
||||||
import cloud.kubelet.foundation.heimdall.table.PlayerSessionTable
|
import cloud.kubelet.foundation.heimdall.table.PlayerSessionTable
|
||||||
import com.github.ajalt.clikt.core.CliktCommand
|
import com.github.ajalt.clikt.core.CliktCommand
|
||||||
import com.github.ajalt.clikt.core.requireObject
|
import com.github.ajalt.clikt.core.requireObject
|
||||||
|
@ -72,7 +72,8 @@ class BlockStateImage {
|
|||||||
private fun buildPixelQuadImage(expanse: BlockExpanse, callback: BufferedImage.(Long, Long) -> Unit): BufferedImage {
|
private fun buildPixelQuadImage(expanse: BlockExpanse, callback: BufferedImage.(Long, Long) -> Unit): BufferedImage {
|
||||||
val width = expanse.size.x
|
val width = expanse.size.x
|
||||||
val height = expanse.size.z
|
val height = expanse.size.z
|
||||||
val bufferedImage = BufferedImage(width.toInt() * quadImageSize, height.toInt() * quadImageSize, BufferedImage.TYPE_4BYTE_ABGR)
|
val bufferedImage =
|
||||||
|
BufferedImage(width.toInt() * quadImageSize, height.toInt() * quadImageSize, BufferedImage.TYPE_4BYTE_ABGR)
|
||||||
|
|
||||||
for (x in 0 until width) {
|
for (x in 0 until width) {
|
||||||
for (z in 0 until height) {
|
for (z in 0 until height) {
|
||||||
|
@ -17,6 +17,17 @@ class BlockStateTracker(private val mode: BlockTrackMode = BlockTrackMode.Remove
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun trimOutsideXAndZRange(min: BlockPosition, max: BlockPosition) {
|
||||||
|
val blockPositionsToRemove = blocks.keys.filter {
|
||||||
|
it.x < min.x ||
|
||||||
|
it.z < min.z ||
|
||||||
|
it.x > max.x ||
|
||||||
|
it.z > max.z
|
||||||
|
}.toList()
|
||||||
|
|
||||||
|
blockPositionsToRemove.forEach { blocks.remove(it) }
|
||||||
|
}
|
||||||
|
|
||||||
fun calculateZeroBlockOffset(): BlockPosition {
|
fun calculateZeroBlockOffset(): BlockPosition {
|
||||||
val x = blocks.keys.minOf { it.x }
|
val x = blocks.keys.minOf { it.x }
|
||||||
val y = blocks.keys.minOf { it.y }
|
val y = blocks.keys.minOf { it.y }
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
package cloud.kubelet.foundation.gjallarhorn
|
package cloud.kubelet.foundation.gjallarhorn.util
|
||||||
|
|
||||||
import org.jetbrains.exposed.sql.Op
|
import org.jetbrains.exposed.sql.Op
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user