From 2f24e13c9314055a2adf332b4457648d137f3cd3 Mon Sep 17 00:00:00 2001 From: Bixilon Date: Tue, 17 Jan 2023 14:11:52 +0100 Subject: [PATCH] wip use Path over String --- .../minosoft/assets/util/FileAssetsTypes.kt | 21 ++++++ .../minosoft/assets/util/FileAssetsUtil.kt | 8 +-- .../config/profile/GlobalProfileManager.kt | 11 ++- .../minosoft/config/profile/ProfileManager.kt | 9 +-- .../gui/eros/crash/ErosCrashReport.kt | 5 +- .../gui/rendering/util/ScreenshotTaker.kt | 16 ++--- .../minosoft/modding/loader/ModLoader.kt | 6 +- .../minosoft/terminal/CommandLineArguments.kt | 15 ++++ .../minosoft/terminal/RunConfiguration.kt | 69 +++++++++++++------ .../util/crash/section/RuntimeSection.kt | 3 +- 10 files changed, 112 insertions(+), 51 deletions(-) create mode 100644 src/main/java/de/bixilon/minosoft/assets/util/FileAssetsTypes.kt diff --git a/src/main/java/de/bixilon/minosoft/assets/util/FileAssetsTypes.kt b/src/main/java/de/bixilon/minosoft/assets/util/FileAssetsTypes.kt new file mode 100644 index 000000000..1662025ae --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/assets/util/FileAssetsTypes.kt @@ -0,0 +1,21 @@ +/* + * Minosoft + * Copyright (C) 2020-2023 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.assets.util + +object FileAssetsTypes { + const val GAME = "game" + const val SKINS = "skins" + const val SOUNDS = "sounds" + const val PIXLYZER = "pixlyzer" +} diff --git a/src/main/java/de/bixilon/minosoft/assets/util/FileAssetsUtil.kt b/src/main/java/de/bixilon/minosoft/assets/util/FileAssetsUtil.kt index 88c1c66cc..4280aa40e 100644 --- a/src/main/java/de/bixilon/minosoft/assets/util/FileAssetsUtil.kt +++ b/src/main/java/de/bixilon/minosoft/assets/util/FileAssetsUtil.kt @@ -29,20 +29,20 @@ import de.bixilon.minosoft.util.KUtil import java.io.* import java.net.URL import java.nio.file.Files +import java.nio.file.Path import java.security.MessageDigest object FileAssetsUtil { - private val EMPTY_BYTE_ARRAY = ByteArray(0) - private val BASE_PATH = RunConfiguration.HOME_DIRECTORY + "assets/objects/" + var BASE_PATH = RunConfiguration.HOME_DIRECTORY.resolve("assets/") - fun getPath(hash: String): String { + fun getPath(type: String, hash: String): Path { if (hash.length <= 10) { throw IllegalArgumentException("Hash too short: $hash") } if (!hash.isHexString) { throw IllegalArgumentException("String is not a hex string. Invalid data or manipulated?: $hash") } - return BASE_PATH + hash.substring(0, 2) + "/" + hash + return BASE_PATH.resolve(type).resolve(hash.substring(0, 2)).resolve(hash) } fun downloadAsset(url: String, compress: Boolean = true, hashType: HashTypes = HashTypes.SHA256): String { diff --git a/src/main/java/de/bixilon/minosoft/config/profile/GlobalProfileManager.kt b/src/main/java/de/bixilon/minosoft/config/profile/GlobalProfileManager.kt index dedd54b82..6e31cf595 100644 --- a/src/main/java/de/bixilon/minosoft/config/profile/GlobalProfileManager.kt +++ b/src/main/java/de/bixilon/minosoft/config/profile/GlobalProfileManager.kt @@ -13,7 +13,6 @@ package de.bixilon.minosoft.config.profile -import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.databind.type.MapType import de.bixilon.kutil.cast.CastUtil.unsafeCast import de.bixilon.kutil.collections.CollectionUtil.lockMapOf @@ -41,13 +40,12 @@ import de.bixilon.minosoft.data.registries.identified.ResourceLocation import de.bixilon.minosoft.gui.eros.crash.ErosCrashReport.Companion.crash import de.bixilon.minosoft.terminal.RunConfiguration import de.bixilon.minosoft.util.json.Jackson -import de.bixilon.minosoft.util.json.ResourceLocationSerializer import de.bixilon.minosoft.util.logging.Log import de.bixilon.minosoft.util.logging.LogLevels import de.bixilon.minosoft.util.logging.LogMessageType -import java.io.File object GlobalProfileManager { + private val SELECTED_PROFILES_PATH = RunConfiguration.CONFIG_DIRECTORY.resolve("selected_profiles.json").toFile() val DEFAULT_MANAGERS: Map> private val SELECTED_PROFILES_TYPE: MapType = Jackson.MAPPER.typeFactory.constructMapType(HashMap::class.java, ResourceLocation::class.java, String::class.java) val CLASS_MAPPING: Map, ProfileManager<*>> @@ -87,13 +85,12 @@ object GlobalProfileManager { private fun loadSelectedProfiles() { selectedProfiles.lock.lock() try { - val file = File(RunConfiguration.HOME_DIRECTORY + "config/selected_profiles.json") - if (!file.exists()) { + if (!SELECTED_PROFILES_PATH.exists()) { return } this.selectedProfiles.unsafe.clear() - this.selectedProfiles.unsafe.putAll(Jackson.MAPPER.readValue(file.read(), SELECTED_PROFILES_TYPE)) + this.selectedProfiles.unsafe.putAll(Jackson.MAPPER.readValue(SELECTED_PROFILES_PATH.read(), SELECTED_PROFILES_TYPE)) } finally { selectedProfiles.lock.unlock() } @@ -109,7 +106,7 @@ object GlobalProfileManager { val data: Map = Jackson.MAPPER.convertValue(selectedProfiles.unsafe, SELECTED_PROFILES_TYPE) val jsonString = Jackson.MAPPER.writerWithDefaultPrettyPrinter().writeValueAsString(data) - FileUtil.safeSaveToFile(File(RunConfiguration.HOME_DIRECTORY + "config/selected_profiles.json"), jsonString) + FileUtil.safeSaveToFile(SELECTED_PROFILES_PATH, jsonString) selectedProfilesChanges = false } catch (exception: Exception) { exception.crash() diff --git a/src/main/java/de/bixilon/minosoft/config/profile/ProfileManager.kt b/src/main/java/de/bixilon/minosoft/config/profile/ProfileManager.kt index 742a78588..fe4f913e5 100644 --- a/src/main/java/de/bixilon/minosoft/config/profile/ProfileManager.kt +++ b/src/main/java/de/bixilon/minosoft/config/profile/ProfileManager.kt @@ -37,6 +37,7 @@ import org.kordamp.ikonli.fontawesome5.FontAwesomeSolid import java.io.File import java.io.FileNotFoundException import java.io.IOException +import java.nio.file.Path import java.nio.file.StandardWatchEventKinds import java.util.concurrent.locks.ReentrantLock @@ -57,11 +58,11 @@ interface ProfileManager { val profiles: AbstractMutableBiMap var selected: T - val baseDirectory: File - get() = File(RunConfiguration.HOME_DIRECTORY + "config/" + namespace.namespace + "/") + val baseDirectory: Path + get() = RunConfiguration.CONFIG_DIRECTORY.resolve(namespace.namespace) - fun getPath(profileName: String, baseDirectory: File = this.baseDirectory): String { - return baseDirectory.path + "/" + profileName + "/" + namespace.path + ".json" + fun getPath(profileName: String, baseDirectory: Path = this.baseDirectory): Path { + return baseDirectory.resolve(profileName).resolve(namespace.path + ".json") } /** diff --git a/src/main/java/de/bixilon/minosoft/gui/eros/crash/ErosCrashReport.kt b/src/main/java/de/bixilon/minosoft/gui/eros/crash/ErosCrashReport.kt index 344829126..66252befe 100644 --- a/src/main/java/de/bixilon/minosoft/gui/eros/crash/ErosCrashReport.kt +++ b/src/main/java/de/bixilon/minosoft/gui/eros/crash/ErosCrashReport.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2022 Moritz Zwerger + * Copyright (C) 2020-2023 Moritz Zwerger * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * @@ -42,7 +42,6 @@ import javafx.scene.text.TextFlow import javafx.stage.Modality import javafx.stage.Stage import javafx.stage.Window -import java.io.File import java.io.FileOutputStream import java.nio.charset.StandardCharsets import java.text.SimpleDateFormat @@ -118,7 +117,7 @@ class ErosCrashReport : JavaFXWindowController() { var crashReportPath: String? try { - val crashReportFolder = File(RunConfiguration.HOME_DIRECTORY + "crash-reports") + val crashReportFolder = RunConfiguration.HOME_DIRECTORY.resolve("crash-reports").toFile() crashReportFolder.mkdirs() crashReportPath = "${crashReportFolder.slashPath}/crash-${SimpleDateFormat("yyyy-MM-dd-HH.mm.ss").format(millis())}.txt" diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/util/ScreenshotTaker.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/util/ScreenshotTaker.kt index dea372866..574d707ce 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/util/ScreenshotTaker.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/util/ScreenshotTaker.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2022 Moritz Zwerger + * Copyright (C) 2020-2023 Moritz Zwerger * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * @@ -19,7 +19,6 @@ import de.bixilon.kutil.concurrent.pool.ThreadPool import de.bixilon.kutil.concurrent.pool.ThreadPoolRunnable import de.bixilon.kutil.file.FileUtil.createParent import de.bixilon.kutil.file.FileUtil.slashPath -import de.bixilon.kutil.time.TimeUtil import de.bixilon.kutil.time.TimeUtil.millis import de.bixilon.minosoft.data.text.BaseComponent import de.bixilon.minosoft.data.text.TextComponent @@ -33,7 +32,6 @@ import de.bixilon.minosoft.gui.rendering.gui.gui.screen.menu.confirmation.Delete import de.bixilon.minosoft.gui.rendering.system.base.PixelTypes import de.bixilon.minosoft.terminal.RunConfiguration import java.awt.image.BufferedImage -import java.io.File import java.text.SimpleDateFormat import javax.imageio.ImageIO @@ -47,11 +45,13 @@ class ScreenshotTaker( val height = context.window.size.y val buffer = context.renderSystem.readPixels(Vec2i(0, 0), Vec2i(width, height), PixelTypes.RGBA) - val basePath = "${RunConfiguration.HOME_DIRECTORY}/screenshots/${context.connection.address.hostname}/${DATE_FORMATTER.format(millis())}" - var path = "$basePath.png" + val path = RunConfiguration.HOME_DIRECTORY.resolve("screenshots").resolve(context.connection.address.hostname) + + val timestamp = DATE_FORMATTER.format(millis()) + var filename = "$timestamp.png" var i = 1 - while (File(path).exists()) { - path = "${basePath}_${i++}.png" + while (path.resolve(filename).toFile().exists()) { + filename = "${timestamp}_${i++}.png" if (i > MAX_FILES_CHECK) { throw StackOverflowError("There are already > $MAX_FILES_CHECK screenshots with this date! Please try again later!") } @@ -71,7 +71,7 @@ class ScreenshotTaker( } } - val file = File(path) + val file = path.resolve(filename).toFile() file.createParent() ImageIO.write(bufferedImage, "png", file) diff --git a/src/main/java/de/bixilon/minosoft/modding/loader/ModLoader.kt b/src/main/java/de/bixilon/minosoft/modding/loader/ModLoader.kt index 9cd3776a9..374f3b3fb 100644 --- a/src/main/java/de/bixilon/minosoft/modding/loader/ModLoader.kt +++ b/src/main/java/de/bixilon/minosoft/modding/loader/ModLoader.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2022 Moritz Zwerger + * Copyright (C) 2020-2023 Moritz Zwerger * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * @@ -31,7 +31,7 @@ import kotlin.reflect.jvm.javaField object ModLoader { - private val BASE_PATH = RunConfiguration.HOME_DIRECTORY + "mods/" + private val BASE_PATH = RunConfiguration.HOME_DIRECTORY.resolve("mods") private var latch: CountUpAndDownLatch? = null val mods = ModList() var currentPhase by observed(LoadingPhases.PRE_BOOT) @@ -39,7 +39,7 @@ object ModLoader { var state by observed(PhaseStates.WAITING) private set - private val LoadingPhases.path: File get() = File(BASE_PATH + name.lowercase()) + private val LoadingPhases.path: File get() = BASE_PATH.resolve(name.lowercase()).toFile() private fun createDirectories() { val created: MutableList = mutableListOf() diff --git a/src/main/java/de/bixilon/minosoft/terminal/CommandLineArguments.kt b/src/main/java/de/bixilon/minosoft/terminal/CommandLineArguments.kt index 5b8183a95..60f3a5711 100644 --- a/src/main/java/de/bixilon/minosoft/terminal/CommandLineArguments.kt +++ b/src/main/java/de/bixilon/minosoft/terminal/CommandLineArguments.kt @@ -15,6 +15,7 @@ package de.bixilon.minosoft.terminal import de.bixilon.kutil.shutdown.AbstractShutdownReason import de.bixilon.kutil.shutdown.ShutdownManager +import de.bixilon.minosoft.assets.util.FileAssetsUtil import de.bixilon.minosoft.data.registries.identified.ResourceLocation import de.bixilon.minosoft.modding.loader.parameters.ModParameters import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition @@ -26,6 +27,7 @@ import net.sourceforge.argparse4j.impl.Arguments import net.sourceforge.argparse4j.inf.ArgumentParserException import net.sourceforge.argparse4j.inf.Namespace import java.io.PrintWriter +import java.nio.file.Path object CommandLineArguments { lateinit var ARGUMENTS: List @@ -92,6 +94,14 @@ object CommandLineArguments { addArgument("--mod_parameters") .action(Arguments.store()) .help("JSON of custom mod parameters") + + addArgument("--home") + .action(Arguments.store()) + .help("Home path of minosoft") + + addArgument("--assets") + .action(Arguments.store()) + .help("Path where assets are stored") } fun parse(args: Array) { @@ -137,5 +147,10 @@ object CommandLineArguments { RunConfiguration.IGNORE_YGGDRASIL = namespace.getBoolean("ignore_yggdrasil") RunConfiguration.IGNORE_MODS = namespace.getBoolean("ignore_mods") namespace.getString("mod_parameters")?.let { RunConfiguration.MOD_PARAMETERS = Jackson.MAPPER.readValue(it, ModParameters::class.java) } + + + + namespace.getString("home")?.let { RunConfiguration.setHome(Path.of(it)) } + namespace.getString("assets")?.let { FileAssetsUtil.BASE_PATH = Path.of(it) } } } diff --git a/src/main/java/de/bixilon/minosoft/terminal/RunConfiguration.kt b/src/main/java/de/bixilon/minosoft/terminal/RunConfiguration.kt index cd90fe470..a297fa1af 100644 --- a/src/main/java/de/bixilon/minosoft/terminal/RunConfiguration.kt +++ b/src/main/java/de/bixilon/minosoft/terminal/RunConfiguration.kt @@ -14,13 +14,13 @@ package de.bixilon.minosoft.terminal import com.google.common.base.StandardSystemProperty -import de.bixilon.kutil.file.FileUtil.slashPath +import de.bixilon.kutil.cast.CastUtil.unsafeNull import de.bixilon.kutil.os.OSTypes import de.bixilon.kutil.os.PlatformInfo import de.bixilon.minosoft.data.registries.identified.ResourceLocation import de.bixilon.minosoft.modding.loader.parameters.ModParameters -import java.io.File import java.io.IOException +import java.nio.file.Path object RunConfiguration { var LOG_COLOR_MESSAGE = true // The message (after all prefixes) should be colored with ANSI color codes @@ -35,27 +35,17 @@ object RunConfiguration { var AUTO_CONNECT_TO: String? = null - var HOME_DIRECTORY: String = let { - // Sets Config.homeDir to the correct folder per OS - var homeDir: String = System.getProperty(StandardSystemProperty.USER_HOME.key()) - if (!homeDir.endsWith(File.separator)) { - homeDir += "/" - } - homeDir += when (PlatformInfo.OS) { - OSTypes.LINUX -> ".local/share/minosoft/" - OSTypes.WINDOWS -> "AppData/Roaming/Minosoft/" - OSTypes.MAC -> "Library/Application Support/Minosoft/" - else -> ".minosoft/" - } - val folder = File(homeDir) - if (!folder.exists() && !folder.mkdirs()) { - // failed creating folder - throw IOException("Could not create home folder ($homeDir)!") - } - folder.slashPath + "/" + var HOME_DIRECTORY: Path = unsafeNull() + private set + var CONFIG_DIRECTORY: Path = unsafeNull() + private set + + init { + setDefaultHome() } - val TEMPORARY_FOLDER = System.getProperty("java.io.tmpdir", "$HOME_DIRECTORY/tmp/") + "/minosoft/" + + val TEMPORARY_FOLDER: Path = Path.of(System.getProperty("java.io.tmpdir") ?: "$HOME_DIRECTORY/tmp/", "/minosoft/") val X_START_ON_FIRST_THREAD_SET = System.getenv("JAVA_STARTED_ON_FIRST_THREAD_${ProcessHandle.current().pid()}") == "1" @@ -71,4 +61,41 @@ object RunConfiguration { var IGNORE_MODS = false var MOD_PARAMETERS = ModParameters() + + + private fun setDefaultHome() { + val user = System.getProperty(StandardSystemProperty.USER_HOME.key()) ?: throw IllegalStateException("Can not get user home!") + + val home = Path.of(user, when (PlatformInfo.OS) { + OSTypes.LINUX -> ".local/share/minosoft/" + OSTypes.WINDOWS -> "AppData/Roaming/Minosoft/" + OSTypes.MAC -> "Library/Application Support/Minosoft/" + else -> ".minosoft/" + }) + setHome(home) + + val config = when (PlatformInfo.OS) { + OSTypes.LINUX -> Path.of(user, ".config/minosoft") + else -> home + } + setConfig(config) + } + + fun setHome(path: Path) { + val folder = path.toFile() + + if (!folder.exists() && !folder.mkdirs()) { + throw IOException("Can not create home directory: $path") + } + HOME_DIRECTORY = path + } + + fun setConfig(path: Path) { + val folder = path.toFile() + + if (!folder.exists() && !folder.mkdirs()) { + throw IOException("Can not create home directory: $path") + } + CONFIG_DIRECTORY = path + } } diff --git a/src/main/java/de/bixilon/minosoft/util/crash/section/RuntimeSection.kt b/src/main/java/de/bixilon/minosoft/util/crash/section/RuntimeSection.kt index 66164b89f..cca4e0bdb 100644 --- a/src/main/java/de/bixilon/minosoft/util/crash/section/RuntimeSection.kt +++ b/src/main/java/de/bixilon/minosoft/util/crash/section/RuntimeSection.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2022 Moritz Zwerger + * Copyright (C) 2020-2023 Moritz Zwerger * * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. * @@ -23,5 +23,6 @@ class RuntimeSection : CrashSection( "JVM flags" to ManagementFactory.getRuntimeMXBean().inputArguments, "Environment" to System.getenv(), "Home directory" to RunConfiguration.HOME_DIRECTORY, + "Config directory" to RunConfiguration.CONFIG_DIRECTORY, ) )