jvmMain.de.griefed.serverpackcreator.api.ApiProperties.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of serverpackcreator-api-jvm Show documentation
Show all versions of serverpackcreator-api-jvm Show documentation
ServerPackCreators API, to create server packs from Forge, Fabric, Quilt, LegacyFabric and NeoForge modpacks.
The newest version!
/* Copyright (C) 2024 Griefed
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*
* The full license can be found at https:github.com/Griefed/ServerPackCreator/blob/main/LICENSE
*/
package de.griefed.serverpackcreator.api
import de.comahe.i18n4k.Locale
import de.comahe.i18n4k.config.I18n4kConfigDefault
import de.comahe.i18n4k.i18n4k
import de.comahe.i18n4k.toTag
import de.griefed.serverpackcreator.api.utilities.common.*
import org.apache.logging.log4j.kotlin.cachedLoggerOf
import java.io.BufferedReader
import java.io.File
import java.io.IOException
import java.io.InputStreamReader
import java.net.URI
import java.util.*
import java.util.prefs.Preferences
/**
* Base settings of ServerPackCreator, such as working directories, default list of clientside-only
* mods, default list of directories to include in a server pack, script templates, java paths and
* much more.
*
* @param fileUtilities Instance of {@link FileUtilities} for file-operations.
* @param systemUtilities Instance of {@link SystemUtilities} to acquire the Java path
* automatically.
* @param listUtilities Used to print the configured fallback modlists in chunks.
* @param jarUtilities Instance of {@link JarUtilities} used to acquire .exe or JAR-, as well
* as system information.
* @param propertiesFile serverpackcreator.properties-file containing settings and configurations to load the API with.
* @author Griefed
*/
@Suppress("unused")
actual class ApiProperties(
private val fileUtilities: FileUtilities,
private val systemUtilities: SystemUtilities,
private val listUtilities: ListUtilities,
jarUtilities: JarUtilities,
propertiesFile: File = File("serverpackcreator.properties")
) {
private val log = cachedLoggerOf(javaClass)
private val internalProps = Properties()
private val userPreferences = Preferences.userRoot().node("ServerPackCreator")
private val serverPackCreatorProperties = "serverpackcreator.properties"
private val jarInformation: JarInformation = JarInformation(javaClass, jarUtilities)
private val jarFolderProperties: File =
File(jarInformation.jarFolder.absoluteFile, serverPackCreatorProperties).absoluteFile
private val pVersionCheckPreRelease =
"de.griefed.serverpackcreator.versioncheck.prerelease"
private val pLanguage =
"de.griefed.serverpackcreator.language"
private val pConfigurationFallbackUpdateURL =
"de.griefed.serverpackcreator.configuration.fallback.updateurl"
private val pConfigurationFallbackModsList =
"de.griefed.serverpackcreator.configuration.fallbackmodslist"
private val pConfigurationFallbackModsListRegex =
"de.griefed.serverpackcreator.configuration.fallbackmodslist.regex"
private val pConfigurationFallbackModsWhiteList =
"de.griefed.serverpackcreator.configuration.modswhitelist"
private val pConfigurationHasteBinServerUrl =
"de.griefed.serverpackcreator.configuration.hastebinserver"
private val pConfigurationAikarsFlags =
"de.griefed.serverpackcreator.configuration.aikar"
private val pServerPackAutoDiscoveryEnabled =
"de.griefed.serverpackcreator.serverpack.autodiscovery.enabled"
private val pServerPackAutoDiscoveryEnabledLegacy =
"de.griefed.serverpackcreator.serverpack.autodiscoverenabled"
private val pGuiDarkMode =
"de.griefed.serverpackcreator.gui.darkmode"
private val pConfigurationDirectoriesServerPacks =
"de.griefed.serverpackcreator.configuration.directories.serverpacks"
private val pServerPackCleanupEnabled =
"de.griefed.serverpackcreator.serverpack.cleanup.enabled"
private val pServerPackOverwriteEnabled =
"de.griefed.serverpackcreator.serverpack.overwrite.enabled"
private val pConfigurationDirectoriesShouldExclude =
"de.griefed.serverpackcreator.configuration.directories.shouldexclude"
private val pSpringSchedulesDatabaseCleanup =
"de.griefed.serverpackcreator.spring.schedules.database.cleanup"
private val pStringSchedulesFilesCleanup =
"de.griefed.serverpackcreator.spring.schedules.files.cleanup"
private val pSpringSchedulesVersionMetaRefresh =
"de.griefed.serverpackcreator.spring.schedules.versions.refresh"
private val pConfigurationSaveLastLoadedConfigEnabled =
"de.griefed.serverpackcreator.configuration.saveloadedconfig"
private val pConfigurationDirectoriesMustInclude =
"de.griefed.serverpackcreator.configuration.directories.mustinclude"
private val pServerPackZipExclusions =
"de.griefed.serverpackcreator.serverpack.zip.exclude"
private val pServerPackZipExclusionEnabled =
"de.griefed.serverpackcreator.serverpack.zip.exclude.enabled"
private val pServerPackScriptTemplates =
"de.griefed.serverpackcreator.serverpack.script.template"
private val pPostInstallCleanupFiles =
"de.griefed.serverpackcreator.install.post.files"
private val pPreInstallCleanupFiles =
"de.griefed.serverpackcreator.install.pre.files"
private val pAllowUseMinecraftSnapshots =
"de.griefed.serverpackcreator.minecraft.snapshots"
private val pServerPackAutoDiscoveryFilterMethod =
"de.griefed.serverpackcreator.serverpack.autodiscovery.filter"
private val pJavaForServerInstall =
"de.griefed.serverpackcreator.java"
private val pScriptVariablesJavaPaths =
"de.griefed.serverpackcreator.script.java"
private val pScriptVariablesAutoUpdateJavaPathsEnabled =
"de.griefed.serverpackcreator.script.java.autoupdate"
private val pHomeDirectory =
"de.griefed.serverpackcreator.home"
private val pOldVersion =
"de.griefed.serverpackcreator.version.old"
private val customPropertyPrefix =
"custom.property."
private val pTomcatBaseDirectory =
"server.tomcat.basedir"
private val pTomcatLogsDirectory =
"server.tomcat.accesslog.directory"
private val pSpringDatasourceUrl =
"spring.datasource.url"
private val pSpringDatasourceUsername =
"spring.datasource.username"
private val pSpringDatasourcePassword =
"spring.datasource.password"
val home: File = if (System.getProperty("user.home").isNotEmpty()) {
File(System.getProperty("user.home"))
} else {
jarInformation.jarFolder.absoluteFile
}
private var fallbackModsWhitelist = TreeSet(
listOf(
"Ping-Wheel-"
)
)
@Suppress("SpellCheckingInspection")
private var fallbackMods = TreeSet(
listOf(
"3dskinlayers-",
"Absolutely-Not-A-Zoom-Mod-",
"AdvancedChat-",
"AdvancedChatCore-",
"AdvancedChatHUD-",
"AdvancedCompas-",
"Ambience",
"AmbientEnvironment-",
"AmbientSounds_",
"AnimaticaReforged-",
"AreYouBlind-",
"Armor Status HUD-",
"ArmorSoundTweak-",
"BH-Menu-",
"Batty's Coordinates PLUS Mod",
"BetterAdvancements-",
"BetterAnimationsCollection-",
"BetterModsButton-",
"BetterDarkMode-",
"BetterF3-",
"BetterFog-",
"BetterFoliage-",
"BetterPingDisplay-",
"BetterPlacement-",
"BetterTaskbar-",
"BetterThirdPerson",
"BetterTitleScreen-",
"Blur-",
"BorderlessWindow-",
"CTM-",
"ChunkAnimator-",
"ClientTweaks_",
"CompletionistsIndex-",
"Controller Support-",
"Controlling-",
"CraftPresence-",
"CullLessLeaves-Reforged-",
"CustomCursorMod-",
"CustomMainMenu-",
"DefaultOptions_",
"DefaultSettings-",
"DeleteWorldsToTrash-",
"DetailArmorBar-",
"Ding-",
"DistantHorizons-",
"DripSounds-",
"Durability101-",
"DurabilityNotifier-",
"DynamicSurroundings-",
"DynamicSurroundingsHuds-",
"EasyLAN-",
"EffectsLeft-",
"EiraMoticons_",
"EnchantmentDescriptions-",
"EnhancedVisuals_",
"EquipmentCompare-",
"EuphoriaPatcher-",
"FPS-Monitor-",
"FabricCustomCursorMod-",
"FadingNightVision-",
"Fallingleaves-",
"FancySpawnEggs",
"FancyVideo-API-",
"farsight-",
"FirstPersonMod",
"FogTweaker-",
"ForgeCustomCursorMod-",
"FpsReducer-",
"FpsReducer2-",
"FullscreenWindowed-",
"GameMenuModOption-",
"HealthOverlay-",
"HeldItemTooltips-",
"HorseStatsMod-",
"ImmediatelyFastReforged-",
"InventoryEssentials_",
"InventoryHud_[1.17.1].forge-",
"InventorySpam-",
"InventoryTweaks-",
"ItemBorders-",
"ItemLocks-",
"ItemPhysicLite_",
"ItemStitchingFix-",
"JBRA-Client-",
"JustEnoughCalculation-",
"JustEnoughEffects-",
"JustEnoughProfessions-",
"LeaveMyBarsAlone-",
"LLOverlayReloaded-",
"LOTRDRP-",
"LegendaryTooltips",
"LegendaryTooltips-",
"LightOverlay-",
"MinecraftCapes ",
"MineMenu-",
"MoBends",
"ModernUI-",
"MouseTweaks-",
"MyServerIsCompatible-",
"Neat ",
"Neat-",
"NekosEnchantedBooks-",
"NoAutoJump-",
"NoFog-",
"Notes-",
"NotifMod-",
"OldJavaWarning-",
"OptiFine",
"OptiFine_",
"OptiForge",
"OptiForge-",
"OverflowingBars-",
"PackMenu-",
"PackModeMenu-",
"PickUpNotifier-",
"Ping-",
"PingHUD-",
"PresenceFootsteps-",
"RPG-HUD-",
"ReAuth-",
"Reforgium-",
"ResourceLoader-",
"ResourcePackOrganizer",
"Ryoamiclights-",
"RyoamicLights-",
"ShoulderSurfing-",
"ShulkerTooltip-",
"SimpleDiscordRichPresence-",
"SimpleWorldTimer-",
"SoundFilters-",
"SpawnerFix-",
"StylishEffects-",
"TextruesRubidiumOptions-",
"TRansliterationLib-",
"TipTheScales-",
"Tips-",
"Toast Control-",
"Toast-Control-",
"ToastControl-",
"TravelersTitles-",
"VoidFog-",
"VR-Combat_",
"WindowedFullscreen-",
"WorldNameRandomizer-",
"YeetusExperimentus-",
"YungsMenuTweaks-",
"[1.12.2]DamageIndicatorsMod-",
"[1.12.2]bspkrscore-",
"antighost-",
"anviltooltipmod-",
"appleskin-",
"armorchroma-",
"armorpointspp-",
"auditory-",
"authme-",
"auto-reconnect-",
"autojoin-",
"autoreconnect-",
"axolotl-item-fix-",
"backtools-",
"bannerunlimited-",
"beenfo-1.19-",
"better-recipe-book-",
"betterbiomeblend-",
"bhmenu-",
"blur-",
"borderless-mining-",
"cat_jam-",
"catalogue-",
"charmonium-",
"chat_heads-",
"cherishedworlds-",
"cirback-1.0-",
"classicbar-",
"clickadv-",
"clienttweaks-",
"combat_music-",
"connectedness-",
"controllable-",
"cullleaves-",
"cullparticles-",
"custom-crosshair-mod-",
"customdiscordrpc-",
"darkness-",
"dashloader-",
"defaultoptions-",
"desiredservers-",
"discordrpc-",
"drippyloadingscreen-",
"drippyloadingscreen_",
"durabilitytooltip-",
"dynamic-fps-",
"dynamic-music-",
"dynamiclights-",
"dynmus-",
"effective-",
"eggtab-",
"eguilib-",
"eiramoticons-",
"embeddium-",
"enchantment-lore-",
"entity-texture-features-",
"entityculling-",
"essential_",
"exhaustedstamina-",
"extremesoundmuffler-",
"fabricemotes-",
"fancymenu_",
"fancymenu_video_extension",
"fast-ip-ping-",
"flickerfix-",
"fm_audio_extension_",
"forgemod_VoxelMap-",
"freelook-",
"galacticraft-rpc-",
"gamestagesviewer-",
"gpumemleakfix-",
"grid-",
"helium-",
"hiddenrecipebook_",
"hiddenrecipebook-",
"infinitemusic-",
"inventoryprofiles",
"invtweaks-",
"itemzoom",
"itlt-",
"jeed-",
"jehc-",
"jeiintegration_",
"jumpoverfences-",
"just-enough-harvestcraft-",
"justenoughbeacons-",
"justenoughdrags-",
"justzoom_",
"keymap-",
"keywizard-",
"lazurite-",
"lazydfu-",
"lib39-",
"light-overlay-",
"lightfallclient-",
"lightspeed-",
"loadmyresources_",
"lock_minecart_view-",
"lootbeams-",
"lwl-",
"macos-input-fixes-",
"magnesium_extras-",
"maptooltip-",
"massunbind",
"mcbindtype-",
"mcwifipnp-",
"medievalmusic-",
"memoryusagescreen-",
"mightyarchitect-",
"mindful-eating-",
"minetogether-",
"mobplusplus-",
"modcredits-",
"modernworldcreation_",
"modnametooltip-",
"modnametooltip_",
"moreoverlays-",
"mousewheelie-",
"movement-vision-",
"multihotbar-",
"music-duration-reducer-",
"musicdr-",
"neiRecipeHandlers-",
"ngrok-lan-expose-mod-",
"no_nv_flash-",
"nopotionshift_",
"notenoughanimations-",
"oculus-",
"ornaments-",
"overloadedarmorbar-",
"panorama-",
"paperdoll-",
"physics-mod-",
"phosphor-",
"preciseblockplacing-",
"radon-",
"realm-of-lost-souls-",
"rebind_narrator-",
"rebind-narrator-",
"rebindnarrator-",
"rebrand-",
"reforgium-",
"replanter-",
"rrls-",
"rubidium-",
"rubidium_extras-",
"screenshot-to-clipboard-",
"servercountryflags-",
"shutupexperimentalsettings-",
"shutupmodelloader-",
"signtools-",
"simple-rpc-",
"simpleautorun-",
"smartcursor-",
"smarthud-",
"smoothboot-",
"smoothfocus-",
"sodium-fabric-",
"sounddeviceoptions-",
"soundreloader-",
"spoticraft-",
"skinlayers3d-forge",
"tconplanner-",
"textrues_embeddium_options-",
"timestamps-",
"tooltipscroller-",
"torchoptimizer-",
"torohealth-",
"totaldarkness",
"toughnessbar-",
"watermedia-",
"whats-that-slot-forge-",
"wisla-",
"xenon-",
"xlifeheartcolors-",
"yisthereautojump-"
)
)
@Suppress("MemberVisibilityCanBePrivate")
val fallbackDirectoriesInclusion = TreeSet(
listOf(
"addonpacks",
"blueprints",
"config",
"configs",
"customnpcs",
"defaultconfigs",
"global_data_packs",
"global_packs",
"kubejs",
"maps",
"mods",
"openloader",
"scripts",
"schematics",
"shrines-saves",
"structures",
"structurize",
"worldshape",
"Zoestria"
)
)
@Suppress("MemberVisibilityCanBePrivate")
val fallbackDirectoriesExclusion = TreeSet(
listOf(
"animation",
"asm",
"cache",
"changelogs",
"craftpresence",
"crash-reports",
"downloads",
"icons",
"libraries",
"local",
"logs",
"overrides",
"packmenu",
"profileImage",
"profileImage",
"resourcepacks",
"screenshots",
"server_pack",
"shaderpacks",
"simple-rpc",
"tv-cache"
)
)
@Suppress("MemberVisibilityCanBePrivate")
val fallbackZipExclusions = TreeSet(
listOf(
"minecraft_server.MINECRAFT_VERSION.jar",
"server.jar",
"libraries/net/minecraft/server/MINECRAFT_VERSION/server-MINECRAFT_VERSION.jar"
)
)
val fallbackPostInstallCleanupFiles = TreeSet(
listOf(
"fabric-installer.jar",
"forge-installer.jar",
"quilt-installer.jar",
"installer.log",
"forge-installer.jar.log",
"legacyfabric-installer.jar",
"run.bat",
"run.sh",
"user_jvm_args.txt"
)
)
val fallbackPreInstallCleanupFiles = TreeSet(
listOf(
"libraries",
"server.jar",
"forge-installer.jar",
"quilt-installer.jar",
"installer.log",
"forge-installer.jar.log",
"legacyfabric-installer.jar",
"run.bat",
"run.sh",
"user_jvm_args.txt",
"quilt-server-launch.jar",
"minecraft_server.1.16.5.jar",
"forge.jar"
)
)
@Suppress("MemberVisibilityCanBePrivate")
val fallbackAikarsFlags = "-Xms4G" +
" -Xmx4G" +
" -XX:+UseG1GC" +
" -XX:+ParallelRefProcEnabled" +
" -XX:MaxGCPauseMillis=200" +
" -XX:+UnlockExperimentalVMOptions" +
" -XX:+DisableExplicitGC" +
" -XX:+AlwaysPreTouch" +
" -XX:G1NewSizePercent=30" +
" -XX:G1MaxNewSizePercent=40" +
" -XX:G1HeapRegionSize=8M" +
" -XX:G1ReservePercent=20" +
" -XX:G1HeapWastePercent=5" +
" -XX:G1MixedGCCountTarget=4" +
" -XX:InitiatingHeapOccupancyPercent=15" +
" -XX:G1MixedGCLiveThresholdPercent=90" +
" -XX:G1RSetUpdatingPauseTimePercent=5" +
" -XX:SurvivorRatio=32" +
" -XX:+PerfDisableSharedMem" +
" -XX:MaxTenuringThreshold=1" +
" -Dusing.aikars.flags=https://mcflags.emc.gs" +
" -Daikars.new.flags=true"
val fallbackUpdateURL =
"https://raw.githubusercontent.com/Griefed/ServerPackCreator/main/serverpackcreator-api/src/jvmMain/resources/serverpackcreator.properties"
val fallbackExclusionFilter = ExclusionFilter.START
val fallbackOverwriteEnabled = true
val fallbackJavaScriptAutoupdateEnabled = true
val fallbackCheckingForPreReleasesEnabled = false
val fallbackZipFileExclusionEnabled = true
val fallbackServerPackCleanupEnabled = true
val fallbackMinecraftPreReleasesAvailabilityEnabled = false
val fallbackAutoExcludingModsEnabled = true
val fallbackArtemisQueueMaxDiskUsage = 90
val fallbackCleanupSchedule = "0 0 0 * * *"
val fallbackVersionSchedule = "0 0 0 * * *"
val fallbackDatabaseCleanupSchedule = "0 0 0 * * *"
private val checkedJavas = hashMapOf()
@Suppress("MemberVisibilityCanBePrivate")
val trueFalseRegex = "^(true|false)$".toRegex()
@Suppress("MemberVisibilityCanBePrivate")
val alphaBetaRegex = "^(.*alpha.*|.*beta.*)$".toRegex()
@Suppress("MemberVisibilityCanBePrivate")
val serverPacksRegex = "^(?:\\./)?server-packs$".toRegex()
val i18n4kConfig = I18n4kConfigDefault()
/**
* String-list of clientside-only mods to exclude from server packs.
*/
@Suppress("MemberVisibilityCanBePrivate")
var clientsideMods = fallbackMods
private set
/**
* String-list of mods to include if present, regardless whether a match was found through [clientsideMods].
*/
@Suppress("MemberVisibilityCanBePrivate")
var modsWhitelist = fallbackModsWhitelist
private set
/**
* Regex-list of clientside-only mods to exclude from server packs.
*/
@Suppress("MemberVisibilityCanBePrivate")
var clientsideModsRegex: TreeSet = TreeSet()
get() {
field.clear()
for (mod in clientsideMods) {
field.add("^$mod.*$")
}
return field
}
private set
/**
* Regex-list of mods to include if present, regardless whether a match was found throug [clientsideModsRegex].
*/
@Suppress("MemberVisibilityCanBePrivate")
var modsWhitelistRegex: TreeSet = TreeSet()
get() {
field.clear()
for (mod in modsWhitelist) {
field.add("^$mod.*$")
}
return field
}
private set
/**
* Modloaders supported by ServerPackCreator.
*/
val supportedModloaders = arrayOf("Fabric", "Forge", "Quilt", "LegacyFabric", "NeoForge")
/**
* The folder containing the ServerPackCreator.exe or JAR-file.
*
* @return Folder containing the ServerPackCreator.exe or JAR-file.
* @author Griefed
*/
fun getJarFolder() = jarInformation.jarFolder
/**
* Whether a .exe or JAR-file was used for running ServerPackCreator.
*
* @return `true` if a .exe was/is used.
* @author Griefed
*/
fun isExe() = jarInformation.isExe
/**
* The .exe or JAR-file of ServerPackCreator.
*
* @return The .exe or JAR-file of ServerPackCreator.
* @author Griefed
*/
fun getJarFile() = jarInformation.jarFile
/**
* The name of the .exe or JAR-file.
*
* @return The name of the .exe or JAR-file.
* @author Griefed
*/
fun getJarName(): String = jarInformation.jarFile.name
/**
* The Java version used to run ServerPackCreator.
*
* @return Java version.
* @author Griefed
*/
fun getJavaVersion() = jarInformation.javaVersion
/**
* Architecture of the operating system on which ServerPackCreator is running on.
*
* @return Arch.
* @author Griefed
*/
fun getOSArch() = jarInformation.osArch
/**
* The name of the operating system on which ServerPackCreator is running on.
*
* @return OS name.
* @author Griefed
*/
fun getOSName() = jarInformation.osName
/**
* The version of the OS on which ServerPackCreator is running on.
*
* @return Version of the OS.
* @author Griefed
*/
fun getOSVersion() = jarInformation.osVersion
/**
* The version of the ServerPackCreator API.
*/
val apiVersion: String = javaClass.getPackage().implementationVersion ?: "dev"
val devBuild: Boolean
get() {
return apiVersion == "dev"
}
val preRelease: Boolean
get() {
return apiVersion.matches(alphaBetaRegex)
}
val configVersion: String = if (preRelease || devBuild) {
"TEST"
} else {
"4"
}
init {
i18n4k = i18n4kConfig
i18n4kConfig.defaultLocale = Locale("en_GB")
loadProperties(propertiesFile, false)
}
/**
* Only the first call to this property will return true if this is the first time ServerPackCreator is being run
* on a given host. Any subsequent call will return false. Handle with care!
*
* @author Griefed
*/
val firstRun: Boolean
init {
firstRun = getBoolProperty("de.griefed.serverpackcreator.firstrun", true)
setBoolProperty("de.griefed.serverpackcreator.firstrun", false)
}
/**
* Directories to include in a server pack.
*/
var directoriesToInclude = fallbackDirectoriesInclusion
get() {
val entries =
getListProperty(pConfigurationDirectoriesMustInclude, fallbackDirectoriesInclusion.joinToString(","))
field.addAll(entries)
return field
}
set(value) {
setListProperty(pConfigurationDirectoriesMustInclude, value.toList(), ",")
field.clear()
field.addAll(value)
log.info("Directories which must always be included set to: $value")
}
/**
* Directories to exclude from a server pack.
*/
var directoriesToExclude = fallbackDirectoriesExclusion
get() {
val prop =
getListProperty(pConfigurationDirectoriesShouldExclude, fallbackDirectoriesExclusion.joinToString(","))
val use = TreeSet(prop)
use.removeIf { n -> directoriesToInclude.contains(n) }
field.clear()
field.addAll(use)
return field
}
set(value) {
val use = TreeSet()
use.addAll(value)
use.removeIf { n -> directoriesToInclude.contains(n) }
setListProperty(pConfigurationDirectoriesShouldExclude, use.toList(), ",")
field.clear()
field.addAll(use)
log.info("Directories which must always be excluded set to: $field")
}
/**
* List of files to delete after a server pack server installation.
*/
var postInstallCleanupFiles = fallbackPostInstallCleanupFiles
get() {
val entries = getListProperty(pPostInstallCleanupFiles, fallbackPostInstallCleanupFiles.joinToString(","))
field.addAll(entries)
return field
}
set(value) {
setListProperty(pPostInstallCleanupFiles, value.toList(), ",")
field.clear()
field.addAll(value)
log.info("Files to cleanup after server installation set to: $value")
}
/**
* List of files to delete before a server pack server installation.
*/
var preInstallCleanupFiles = fallbackPreInstallCleanupFiles
get() {
val entries = getListProperty(pPreInstallCleanupFiles, fallbackPreInstallCleanupFiles.joinToString(","))
field.addAll(entries)
return field
}
set(value) {
setListProperty(pPreInstallCleanupFiles, value.toList(), ",")
field.clear()
field.addAll(value)
log.info("Files to cleanup before server installation set to: $value")
}
/**
* List of files to be excluded from ZIP-archives. Current filters are:
*
* * `MINECRAFT_VERSION` - Will be replaced with the Minecraft version of the server pack
* * `MODLOADER` - Will be replaced with the modloader of the server pack
* * `MODLOADER_VERSION` - Will be replaced with the modloader version of the server pack
*
* Should you want these filters to be expanded, open an issue on [GitHub](https://github.com/Griefed/ServerPackCreator/issues)
*/
var zipArchiveExclusions = fallbackZipExclusions
get() {
val entries = getListProperty(pServerPackZipExclusions, fallbackZipExclusions.joinToString(","))
field.addAll(entries)
return field
}
set(value) {
setListProperty(pServerPackZipExclusions, value.toList(), ",")
field.clear()
field.addAll(value)
log.info("Files which must be excluded from ZIP-archives set to: $value")
}
/**
* Paths to Java installations available to SPC for automatically updating the script variables of a given server pack
* configuration.
* * key: Java version
* * value: Path to the Java .exe or binary
*
* If you plan on overwriting this property, make sure to format they key-value-pairs as follows:
* * key: `de.griefed.serverpackcreator.script.java` followed by the number representing the Java version
* * value: Valid path to a Java installation corresponding to the number used in the key
*/
@Suppress("MemberVisibilityCanBePrivate")
var javaPaths = HashMap(256)
get() {
val paths = HashMap(256)
var path: String
var position: String
for (i in 8..255) {
position = pScriptVariablesJavaPaths + i
path = internalProps.getProperty(position, "")
if (checkJavaPath(path)) {
paths[i.toString()] = path
internalProps.setProperty(position, path)
}
}
field = paths
return paths
}
set(values) {
var position: Int?
var newKey: String
val paths = HashMap(256)
for (i in 8..255) {
internalProps.remove(pScriptVariablesJavaPaths + i)
}
for ((key, value) in values) {
if (!checkJavaPath(value)) {
continue
}
position = key.replace(pScriptVariablesJavaPaths, "").toIntOrNull()
newKey = pScriptVariablesJavaPaths + position
if (position != null && 8 <= position!! && position!! < 256) {
internalProps.setProperty(newKey, value)
paths[newKey] = value
}
}
field = paths
log.info("Available Java paths for scripts:")
for ((key, value) in field) {
log.info("Java $key path: $value")
}
}
/**
* Default list of script templates used by ServerPackCreator.
*
* @author Griefed
*/
fun defaultScriptTemplates(): List {
// See whether we have custom files.
val currentFiles = serverFilesDirectory.walk().maxDepth(1).filter {
it.name.endsWith("sh", ignoreCase = true) ||
it.name.endsWith("ps1", ignoreCase = true) ||
it.name.endsWith("bat", ignoreCase = true)
}.toList()
val customTemplates = currentFiles.filter {
!it.name.contains("default_template", ignoreCase = true)
}
val newTemplates = mutableListOf()
var shellPresent = false
var powershellPresent = false
var batchPresent = false
for (customTemplate in customTemplates) {
when {
customTemplate.name.endsWith("sh", ignoreCase = true) && !shellPresent -> {
newTemplates.add(customTemplate.absoluteFile)
shellPresent = true
}
customTemplate.name.endsWith("ps1", ignoreCase = true) && !powershellPresent -> {
newTemplates.add(customTemplate.absoluteFile)
powershellPresent = true
}
customTemplate.name.endsWith("bat", ignoreCase = true) && !batchPresent -> {
newTemplates.add(customTemplate.absoluteFile)
batchPresent = true
}
else -> {
newTemplates.add(customTemplate.absoluteFile)
}
}
}
if (!shellPresent) {
newTemplates.add(File(serverFilesDirectory.absolutePath, defaultShellScriptTemplate.name).absoluteFile)
}
if (!powershellPresent) {
newTemplates.add(File(serverFilesDirectory.absolutePath, defaultPowerShellScriptTemplate.name).absoluteFile)
}
return newTemplates.toList()
}
/**
* Start-script templates to use during server pack generation.
*/
@Suppress("SetterBackingFieldAssignment")
var scriptTemplates: TreeSet = TreeSet()
get() {
val scriptSetting = internalProps.getProperty(pServerPackScriptTemplates)
val entries = if (scriptSetting != null && scriptSetting == "default_template.ps1,default_template.sh") {
defaultScriptTemplates()
} else {
getListProperty(
pServerPackScriptTemplates,
defaultScriptTemplates().joinToString(",") { it.absolutePath }
).map { File(it).absoluteFile }
}
field.clear()
field.addAll(entries)
return field
}
set(value) {
val entries = value.map { it.absolutePath }
setListProperty(pServerPackScriptTemplates, entries, ",")
field.clear()
field.addAll(value.map { it.absoluteFile })
log.info("Using script templates:")
for (template in field) {
log.info(" " + template.path)
}
}
/**
* The URL from which a .properties-file is read during updating of the fallback clientside-mods list.
* The default can be found in [fallbackUpdateURL].
*/
var updateUrl = URI(fallbackUpdateURL).toURL()
get() {
field = URI(acquireProperty(pConfigurationFallbackUpdateURL, fallbackUpdateURL)).toURL()
return field
}
set(value) {
defineProperty(pConfigurationFallbackUpdateURL, value.toString())
field = value
}
/**
* The filter method with which to determine whether a user-specified clientside-only mod should
* be excluded from the server pack. Available settings are:
*
* * [ExclusionFilter.START]
* * [ExclusionFilter.END]
* * [ExclusionFilter.CONTAIN]
* * [ExclusionFilter.REGEX]
* * [ExclusionFilter.EITHER]
*/
var exclusionFilter = fallbackExclusionFilter
get() {
val prop = acquireProperty(pServerPackAutoDiscoveryFilterMethod, "START")
field = try {
when (prop) {
"END" -> ExclusionFilter.END
"CONTAIN" -> ExclusionFilter.CONTAIN
"REGEX" -> ExclusionFilter.REGEX
"EITHER" -> ExclusionFilter.EITHER
"START" -> ExclusionFilter.START
else -> {
log.error("Invalid filter specified. Defaulting to START.")
fallbackExclusionFilter
}
}
} catch (ex: NullPointerException) {
log.error("No filter specified. Defaulting to START.")
fallbackExclusionFilter
}
return field
}
set(value) {
internalProps.setProperty(pServerPackAutoDiscoveryFilterMethod, value.toString())
field = value
log.info("User specified clientside-only mod exclusion filter set to: $field")
}
/**
* Whether the search for available PreReleases is enabled or disabled. Depending on
* `de.griefed.serverpackcreator.versioncheck.prerelease`, returns `true` if checks for available PreReleases are
* enabled, `false` if no checks for available PreReleases should be made.
*/
var isCheckingForPreReleasesEnabled = fallbackCheckingForPreReleasesEnabled
get() {
field = getBoolProperty(pVersionCheckPreRelease, fallbackCheckingForPreReleasesEnabled)
return field
}
set(value) {
setBoolProperty(pVersionCheckPreRelease, value)
field = value
log.info("Checking for pre-releases set to $field.")
}
/**
* Whether the exclusion of files from the ZIP-archive of the server pack is enabled.
*/
var isZipFileExclusionEnabled = fallbackZipFileExclusionEnabled
get() {
field = getBoolProperty(pServerPackZipExclusionEnabled, fallbackZipFileExclusionEnabled)
return field
}
set(value) {
setBoolProperty(pServerPackZipExclusionEnabled, value)
field = value
log.info("Zip-file exclusion enabled set to: $field")
}
/**
* Is auto excluding of clientside-only mods enabled.
*/
var isAutoExcludingModsEnabled = fallbackAutoExcludingModsEnabled
get() {
var value = getBoolProperty(pServerPackAutoDiscoveryEnabled, fallbackAutoExcludingModsEnabled)
try {
val legacyProp = internalProps.getProperty(pServerPackAutoDiscoveryEnabledLegacy)
if (legacyProp.matches(trueFalseRegex)) {
value = java.lang.Boolean.parseBoolean(legacyProp)
internalProps.setProperty(pServerPackAutoDiscoveryEnabled, value.toString())
internalProps.remove(pServerPackAutoDiscoveryEnabledLegacy)
log.info(
"Migrated '$pServerPackAutoDiscoveryEnabledLegacy' to '$pServerPackAutoDiscoveryEnabled'."
)
}
} catch (ignored: Exception) {
// No legacy declaration present, so we can safely ignore any exception.
}
field = value
return field
}
set(value) {
setBoolProperty(pServerPackAutoDiscoveryEnabled, value)
field = value
log.info("Auto-discovery of clientside-only mods set to: $field")
}
/**
* Whether overwriting of already existing server packs is enabled.
*/
var isServerPacksOverwriteEnabled = fallbackOverwriteEnabled
get() {
field = getBoolProperty(pServerPackOverwriteEnabled, fallbackOverwriteEnabled)
return field
}
set(value) {
setBoolProperty(pServerPackOverwriteEnabled, value)
field = value
log.info("Overwriting of already existing server packs set to: $field")
}
/**
* Whether cleanup procedures after server pack generation are enabled.
*/
var isServerPackCleanupEnabled = fallbackServerPackCleanupEnabled
get() {
field = getBoolProperty(pServerPackCleanupEnabled, fallbackServerPackCleanupEnabled)
return field
}
set(value) {
setBoolProperty(pServerPackCleanupEnabled, value)
field = value
log.info("Cleanup of already existing server packs set to: $field")
}
/**
* Whether Minecraft pre-releases and snapshots are available to the user in, for example, the GUI.
*/
var isMinecraftPreReleasesAvailabilityEnabled = fallbackMinecraftPreReleasesAvailabilityEnabled
get() {
field = getBoolProperty(pAllowUseMinecraftSnapshots, fallbackMinecraftPreReleasesAvailabilityEnabled)
return field
}
set(value) {
setBoolProperty(pAllowUseMinecraftSnapshots, value)
field = value
log.info("Minecraft pre-releases and snapshots available set to: $field")
}
/**
* Whether to automatically update the `SPC_JAVA_SPC`-placeholder in the script variables
* table with a Java path matching the required Java version for the Minecraft server.
*/
var isJavaScriptAutoupdateEnabled = fallbackJavaScriptAutoupdateEnabled
get() {
field = getBoolProperty(pScriptVariablesAutoUpdateJavaPathsEnabled, fallbackJavaScriptAutoupdateEnabled)
return field
}
set(value) {
setBoolProperty(pScriptVariablesAutoUpdateJavaPathsEnabled, value)
field = value
log.info("Automatically update SPC_JAVA_SPC-placeholder in script variables table set to: $field")
}
/**
* Aikars Flags commonly used for Minecraft servers to improve performance in various places.
*/
var aikarsFlags: String = fallbackAikarsFlags
get() {
field = acquireProperty(pConfigurationAikarsFlags, fallbackAikarsFlags)
return field
}
set(value) {
defineProperty(pConfigurationAikarsFlags, value)
field = value
log.info("Set Aikars flags to: $field.")
}
/**
* Path to the PostgreSQL database used by the webservice-side of ServerPackCreator.
*
* When setting this to a different URL, you may leave out the `jdbc:postgresql://`-part, it will be prefixed automatically.
*/
@Suppress("MemberVisibilityCanBePrivate")
var jdbcDatabaseUrl: String = "jdbc:postgresql://localhost:5432/serverpackcreator"
get() {
var dbPath =
internalProps.getProperty(pSpringDatasourceUrl, "jdbc:postgresql://localhost:5432/serverpackcreator")
if (dbPath.isEmpty() || dbPath.contains("jdbc:sqlite") || !dbPath.startsWith("jdbc:postgresql://")) {
log.warn("Your spring.datasource.url-property didn't match a PostgreSQL JDBC URL: $dbPath. It has been migrated to jdbc:postgresql://localhost:5432/serverpackcreator.")
dbPath = "jdbc:postgresql://localhost:5432/serverpackcreator"
}
internalProps.setProperty(pSpringDatasourceUrl, dbPath)
field = dbPath
return field
}
set(value) {
if (!value.startsWith("jdbc:postgresql://")) {
internalProps.setProperty(pSpringDatasourceUrl, "jdbc:postgresql://$value")
} else {
internalProps.setProperty(pSpringDatasourceUrl, value)
}
field = internalProps.getProperty(pSpringDatasourceUrl)
log.info("Set database url to: $field.")
log.warn("Restart ServerPackCreator for this change to take effect.")
}
var jdbcDatabaseUsername: String = ""
get() {
field = internalProps.getProperty(pSpringDatasourceUsername, "")
return field
}
set(value) {
field = value
internalProps.setProperty(pSpringDatasourceUsername, field)
log.info("Set username url to: $field.")
log.warn("Restart ServerPackCreator for this change to take effect.")
}
var jdbcDatabasePassword: String = ""
get() {
field = internalProps.getProperty(pSpringDatasourcePassword, "")
return field
}
set(value) {
field = value
internalProps.setProperty(pSpringDatasourcePassword, field)
log.info("Set password url to: $field.")
log.warn("Restart ServerPackCreator for this change to take effect.")
}
/**
* Language used by ServerPackCreator.
*/
var language = Locale("en", "GB")
get() {
val prop = internalProps.getProperty(pLanguage)
val lang = if (prop.contains("_")) {
val split = prop.split("_")
if (split.size == 3) {
Locale(split[0], split[1], split[2])
} else {
Locale(split[0], split[1])
}
} else {
Locale(prop)
}
field = lang
i18n4kConfig.locale = field
return field
}
set(value) {
internalProps.setProperty(pLanguage, value.toTag())
i18n4kConfig.locale = value
field = value
log.info("Language set to: ${field.displayLanguage} (${field.toTag()}).")
}
/**
* URL to the HasteBin server where logs and configs are uploaded to.
*/
var hasteBinServerUrl = "https://haste.zneix.eu/documents"
get() {
field = acquireProperty(pConfigurationHasteBinServerUrl, "https://haste.zneix.eu/documents")
return field
}
set(value) {
defineProperty(pConfigurationHasteBinServerUrl, value)
field = value
log.info("HasteBin documents endpoint set to: $field")
}
/**
* Java installation used for installing the modloader server during server pack creation.
*/
var javaPath = "java"
get() {
val prop = internalProps.getProperty(pJavaForServerInstall, "")
field = if (checkJavaPath(prop)) {
prop
} else {
val acquired = acquireJavaPath()
internalProps.setProperty(pJavaForServerInstall, acquired)
acquired
}
return field
}
set(value) {
if (checkJavaPath(value)) {
internalProps.setProperty(pJavaForServerInstall, value)
field = value
log.info("Java path set to: $field")
} else {
log.error("Invalid Java path specified: $value")
}
}
var webserviceCleanupSchedule: String
get() {
return internalProps.getProperty("de.griefed.serverpackcreator.spring.schedules.database.cleanup")
}
set(value) {
internalProps.setProperty("de.griefed.serverpackcreator.spring.schedules.database.cleanup", value)
}
var webserviceVersionSchedule: String
get() {
return internalProps.getProperty("de.griefed.serverpackcreator.spring.schedules.versions.refresh")
}
set(value) {
internalProps.setProperty("de.griefed.serverpackcreator.spring.schedules.versions.refresh", value)
}
var webserviceDatabaseCleanupSchedule: String
get() {
return internalProps.getProperty("de.griefed.serverpackcreator.spring.schedules.files.cleanup")
}
set(value) {
internalProps.setProperty("de.griefed.serverpackcreator.spring.schedules.files.cleanup", value)
}
fun defaultWebserviceDatabase(): String {
return "jdbc:postgresql://localhost:5432/serverpackcreator"
}
/**
* Default home-directory for ServerPackCreator. If there's no user-home, then the directory containing the
* ServerPackCreator JAR will be used as the home-directory for ServerPackCreator.
*
* @author Griefed
*/
fun defaultHomeDirectory(): File {
return File(home, "ServerPackCreator").absoluteFile
}
/**
* ServerPackCreators home directory, in which all important files and folders are stored in.
*
* Changes made to this variable are stored in an overrides.properties inside the installation directory of the
* ServerPackCreator application.
*
* Every operation is based on this home-directory, with the exception being the
* [serverPacksDirectory], which can be configured independently of ServerPackCreators
* home-directory.
*/
var homeDirectory: File = File(home, "ServerPackCreator").absoluteFile
get() {
val prop = internalProps.getProperty(pHomeDirectory)
field = if (internalProps.containsKey(pHomeDirectory) && File(prop).absoluteFile.isDirectory) {
File(prop).absoluteFile
} else if (jarInformation.jarPath.toFile().isDirectory) {
// Dev environment
File("").absoluteFile
} else {
File(home, "ServerPackCreator").absoluteFile
}
if (!field.isDirectory) {
field.createDirectories(create = true, directory = true)
}
return field
}
set(value) {
internalProps.setProperty(pHomeDirectory, value.absolutePath)
userPreferences.put(pHomeDirectory, value.absolutePath)
field = value.absoluteFile
log.info("Home directory set to: $field")
log.warn("Restart ServerPackCreator for this change to take full effect.")
}
/**
* The `serverpackcreator.properties`-file which both resulted from starting
* ServerPackCreator and provided the settings, properties and configurations for the currently
* running instance.
*/
var serverPackCreatorPropertiesFile: File = File(homeDirectory, serverPackCreatorProperties).absoluteFile
get() {
field = File(homeDirectory, serverPackCreatorProperties).absoluteFile
return field
}
private set
/**
* Default configuration-file for a server pack generation inside ServerPackCreators
* home-directory.
*/
var defaultConfig: File = File(homeDirectory, "serverpackcreator.conf").absoluteFile
get() {
field = File(homeDirectory, "serverpackcreator.conf").absoluteFile
return field
}
private set
/**
* Directory in which ServerPackCreator configurations from the GUI get saved in by default.
*/
var configsDirectory: File = File(homeDirectory, "configs").absoluteFile
get() {
field = File(homeDirectory, "configs").absoluteFile
return field
}
private set
/**
* Base-directory for Tomcat, used by the webservice-side of ServerPackCreator.
*/
@Suppress("MemberVisibilityCanBePrivate")
var tomcatBaseDirectory: File = homeDirectory
get() {
val prop = internalProps.getProperty(pTomcatBaseDirectory, homeDirectory.absolutePath)
val dir = if (prop != homeDirectory.absolutePath) {
internalProps.setProperty(pTomcatBaseDirectory, homeDirectory.absolutePath)
homeDirectory.absolutePath
} else {
internalProps.getProperty(pTomcatBaseDirectory, homeDirectory.absolutePath)
}
field = File(dir).absoluteFile
return field
}
set(value) {
internalProps.setProperty(pTomcatBaseDirectory, value.absolutePath)
field = value.absoluteFile
log.info("Set Tomcat base-directory to: $field")
}
fun defaultTomcatBaseDirectory(): File {
return homeDirectory.absoluteFile
}
fun defaultServerPacksDirectory(): File {
return File(homeDirectory, "server-packs").absoluteFile
}
/**
* Directory in which generated server packs, or server packs being generated, are stored in, as
* well as their ZIP-archives, if created.
*
* By default, this directory will be the `server-packs`-directory in the home-directory of
* ServerPackCreator, but it can be configured using the property
* `de.griefed.serverpackcreator.configuration.directories.serverpacks` and can even be
* configured to be completely independent of ServerPackCreators home-directory.
*/
var serverPacksDirectory: File = File(homeDirectory, "server-packs")
get() {
val prop = internalProps.getProperty(pConfigurationDirectoriesServerPacks)
val directory: File = if (prop.isNullOrBlank() || prop.matches(serverPacksRegex)) {
defaultServerPacksDirectory()
} else {
File(internalProps.getProperty(pConfigurationDirectoriesServerPacks))
}
if (field.absolutePath != directory.absolutePath) {
field = directory
}
return field
}
set(value) {
internalProps.setProperty(pConfigurationDirectoriesServerPacks, value.absolutePath)
field = value.absoluteFile
log.info("Server packs directory set to: $field")
}
/**
* Storage location for logs created by ServerPackCreator. This is the `logs`-directory
* inside ServerPackCreators home-directory.
*/
var logsDirectory: File = File(homeDirectory, "logs").absoluteFile
get() {
field = File(homeDirectory, "logs").absoluteFile
return field
}
private set
/**
* Logs-directory for Tomcat, used by the webservice-side of ServerPackCreator.
*/
@Suppress("MemberVisibilityCanBePrivate")
var tomcatLogsDirectory: File = logsDirectory
get() {
val default = File(homeDirectory, "logs").absolutePath
val dir = internalProps.getProperty(pTomcatLogsDirectory, default)
field = File(dir).absoluteFile
return field
}
set(value) {
internalProps.setProperty(pTomcatLogsDirectory, value.absolutePath)
field = value.absoluteFile
log.info("Set Tomcat logs-directory to: $field")
}
fun defaultTomcatLogsDirectory(): File {
return File(homeDirectory, "logs").absoluteFile
}
/**
* Directory to which default/fallback manifests are copied to during the startup of
* ServerPackCreator.
*
* When the [de.griefed.serverpackcreator.api.versionmeta.VersionMeta] is initialized, the
* manifests copied to this directory will provide ServerPackCreator with the information required
* to check and create your server packs.
*
* By default, this is the `manifests`-directory inside ServerPackCreators home-directory.
*/
var manifestsDirectory: File = File(homeDirectory, "manifests").absoluteFile
get() {
field = File(homeDirectory, "manifests").absoluteFile
return field
}
private set
/**
* The Fabric intermediaries manifest containing all required information about Fabrics
* intermediaries. These intermediaries are used by Quilt, Fabric and LegacyFabric.
*
*
* By default, the `fabric-intermediaries-manifest.json`-file resides in the
* `manifests`-directory inside ServerPackCreators home-directory.
*/
var fabricIntermediariesManifest: File =
File(manifestsDirectory, "fabric-intermediaries-manifest.json").absoluteFile
get() {
field = File(manifestsDirectory, "fabric-intermediaries-manifest.json").absoluteFile
return field
}
private set
/**
* The LegacyFabric game version manifest containing information about which Minecraft version
* LegacyFabric is available for.
*
*
* By default, the `legacy-fabric-game-manifest.json`-file resides in the
* `manifests`-directory inside ServerPackCreators home-directory.
*/
var legacyFabricGameManifest: File = File(manifestsDirectory, "legacy-fabric-game-manifest.json").absoluteFile
get() {
field = File(manifestsDirectory, "legacy-fabric-game-manifest.json").absoluteFile
return field
}
private set
/**
* LegacyFabric loader manifest containing information about Fabric loader maven versions.
*
* By default, the `legacy-fabric-loader-manifest.json`-file resides in the
* `manifests`-directory inside ServerPackCreators home-directory.
*/
var legacyFabricLoaderManifest: File = File(manifestsDirectory, "legacy-fabric-loader-manifest.json").absoluteFile
get() {
field = File(manifestsDirectory, "legacy-fabric-loader-manifest.json").absoluteFile
return field
}
private set
/**
* LegacyFabric installer manifest containing information about available LegacyFabric installers
* with which to install a server.
*
* By default, the `legacy-fabric-installer-manifest.xml`-file resides in the
* `manifests`-directory inside ServerPackCreators home-directory.
*/
var legacyFabricInstallerManifest: File =
File(manifestsDirectory, "legacy-fabric-installer-manifest.xml").absoluteFile
get() {
field = File(manifestsDirectory, "legacy-fabric-installer-manifest.xml").absoluteFile
return field
}
private set
/**
* Fabric installer manifest containing information about available Fabric installers with which
* to install a server.
*
* By default, the `fabric-installer-manifest.xml`-file resides in the
* `manifests`-directory inside ServerPackCreators home-directory.
*/
var fabricInstallerManifest: File = File(manifestsDirectory, "fabric-installer-manifest.xml").absoluteFile
get() {
field = File(manifestsDirectory, "fabric-installer-manifest.xml").absoluteFile
return field
}
private set
/**
* Quilt version manifest containing information about available Quilt loader versions.
*
* By default, the `quilt-manifest.xml`-file resides in the `manifests`-directory
* inside ServerPackCreators home-directory.
*/
var quiltVersionManifest: File = File(manifestsDirectory, "quilt-manifest.xml").absoluteFile
get() {
field = File(manifestsDirectory, "quilt-manifest.xml").absoluteFile
return field
}
private set
/**
* Quilt installer manifest containing information about available Quilt installers with which to
* install a server.
*
* By default, the `quilt-installer-manifest.xml`-file resides in the
* `manifests`-directory inside ServerPackCreators home-directory.
*/
var quiltInstallerManifest: File = File(manifestsDirectory, "quilt-installer-manifest.xml").absoluteFile
get() {
field = File(manifestsDirectory, "quilt-installer-manifest.xml").absoluteFile
return field
}
private set
/**
* Forge version manifest containing information about available Forge loader versions.
*
*
* By default, the `forge-manifest.json`-file resides in the `manifests`-directory
* inside ServerPackCreators home-directory.
*/
var forgeVersionManifest: File = File(manifestsDirectory, "forge-manifest.json").absoluteFile
get() {
field = File(manifestsDirectory, "forge-manifest.json").absoluteFile
return field
}
private set
/**
* Old NeoForge version manifest containing information about available NeoForge loader versions.
* This manifest only contains versions for Minecraft 1.20.1.
*
*
* By default, the `neoforge-manifest.xml`-file resides in the `manifests`-directory
* inside ServerPackCreators home-directory.
*/
var oldNeoForgeVersionManifest: File = File(manifestsDirectory, "neoforge-manifest.xml").absoluteFile
get() {
field = File(manifestsDirectory, "neoforge-manifest.xml").absoluteFile
return field
}
private set
/**
* New NeoForge version manifest containing information about available NeoForge loader versions.
* This manifest contains versions for Minecraft 1.20.2 and up.
*
*
* By default, the `neoforge-manifest-new.xml`-file resides in the `manifests`-directory
* inside ServerPackCreators home-directory.
*/
var newNeoForgeVersionManifest: File = File(manifestsDirectory, "neoforge-manifest-new.xml").absoluteFile
get() {
field = File(manifestsDirectory, "neoforge-manifest-new.xml").absoluteFile
return field
}
private set
/**
* Fabric version manifest containing information about available Fabric loader versions.
*
*
* By default, the `fabric-manifest.xml`-file resides in the `manifests`-directory
* inside ServerPackCreators home-directory.
*/
var fabricVersionManifest: File = File(manifestsDirectory, "fabric-manifest.xml").absoluteFile
get() {
field = File(manifestsDirectory, "fabric-manifest.xml").absoluteFile
return field
}
private set
/**
* Directory to which Minecraft server manifests are copied during the startup of
* ServerPackCreator.
*
* When the [de.griefed.serverpackcreator.api.versionmeta.VersionMeta] is initialized, the
* manifests copied to this directory will provide ServerPackCreator with the information required
* to check and create your server packs.
*
* The Minecraft server manifests contain information about the Java version required, the
* download-URL of the server-JAR and much more.
*
* By default, this is the `mcserver`-directory inside the `manifests`-directory
* inside ServerPackCreators home-directory.
*/
var minecraftServerManifestsDirectory: File = File(manifestsDirectory, "mcserver").absoluteFile
get() {
field = File(manifestsDirectory, "mcserver").absoluteFile
return field
}
private set
/**
* Minecraft version manifest containing information about available Minecraft versions.
*
* By default, the `minecraft-manifest.json`-file resides in the `manifests`-directory
* inside ServerPackCreators home-directory.
*/
var minecraftVersionManifest: File = File(manifestsDirectory, "minecraft-manifest.json").absoluteFile
get() {
field = File(manifestsDirectory, "minecraft-manifest.json").absoluteFile
return field
}
private set
/**
* Work-directory for storing temporary, non-critical, files and directories.
*
* Any file and/or directory inside the work-directory is considered `safe-to-delete`,
* meaning that it can safely be emptied when ServerPackCreator is not running, without running
* the risk of corrupting anything. It is not recommended to empty this directory whilst
* ServerPackCreator is running, as in that case, it may interfere with any currently running
* operation.
*
* By default, this is the `work`-directory inside ServerPackCreators home-directory.
*/
var workDirectory: File = File(homeDirectory, "work").absoluteFile
get() {
field = File(homeDirectory, "work").absoluteFile
return field
}
private set
/**
* Caching directory for various types of installers. Mainly used by the version-meta for caching modloaders
* server installers, but also used as the ServerPackCreator installer cache-directory in certain scenarios.
*
* @author Griefed
*/
var installerCacheDirectory: File = File(workDirectory, "installers").absoluteFile
get() {
field = File(workDirectory, "installers").absoluteFile
return field
}
private set
/**
* Temp-directory storing files and folders required temporarily during the run of a server pack
* generation or other operations.
*
* One example would be when running ServerPackCreator as a webservice and uploading a zipped
* modpack for the automatic creation of a server pack from said modpack.
*
* Any file and/or directory inside the work-directory is considered `safe-to-delete`,
* meaning that it can safely be emptied when ServerPackCreator is not running, without running
* the risk of corrupting anything. It is not recommended to empty this directory whilst
* ServerPackCreator is running, as in that case, it may interfere with any currently running
* operation.
*
*
* By default, this directory is `work/temp` inside ServerPackCreators home-directory.
*/
var tempDirectory: File = File(workDirectory, "temp").absoluteFile
get() {
field = File(workDirectory, "temp").absoluteFile
return field
}
private set
/**
* Modpacks directory in which uploaded modpack ZIP-archives and extracted modpacks are stored.
*
* By default, this is the `modpacks`-directory inside the `temp`-directory inside
* ServerPackCreators home-directory.
*/
var modpacksDirectory: File = File(homeDirectory, "modpacks").absoluteFile
get() {
field = File(homeDirectory, "modpacks").absoluteFile
return field
}
private set
/**
* Directory in which default server-files are stored in.
*
* Default server-files are, for example, the `server.properties`, `server-icon.png`,
* `default_template.sh` and `default_template.ps1`.
*
* The properties and icon are placeholders and/or templates for the user to change to their
* liking, should they so desire. The script-templates serve as a one-size-fits-all template for
* supporting `Forge`, `Fabric`, `LegacyFabric` and `Quilt`.
*
* By default, this directory is `server_files` inside ServerPackCreators home-directory.
*/
var serverFilesDirectory: File = File(homeDirectory, "server_files").absoluteFile
get() {
field = File(homeDirectory, "server_files").absoluteFile
return field
}
private set
/**
* The default shell-template for the modded server start scripts. The file returned by this
* method does not represent the script-template in the `server_files`-directory. If you
* wish access the configured script templates inside the `server_files`-directory, use
* [scriptTemplates].
*/
val defaultShellScriptTemplate = File(serverFilesDirectory, "default_template.sh")
/**
* The default PowerShell-template for the modded server start scripts. The file returned by this
* method does not represent the script-template in the `server_files`-directory. If you
* wish access the configured script templates inside the `server_files`-directory, use
* [scriptTemplates].
*/
val defaultPowerShellScriptTemplate = File(serverFilesDirectory, "default_template.ps1")
@Suppress("MemberVisibilityCanBePrivate")
val fallbackScriptTemplates = defaultScriptTemplates().joinToString(",")
/**
* Directory in which the properties for quick selection are to be stored in and retrieved from.
*/
var propertiesDirectory: File = File(serverFilesDirectory, "properties").absoluteFile
get() {
field = File(serverFilesDirectory, "properties").absoluteFile
return field
}
private set
/**
* Directory in which the icons for quick selection are to be stored in and retrieved from.
*/
var iconsDirectory: File = File(serverFilesDirectory, "icons").absoluteFile
get() {
field = File(serverFilesDirectory, "icons").absoluteFile
return field
}
private set
/**
* Default server.properties-file used by Minecraft servers. This file resides in the
* `server_files`-directory inside ServerPackCreators home-directory.
*/
var defaultServerProperties: File = File(serverFilesDirectory, "server.properties").absoluteFile
get() {
field = File(serverFilesDirectory, "server.properties").absoluteFile
return field
}
private set
/**
* Default server-icon.png-file used by Minecraft servers. This file resides in the
* `server_files`-directory inside ServerPackCreators home-directory.
*/
var defaultServerIcon: File = File(serverFilesDirectory, "server-icon.png").absoluteFile
get() {
field = File(serverFilesDirectory, "server-icon.png").absoluteFile
return field
}
private set
/**
* Directory in which plugins for ServerPackCreator are to be placed in.
*
* This directory not only holds any potential plugins for ServerPackCreator, but also contains the
* directory in which plugin-specific config-files are stored in, as well as the
* `disabled.txt`-file, which allows a user to disable any installed plugin.
*
*
* By default, this is the `plugins`-directory inside the ServerPackCreator home-directory.
*/
var pluginsDirectory: File = File(homeDirectory, "plugins").absoluteFile
get() {
field = File(homeDirectory, "plugins").absoluteFile
return field
}
private set
/**
* Directory in which plugin-specific configurations are stored in.
*
* When ServerPackCreator starts and loads all available plugins, it will also extract a plugins
* config-file, if available. This file will be stored inside the config-directory using the ID of
* the plugin as its name, with `.toml` appended to it. Think of this like the
* config-directory in a modded Minecraft server. Do the names of the config-files there look
* familiar to the mods they belong to? Well, they should!
*
* By default, this is the `config`-directory inside the `plugins`-directory inside
* ServerPackCreators home-directory.
*/
var pluginsConfigsDirectory: File = File(pluginsDirectory, "config").absoluteFile
get() {
field = File(pluginsDirectory, "config").absoluteFile
return field
}
private set
/**
* Load the [propertiesFile] into the provided [props]
*
* @author Griefed
*/
private fun loadFile(propertiesFile: File, props: Properties) {
if (!propertiesFile.isFile) {
log.warn("Properties-file does not exist: ${propertiesFile.absolutePath}.")
return
}
props.entries.removeIf { entry -> entry.value.toString().isBlank() }
try {
val tempProps = Properties()
propertiesFile.inputStream().use {
tempProps.load(it)
}
tempProps.entries.removeIf { entry -> entry.value.toString().isBlank() }
for ((key, value) in tempProps.entries) {
props[key] = value
}
log.info("Loaded properties from $propertiesFile.")
} catch (ex: Exception) {
log.error("Couldn't read properties from ${propertiesFile.absolutePath}.", ex)
}
}
private fun loadOverrides(): Properties {
val tempProps = Properties()
val overrides = File(homeDirectory, "overrides.properties")
if (overrides.isFile) {
File(homeDirectory, "overrides.properties").inputStream().use {
tempProps.load(it)
}
}
return tempProps
}
/**
* Load properties using the default file path.
* Only call this method on an already initialized ApiProperties-object.
*
* @author Griefed
*/
fun loadProperties(saveProps: Boolean = true) {
loadProperties(serverPackCreatorPropertiesFile, saveProps)
}
/**
* Reload from a specific properties-file.
*
* @param propertiesFile The properties-file with which to loadProperties the settings and
* configuration.
* @author Griefed
*/
fun loadProperties(propertiesFile: File = File(serverPackCreatorProperties), saveProps: Boolean = true) {
val props = Properties()
val jarFolderFile = File(jarInformation.jarFolder.absoluteFile, serverPackCreatorProperties).absoluteFile
val serverPackCreatorHomeDir = File(home, "ServerPackCreator").absoluteFile
val homeDirFile = File(serverPackCreatorHomeDir, serverPackCreatorProperties).absoluteFile
val relativeDirFile = File(serverPackCreatorProperties).absoluteFile
// Load the properties file from the classpath, providing default values.
try {
javaClass.getResourceAsStream("/$serverPackCreatorProperties").use {
props.load(it)
}
log.info("Loaded properties from classpath.")
} catch (ex: Exception) {
log.error("Couldn't read properties from classpath.", ex)
}
// If our properties-file exists in SPCs home directory, load it.
loadFile(jarFolderFile, props)
// If our properties-file exists in the users home dir ServerPackCreator-dir, load it.
loadFile(homeDirFile, props)
// If our properties-file in the directory from which the user is executing SPC exists, load it.
loadFile(relativeDirFile, props)
// Load the specified properties-file.
loadFile(propertiesFile, props)
// Load all values from the overrides-properties
for (key in userPreferences.keys()) {
props[key] = userPreferences[key, null]
}
internalProps.putAll(props)
internalProps.setProperty(pTomcatBaseDirectory, homeDirectory.absolutePath)
if (internalProps.getProperty(pLanguage) != "en_GB") {
changeLocale(Locale(internalProps.getProperty(pLanguage)))
}
val overrides = loadOverrides()
for ((key, value) in overrides) {
log.warn("Overriding:")
log.warn(" $key")
log.warn(" $value")
}
internalProps.putAll(overrides)
if (updateFallback()) {
log.info("Fallback lists updated.")
} else {
setFallbackModsList()
setFallbackWhitelist()
}
if (saveProps) {
//Store properties in the configured SPC home-directory
saveProperties(serverPackCreatorPropertiesFile)
}
}
/**
* Set up our fallback list of clientside-only mods.
*
* @author Griefed
*/
private fun setFallbackModsList() {
// Regular list
clientsideMods.addAll(
getListProperty(
pConfigurationFallbackModsList,
fallbackMods.joinToString(",")
)
)
internalProps.setProperty(
pConfigurationFallbackModsList,
clientsideMods.joinToString(",")
)
}
/**
* Set up our fallback list of clientside-only mods.
*
* @author Griefed
*/
private fun setFallbackWhitelist() {
// Regular list
modsWhitelist.addAll(
getListProperty(
pConfigurationFallbackModsWhiteList,
fallbackModsWhitelist.joinToString(",")
)
)
internalProps.setProperty(
pConfigurationFallbackModsWhiteList,
fallbackModsWhitelist.joinToString(",")
)
}
/**
* Get a property from our ApplicationProperties. If the property is not available, it is created
* with the specified value, thus allowing subsequent calls.
*
* @param key The key of the property to acquire.
* @param defaultValue The default value for the specified key in case the key is not present or
* empty.
* @return The value stored in the specified key.
* @author Griefed
*/
private fun acquireProperty(key: String, defaultValue: String) =
if (internalProps.getProperty(key).isNullOrBlank()) {
defineProperty(key, defaultValue)
} else {
internalProps.getProperty(key, defaultValue)
}
/**
* Set a property in our ApplicationProperties.
*
* @param key The key in which to store the property.
* @param value The value to store in the specified key.
* @return The [value] to which the [key] was set to.
* @author Griefed
*/
private fun defineProperty(key: String, value: String): String {
internalProps.setProperty(key, value)
return value
}
/**
* Get a list from our properties.
*
* @param key The key of the property which holds the comma-separated list.
* @param defaultValue The default value to set the property to in case it is undefined.
* @return The requested list.
* @author Griefed
*/
private fun getListProperty(
key: String,
defaultValue: String
) = if (acquireProperty(key, defaultValue).contains(",")) {
acquireProperty(key, defaultValue)
.split(",")
.dropLastWhile { it.isEmpty() }
} else {
listOf(acquireProperty(key, defaultValue))
}
/**
* Join the [value] via usage of the [separator] and overwrite the [key].
* @author Griefed
*/
@Suppress("SameParameterValue")
private fun setListProperty(key: String, value: List, separator: String) {
internalProps.setProperty(key, value.joinToString(separator))
}
/**
* Get an integer from our properties.
*
* @param key The key of the property which holds the comma-separated list.
* @param defaultValue The default value to set the property to in case it is undefined.
* @return The requested integer.
* @author Griefed
*/
@Suppress("SameParameterValue")
private fun getIntProperty(key: String, defaultValue: Int) =
try {
acquireProperty(key, defaultValue.toString()).toInt()
} catch (ex: NumberFormatException) {
defineProperty(key, defaultValue.toString())
defaultValue
}
/**
* Set the integer property with the given [key] to the given [value].
*
* @author Griefed
*/
@Suppress("SameParameterValue")
private fun setIntProperty(key: String, value: Int) = defineProperty(key, value.toString())
/**
* Get a list of files from our properties, with each file having a specific prefix.
*
* @param key The key of the property which holds the comma-separated list.
* @param defaultValue The default value to set the property to in case it is undefined.
* @param filePrefix The prefix every file should receive.
* @return The requested list of files.
* @author Griefed
*/
@Suppress("SameParameterValue")
private fun getFileListProperty(key: String, defaultValue: String, filePrefix: String): List {
val files: MutableList = ArrayList(4)
val entries = getListProperty(key, defaultValue)
for (entry in entries) {
files.add(File(filePrefix + entry))
}
return files
}
/**
* Get a boolean from our properties.
*
* @param key The key of the property which holds the comma-separated list.
* @param defaultValue The default value to set the property to in case it is undefined.
* @return The requested integer.
* @author Griefed
*/
private fun getBoolProperty(key: String, defaultValue: Boolean) =
acquireProperty(key, defaultValue.toString()).toBoolean()
/**
* Set the integer property with the given [key] to the given [value].
*
* @author Griefed
*/
private fun setBoolProperty(key: String, value: Boolean) = defineProperty(key, value.toString())
/**
* Adder for the list of directories to exclude from server packs.
*
* @param entry The directory to add to the list of directories to exclude from server packs.
* @author Griefed
*/
private fun addDirectoryToExclude(entry: String) {
if (!directoriesToInclude.contains(entry) && directoriesToExclude.add(entry)) {
log.debug("Adding $entry to list of files or directories to exclude.")
}
}
/**
* Check the given path to a Java installation for validity and return it, if it is valid. If the
* passed path is a UNIX symlink or Windows lnk, it is resolved, then returned. If the passed path
* is considered invalid, the system default is acquired and returned.
*
* @param pathToJava The path to check for whether it is a valid Java installation.
* @return Returns the path to the Java installation. If user input was incorrect, SPC will try to
* acquire the path automatically.
* @author Griefed
*/
fun acquireJavaPath(pathToJava: String = ""): String {
var checkedJavaPath: String
try {
if (pathToJava.isNotEmpty()) {
if (checkJavaPath(pathToJava)) {
return pathToJava
}
if (checkJavaPath("$pathToJava.exe")) {
return "$pathToJava.exe"
}
if (checkJavaPath("$pathToJava.lnk")) {
return fileUtilities.resolveLink(File("$pathToJava.lnk"))
}
}
checkedJavaPath = systemUtilities.acquireJavaPathFromSystem()
log.debug("Acquired path to Java installation: $checkedJavaPath")
} catch (ex: NullPointerException) {
log.info("Java setting invalid or otherwise not usable. Using system default.")
checkedJavaPath = systemUtilities.acquireJavaPathFromSystem()
log.debug("Automatically acquired path to Java installation: $checkedJavaPath", ex)
} catch (ex: InvalidFileTypeException) {
log.info("Java setting invalid or otherwise not usable. Using system default.")
checkedJavaPath = systemUtilities.acquireJavaPathFromSystem()
log.debug("Automatically acquired path to Java installation: $checkedJavaPath", ex)
} catch (ex: IOException) {
log.info("Java setting invalid or otherwise not usable. Using system default.")
checkedJavaPath = systemUtilities.acquireJavaPathFromSystem()
log.debug("Automatically acquired path to Java installation: $checkedJavaPath", ex)
}
return checkedJavaPath
}
/**
* Store the ApplicationProperties to disk, overwriting the existing one.
*
* @param propertiesFile The file to store the properties to.
* @author Griefed
*/
@Suppress("MemberVisibilityCanBePrivate")
fun saveProperties(propertiesFile: File) {
cleanupInternalProps()
try {
propertiesFile.outputStream().use {
internalProps.store(
it,
"For details about each property, see https://help.serverpackcreator.de/settings-and-configs.html"
)
}
log.info("Saved properties to: $propertiesFile")
} catch (ex: IOException) {
log.error("Couldn't write properties-file.", ex)
}
}
/**
* Write the overrides-properties which, as the name implies, will override any other property loaded previously during [loadProperties].
* CAUTION: Depending on the type of installation, the overrides.properties will reside inside a directory which
* requires root/admin-privileges to write in. The directory in which this file will be created in is [getJarFolder].
*
* @author Griefed
*/
fun saveOverrides() {
userPreferences.sync()
}
/**
* Removes unwanted properties. Called during the save-operation, to ensure that legacy-properties are removed.
*
* @author Griefed
*/
private fun cleanupInternalProps() {
internalProps.remove(pConfigurationFallbackModsListRegex)
}
/**
* Check whether the given path is a valid Java specification.
*
* @param pathToJava Path to the Java executable
* @return `true` if the path is valid.
* @author Griefed
*/
private fun checkJavaPath(pathToJava: String): Boolean {
if (pathToJava.isEmpty()) {
return false
}
if (checkedJavas.containsKey(pathToJava)) {
return checkedJavas[pathToJava]!!
}
val result: Boolean
when (fileUtilities.checkFileType(pathToJava)) {
FileType.FILE -> {
result = testJava(pathToJava)
}
FileType.LINK, FileType.SYMLINK -> {
result = try {
testJava(fileUtilities.resolveLink(File(pathToJava)))
} catch (ex: InvalidFileTypeException) {
log.error("Could not read Java link/symlink.", ex)
false
} catch (ex: IOException) {
log.error("Could not read Java link/symlink.", ex)
false
}
}
FileType.DIRECTORY -> {
log.error("Directory specified. Path to Java must lead to a lnk, symlink or file.")
result = false
}
FileType.INVALID -> result = false
}
checkedJavas[pathToJava] = result
return result
}
/**
* Test for a valid Java specification by trying to run `java -version`. If the command goes
* through without errors, it is considered a correct specification.
*
* @param pathToJava Path to the java executable/binary.
* @return `true` if the specified file is a valid Java executable/binary.
* @author Griefed
*/
private fun testJava(pathToJava: String): Boolean {
val testSuccessful: Boolean = try {
val processBuilder = ProcessBuilder(listOf(pathToJava, "-version"))
processBuilder.redirectErrorStream(true)
val process = processBuilder.start()
val bufferedReader = BufferedReader(InputStreamReader(process.inputStream))
while (bufferedReader.readLine() != null && bufferedReader.readLine() != "null") {
println(bufferedReader.readLine())
}
bufferedReader.close()
process.destroyForcibly()
true
} catch (e: IOException) {
log.error("Invalid Java specified.")
false
}
return testSuccessful
}
/**
* Whether a viable path to a Java executable or binary has been configured for
* ServerPackCreator.
*
* @return `true` if a viable path has been set.
* @author Griefed
*/
fun javaAvailable() = checkJavaPath(javaPath)
/**
* Writes the specified locale from -lang your_locale to a lang.properties file to ensure every
* subsequent start of serverpackcreator is executed using said locale.
*
* @param locale The locale the user specified when they ran serverpackcreator with -lang
* -your_locale.
* @author Griefed
*/
fun changeLocale(locale: Locale) {
language = locale
saveProperties(serverPackCreatorPropertiesFile)
log.info("Changed locale to $language")
}
/**
* Acquire the default fallback list of clientside-only mods. If
* `de.griefed.serverpackcreator.serverpack.autodiscovery.filter` is set to
* [ExclusionFilter.REGEX], a regex fallback list is returned.
*
* @return The fallback list of clientside-only mods.
* @author Griefed
*/
fun clientSideMods() =
if (exclusionFilter == ExclusionFilter.REGEX) {
clientsideModsRegex.toList()
} else {
clientsideMods.toList()
}
/**
* Acquire the default fallback list of whitelisted mods. If
* `de.griefed.serverpackcreator.serverpack.autodiscovery.filter` is set to
* [ExclusionFilter.REGEX], a regex fallback list is returned.
*
* @return The fallback list of whitelisted mods.
* @author Griefed
*/
fun whitelistedMods() =
if (exclusionFilter == ExclusionFilter.REGEX) {
modsWhitelistRegex.toList()
} else {
modsWhitelist.toList()
}
/**
* Update the fallback clientside-only mod-list of our `serverpackcreator.properties` from
* the main-repository or one of its mirrors.
*
* @return `true` if the fallback-property was updated.
* @author Griefed
*/
@Suppress("MemberVisibilityCanBePrivate")
fun updateFallback(): Boolean {
var properties: Properties? = null
try {
URI(
acquireProperty(pConfigurationFallbackUpdateURL, fallbackUpdateURL)
).toURL().openStream().use {
properties = Properties()
properties!!.load(it)
}
} catch (e: IOException) {
log.debug("GitHub could not be reached.", e)
}
var updated = false
if (properties != null) {
if (properties!!.getProperty(pConfigurationFallbackModsList) != null &&
internalProps.getProperty(pConfigurationFallbackModsList)
!= properties!!.getProperty(pConfigurationFallbackModsList)
) {
internalProps.setProperty(
pConfigurationFallbackModsList,
properties!!.getProperty(pConfigurationFallbackModsList)
)
clientsideMods.clear()
clientsideMods.addAll(internalProps.getProperty(pConfigurationFallbackModsList).split(","))
log.info("The fallback-list for clientside only mods has been updated to: $clientsideMods")
updated = true
}
if (properties!!.getProperty(pConfigurationFallbackModsWhiteList) != null &&
internalProps.getProperty(pConfigurationFallbackModsWhiteList)
!= properties!!.getProperty(pConfigurationFallbackModsWhiteList)
) {
internalProps.setProperty(
pConfigurationFallbackModsWhiteList,
properties!!.getProperty(pConfigurationFallbackModsWhiteList)
)
modsWhitelist.clear()
modsWhitelist.addAll(internalProps.getProperty(pConfigurationFallbackModsWhiteList).split(","))
log.info("The fallback-list for whitelisted mods has been updated to: $modsWhitelist")
updated = true
}
}
if (updated) {
saveProperties(File(homeDirectory, serverPackCreatorProperties).absoluteFile)
}
return updated
}
/**
* Store a custom property in the serverpackcreator.properties-file. Beware that every property you add
* receives a prefix, to prevent clashes with any other properties.
*
* Said prefix consists of `custom.property.` followed by the property you specified coming in last.
*
* Say you have a value in the property `saved`, then the resulting property in the serverpackcreator.properties
* would be:
* * `custom.property.saved`
*
* @author Griefed
*/
fun storeCustomProperty(property: String, value: String): String {
val customProp = "$customPropertyPrefix$property"
return defineProperty(customProp, value)
}
/**
* Retrieve a custom property in the serverpackcreator.properties-file. Beware that every property you retrieve this
* way contains a prefix, to prevent clashes with any other properties.
*
* Said prefix consists of `custom.property.` followed by the property you specified coming in last.
*
* Say you have a property `saved`, then the resulting property in the serverpackcreator.properties would be:
* `custom.property.saved`
*
* @author Griefed
*/
fun retrieveCustomProperty(property: String): String? {
val customProp = "$customPropertyPrefix$property"
return internalProps.getProperty(customProp)
}
/**
* Get the path to the specified Java executable/binary, wrapped in an [Optional] for your
* convenience.
*
* @param javaVersion The Java version to acquire the path for.
* @return The path to the Java executable/binary, if available.
* @author Griefed
*/
fun javaPath(javaVersion: Int) =
if (javaPaths.containsKey(javaVersion.toString())
&& javaPaths[javaVersion.toString()]?.let { File(it).isFile } == true
) {
Optional.ofNullable(javaPaths[javaVersion.toString()])
} else {
Optional.empty()
}
/**
* Get the path to the specified Java executable/binary, wrapped in an [Optional] for your
* convenience.
*
* @param javaVersion The Java version to acquire the path for.
* @return The path to the Java executable/binary, if available.
* @author Griefed
*/
fun javaPath(javaVersion: String) = javaPath(javaVersion.toInt())
/**
* Set the old version of ServerPackCreator used to perform necessary migrations between the old
* and the current version.
*
* @param version Old version used before upgrading to the current version.
* @author Griefed
*/
fun setOldVersion(version: String) {
internalProps.setProperty(pOldVersion, version)
saveProperties(serverPackCreatorPropertiesFile)
}
/**
* Get the old version of ServerPackCreator used to perform necessary migrations between the old
* and the current version.
*
* @return Old version used before updating. Empty if this is the first run of ServerPackCreator.
*/
fun oldVersion(): String = internalProps.getProperty(pOldVersion, "")
init {
serverFilesDirectory.createDirectories(create = true, directory = true)
propertiesDirectory.createDirectories(create = true, directory = true)
iconsDirectory.createDirectories(create = true, directory = true)
configsDirectory.createDirectories(create = true, directory = true)
workDirectory.createDirectories(create = true, directory = true)
tempDirectory.createDirectories(create = true, directory = true)
modpacksDirectory.createDirectories(create = true, directory = true)
serverPacksDirectory.createDirectories(create = true, directory = true)
pluginsDirectory.createDirectories(create = true, directory = true)
pluginsConfigsDirectory.createDirectories(create = true, directory = true)
manifestsDirectory.createDirectories(create = true, directory = true)
minecraftServerManifestsDirectory.createDirectories(create = true, directory = true)
installerCacheDirectory.createDirectories(create = true, directory = true)
printSettings()
}
@Suppress("MemberVisibilityCanBePrivate")
fun printSettings() {
log.info("============================== PROPERTIES ==============================")
log.info("Set Aikars flags to: $aikarsFlags")
log.info("Set database path to: $jdbcDatabaseUrl")
log.info("Home directory set to: $homeDirectory")
log.info("Language set to: ${language.displayLanguage} (${language.toTag()})")
log.info("Java path set to: $javaPath")
log.info("Set Tomcat base-directory to: $tomcatBaseDirectory")
log.info("Server packs directory set to: $serverPacksDirectory")
log.info("Set Tomcat logs-directory to: $tomcatLogsDirectory")
log.info("Checking for pre-releases set to: $isCheckingForPreReleasesEnabled")
log.info("Zip-file exclusion enabled set to: $isZipFileExclusionEnabled")
log.info("HasteBin documents endpoint set to: $hasteBinServerUrl")
log.info("Directories which must always be included set to: $directoriesToInclude")
log.info("Directories which must always be excluded set to: $directoriesToExclude")
log.info("Cleanup of already existing server packs set to: $isServerPackCleanupEnabled")
log.info("Auto-discovery of clientside-only mods set to: $isAutoExcludingModsEnabled")
log.info("Overwriting of already existing server packs set to: $isServerPacksOverwriteEnabled")
log.info("Minecraft pre-releases and snapshots available set to: $isMinecraftPreReleasesAvailabilityEnabled")
log.info("Files which must be excluded from ZIP-archives set to: $zipArchiveExclusions")
log.info("User specified clientside-only mod exclusion filter set to: $exclusionFilter")
log.info("Automatically update SPC_JAVA_SPC-placeholder in script variables table set to: $isJavaScriptAutoupdateEnabled")
log.info("Clientside-mods set to:")
listUtilities.printListToLogChunked(clientsideMods.toList(), 5, " ", true)
log.info("Regex clientside-mods-list set to:")
listUtilities.printListToLogChunked(clientsideModsRegex.toList(), 5, " ", true)
log.info("Available Java paths for scripts:")
for ((key, value) in javaPaths) {
log.info(" Java $key path: $value")
}
log.info("Using script templates:")
for (template in scriptTemplates) {
log.info(" " + template.path)
}
log.info("============================== PROPERTIES ==============================")
}
init {
System.setProperty("user.dir", homeDirectory.absolutePath)
saveProperties(File(homeDirectory, serverPackCreatorProperties).absoluteFile)
}
actual companion object {
/**
* @author Griefed
*/
@JvmStatic
actual fun getSeparator(): String {
return File.separator
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy