mirror of
				https://github.com/GayPizzaSpecifications/foundation.git
				synced 2025-11-04 03:39:37 +00:00 
			
		
		
		
	Gjallarhorn: Implement trimming at the changelog level, resulting in really fast renderings.
This commit is contained in:
		@ -4,7 +4,9 @@ import cloud.kubelet.foundation.gjallarhorn.render.BlockDiversityRenderer
 | 
			
		||||
import cloud.kubelet.foundation.gjallarhorn.render.BlockHeightMapRenderer
 | 
			
		||||
import cloud.kubelet.foundation.gjallarhorn.render.BlockImageRenderer
 | 
			
		||||
import cloud.kubelet.foundation.gjallarhorn.state.*
 | 
			
		||||
import cloud.kubelet.foundation.gjallarhorn.util.compose
 | 
			
		||||
import cloud.kubelet.foundation.gjallarhorn.util.savePngFile
 | 
			
		||||
import cloud.kubelet.foundation.heimdall.view.BlockChangeView
 | 
			
		||||
import com.github.ajalt.clikt.core.CliktCommand
 | 
			
		||||
import com.github.ajalt.clikt.core.requireObject
 | 
			
		||||
import com.github.ajalt.clikt.parameters.options.flag
 | 
			
		||||
@ -13,6 +15,9 @@ 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 org.jetbrains.exposed.sql.Database
 | 
			
		||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.greaterEq
 | 
			
		||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.lessEq
 | 
			
		||||
import org.jetbrains.exposed.sql.and
 | 
			
		||||
import org.slf4j.LoggerFactory
 | 
			
		||||
import java.awt.Color
 | 
			
		||||
import java.awt.Font
 | 
			
		||||
@ -45,8 +50,19 @@ class BlockChangeTimelapseCommand : CliktCommand("Block Change Timelapse", name
 | 
			
		||||
 | 
			
		||||
  override fun run() {
 | 
			
		||||
    val threadPoolExecutor = ScheduledThreadPoolExecutor(16)
 | 
			
		||||
    val changelog = BlockChangelog.query(db)
 | 
			
		||||
    val timelapse = BlockMapTimelapse<BufferedImage>(maybeBuildTrim())
 | 
			
		||||
 | 
			
		||||
    val trim = maybeBuildTrim()
 | 
			
		||||
    val filter = compose(
 | 
			
		||||
      combine = { a, b -> a and b },
 | 
			
		||||
    { trim?.first?.x != null } to { BlockChangeView.x greaterEq trim!!.first.x },
 | 
			
		||||
      { trim?.first?.z != null } to { BlockChangeView.z greaterEq trim!!.first.z },
 | 
			
		||||
      { trim?.second?.x != null } to { BlockChangeView.x lessEq trim!!.second.x },
 | 
			
		||||
      { trim?.second?.z != null } to { BlockChangeView.z lessEq trim!!.second.z }
 | 
			
		||||
    )
 | 
			
		||||
 | 
			
		||||
    val changelog = BlockChangelog.query(db, filter)
 | 
			
		||||
    logger.info("Block Changelog: ${changelog.changes.size} changes")
 | 
			
		||||
    val timelapse = BlockMapTimelapse<BufferedImage>()
 | 
			
		||||
    var slices = timelapse.calculateChangelogSlices(changelog, timelapseMode.interval, timelapseIntervalLimit)
 | 
			
		||||
 | 
			
		||||
    if (timelapseSpeedChangeThreshold != null && timelapseSpeedChangeMinimumIntervalSeconds != null) {
 | 
			
		||||
 | 
			
		||||
@ -17,17 +17,6 @@ class BlockLogTracker(private val mode: BlockTrackMode = BlockTrackMode.RemoveOn
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fun trimOutsideXAndZRange(min: BlockCoordinate, max: BlockCoordinate) {
 | 
			
		||||
    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(): BlockCoordinate {
 | 
			
		||||
    val x = blocks.keys.minOf { it.x }
 | 
			
		||||
    val y = blocks.keys.minOf { it.y }
 | 
			
		||||
@ -48,7 +37,7 @@ class BlockLogTracker(private val mode: BlockTrackMode = BlockTrackMode.RemoveOn
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  fun isEmpty() = blocks.isEmpty()
 | 
			
		||||
  fun isNotEmpty() = blocks.isNotEmpty()
 | 
			
		||||
  fun isNotEmpty() = !isEmpty()
 | 
			
		||||
 | 
			
		||||
  fun buildBlockMap(offset: BlockCoordinate = BlockCoordinate.zero): BlockMap {
 | 
			
		||||
    val map = BlockMap()
 | 
			
		||||
 | 
			
		||||
@ -60,7 +60,6 @@ class BlockMapRenderPool<T>(
 | 
			
		||||
    val sliced = changelog.slice(slice)
 | 
			
		||||
    val tracker = BlockLogTracker(blockTrackMode)
 | 
			
		||||
    tracker.replay(sliced)
 | 
			
		||||
    delegate.postProcessTracker(tracker)
 | 
			
		||||
    if (tracker.isNotEmpty()) {
 | 
			
		||||
      trackers[slice] = tracker
 | 
			
		||||
    }
 | 
			
		||||
@ -70,7 +69,6 @@ class BlockMapRenderPool<T>(
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  interface RenderPoolDelegate<T> {
 | 
			
		||||
    fun postProcessTracker(tracker: BlockLogTracker)
 | 
			
		||||
    fun buildRenderJobs(pool: BlockMapRenderPool<T>, trackers: MutableMap<BlockChangelogSlice, BlockLogTracker>)
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@ import java.time.Duration
 | 
			
		||||
import java.time.Instant
 | 
			
		||||
import java.util.stream.Stream
 | 
			
		||||
 | 
			
		||||
class BlockMapTimelapse<T>(val trim: Pair<BlockCoordinate, BlockCoordinate>? = null) :
 | 
			
		||||
class BlockMapTimelapse<T> :
 | 
			
		||||
  BlockMapRenderPool.RenderPoolDelegate<T> {
 | 
			
		||||
  fun calculateChangelogSlices(
 | 
			
		||||
    changelog: BlockChangelog, interval: Duration, limit: Int? = null
 | 
			
		||||
@ -46,6 +46,10 @@ class BlockMapTimelapse<T>(val trim: Pair<BlockCoordinate, BlockCoordinate>? = n
 | 
			
		||||
    pool: BlockMapRenderPool<T>,
 | 
			
		||||
    trackers: MutableMap<BlockChangelogSlice, BlockLogTracker>
 | 
			
		||||
  ) {
 | 
			
		||||
    if (trackers.isEmpty()) {
 | 
			
		||||
      return
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    val allBlockOffsets = trackers.map { it.value.calculateZeroBlockOffset() }
 | 
			
		||||
    val globalBlockOffset = BlockCoordinate.maxOf(allBlockOffsets)
 | 
			
		||||
    val allBlockMaxes = trackers.map { it.value.calculateMaxBlock() }
 | 
			
		||||
@ -60,10 +64,4 @@ class BlockMapTimelapse<T>(val trim: Pair<BlockCoordinate, BlockCoordinate>? = n
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  override fun postProcessTracker(tracker: BlockLogTracker) {
 | 
			
		||||
    if (trim != null) {
 | 
			
		||||
      tracker.trimOutsideXAndZRange(trim.first, trim.second)
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user