mirror of
				https://github.com/GayPizzaSpecifications/foundation.git
				synced 2025-11-04 11:39:39 +00:00 
			
		
		
		
	Gjallarhorn: Timelapse Limiting and Coordinate Cropping
This commit is contained in:
		@ -25,6 +25,7 @@ class GjallarhornCommand : CliktCommand(invokeWithoutSubcommand = true) {
 | 
			
		||||
      jdbcUrl = jdbcConnectionUrl
 | 
			
		||||
      username = jdbcConnectionUsername
 | 
			
		||||
      password = jdbcConnectionPassword
 | 
			
		||||
      minimumIdle = dbPoolSize / 2
 | 
			
		||||
      maximumPoolSize = dbPoolSize
 | 
			
		||||
    })
 | 
			
		||||
    val db = Database.connect(pool)
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
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.util.RandomColorKey
 | 
			
		||||
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.required
 | 
			
		||||
import com.github.ajalt.clikt.parameters.types.enum
 | 
			
		||||
import com.github.ajalt.clikt.parameters.types.int
 | 
			
		||||
import jetbrains.exodus.kotlin.notNull
 | 
			
		||||
import org.jetbrains.exposed.sql.*
 | 
			
		||||
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 exactTimeAsString by option("--time", help = "Replay Time")
 | 
			
		||||
  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 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)
 | 
			
		||||
 | 
			
		||||
  override fun run() {
 | 
			
		||||
@ -43,13 +48,17 @@ class BlockLogReplay : CliktCommand("Replay Block Logs", name = "replay-block-lo
 | 
			
		||||
        row[minTimeColumn]!! to row[maxTimeColumn]!!
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      val intervals = mutableListOf<Instant>()
 | 
			
		||||
      var intervals = mutableListOf<Instant>()
 | 
			
		||||
      var current = start
 | 
			
		||||
      while (!current.isAfter(end)) {
 | 
			
		||||
        intervals.add(current)
 | 
			
		||||
        current = current.plus(timelapseMode!!.interval)
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      if (timelapseIntervalLimit != null) {
 | 
			
		||||
        intervals = intervals.takeLast(timelapseIntervalLimit!!).toMutableList()
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      val trackerPool = ScheduledThreadPoolExecutor(8)
 | 
			
		||||
      val trackers = ConcurrentHashMap<Int, BlockStateTracker>()
 | 
			
		||||
      for (time in intervals) {
 | 
			
		||||
@ -69,14 +78,14 @@ class BlockLogReplay : CliktCommand("Replay Block Logs", name = "replay-block-lo
 | 
			
		||||
      logger.info("State Tracking Completed")
 | 
			
		||||
      val allBlockOffsets = trackers.map { it.value.calculateZeroBlockOffset() }
 | 
			
		||||
      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 globalBlockExpanse = BlockExpanse.offsetAndMax(globalBlockOffset, globalBlockMax)
 | 
			
		||||
 | 
			
		||||
      logger.info("Calculations Completed")
 | 
			
		||||
 | 
			
		||||
      val renderState = render.createState()
 | 
			
		||||
      val renderPool = ScheduledThreadPoolExecutor(8)
 | 
			
		||||
      val renderPool = ScheduledThreadPoolExecutor(16)
 | 
			
		||||
      for ((i, tracker) in trackers.entries) {
 | 
			
		||||
        renderPool.submit {
 | 
			
		||||
          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
 | 
			
		||||
    logger.info("Job $job Unique Block Positions... $uniqueBlockPositions")
 | 
			
		||||
    maybeTrimState(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")
 | 
			
		||||
  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",
 | 
			
		||||
      { TopDownState(RandomColorKey()) },
 | 
			
		||||
      { state, image, expanse -> image.buildTopDownImage(expanse, (state as TopDownState).randomColorKey) }),
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
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 com.github.ajalt.clikt.core.CliktCommand
 | 
			
		||||
import com.github.ajalt.clikt.core.requireObject
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
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 com.github.ajalt.clikt.core.CliktCommand
 | 
			
		||||
import com.github.ajalt.clikt.core.requireObject
 | 
			
		||||
 | 
			
		||||
@ -72,7 +72,8 @@ class BlockStateImage {
 | 
			
		||||
  private fun buildPixelQuadImage(expanse: BlockExpanse, callback: BufferedImage.(Long, Long) -> Unit): BufferedImage {
 | 
			
		||||
    val width = expanse.size.x
 | 
			
		||||
    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 (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 {
 | 
			
		||||
    val x = blocks.keys.minOf { it.x }
 | 
			
		||||
    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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user