Add WorldManager and map-system support

Introduce WorldManager to select and unpack a random map ZIP into the server root before startup. The plugin now calls WorldManager.prepareRandomWorld() in onLoad (before onEnable) and reloads config there. Added map-system config options (enabled, zip-folder, target-world-name, maps) with example entries. WorldManager deletes existing world folders, extracts the chosen ZIP (with zip-slip protection) and logs progress.
This commit is contained in:
TDSTOS
2026-03-28 02:50:51 +01:00
parent 8e96a07a65
commit 84be2a30bc
3 changed files with 112 additions and 2 deletions

View File

@@ -18,6 +18,7 @@ import club.mcscrims.speedhg.listener.SoupListener
import club.mcscrims.speedhg.listener.StatsListener import club.mcscrims.speedhg.listener.StatsListener
import club.mcscrims.speedhg.scoreboard.ScoreboardManager import club.mcscrims.speedhg.scoreboard.ScoreboardManager
import club.mcscrims.speedhg.webhook.DiscordWebhookManager import club.mcscrims.speedhg.webhook.DiscordWebhookManager
import club.mcscrims.speedhg.world.WorldManager
import org.bukkit.Bukkit import org.bukkit.Bukkit
import org.bukkit.Material import org.bukkit.Material
import org.bukkit.NamespacedKey import org.bukkit.NamespacedKey
@@ -58,11 +59,19 @@ class SpeedHG : JavaPlugin() {
lateinit var discordWebhookManager: DiscordWebhookManager lateinit var discordWebhookManager: DiscordWebhookManager
private set private set
override fun onEnable() override fun onLoad()
{ {
instance = this instance = this
saveDefaultConfig()
saveDefaultConfig()
reloadConfig()
val worldManager = WorldManager( this )
worldManager.prepareRandomWorld()
}
override fun onEnable()
{
databaseManager = DatabaseManager( this ) databaseManager = DatabaseManager( this )
try { try {
databaseManager.connect() databaseManager.connect()

View File

@@ -0,0 +1,89 @@
package club.mcscrims.speedhg.world
import club.mcscrims.speedhg.SpeedHG
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.util.zip.ZipInputStream
class WorldManager(
private val plugin: SpeedHG
) {
/**
* Wird in onLoad() aufgerufen, um die Welt VOR dem Server-Start auszutauschen
*/
fun prepareRandomWorld()
{
if (!plugin.config.getBoolean( "map-system.enabled", false ))
return
val maps = plugin.config.getStringList( "map-system.maps" )
if ( maps.isEmpty() )
{
plugin.logger.warning( "[WorldManager] Keine Maps in der Config definiert" )
return
}
val randomMapName = maps.random()
val mapsFolder = File( plugin.dataFolder, plugin.config.getString( "map-system.zip-folder", "maps" )!!)
val zipFile = File( mapsFolder, randomMapName )
if ( !zipFile.exists() )
{
plugin.logger.severe( "[WorldManager] Map-ZIP nicht gefunden: $randomMapName" )
return
}
plugin.logger.info( "[WorldManager] Ausgewählte Map: $randomMapName. Entpacke..." )
val targetWorldName = plugin.config.getString( "map-system.target-world-name", "world" )!!
val serverRoot = plugin.dataFolder.parentFile.parentFile // Geht von plugins/SpeedHG -> plugins -> Server Root
val targetWorldFolder = File( serverRoot, targetWorldName )
if ( targetWorldFolder.exists() )
{
plugin.logger.info( "[WorldManager] Lösche alte Welt..." )
targetWorldFolder.deleteRecursively()
}
File( serverRoot, "${targetWorldName}_nether" ).deleteRecursively()
File( serverRoot, "${targetWorldName}_the_end" ).deleteRecursively()
targetWorldFolder.mkdirs()
unzip( zipFile, targetWorldFolder )
plugin.logger.info( "[WorldManager] Map erfolgreich entpackt!" )
}
private fun unzip(
zipFile: File,
targetDir: File
) {
ZipInputStream(FileInputStream( zipFile )).use { zis ->
var entry = zis.nextEntry
while ( entry != null )
{
val newFile = File( targetDir, entry.name )
if (!newFile.canonicalPath.startsWith( targetDir.canonicalPath + File.separator ))
throw SecurityException("Ungültiger ZIP-Eintrag (Zip Slip): ${entry.name}")
if ( entry.isDirectory )
{
newFile.mkdirs()
}
else
{
File( newFile.parent ).mkdirs()
FileOutputStream( newFile ).use { fos ->
zis.copyTo( fos )
}
}
zis.closeEntry()
entry = zis.nextEntry
}
}
}
}

View File

@@ -25,6 +25,18 @@ recraftNerf:
beforeFeast: true beforeFeast: true
maxAmount: 64 maxAmount: 64
map-system:
enabled: false
# Der Ordner im Plugin-Verzeichnis, in welchem die ZIPs liegen
zip-folder: "maps"
# Name der Zielwelt
target-world-name: "world"
# Liste der verfügbaren Maps
maps:
- "hg_map_1.zip"
- "hg_map_2.zip"
- "hg_map_3.zip"
discord: discord:
enabled: false enabled: false
webhook-url: "DEINE_WEBHOOK_URL_HIER" webhook-url: "DEINE_WEBHOOK_URL_HIER"