mirror of
https://github.com/GayPizzaSpecifications/foundation.git
synced 2025-10-06 16:09:39 +00:00
Heimdall: It's back!
This commit is contained in:
@ -0,0 +1,30 @@
|
||||
package gay.pizza.foundation.heimdall.tool.render
|
||||
|
||||
import gay.pizza.foundation.heimdall.tool.state.BlockExpanse
|
||||
import gay.pizza.foundation.heimdall.tool.state.BlockStateMap
|
||||
import gay.pizza.foundation.heimdall.tool.state.ChangelogSlice
|
||||
import gay.pizza.foundation.heimdall.tool.util.BlockColorKey
|
||||
import gay.pizza.foundation.heimdall.tool.util.defaultBlockColorMap
|
||||
import java.awt.Color
|
||||
import java.awt.image.BufferedImage
|
||||
|
||||
class BlockDiversityRenderer(val expanse: BlockExpanse, quadPixelSize: Int = defaultQuadPixelSize) :
|
||||
BlockGridRenderer(quadPixelSize) {
|
||||
private val blockColorKey = BlockColorKey(defaultBlockColorMap)
|
||||
|
||||
override fun render(slice: ChangelogSlice, map: BlockStateMap): BufferedImage = buildPixelQuadImage(expanse) { graphics, x, z ->
|
||||
val maybeYBlocks = map.getVerticalSection(x, z)
|
||||
if (maybeYBlocks == null) {
|
||||
setPixelQuad(graphics, x, z, Color.white)
|
||||
return@buildPixelQuadImage
|
||||
}
|
||||
val maxBlockState = maybeYBlocks.maxByOrNull { it.key }?.value
|
||||
if (maxBlockState == null) {
|
||||
setPixelQuad(graphics, x, z, Color.white)
|
||||
return@buildPixelQuadImage
|
||||
}
|
||||
|
||||
val color = blockColorKey.map(maxBlockState.type)
|
||||
setPixelQuad(graphics, x, z, color)
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package gay.pizza.foundation.heimdall.tool.render
|
||||
|
||||
import gay.pizza.foundation.heimdall.tool.state.BlockExpanse
|
||||
import java.awt.Color
|
||||
import java.awt.Graphics2D
|
||||
import java.awt.Rectangle
|
||||
import java.awt.image.BufferedImage
|
||||
|
||||
abstract class BlockGridRenderer(val quadPixelSize: Int = defaultQuadPixelSize) : BlockImageRenderer {
|
||||
protected fun setPixelQuad(graphics: Graphics2D, x: Long, z: Long, color: Color) {
|
||||
if (globalQuadPixelNoop) {
|
||||
return
|
||||
}
|
||||
drawSquare(graphics, x * quadPixelSize, z * quadPixelSize, quadPixelSize.toLong(), color)
|
||||
}
|
||||
|
||||
protected fun drawSquare(graphics: Graphics2D, x: Long, y: Long, side: Long, color: Color) {
|
||||
graphics.color = color
|
||||
graphics.fill(Rectangle(x.toInt(), y.toInt(), side.toInt(), side.toInt()))
|
||||
}
|
||||
|
||||
protected fun buildPixelQuadImage(
|
||||
expanse: BlockExpanse,
|
||||
callback: BufferedImage.(Graphics2D, Long, Long) -> Unit
|
||||
): BufferedImage {
|
||||
val widthInBlocks = expanse.size.x
|
||||
val heightInBlocks = expanse.size.z
|
||||
val widthInPixels = widthInBlocks.toInt() * quadPixelSize
|
||||
val heightInPixels = heightInBlocks.toInt() * quadPixelSize
|
||||
val bufferedImage =
|
||||
BufferedImage(widthInPixels, heightInPixels, BufferedImage.TYPE_3BYTE_BGR)
|
||||
|
||||
val graphics = bufferedImage.createGraphics()
|
||||
for (x in 0 until widthInBlocks) {
|
||||
for (z in 0 until heightInBlocks) {
|
||||
callback(bufferedImage, graphics, x, z)
|
||||
}
|
||||
}
|
||||
graphics.dispose()
|
||||
return bufferedImage
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val defaultQuadPixelSize = 4
|
||||
var globalQuadPixelNoop = false
|
||||
}
|
||||
}
|
@ -0,0 +1,26 @@
|
||||
package gay.pizza.foundation.heimdall.tool.render
|
||||
|
||||
import gay.pizza.foundation.heimdall.tool.state.BlockExpanse
|
||||
import gay.pizza.foundation.heimdall.tool.util.ColorGradient
|
||||
import gay.pizza.foundation.heimdall.tool.util.FloatClamp
|
||||
import java.awt.Color
|
||||
import java.awt.image.BufferedImage
|
||||
|
||||
abstract class BlockHeatMapRenderer(quadPixelSize: Int = defaultQuadPixelSize) : BlockGridRenderer(quadPixelSize) {
|
||||
protected fun buildHeatMapImage(
|
||||
expanse: BlockExpanse,
|
||||
clamp: FloatClamp,
|
||||
calculate: (Long, Long) -> Long?
|
||||
): BufferedImage =
|
||||
buildPixelQuadImage(expanse) { graphics, x, z ->
|
||||
val value = calculate(x, z)
|
||||
val color = if (value != null) {
|
||||
val floatValue = clamp.convert(value)
|
||||
ColorGradient.HeatMap.getColorAtValue(floatValue)
|
||||
} else {
|
||||
Color.white
|
||||
}
|
||||
|
||||
setPixelQuad(graphics, x, z, color)
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package gay.pizza.foundation.heimdall.tool.render
|
||||
|
||||
import gay.pizza.foundation.heimdall.tool.state.BlockExpanse
|
||||
import gay.pizza.foundation.heimdall.tool.state.BlockStateMap
|
||||
import gay.pizza.foundation.heimdall.tool.state.SparseBlockStateMap
|
||||
import gay.pizza.foundation.heimdall.tool.state.ChangelogSlice
|
||||
import gay.pizza.foundation.heimdall.tool.util.FloatClamp
|
||||
import java.awt.image.BufferedImage
|
||||
|
||||
class BlockHeightMapRenderer(val expanse: BlockExpanse, quadPixelSize: Int = defaultQuadPixelSize) :
|
||||
BlockHeatMapRenderer(quadPixelSize) {
|
||||
override fun render(slice: ChangelogSlice, map: BlockStateMap): BufferedImage {
|
||||
val blockMap = map as SparseBlockStateMap
|
||||
val yMin = blockMap.blocks.minOf { xSection -> xSection.value.minOf { zSection -> zSection.value.minOf { it.key } } }
|
||||
val yMax = blockMap.blocks.maxOf { xSection -> xSection.value.maxOf { zSection -> zSection.value.maxOf { it.key } } }
|
||||
val clamp = FloatClamp(yMin, yMax)
|
||||
|
||||
return buildHeatMapImage(expanse, clamp) { x, z -> blockMap.blocks[x]?.get(z)?.maxOf { it.key } }
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
package gay.pizza.foundation.heimdall.tool.render
|
||||
|
||||
import java.awt.image.BufferedImage
|
||||
|
||||
interface BlockImageRenderer : BlockMapRenderer<BufferedImage>
|
@ -0,0 +1,8 @@
|
||||
package gay.pizza.foundation.heimdall.tool.render
|
||||
|
||||
import gay.pizza.foundation.heimdall.tool.state.BlockStateMap
|
||||
import gay.pizza.foundation.heimdall.tool.state.ChangelogSlice
|
||||
|
||||
interface BlockMapRenderer<T> {
|
||||
fun render(slice: ChangelogSlice, map: BlockStateMap): T
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package gay.pizza.foundation.heimdall.tool.render
|
||||
|
||||
import gay.pizza.foundation.heimdall.tool.state.BlockExpanse
|
||||
import gay.pizza.foundation.heimdall.tool.state.BlockStateMap
|
||||
import gay.pizza.foundation.heimdall.tool.state.SparseBlockStateMap
|
||||
import gay.pizza.foundation.heimdall.tool.state.ChangelogSlice
|
||||
import gay.pizza.foundation.heimdall.tool.util.FloatClamp
|
||||
import java.awt.image.BufferedImage
|
||||
|
||||
class BlockVerticalFillMapRenderer(val expanse: BlockExpanse, quadPixelSize: Int = defaultQuadPixelSize) :
|
||||
BlockHeatMapRenderer(quadPixelSize) {
|
||||
override fun render(slice: ChangelogSlice, map: BlockStateMap): BufferedImage {
|
||||
val blockMap = map as SparseBlockStateMap
|
||||
val yMin = blockMap.blocks.minOf { xSection -> xSection.value.minOf { zSection -> zSection.value.size } }
|
||||
val yMax = blockMap.blocks.maxOf { xSection -> xSection.value.maxOf { zSection -> zSection.value.size } }
|
||||
val clamp = FloatClamp(yMin.toLong(), yMax.toLong())
|
||||
|
||||
return buildHeatMapImage(expanse, clamp) { x, z -> blockMap.blocks[x]?.get(z)?.maxOf { it.key } }
|
||||
}
|
||||
}
|
@ -0,0 +1,20 @@
|
||||
package gay.pizza.foundation.heimdall.tool.render
|
||||
|
||||
import gay.pizza.foundation.heimdall.tool.render.ui.GraphicalRenderSession
|
||||
import gay.pizza.foundation.heimdall.tool.state.BlockExpanse
|
||||
import gay.pizza.foundation.heimdall.tool.state.BlockStateMap
|
||||
import gay.pizza.foundation.heimdall.tool.state.ChangelogSlice
|
||||
import java.awt.image.BufferedImage
|
||||
import javax.swing.WindowConstants
|
||||
|
||||
class LaunchGraphicalRenderSession(val expanse: BlockExpanse) : BlockImageRenderer {
|
||||
override fun render(slice: ChangelogSlice, map: BlockStateMap): BufferedImage {
|
||||
val session = GraphicalRenderSession(expanse, map)
|
||||
session.isVisible = true
|
||||
session.defaultCloseOperation = WindowConstants.HIDE_ON_CLOSE
|
||||
while (session.isVisible) {
|
||||
Thread.sleep(1000)
|
||||
}
|
||||
return BufferedImage(1, 1, BufferedImage.TYPE_3BYTE_BGR)
|
||||
}
|
||||
}
|
@ -0,0 +1,56 @@
|
||||
package gay.pizza.foundation.heimdall.tool.render
|
||||
|
||||
import gay.pizza.foundation.heimdall.table.PlayerPositionTable
|
||||
import gay.pizza.foundation.heimdall.tool.state.*
|
||||
import gay.pizza.foundation.heimdall.tool.util.BlockColorKey
|
||||
import org.jetbrains.exposed.sql.Database
|
||||
import org.jetbrains.exposed.sql.and
|
||||
import org.jetbrains.exposed.sql.select
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
import java.awt.Color
|
||||
import java.awt.image.BufferedImage
|
||||
import java.util.*
|
||||
|
||||
class PlayerLocationShareRenderer(
|
||||
val expanse: BlockExpanse,
|
||||
val db: Database,
|
||||
quadPixelSize: Int = defaultQuadPixelSize
|
||||
) : BlockGridRenderer(quadPixelSize) {
|
||||
private val colorKey = BlockColorKey(mapOf())
|
||||
|
||||
override fun render(slice: ChangelogSlice, map: BlockStateMap): BufferedImage {
|
||||
val start = slice.sliceChangeRange.start
|
||||
val end = slice.sliceChangeRange.endInclusive
|
||||
|
||||
val playerSparseMap = BlockCoordinateSparseMap<MutableList<UUID>>()
|
||||
val allPlayerIds = HashSet<UUID>()
|
||||
transaction(db) {
|
||||
gay.pizza.foundation.heimdall.table.PlayerPositionTable.select {
|
||||
(gay.pizza.foundation.heimdall.table.PlayerPositionTable.time greater start) and
|
||||
(gay.pizza.foundation.heimdall.table.PlayerPositionTable.time lessEq end)
|
||||
}.forEach {
|
||||
val x = it[gay.pizza.foundation.heimdall.table.PlayerPositionTable.x].toLong()
|
||||
val y = it[gay.pizza.foundation.heimdall.table.PlayerPositionTable.y].toLong()
|
||||
val z = it[gay.pizza.foundation.heimdall.table.PlayerPositionTable.z].toLong()
|
||||
val coordinate = expanse.offset.applyAsOffset(BlockCoordinate(x, y, z))
|
||||
val player = it[gay.pizza.foundation.heimdall.table.PlayerPositionTable.player]
|
||||
playerSparseMap.createOrModify(
|
||||
coordinate,
|
||||
create = { mutableListOf(player) },
|
||||
modify = { players -> players.add(player) })
|
||||
allPlayerIds.add(player)
|
||||
}
|
||||
}
|
||||
|
||||
val colorOfPlayers = allPlayerIds.associateWith { colorKey.map(it.toString()) }
|
||||
|
||||
return buildPixelQuadImage(expanse) { g, x, z ->
|
||||
val players = playerSparseMap.getVerticalSection(x, z)?.flatMap { it.value }?.distinct()
|
||||
if (players != null) {
|
||||
setPixelQuad(g, x, z, colorOfPlayers[players.first()]!!)
|
||||
} else {
|
||||
setPixelQuad(g, x, z, Color.white)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package gay.pizza.foundation.heimdall.tool.render.ui
|
||||
|
||||
import gay.pizza.foundation.heimdall.tool.render.BlockDiversityRenderer
|
||||
import gay.pizza.foundation.heimdall.tool.render.BlockHeightMapRenderer
|
||||
import gay.pizza.foundation.heimdall.tool.render.BlockVerticalFillMapRenderer
|
||||
import gay.pizza.foundation.heimdall.tool.state.BlockExpanse
|
||||
import gay.pizza.foundation.heimdall.tool.state.BlockStateMap
|
||||
import java.awt.Dimension
|
||||
import javax.swing.JFrame
|
||||
import javax.swing.JTabbedPane
|
||||
|
||||
class GraphicalRenderSession(val expanse: BlockExpanse, val map: BlockStateMap) : JFrame() {
|
||||
init {
|
||||
name = "Gjallarhorn Renderer"
|
||||
size = Dimension(1024, 1024)
|
||||
val pane = JTabbedPane()
|
||||
pane.addTab("Block Diversity", LazyImageRenderer(map, BlockDiversityRenderer(expanse)))
|
||||
pane.addTab("Height Map", LazyImageRenderer(map, BlockHeightMapRenderer(expanse)))
|
||||
pane.addTab("Vertical Fill Map", LazyImageRenderer(map, BlockVerticalFillMapRenderer(expanse)))
|
||||
add(pane)
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
package gay.pizza.foundation.heimdall.tool.render.ui
|
||||
|
||||
import gay.pizza.foundation.heimdall.tool.render.BlockImageRenderer
|
||||
import gay.pizza.foundation.heimdall.tool.state.BlockStateMap
|
||||
import gay.pizza.foundation.heimdall.tool.state.ChangelogSlice
|
||||
import java.awt.Graphics
|
||||
import javax.swing.JComponent
|
||||
|
||||
class LazyImageRenderer(val map: BlockStateMap, private val renderer: BlockImageRenderer) : JComponent() {
|
||||
private val image by lazy {
|
||||
renderer.render(ChangelogSlice.none, map)
|
||||
}
|
||||
|
||||
override fun paint(g: Graphics?) {
|
||||
g?.drawImage(image, 0, 0, this)
|
||||
}
|
||||
|
||||
override fun paintComponent(g: Graphics?) {
|
||||
g?.drawImage(image, 0, 0, this)
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user