mirror of
				https://github.com/GayPizzaSpecifications/foundation.git
				synced 2025-11-03 19:29:38 +00:00 
			
		
		
		
	More stuff.
This commit is contained in:
		@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					package gay.pizza.foundation.heimdall.load
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import gay.pizza.foundation.heimdall.export.ExportedBlock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ExportedBlockTable {
 | 
				
			||||||
 | 
					  private val internalBlocks = mutableListOf<ExportedBlock>()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  val blocks: List<ExportedBlock>
 | 
				
			||||||
 | 
					    get() = internalBlocks
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  fun index(block: ExportedBlock): Int {
 | 
				
			||||||
 | 
					    val existing = internalBlocks.indexOf(block)
 | 
				
			||||||
 | 
					    if (existing >= 0) {
 | 
				
			||||||
 | 
					      return existing
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    internalBlocks.add(block)
 | 
				
			||||||
 | 
					    return internalBlocks.size - 1
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,69 @@
 | 
				
			|||||||
 | 
					package gay.pizza.foundation.heimdall.load
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import kotlinx.serialization.Serializable
 | 
				
			||||||
 | 
					import kotlin.math.absoluteValue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Serializable
 | 
				
			||||||
 | 
					data class OffsetList<L: List<T>, T>(
 | 
				
			||||||
 | 
					  val offset: Int,
 | 
				
			||||||
 | 
					  val data: L
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					  fun <K> toMap(toKey: (Int) -> K): Map<K, T> {
 | 
				
			||||||
 | 
					    val map = mutableMapOf<K, T>()
 | 
				
			||||||
 | 
					    for ((index, value) in data.withIndex()) {
 | 
				
			||||||
 | 
					      val real = index + offset
 | 
				
			||||||
 | 
					      val key = toKey(real)
 | 
				
			||||||
 | 
					      map[key] = value
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return map
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  fun <R> map(value: (T) -> R): ImmutableOffsetList<R> =
 | 
				
			||||||
 | 
					    ImmutableOffsetList(offset, MutableList(data.size) { index -> value(data[index]) })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  fun eachRealIndex(block: (Int, T) -> Unit) {
 | 
				
			||||||
 | 
					    for ((fakeIndex, value) in data.withIndex()) {
 | 
				
			||||||
 | 
					      val realIndex = fakeIndex + offset
 | 
				
			||||||
 | 
					      block(realIndex, value)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  companion object {
 | 
				
			||||||
 | 
					    fun <K, T, V> transform(
 | 
				
			||||||
 | 
					      map: Map<K, T>,
 | 
				
			||||||
 | 
					      minAndTotal: (Map<K, T>) -> Pair<Int, Int>,
 | 
				
			||||||
 | 
					      keyToInt: (K) -> Int,
 | 
				
			||||||
 | 
					      valueTransform: (T) -> V
 | 
				
			||||||
 | 
					    ): ImmutableOffsetList<V?> {
 | 
				
			||||||
 | 
					      val (min, total) = minAndTotal(map)
 | 
				
			||||||
 | 
					      val offset = if (min < 0) min.absoluteValue else 0
 | 
				
			||||||
 | 
					      val list = MutableList<V?>(total) { null }
 | 
				
			||||||
 | 
					      for ((key, value) in map) {
 | 
				
			||||||
 | 
					        val pkey = keyToInt(key)
 | 
				
			||||||
 | 
					        val rkey = pkey + offset
 | 
				
			||||||
 | 
					          list[rkey] = valueTransform(value)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return OffsetList(if (min < 0) min else 0, list)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					typealias ImmutableOffsetList<T> = OffsetList<List<T>, T>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Serializable
 | 
				
			||||||
 | 
					class WorldLoadCompactWorld(
 | 
				
			||||||
 | 
					  override val name: String,
 | 
				
			||||||
 | 
					  val data: ImmutableOffsetList<ImmutableOffsetList<ImmutableOffsetList<Int?>?>?>
 | 
				
			||||||
 | 
					) : WorldLoadWorld() {
 | 
				
			||||||
 | 
					  override fun crawl(block: (Long, Long, Long, Int) -> Unit) {
 | 
				
			||||||
 | 
					    data.eachRealIndex { x, zList ->
 | 
				
			||||||
 | 
					      zList?.eachRealIndex { z, yList ->
 | 
				
			||||||
 | 
					        yList?.eachRealIndex { y, index ->
 | 
				
			||||||
 | 
					          if (index != null) {
 | 
				
			||||||
 | 
					            block(x.toLong(), z.toLong(), y.toLong(), index)
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,8 +1,10 @@
 | 
				
			|||||||
package gay.pizza.foundation.heimdall.load
 | 
					package gay.pizza.foundation.heimdall.load
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import gay.pizza.foundation.heimdall.export.ExportedBlock
 | 
				
			||||||
import kotlinx.serialization.Serializable
 | 
					import kotlinx.serialization.Serializable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Serializable
 | 
					@Serializable
 | 
				
			||||||
class WorldLoadFormat(
 | 
					class WorldLoadFormat(
 | 
				
			||||||
 | 
					  val blockLookupTable: List<ExportedBlock>,
 | 
				
			||||||
  val worlds: Map<String, WorldLoadWorld>
 | 
					  val worlds: Map<String, WorldLoadWorld>
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,64 @@
 | 
				
			|||||||
 | 
					package gay.pizza.foundation.heimdall.load
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import kotlinx.serialization.Serializable
 | 
				
			||||||
 | 
					import kotlin.math.absoluteValue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@Serializable
 | 
				
			||||||
 | 
					class WorldLoadSimpleWorld(
 | 
				
			||||||
 | 
					  override val name: String,
 | 
				
			||||||
 | 
					  val blocks: Map<Long, Map<Long, Map<Long, Int>>>
 | 
				
			||||||
 | 
					) : WorldLoadWorld() {
 | 
				
			||||||
 | 
					  fun compact(): WorldLoadCompactWorld {
 | 
				
			||||||
 | 
					    val list = OffsetList.transform(
 | 
				
			||||||
 | 
					      blocks,
 | 
				
			||||||
 | 
					      minAndTotal = ::minAndTotal,
 | 
				
			||||||
 | 
					      keyToInt = Long::toInt,
 | 
				
			||||||
 | 
					      valueTransform = { zValue ->
 | 
				
			||||||
 | 
					        OffsetList.transform(
 | 
				
			||||||
 | 
					          zValue,
 | 
				
			||||||
 | 
					          minAndTotal = ::minAndTotal,
 | 
				
			||||||
 | 
					          keyToInt = Long::toInt,
 | 
				
			||||||
 | 
					          valueTransform = { yValue ->
 | 
				
			||||||
 | 
					            OffsetList.transform(
 | 
				
			||||||
 | 
					              yValue,
 | 
				
			||||||
 | 
					              minAndTotal = ::minAndTotal,
 | 
				
			||||||
 | 
					              keyToInt = Long::toInt,
 | 
				
			||||||
 | 
					              valueTransform = { it }
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					      })
 | 
				
			||||||
 | 
					    return WorldLoadCompactWorld(name, list)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private fun <T> minAndTotal(map: Map<Long, T>): Pair<Int, Int> {
 | 
				
			||||||
 | 
					    val keys = map.keys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (keys.isEmpty()) {
 | 
				
			||||||
 | 
					      return 0 to 0
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    val min = keys.min()
 | 
				
			||||||
 | 
					    val max = keys.max()
 | 
				
			||||||
 | 
					    var total = 1L
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (max > 0) {
 | 
				
			||||||
 | 
					      total += max
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    if (min < 0) {
 | 
				
			||||||
 | 
					      total += min.absoluteValue
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    return min.toInt() to total.toInt()
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  override fun crawl(block: (Long, Long, Long, Int) -> Unit) {
 | 
				
			||||||
 | 
					    for ((x, zBlocks) in blocks) {
 | 
				
			||||||
 | 
					      for ((z, yBlocks) in zBlocks) {
 | 
				
			||||||
 | 
					        for ((y, index) in yBlocks) {
 | 
				
			||||||
 | 
					          block(x, z, y, index)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -1,10 +1,10 @@
 | 
				
			|||||||
package gay.pizza.foundation.heimdall.load
 | 
					package gay.pizza.foundation.heimdall.load
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import gay.pizza.foundation.heimdall.export.ExportedBlock
 | 
					 | 
				
			||||||
import kotlinx.serialization.Serializable
 | 
					import kotlinx.serialization.Serializable
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@Serializable
 | 
					@Serializable
 | 
				
			||||||
class WorldLoadWorld(
 | 
					sealed class WorldLoadWorld {
 | 
				
			||||||
  val name: String,
 | 
					  abstract val name: String
 | 
				
			||||||
  val blocks: Map<Long, Map<Long, Map<Long, ExportedBlock>>>
 | 
					
 | 
				
			||||||
)
 | 
					  abstract fun crawl(block: (Long, Long, Long, Int) -> Unit)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,21 @@
 | 
				
			|||||||
 | 
					package gay.pizza.foundation.common
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.bukkit.command.CommandExecutor
 | 
				
			||||||
 | 
					import org.bukkit.command.TabCompleter
 | 
				
			||||||
 | 
					import org.bukkit.plugin.java.JavaPlugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					abstract class BaseFoundationPlugin : JavaPlugin() {
 | 
				
			||||||
 | 
					  fun registerCommandExecutor(name: String, executor: CommandExecutor) {
 | 
				
			||||||
 | 
					    registerCommandExecutor(listOf(name), executor)
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  fun registerCommandExecutor(names: List<String>, executor: CommandExecutor) {
 | 
				
			||||||
 | 
					    for (name in names) {
 | 
				
			||||||
 | 
					      val command = getCommand(name) ?: throw Exception("Failed to get $name command")
 | 
				
			||||||
 | 
					      command.setExecutor(executor)
 | 
				
			||||||
 | 
					      if (executor is TabCompleter) {
 | 
				
			||||||
 | 
					        command.tabCompleter = executor
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -2,6 +2,7 @@ package gay.pizza.foundation.bifrost
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import com.charleskorn.kaml.Yaml
 | 
					import com.charleskorn.kaml.Yaml
 | 
				
			||||||
import gay.pizza.foundation.bifrost.model.BifrostConfig
 | 
					import gay.pizza.foundation.bifrost.model.BifrostConfig
 | 
				
			||||||
 | 
					import gay.pizza.foundation.common.BaseFoundationPlugin
 | 
				
			||||||
import gay.pizza.foundation.common.FoundationCoreLoader
 | 
					import gay.pizza.foundation.common.FoundationCoreLoader
 | 
				
			||||||
import gay.pizza.foundation.shared.*
 | 
					import gay.pizza.foundation.shared.*
 | 
				
			||||||
import io.papermc.paper.event.player.AsyncChatEvent
 | 
					import io.papermc.paper.event.player.AsyncChatEvent
 | 
				
			||||||
@ -22,14 +23,13 @@ import org.bukkit.event.entity.PlayerDeathEvent
 | 
				
			|||||||
import org.bukkit.event.player.PlayerAdvancementDoneEvent
 | 
					import org.bukkit.event.player.PlayerAdvancementDoneEvent
 | 
				
			||||||
import org.bukkit.event.player.PlayerJoinEvent
 | 
					import org.bukkit.event.player.PlayerJoinEvent
 | 
				
			||||||
import org.bukkit.event.player.PlayerQuitEvent
 | 
					import org.bukkit.event.player.PlayerQuitEvent
 | 
				
			||||||
import org.bukkit.plugin.java.JavaPlugin
 | 
					 | 
				
			||||||
import java.awt.Color
 | 
					import java.awt.Color
 | 
				
			||||||
import kotlin.io.path.inputStream
 | 
					import kotlin.io.path.inputStream
 | 
				
			||||||
import net.dv8tion.jda.api.hooks.EventListener as DiscordEventListener
 | 
					import net.dv8tion.jda.api.hooks.EventListener as DiscordEventListener
 | 
				
			||||||
import org.bukkit.event.Listener as BukkitEventListener
 | 
					import org.bukkit.event.Listener as BukkitEventListener
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@PluginMainClass
 | 
					@PluginMainClass
 | 
				
			||||||
class FoundationBifrostPlugin : JavaPlugin(), DiscordEventListener, BukkitEventListener {
 | 
					class FoundationBifrostPlugin : BaseFoundationPlugin(), DiscordEventListener, BukkitEventListener {
 | 
				
			||||||
  private lateinit var config: BifrostConfig
 | 
					  private lateinit var config: BifrostConfig
 | 
				
			||||||
  private var jda: JDA? = null
 | 
					  private var jda: JDA? = null
 | 
				
			||||||
  private var isDev = false
 | 
					  private var isDev = false
 | 
				
			||||||
 | 
				
			|||||||
@ -2,14 +2,14 @@ package gay.pizza.foundation.chaos
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import com.charleskorn.kaml.Yaml
 | 
					import com.charleskorn.kaml.Yaml
 | 
				
			||||||
import gay.pizza.foundation.chaos.model.ChaosConfig
 | 
					import gay.pizza.foundation.chaos.model.ChaosConfig
 | 
				
			||||||
 | 
					import gay.pizza.foundation.common.BaseFoundationPlugin
 | 
				
			||||||
import gay.pizza.foundation.common.FoundationCoreLoader
 | 
					import gay.pizza.foundation.common.FoundationCoreLoader
 | 
				
			||||||
import gay.pizza.foundation.shared.PluginMainClass
 | 
					import gay.pizza.foundation.shared.PluginMainClass
 | 
				
			||||||
import gay.pizza.foundation.shared.copyDefaultConfig
 | 
					import gay.pizza.foundation.shared.copyDefaultConfig
 | 
				
			||||||
import org.bukkit.plugin.java.JavaPlugin
 | 
					 | 
				
			||||||
import kotlin.io.path.inputStream
 | 
					import kotlin.io.path.inputStream
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@PluginMainClass
 | 
					@PluginMainClass
 | 
				
			||||||
class FoundationChaosPlugin : JavaPlugin() {
 | 
					class FoundationChaosPlugin : BaseFoundationPlugin() {
 | 
				
			||||||
  lateinit var config: ChaosConfig
 | 
					  lateinit var config: ChaosConfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  val controller by lazy {
 | 
					  val controller by lazy {
 | 
				
			||||||
@ -24,7 +24,6 @@ class FoundationChaosPlugin : JavaPlugin() {
 | 
				
			|||||||
      "chaos.yaml"
 | 
					      "chaos.yaml"
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    config = Yaml.default.decodeFromStream(ChaosConfig.serializer(), configPath.inputStream())
 | 
					    config = Yaml.default.decodeFromStream(ChaosConfig.serializer(), configPath.inputStream())
 | 
				
			||||||
    val chaosCommand = getCommand("chaos")!!
 | 
					    registerCommandExecutor("chaos", ChaosToggleCommand())
 | 
				
			||||||
    chaosCommand.setExecutor(ChaosToggleCommand())
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -8,6 +8,7 @@ object ChaosModules {
 | 
				
			|||||||
    TeleportAllEntitiesNearestPlayer(plugin),
 | 
					    TeleportAllEntitiesNearestPlayer(plugin),
 | 
				
			||||||
    KillRandomPlayer(plugin),
 | 
					    KillRandomPlayer(plugin),
 | 
				
			||||||
    TntAllPlayers(plugin),
 | 
					    TntAllPlayers(plugin),
 | 
				
			||||||
    MegaTnt(plugin)
 | 
					    MegaTnt(plugin),
 | 
				
			||||||
  )
 | 
					    PlayerSwap(plugin)
 | 
				
			||||||
 | 
					  ).shuffled()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,30 @@
 | 
				
			|||||||
 | 
					package gay.pizza.foundation.chaos.modules
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.bukkit.Location
 | 
				
			||||||
 | 
					import org.bukkit.entity.Player
 | 
				
			||||||
 | 
					import org.bukkit.plugin.Plugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class PlayerSwap(val plugin: Plugin) : ChaosModule {
 | 
				
			||||||
 | 
					  override fun id(): String = "player-swap"
 | 
				
			||||||
 | 
					  override fun name(): String = "Player Swap"
 | 
				
			||||||
 | 
					  override fun what(): String = "Randomly swaps player positions."
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  override fun activate() {
 | 
				
			||||||
 | 
					    for (world in plugin.server.worlds) {
 | 
				
			||||||
 | 
					      if (world.playerCount <= 0) {
 | 
				
			||||||
 | 
					        continue
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      val players = world.players
 | 
				
			||||||
 | 
					      val map = mutableMapOf<Player, Location>()
 | 
				
			||||||
 | 
					      for (player in players) {
 | 
				
			||||||
 | 
					        val next = players.filter { it != player }.randomOrNull() ?: continue
 | 
				
			||||||
 | 
					        map[player] = next.location.clone()
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      for ((player, next) in map) {
 | 
				
			||||||
 | 
					        player.teleport(next)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -4,6 +4,7 @@ plugins {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
dependencies {
 | 
					dependencies {
 | 
				
			||||||
  api(project(":common-all"))
 | 
					  api(project(":common-all"))
 | 
				
			||||||
 | 
					  api(project(":common-plugin"))
 | 
				
			||||||
  implementation(project(":foundation-shared"))
 | 
					  implementation(project(":foundation-shared"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  implementation(libs.aws.sdk.s3)
 | 
					  implementation(libs.aws.sdk.s3)
 | 
				
			||||||
 | 
				
			|||||||
@ -1,8 +1,6 @@
 | 
				
			|||||||
package gay.pizza.foundation.core.abstraction
 | 
					package gay.pizza.foundation.core.abstraction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import gay.pizza.foundation.core.FoundationCorePlugin
 | 
					import gay.pizza.foundation.core.FoundationCorePlugin
 | 
				
			||||||
import org.bukkit.command.CommandExecutor
 | 
					 | 
				
			||||||
import org.bukkit.command.TabCompleter
 | 
					 | 
				
			||||||
import org.bukkit.event.Listener
 | 
					import org.bukkit.event.Listener
 | 
				
			||||||
import org.koin.core.component.KoinComponent
 | 
					import org.koin.core.component.KoinComponent
 | 
				
			||||||
import org.koin.core.component.inject
 | 
					import org.koin.core.component.inject
 | 
				
			||||||
@ -16,18 +14,4 @@ abstract class Feature : CoreFeature, KoinComponent, Listener {
 | 
				
			|||||||
  override fun enable() {}
 | 
					  override fun enable() {}
 | 
				
			||||||
  override fun disable() {}
 | 
					  override fun disable() {}
 | 
				
			||||||
  override fun module() = module {}
 | 
					  override fun module() = module {}
 | 
				
			||||||
 | 
					 | 
				
			||||||
  protected fun registerCommandExecutor(name: String, executor: CommandExecutor) {
 | 
					 | 
				
			||||||
    registerCommandExecutor(listOf(name), executor)
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  protected fun registerCommandExecutor(names: List<String>, executor: CommandExecutor) {
 | 
					 | 
				
			||||||
    for (name in names) {
 | 
					 | 
				
			||||||
      val command = plugin.getCommand(name) ?: throw Exception("Failed to get $name command")
 | 
					 | 
				
			||||||
      command.setExecutor(executor)
 | 
					 | 
				
			||||||
      if (executor is TabCompleter) {
 | 
					 | 
				
			||||||
        command.tabCompleter = executor
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,13 +1,13 @@
 | 
				
			|||||||
package gay.pizza.foundation.core.abstraction
 | 
					package gay.pizza.foundation.core.abstraction
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import org.bukkit.plugin.java.JavaPlugin
 | 
					import gay.pizza.foundation.common.BaseFoundationPlugin
 | 
				
			||||||
import org.koin.core.KoinApplication
 | 
					import org.koin.core.KoinApplication
 | 
				
			||||||
import org.koin.core.context.startKoin
 | 
					import org.koin.core.context.startKoin
 | 
				
			||||||
import org.koin.core.context.stopKoin
 | 
					import org.koin.core.context.stopKoin
 | 
				
			||||||
import org.koin.core.module.Module
 | 
					import org.koin.core.module.Module
 | 
				
			||||||
import org.koin.dsl.module
 | 
					import org.koin.dsl.module
 | 
				
			||||||
 | 
					
 | 
				
			||||||
abstract class FoundationPlugin : JavaPlugin() {
 | 
					abstract class FoundationPlugin : BaseFoundationPlugin() {
 | 
				
			||||||
  private lateinit var pluginModule: Module
 | 
					  private lateinit var pluginModule: Module
 | 
				
			||||||
  private lateinit var pluginApplication: KoinApplication
 | 
					  private lateinit var pluginApplication: KoinApplication
 | 
				
			||||||
  private lateinit var features: List<CoreFeature>
 | 
					  private lateinit var features: List<CoreFeature>
 | 
				
			||||||
 | 
				
			|||||||
@ -1,11 +1,11 @@
 | 
				
			|||||||
package gay.pizza.foundation.core.features.backup
 | 
					package gay.pizza.foundation.core.features.backup
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import com.charleskorn.kaml.Yaml
 | 
					import com.charleskorn.kaml.Yaml
 | 
				
			||||||
import gay.pizza.foundation.shared.copyDefaultConfig
 | 
					 | 
				
			||||||
import gay.pizza.foundation.core.FoundationCorePlugin
 | 
					import gay.pizza.foundation.core.FoundationCorePlugin
 | 
				
			||||||
import gay.pizza.foundation.core.abstraction.Feature
 | 
					import gay.pizza.foundation.core.abstraction.Feature
 | 
				
			||||||
import gay.pizza.foundation.core.features.scheduler.cancel
 | 
					import gay.pizza.foundation.core.features.scheduler.cancel
 | 
				
			||||||
import gay.pizza.foundation.core.features.scheduler.cron
 | 
					import gay.pizza.foundation.core.features.scheduler.cron
 | 
				
			||||||
 | 
					import gay.pizza.foundation.shared.copyDefaultConfig
 | 
				
			||||||
import org.koin.core.component.inject
 | 
					import org.koin.core.component.inject
 | 
				
			||||||
import org.koin.dsl.module
 | 
					import org.koin.dsl.module
 | 
				
			||||||
import software.amazon.awssdk.auth.credentials.AwsSessionCredentials
 | 
					import software.amazon.awssdk.auth.credentials.AwsSessionCredentials
 | 
				
			||||||
@ -25,7 +25,7 @@ class BackupFeature : Feature() {
 | 
				
			|||||||
    val backupPath = plugin.pluginDataPath.resolve(BACKUPS_DIRECTORY)
 | 
					    val backupPath = plugin.pluginDataPath.resolve(BACKUPS_DIRECTORY)
 | 
				
			||||||
    backupPath.toFile().mkdir()
 | 
					    backupPath.toFile().mkdir()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    registerCommandExecutor("fbackup", BackupCommand(plugin, backupPath, config, s3Client))
 | 
					    plugin.registerCommandExecutor("fbackup", BackupCommand(plugin, backupPath, config, s3Client))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (config.schedule.cron.isNotEmpty()) {
 | 
					    if (config.schedule.cron.isNotEmpty()) {
 | 
				
			||||||
      // Assume the user never wants to modify the second. I'm not sure why this is enforced in Quartz.
 | 
					      // Assume the user never wants to modify the second. I'm not sure why this is enforced in Quartz.
 | 
				
			||||||
 | 
				
			|||||||
@ -4,9 +4,9 @@ import com.charleskorn.kaml.Yaml
 | 
				
			|||||||
import com.google.common.cache.Cache
 | 
					import com.google.common.cache.Cache
 | 
				
			||||||
import com.google.common.cache.CacheBuilder
 | 
					import com.google.common.cache.CacheBuilder
 | 
				
			||||||
import com.google.common.cache.RemovalCause
 | 
					import com.google.common.cache.RemovalCause
 | 
				
			||||||
import gay.pizza.foundation.shared.copyDefaultConfig
 | 
					 | 
				
			||||||
import gay.pizza.foundation.core.FoundationCorePlugin
 | 
					import gay.pizza.foundation.core.FoundationCorePlugin
 | 
				
			||||||
import gay.pizza.foundation.core.abstraction.Feature
 | 
					import gay.pizza.foundation.core.abstraction.Feature
 | 
				
			||||||
 | 
					import gay.pizza.foundation.shared.copyDefaultConfig
 | 
				
			||||||
import net.kyori.adventure.text.Component
 | 
					import net.kyori.adventure.text.Component
 | 
				
			||||||
import org.bukkit.GameMode
 | 
					import org.bukkit.GameMode
 | 
				
			||||||
import org.bukkit.event.EventHandler
 | 
					import org.bukkit.event.EventHandler
 | 
				
			||||||
@ -42,13 +42,13 @@ class PlayerFeature : Feature() {
 | 
				
			|||||||
      playerActivity.cleanUp()
 | 
					      playerActivity.cleanUp()
 | 
				
			||||||
    }, 20, 100)
 | 
					    }, 20, 100)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    registerCommandExecutor(listOf("survival", "s"), GamemodeCommand(GameMode.SURVIVAL))
 | 
					    plugin.registerCommandExecutor(listOf("survival", "s"), GamemodeCommand(GameMode.SURVIVAL))
 | 
				
			||||||
    registerCommandExecutor(listOf("creative", "c"), GamemodeCommand(GameMode.CREATIVE))
 | 
					    plugin.registerCommandExecutor(listOf("creative", "c"), GamemodeCommand(GameMode.CREATIVE))
 | 
				
			||||||
    registerCommandExecutor(listOf("adventure", "a"), GamemodeCommand(GameMode.ADVENTURE))
 | 
					    plugin.registerCommandExecutor(listOf("adventure", "a"), GamemodeCommand(GameMode.ADVENTURE))
 | 
				
			||||||
    registerCommandExecutor(listOf("spectator", "sp"), GamemodeCommand(GameMode.SPECTATOR))
 | 
					    plugin.registerCommandExecutor(listOf("spectator", "sp"), GamemodeCommand(GameMode.SPECTATOR))
 | 
				
			||||||
    registerCommandExecutor(listOf("localweather", "lw"), LocalWeatherCommand())
 | 
					    plugin.registerCommandExecutor(listOf("localweather", "lw"), LocalWeatherCommand())
 | 
				
			||||||
    registerCommandExecutor(listOf("goose", "the_most_wonderful_kitty_ever"), GooseCommand())
 | 
					    plugin.registerCommandExecutor(listOf("goose", "the_most_wonderful_kitty_ever"), GooseCommand())
 | 
				
			||||||
    registerCommandExecutor(listOf("megatnt"), MegaTntCommand())
 | 
					    plugin.registerCommandExecutor(listOf("megatnt"), MegaTntCommand())
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  override fun module() = org.koin.dsl.module {
 | 
					  override fun module() = org.koin.dsl.module {
 | 
				
			||||||
 | 
				
			|||||||
@ -19,8 +19,8 @@ class StatsFeature : Feature() {
 | 
				
			|||||||
  override fun enable() {
 | 
					  override fun enable() {
 | 
				
			||||||
    chatLogStore = persistence.value.store("chat-logs")
 | 
					    chatLogStore = persistence.value.store("chat-logs")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    registerCommandExecutor(listOf("leaderboard", "lb"), LeaderboardCommand())
 | 
					    plugin.registerCommandExecutor(listOf("leaderboard", "lb"), LeaderboardCommand())
 | 
				
			||||||
    registerCommandExecutor("pstore", PersistentStoreCommand(this))
 | 
					    plugin.registerCommandExecutor("pstore", PersistentStoreCommand(this))
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  @EventHandler
 | 
					  @EventHandler
 | 
				
			||||||
 | 
				
			|||||||
@ -4,6 +4,6 @@ import gay.pizza.foundation.core.abstraction.Feature
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class UpdateFeature : Feature() {
 | 
					class UpdateFeature : Feature() {
 | 
				
			||||||
  override fun enable() {
 | 
					  override fun enable() {
 | 
				
			||||||
    registerCommandExecutor("fupdate", UpdateCommand())
 | 
					    plugin.registerCommandExecutor("fupdate", UpdateCommand())
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -4,7 +4,7 @@ import gay.pizza.foundation.core.abstraction.Feature
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
class WorldFeature : Feature() {
 | 
					class WorldFeature : Feature() {
 | 
				
			||||||
  override fun enable() {
 | 
					  override fun enable() {
 | 
				
			||||||
    registerCommandExecutor("setspawn", SetSpawnCommand())
 | 
					    plugin.registerCommandExecutor("setspawn", SetSpawnCommand())
 | 
				
			||||||
    registerCommandExecutor("spawn", SpawnCommand())
 | 
					    plugin.registerCommandExecutor("spawn", SpawnCommand())
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -3,6 +3,7 @@ package gay.pizza.foundation.heimdall.plugin
 | 
				
			|||||||
import com.charleskorn.kaml.Yaml
 | 
					import com.charleskorn.kaml.Yaml
 | 
				
			||||||
import com.zaxxer.hikari.HikariConfig
 | 
					import com.zaxxer.hikari.HikariConfig
 | 
				
			||||||
import com.zaxxer.hikari.HikariDataSource
 | 
					import com.zaxxer.hikari.HikariDataSource
 | 
				
			||||||
 | 
					import gay.pizza.foundation.common.BaseFoundationPlugin
 | 
				
			||||||
import gay.pizza.foundation.common.FoundationCoreLoader
 | 
					import gay.pizza.foundation.common.FoundationCoreLoader
 | 
				
			||||||
import gay.pizza.foundation.heimdall.plugin.buffer.BufferFlushThread
 | 
					import gay.pizza.foundation.heimdall.plugin.buffer.BufferFlushThread
 | 
				
			||||||
import gay.pizza.foundation.heimdall.plugin.buffer.EventBuffer
 | 
					import gay.pizza.foundation.heimdall.plugin.buffer.EventBuffer
 | 
				
			||||||
@ -14,14 +15,13 @@ import gay.pizza.foundation.heimdall.plugin.model.HeimdallConfig
 | 
				
			|||||||
import gay.pizza.foundation.shared.PluginMainClass
 | 
					import gay.pizza.foundation.shared.PluginMainClass
 | 
				
			||||||
import gay.pizza.foundation.shared.copyDefaultConfig
 | 
					import gay.pizza.foundation.shared.copyDefaultConfig
 | 
				
			||||||
import org.bukkit.event.Listener
 | 
					import org.bukkit.event.Listener
 | 
				
			||||||
import org.bukkit.plugin.java.JavaPlugin
 | 
					 | 
				
			||||||
import org.jetbrains.exposed.sql.Database
 | 
					import org.jetbrains.exposed.sql.Database
 | 
				
			||||||
import org.postgresql.Driver
 | 
					import org.postgresql.Driver
 | 
				
			||||||
import java.time.Duration
 | 
					import java.time.Duration
 | 
				
			||||||
import kotlin.io.path.inputStream
 | 
					import kotlin.io.path.inputStream
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@PluginMainClass
 | 
					@PluginMainClass
 | 
				
			||||||
class FoundationHeimdallPlugin : JavaPlugin(), Listener {
 | 
					class FoundationHeimdallPlugin : BaseFoundationPlugin(), Listener {
 | 
				
			||||||
  private lateinit var config: HeimdallConfig
 | 
					  private lateinit var config: HeimdallConfig
 | 
				
			||||||
  private lateinit var pool: HikariDataSource
 | 
					  private lateinit var pool: HikariDataSource
 | 
				
			||||||
  internal var db: Database? = null
 | 
					  internal var db: Database? = null
 | 
				
			||||||
@ -36,6 +36,10 @@ class FoundationHeimdallPlugin : JavaPlugin(), Listener {
 | 
				
			|||||||
      throw Exception("Failed to get export_all_chunks command")
 | 
					      throw Exception("Failed to get export_all_chunks command")
 | 
				
			||||||
    exportChunksCommand.setExecutor(ExportAllChunksCommand(this))
 | 
					    exportChunksCommand.setExecutor(ExportAllChunksCommand(this))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    registerCommandExecutor("export_all_chunks", ExportAllChunksCommand(this))
 | 
				
			||||||
 | 
					    registerCommandExecutor("export_world_load", ExportAllChunksCommand(this))
 | 
				
			||||||
 | 
					    registerCommandExecutor("import_world_load", ExportAllChunksCommand(this))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    val importWorldLoadCommand = getCommand("import_world_load") ?:
 | 
					    val importWorldLoadCommand = getCommand("import_world_load") ?:
 | 
				
			||||||
      throw Exception("Failed to get import_world_load command")
 | 
					      throw Exception("Failed to get import_world_load command")
 | 
				
			||||||
    importWorldLoadCommand.setExecutor(ImportWorldLoadCommand(this))
 | 
					    importWorldLoadCommand.setExecutor(ImportWorldLoadCommand(this))
 | 
				
			||||||
 | 
				
			|||||||
@ -13,10 +13,6 @@ import java.io.File
 | 
				
			|||||||
import java.util.zip.GZIPOutputStream
 | 
					import java.util.zip.GZIPOutputStream
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class ChunkExporter(private val plugin: Plugin) {
 | 
					class ChunkExporter(private val plugin: Plugin) {
 | 
				
			||||||
  private val json = Json {
 | 
					 | 
				
			||||||
    ignoreUnknownKeys = true
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  fun exportLoadedChunksAsync(world: World) {
 | 
					  fun exportLoadedChunksAsync(world: World) {
 | 
				
			||||||
    exportChunkListAsync(world, world.loadedChunks.toList())
 | 
					    exportChunkListAsync(world, world.loadedChunks.toList())
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
@ -56,7 +52,7 @@ class ChunkExporter(private val plugin: Plugin) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    val fileOutputStream = file.outputStream()
 | 
					    val fileOutputStream = file.outputStream()
 | 
				
			||||||
    val gzipOutputStream = GZIPOutputStream(fileOutputStream)
 | 
					    val gzipOutputStream = GZIPOutputStream(fileOutputStream)
 | 
				
			||||||
    json.encodeToStream(ExportedChunk.serializer(), chunk, gzipOutputStream)
 | 
					    Json.encodeToStream(ExportedChunk.serializer(), chunk, gzipOutputStream)
 | 
				
			||||||
    gzipOutputStream.close()
 | 
					    gzipOutputStream.close()
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -0,0 +1,26 @@
 | 
				
			|||||||
 | 
					package gay.pizza.foundation.heimdall.plugin.export
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import org.bukkit.command.Command
 | 
				
			||||||
 | 
					import org.bukkit.command.CommandExecutor
 | 
				
			||||||
 | 
					import org.bukkit.command.CommandSender
 | 
				
			||||||
 | 
					import org.bukkit.plugin.Plugin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class ExportWorldLoadCommand(private val plugin: Plugin) : CommandExecutor {
 | 
				
			||||||
 | 
					  override fun onCommand(
 | 
				
			||||||
 | 
					    sender: CommandSender,
 | 
				
			||||||
 | 
					    command: Command,
 | 
				
			||||||
 | 
					    label: String,
 | 
				
			||||||
 | 
					    args: Array<out String>
 | 
				
			||||||
 | 
					  ): Boolean {
 | 
				
			||||||
 | 
					    sender.sendMessage("Exporting all worlds...")
 | 
				
			||||||
 | 
					    plugin.slF4JLogger.info("Exporting all worlds")
 | 
				
			||||||
 | 
					    val export = WorldLoadExporter()
 | 
				
			||||||
 | 
					    for (world in sender.server.worlds) {
 | 
				
			||||||
 | 
					      export.exportLoadedChunks(world)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    export.save()
 | 
				
			||||||
 | 
					    sender.sendMessage("Exported all worlds...")
 | 
				
			||||||
 | 
					    plugin.slF4JLogger.info("Exported all worlds")
 | 
				
			||||||
 | 
					    return true
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -0,0 +1,48 @@
 | 
				
			|||||||
 | 
					package gay.pizza.foundation.heimdall.plugin.export
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import gay.pizza.foundation.heimdall.export.ExportedBlock
 | 
				
			||||||
 | 
					import gay.pizza.foundation.heimdall.load.ExportedBlockTable
 | 
				
			||||||
 | 
					import gay.pizza.foundation.heimdall.load.WorldLoadFormat
 | 
				
			||||||
 | 
					import gay.pizza.foundation.heimdall.load.WorldLoadSimpleWorld
 | 
				
			||||||
 | 
					import gay.pizza.foundation.heimdall.load.WorldLoadWorld
 | 
				
			||||||
 | 
					import kotlinx.serialization.json.Json
 | 
				
			||||||
 | 
					import kotlinx.serialization.json.encodeToStream
 | 
				
			||||||
 | 
					import org.bukkit.World
 | 
				
			||||||
 | 
					import java.nio.file.Paths
 | 
				
			||||||
 | 
					import kotlin.io.path.outputStream
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class WorldLoadExporter {
 | 
				
			||||||
 | 
					  private val blockTable = ExportedBlockTable()
 | 
				
			||||||
 | 
					  private val worlds = mutableMapOf<String, WorldLoadWorld>()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  fun exportLoadedChunks(world: World) {
 | 
				
			||||||
 | 
					    val data = mutableMapOf<Long, MutableMap<Long, MutableMap<Long, Int>>>()
 | 
				
			||||||
 | 
					    for (chunk in world.loadedChunks) {
 | 
				
			||||||
 | 
					      val snapshot = chunk.chunkSnapshot
 | 
				
			||||||
 | 
					      val yRange = world.minHeight until world.maxHeight
 | 
				
			||||||
 | 
					      val chunkRange = 0..15
 | 
				
			||||||
 | 
					      for (x in chunkRange) {
 | 
				
			||||||
 | 
					        for (z in chunkRange) {
 | 
				
			||||||
 | 
					          for (y in yRange) {
 | 
				
			||||||
 | 
					            val blockInfo = snapshot.getBlockData(x, y, z)
 | 
				
			||||||
 | 
					            val block = ExportedBlock(blockInfo.material.key.toString(), blockInfo.asString)
 | 
				
			||||||
 | 
					            data.getOrPut(x.toLong()) {
 | 
				
			||||||
 | 
					              mutableMapOf()
 | 
				
			||||||
 | 
					            }.getOrPut(z.toLong()) {
 | 
				
			||||||
 | 
					              mutableMapOf()
 | 
				
			||||||
 | 
					            }[y.toLong()] = blockTable.index(block)
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    worlds[world.name] = WorldLoadSimpleWorld(world.name, data).compact()
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  fun save() {
 | 
				
			||||||
 | 
					    val format = WorldLoadFormat(blockTable.blocks, worlds)
 | 
				
			||||||
 | 
					    val path = Paths.get("world.load.json")
 | 
				
			||||||
 | 
					    path.outputStream().use { stream ->
 | 
				
			||||||
 | 
					      Json.encodeToStream(WorldLoadFormat.serializer(), format, stream)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@ -27,20 +27,18 @@ class WorldReassembler(val plugin: Plugin, val server: Server, val format: World
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        val blocksToMake = mutableListOf<Pair<Location, ExportedBlock>>()
 | 
					        val blocksToMake = mutableListOf<Pair<Location, ExportedBlock>>()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for ((x, zBlocks) in load.blocks) {
 | 
					        load.crawl { x, z, y, blockIndex ->
 | 
				
			||||||
          for ((z, yBlocks) in zBlocks) {
 | 
					          val block = format.blockLookupTable[blockIndex]
 | 
				
			||||||
            for ((y, block) in yBlocks) {
 | 
					          val material: Material? = Material.matchMaterial(block.type)
 | 
				
			||||||
              val material: Material? = Material.matchMaterial(block.type)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
              if (material == null) {
 | 
					          if (material == null) {
 | 
				
			||||||
                feedback("Unknown Material '${block.type}' at $x $y $z")
 | 
					            feedback("Unknown Material '${block.type}' at $x $y $z")
 | 
				
			||||||
                continue
 | 
					            return@crawl
 | 
				
			||||||
              }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
              blocksToMake.add(Location(world, x.toDouble(), y.toDouble(), z.toDouble()) to block)
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          blocksToMake.add(Location(world, x.toDouble(), y.toDouble(), z.toDouble()) to block)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        blocksToMake.sortBy { it.first.x }
 | 
					        blocksToMake.sortBy { it.first.x }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        feedback("Will place ${blocksToMake.size} blocks in ${world.name}")
 | 
					        feedback("Will place ${blocksToMake.size} blocks in ${world.name}")
 | 
				
			||||||
 | 
				
			|||||||
@ -13,6 +13,10 @@ commands:
 | 
				
			|||||||
    description: Export All Chunks
 | 
					    description: Export All Chunks
 | 
				
			||||||
    usage: /export_all_chunks
 | 
					    usage: /export_all_chunks
 | 
				
			||||||
    permission: heimdall.command.export_all_chunks
 | 
					    permission: heimdall.command.export_all_chunks
 | 
				
			||||||
 | 
					  export_world_load:
 | 
				
			||||||
 | 
					    description: Export World Load
 | 
				
			||||||
 | 
					    usage: /export_world_load
 | 
				
			||||||
 | 
					    permission: heimdall.command.export_world_load
 | 
				
			||||||
  import_world_load:
 | 
					  import_world_load:
 | 
				
			||||||
    description: Import World Load
 | 
					    description: Import World Load
 | 
				
			||||||
    usage: /import_world_load
 | 
					    usage: /import_world_load
 | 
				
			||||||
 | 
				
			|||||||
@ -5,8 +5,9 @@ import com.github.ajalt.clikt.core.requireObject
 | 
				
			|||||||
import com.github.ajalt.clikt.parameters.arguments.argument
 | 
					import com.github.ajalt.clikt.parameters.arguments.argument
 | 
				
			||||||
import com.github.ajalt.clikt.parameters.types.path
 | 
					import com.github.ajalt.clikt.parameters.types.path
 | 
				
			||||||
import gay.pizza.foundation.heimdall.export.ExportedBlock
 | 
					import gay.pizza.foundation.heimdall.export.ExportedBlock
 | 
				
			||||||
 | 
					import gay.pizza.foundation.heimdall.load.ExportedBlockTable
 | 
				
			||||||
import gay.pizza.foundation.heimdall.load.WorldLoadFormat
 | 
					import gay.pizza.foundation.heimdall.load.WorldLoadFormat
 | 
				
			||||||
import gay.pizza.foundation.heimdall.load.WorldLoadWorld
 | 
					import gay.pizza.foundation.heimdall.load.WorldLoadSimpleWorld
 | 
				
			||||||
import gay.pizza.foundation.heimdall.table.WorldChangeTable
 | 
					import gay.pizza.foundation.heimdall.table.WorldChangeTable
 | 
				
			||||||
import gay.pizza.foundation.heimdall.tool.state.BlockChangelog
 | 
					import gay.pizza.foundation.heimdall.tool.state.BlockChangelog
 | 
				
			||||||
import gay.pizza.foundation.heimdall.tool.state.BlockLogTracker
 | 
					import gay.pizza.foundation.heimdall.tool.state.BlockLogTracker
 | 
				
			||||||
@ -24,23 +25,32 @@ class GenerateWorldLoadFile : CliktCommand(name = "generate-world-load", help =
 | 
				
			|||||||
  val path by argument("load-format-file").path()
 | 
					  val path by argument("load-format-file").path()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  override fun run() {
 | 
					  override fun run() {
 | 
				
			||||||
    val worlds = mutableMapOf<String, WorldLoadWorld>()
 | 
					    val worlds = mutableMapOf<String, WorldLoadSimpleWorld>()
 | 
				
			||||||
    val worldChangelogs = BlockChangelog.query(db).splitBy { it.world }
 | 
					    val worldChangelogs = BlockChangelog.query(db).splitBy { it.world }
 | 
				
			||||||
    val worldNames = transaction(db) {
 | 
					    val worldNames = transaction(db) {
 | 
				
			||||||
      WorldChangeTable.selectAll()
 | 
					      WorldChangeTable.selectAll()
 | 
				
			||||||
        .associate { it[WorldChangeTable.toWorld] to it[WorldChangeTable.toWorldName] }
 | 
					        .associate { it[WorldChangeTable.toWorld] to it[WorldChangeTable.toWorldName] }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    val blockTable = ExportedBlockTable()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for ((id, changelog) in worldChangelogs) {
 | 
					    for ((id, changelog) in worldChangelogs) {
 | 
				
			||||||
      val tracker = BlockLogTracker()
 | 
					      val tracker = BlockLogTracker()
 | 
				
			||||||
      tracker.replay(changelog)
 | 
					      tracker.replay(changelog)
 | 
				
			||||||
      val sparse = tracker.buildBlockMap { ExportedBlock(it.type, it.data) }
 | 
					      val sparse = tracker.buildBlockMap { ExportedBlock(it.type, it.data) }
 | 
				
			||||||
      val blocks = sparse.blocks
 | 
					      val blocks = sparse.blocks
 | 
				
			||||||
      worlds[id.toString().lowercase()] = WorldLoadWorld(
 | 
					      worlds[id.toString().lowercase()] = WorldLoadSimpleWorld(
 | 
				
			||||||
        worldNames[id] ?: "unknown_$id",
 | 
					        worldNames[id] ?: "unknown_$id",
 | 
				
			||||||
        blocks
 | 
					        blocks.mapValues { levelOne ->
 | 
				
			||||||
 | 
					          levelOne.value.mapValues { levelTwo ->
 | 
				
			||||||
 | 
					            levelTwo.value.mapValues { entry ->
 | 
				
			||||||
 | 
					              blockTable.index(entry.value)
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    val format = WorldLoadFormat(worlds)
 | 
					    val format = WorldLoadFormat(blockTable.blocks, worlds)
 | 
				
			||||||
    path.deleteIfExists()
 | 
					    path.deleteIfExists()
 | 
				
			||||||
    Json.encodeToStream(format, path.outputStream())
 | 
					    Json.encodeToStream(format, path.outputStream())
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user