mirror of
https://github.com/GayPizzaSpecifications/foundation.git
synced 2025-08-02 21:20:55 +00:00
More stuff.
This commit is contained in:
parent
c973a1a3c6
commit
3d4862adc0
@ -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())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user