diff --git a/README.md b/README.md
index f982389..849cfc2 100644
--- a/README.md
+++ b/README.md
@@ -1,27 +1,48 @@
-# Options Profiles
+# [1.18.2] Options Profiles
[](https://modrinth.com/mod/options-profiles)
[](https://curseforge.com/minecraft/mc-mods/options-profiles)
-[](https://github.com/AxolotlMaid/options-profiles)
+[](https://github.com/AxolotlMaid/options-profiles)
----
-
-### ⚠️⚠️ Mod requires Architectury API ⚠️⚠️
-
-Options Profiles lets you load and save your options as profiles from in-game.
-
-You may use this mod in modpacks.
+Options Profiles is a Minecraft mod that lets you load and save your options as profiles from in-game.
## Features
-- Profiles are saved in a folder called "options-profiles" in the specified ".minecraft" directory.
-- Sodium support
-- Forge, Fabric and Quilt support
-- Resource packs support
-- Save current options
-- Edit profiles in-game (deleting, renaming, overwriting)
+- Save and load profiles in-game
+- Load specific options (like only load keybinds, resource packs or FOV and GUI scale)
+- Edit profiles in-game (deleting, renaming, overwriting, pick options to only load)
+- Fabric and Forge support
+- Third party mod support (see below)
+
+## Mod Support
+Options Profiles supports these mods which means you can create and load profiles with them and the mod will load their configuration.
+
+- Sodium
+- Sodium Extra
+- Embeddium
+- Distant Horizons
+- OptiFine
+
+If you would like support for another mod, open an issue.
+
+## Frequently Asked Questions
+- Can you port [version]?
+ > Open an issue in the GitHub repository.
+- Can I use this in my modpack?
+ > You may use this mod in modpacks with credit.
+- Where are the profiles saved?
+ > Profiles are saved in a folder called "options-profiles" in the specified ".minecraft" directory.
+- Where can I find the source code for older versions?
+ > You can find them in the branches.
+- Dependencies?
+ > Versions 1.1 require Architectury API, however versions 1.2+ do not.
+- For any other questions, create an issue or contact me at hello@axolotlmaid.com
## Gallery
-Profiles Menu | Edit Profile Screen | Options Screen
-:-------------------------:|:-------------------------:|:-------------------------:
-
|
|
+Profiles Menu | Edit Profile Screen
+:-------------------------:|:-------------------------:
+
|
+
+Options Toggle Menu | Options Screen
+:-------------------------:|:-------------------------:
+
|
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
index ed3778d..ef97479 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,40 +1,28 @@
plugins {
- id "architectury-plugin" version "3.4-SNAPSHOT"
- id "dev.architectury.loom" version "1.4-SNAPSHOT" apply false
+ id 'dev.architectury.loom' version '1.6-SNAPSHOT' apply false
+ id 'architectury-plugin' version '3.4-SNAPSHOT'
+ id 'com.github.johnrengelman.shadow' version '8.1.1' apply false
}
architectury {
- minecraft = rootProject.minecraft_version
-}
-
-subprojects {
- apply plugin: "dev.architectury.loom"
-
- loom {
- silentMojangMappingsLicense()
- }
-
- dependencies {
- minecraft "com.mojang:minecraft:${rootProject.minecraft_version}"
- // The following line declares the mojmap mappings, you may use other mappings as well
- mappings loom.officialMojangMappings()
- // The following line declares the yarn mappings you may select this one as well.
- // mappings "net.fabricmc:yarn:1.20.1+build.10:v2"
- }
+ minecraft = project.minecraft_version
}
allprojects {
- apply plugin: "java"
- apply plugin: "architectury-plugin"
- apply plugin: "maven-publish"
+ group = rootProject.maven_group
+ version = rootProject.mod_version
+}
+
+subprojects {
+ apply plugin: 'dev.architectury.loom'
+ apply plugin: 'architectury-plugin'
+ apply plugin: 'maven-publish'
base {
- archivesName = rootProject.archives_base_name
+ // Set up a suffixed format for the mod jar names, e.g. `example-fabric`.
+ archivesName = "$rootProject.archives_name-$project.name"
}
- version = rootProject.mod_version
- group = rootProject.maven_group
-
repositories {
// Add repositories to retrieve artifacts from in here.
// You should only use this when depending on other mods because
@@ -43,12 +31,44 @@ allprojects {
// for more information about repositories.
}
- tasks.withType(JavaCompile) {
- options.encoding = "UTF-8"
- options.release = 17
+ loom {
+ silentMojangMappingsLicense()
+ }
+
+ dependencies {
+ minecraft "net.minecraft:minecraft:$rootProject.minecraft_version"
+ mappings loom.officialMojangMappings()
}
java {
+ // Loom will automatically attach sourcesJar to a RemapSourcesJar task and to the "build" task
+ // if it is present.
+ // If you remove this line, sources will not be generated.
withSourcesJar()
+
+ sourceCompatibility = JavaVersion.VERSION_17
+ targetCompatibility = JavaVersion.VERSION_17
+ }
+
+ tasks.withType(JavaCompile).configureEach {
+ it.options.release = 17
+ }
+
+ // Configure Maven publishing.
+ publishing {
+ publications {
+ mavenJava(MavenPublication) {
+ artifactId = base.archivesName.get()
+ from components.java
+ }
+ }
+
+ // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
+ repositories {
+ // Add repositories to publish to here.
+ // Notice: This block does NOT have the same function as the block in the top level.
+ // The repositories here will be used for publishing your artifact, not for
+ // retrieving dependencies.
+ }
}
}
diff --git a/common/build.gradle b/common/build.gradle
index 744ed58..44fd481 100644
--- a/common/build.gradle
+++ b/common/build.gradle
@@ -1,9 +1,5 @@
architectury {
- common(rootProject.enabled_platforms.split(","))
-}
-
-loom {
- accessWidenerPath = file("src/main/resources/optionsprofiles.accesswidener")
+ common rootProject.enabled_platforms.split(',')
}
repositories {
@@ -21,26 +17,14 @@ repositories {
}
dependencies {
- // We depend on fabric loader here to use the fabric @Environment annotations and get the mixin dependencies
- // Do NOT use other classes from fabric loader
- modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
- // Remove the next line if you don't want to depend on the API
- modApi "dev.architectury:architectury:${rootProject.architectury_version}"
+ // We depend on Fabric Loader here to use the Fabric @Environment annotations,
+ // which get remapped to the correct annotations on each platform.
+ // Do NOT use other classes from Fabric Loader.
+ modImplementation "net.fabricmc:fabric-loader:$rootProject.fabric_loader_version"
- // sodium
- modImplementation "maven.modrinth:sodium:mc1.18.2-0.4.1"
-}
-
-publishing {
- publications {
- mavenCommon(MavenPublication) {
- artifactId = rootProject.archives_base_name
- from components.java
- }
- }
-
- // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
- repositories {
- // Add repositories to publish to here.
- }
-}
+ // Mod implementations
+ modImplementation "maven.modrinth:sodium:mc1.18.2-0.4.1" // Sodium
+ modImplementation "maven.modrinth:sodium-extra:mc1.18.2-0.4.18" // Sodium Extra
+ modImplementation "maven.modrinth:embeddium:0.3.18+mc1.18.2" // Embeddium
+ modImplementation "maven.modrinth:distanthorizons:2.1.2-a-1.18.2" // Distant Horizons
+}
\ No newline at end of file
diff --git a/common/src/main/java/com/axolotlmaid/optionsprofiles/OptionsProfilesMod.java b/common/src/main/java/com/axolotlmaid/optionsprofiles/OptionsProfilesMod.java
index 07951b2..05147f1 100644
--- a/common/src/main/java/com/axolotlmaid/optionsprofiles/OptionsProfilesMod.java
+++ b/common/src/main/java/com/axolotlmaid/optionsprofiles/OptionsProfilesMod.java
@@ -1,5 +1,9 @@
package com.axolotlmaid.optionsprofiles;
+import com.axolotlmaid.optionsprofiles.profiles.Profiles;
+import org.apache.logging.log4j.LogManager;
+import org.apache.logging.log4j.Logger;
+
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -7,6 +11,7 @@ import java.nio.file.Paths;
public class OptionsProfilesMod {
public static final String MOD_ID = "optionsprofiles";
+ public static final Logger LOGGER = LogManager.getLogger("Options Profiles");
public static void init() {
Path profilesDirectory = Paths.get("options-profiles");
@@ -15,9 +20,11 @@ public class OptionsProfilesMod {
try {
Files.createDirectory(profilesDirectory);
} catch (IOException e) {
- System.out.println("An error occurred when creating the 'options-profiles' directory.");
- e.printStackTrace();
+ LOGGER.error("An error occurred when creating the 'options-profiles' directory.", e);
}
}
+
+ // Update / add configuration for existing profiles
+ Profiles.updateProfiles();
}
-}
+}
\ No newline at end of file
diff --git a/common/src/main/java/com/axolotlmaid/optionsprofiles/gui/EditProfileScreen.java b/common/src/main/java/com/axolotlmaid/optionsprofiles/gui/EditProfileScreen.java
index c8241fa..17facee 100644
--- a/common/src/main/java/com/axolotlmaid/optionsprofiles/gui/EditProfileScreen.java
+++ b/common/src/main/java/com/axolotlmaid/optionsprofiles/gui/EditProfileScreen.java
@@ -27,7 +27,7 @@ public class EditProfileScreen extends Screen {
this.addRenderableWidget(this.profileNameEdit);
this.addRenderableWidget(new Button(this.width / 2 - 50, this.height - 85, 100, 20, new TranslatableComponent("gui.optionsprofiles.overwrite-options"), (button) -> {
- Profiles.writeOptionsFilesIntoProfile(profileName);
+ Profiles.writeProfile(profileName, true);
this.minecraft.setScreen(this.lastScreen);
}));
diff --git a/common/src/main/java/com/axolotlmaid/optionsprofiles/gui/OptionsToggleList.java b/common/src/main/java/com/axolotlmaid/optionsprofiles/gui/OptionsToggleList.java
new file mode 100644
index 0000000..155f08d
--- /dev/null
+++ b/common/src/main/java/com/axolotlmaid/optionsprofiles/gui/OptionsToggleList.java
@@ -0,0 +1,141 @@
+package com.axolotlmaid.optionsprofiles.gui;
+
+import com.axolotlmaid.optionsprofiles.OptionsProfilesMod;
+import com.axolotlmaid.optionsprofiles.profiles.ProfileConfiguration;
+import com.axolotlmaid.optionsprofiles.profiles.Profiles;
+import com.google.common.collect.ImmutableList;
+import com.mojang.blaze3d.vertex.PoseStack;
+import net.minecraft.ChatFormatting;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Font;
+import net.minecraft.client.gui.GuiComponent;
+import net.minecraft.client.gui.components.ContainerObjectSelectionList;
+import net.minecraft.client.gui.components.CycleButton;
+import net.minecraft.client.gui.components.events.GuiEventListener;
+import net.minecraft.client.gui.narration.NarratableEntry;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.chat.TextComponent;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+
+public class OptionsToggleList extends ContainerObjectSelectionList {
+ private final String profileName;
+ private final ProfileConfiguration profileConfiguration;
+
+ public OptionsToggleList(OptionsToggleScreen optionsToggleScreen, Minecraft minecraft, String profileName) {
+ super(minecraft, optionsToggleScreen.width, optionsToggleScreen.height, 20, optionsToggleScreen.height - 32, 20);
+ this.profileConfiguration = optionsToggleScreen.profileConfiguration;
+ this.profileName = profileName;
+
+ refreshEntries(false, false);
+ }
+
+ // If overriding boolean is set to true then this function will set every option in the list to overrideToggle (false or true)
+ public void refreshEntries(boolean overriding, boolean overrideToggle) {
+ this.clearEntries();
+
+ Path profile = Profiles.PROFILES_DIRECTORY.resolve(profileName);
+ Path optionsFile = profile.resolve("options.txt");
+
+ if (overriding) {
+ if (!overrideToggle) { // If set to false, just set the list to nothing instead of removing them one by one.
+ profileConfiguration.setOptionsToLoad(new ArrayList<>());
+ }
+ }
+
+ try (Stream lines = Files.lines(optionsFile)) {
+ lines.forEach((line) -> {
+ String[] option = line.split(":");
+
+ if (option.length > 1) { // If the option value exists (e.g. "lastServer")
+ if (overrideToggle) { // We don't need to check for the overriding boolean since this should never be true while the overriding boolean is false.
+ List optionsToLoad = profileConfiguration.getOptionsToLoad();
+ optionsToLoad.add(option[0]); // Add every option because overrideToggle is set to true
+
+ profileConfiguration.setOptionsToLoad(optionsToLoad); // Configuration is saved in the OptionsToggleScreen.java when the player presses "Done"
+ }
+
+ // Add entry with option key and value and if the key is in the profile configuration
+ this.addEntry(new OptionEntry(option[0], option[1], profileConfiguration.getOptionsToLoad().contains(option[0])));
+ } else {
+ this.addEntry(new OptionEntry(option[0], "", profileConfiguration.getOptionsToLoad().contains(option[0])));
+ }
+ });
+ } catch (IOException e) {
+ OptionsProfilesMod.LOGGER.error("An error occurred when listing options", e);
+ }
+ }
+
+ protected int getScrollbarPosition() {
+ return super.getScrollbarPosition() + 15;
+ }
+
+ public int getRowWidth() {
+ return 340;
+ }
+
+ public class OptionEntry extends Entry {
+ private final Component optionKey;
+ private final CycleButton toggleButton;
+
+ OptionEntry(String optionKey, String optionValue, boolean toggled) {
+ this.optionKey = new TextComponent(optionKey);
+
+ this.toggleButton = CycleButton.onOffBuilder(toggled).displayOnlyValue().create(0, 0, 44, 20, TextComponent.EMPTY, (button, boolean_) -> {
+ List optionsToLoad = profileConfiguration.getOptionsToLoad();
+
+ // If toggled to true
+ if (boolean_) {
+ button.setMessage(button.getMessage().copy().withStyle(ChatFormatting.GREEN)); // Set the button's color to green
+ optionsToLoad.add(optionKey);
+ } else {
+ button.setMessage(button.getMessage().copy().withStyle(ChatFormatting.RED)); // Set the button's color to red
+ optionsToLoad.remove(optionKey);
+ }
+
+ profileConfiguration.setOptionsToLoad(optionsToLoad);
+ });
+
+ // Set tooltip to the option value (e.g. "ao" will show "true")
+// this.toggleButton.renderToolTip(Tooltip.create(Component.literal(optionValue)));
+
+ if (toggled) {
+ this.toggleButton.setMessage(this.toggleButton.getMessage().copy().withStyle(ChatFormatting.GREEN)); // Set the button's color to green
+ } else {
+ this.toggleButton.setMessage(this.toggleButton.getMessage().copy().withStyle(ChatFormatting.RED)); // Set the button's color to red
+ }
+ }
+
+ public void render(PoseStack poseStack, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
+ Font fontRenderer = OptionsToggleList.this.minecraft.font;
+
+ int posX = OptionsToggleList.this.getScrollbarPosition() - this.toggleButton.getWidth() - 10;
+ int posY = y - 2;
+ int textY = y + entryHeight / 2;
+
+ GuiComponent.drawString(poseStack, fontRenderer, this.optionKey, x, textY - 9 / 2, 16777215);
+
+ this.toggleButton.x = posX;
+ this.toggleButton.y = posY;
+ this.toggleButton.render(poseStack, mouseX, mouseY, tickDelta);
+ }
+
+ public List extends GuiEventListener> children() {
+ return ImmutableList.of(this.toggleButton);
+ }
+
+ public List extends NarratableEntry> narratables() {
+ return ImmutableList.of(this.toggleButton);
+ }
+ }
+
+ public abstract static class Entry extends ContainerObjectSelectionList.Entry {
+ public Entry() {
+ }
+ }
+}
\ No newline at end of file
diff --git a/common/src/main/java/com/axolotlmaid/optionsprofiles/gui/OptionsToggleScreen.java b/common/src/main/java/com/axolotlmaid/optionsprofiles/gui/OptionsToggleScreen.java
new file mode 100644
index 0000000..fe64769
--- /dev/null
+++ b/common/src/main/java/com/axolotlmaid/optionsprofiles/gui/OptionsToggleScreen.java
@@ -0,0 +1,47 @@
+package com.axolotlmaid.optionsprofiles.gui;
+
+import com.axolotlmaid.optionsprofiles.profiles.ProfileConfiguration;
+import com.axolotlmaid.optionsprofiles.profiles.Profiles;
+import com.mojang.blaze3d.vertex.PoseStack;
+import net.minecraft.client.gui.GuiComponent;
+import net.minecraft.client.gui.components.Button;
+import net.minecraft.client.gui.screens.Screen;
+import net.minecraft.network.chat.CommonComponents;
+import net.minecraft.network.chat.Component;
+import net.minecraft.network.chat.TranslatableComponent;
+
+public class OptionsToggleScreen extends Screen {
+ private final Screen lastScreen;
+ private final Component profileName;
+ private OptionsToggleList optionsToggleList;
+
+ public ProfileConfiguration profileConfiguration;
+
+ public OptionsToggleScreen(Screen lastScreen, Component profileName) {
+ super(new TranslatableComponent("gui.optionsprofiles.profiles-menu"));
+ this.lastScreen = lastScreen;
+ this.profileName = profileName;
+ this.profileConfiguration = ProfileConfiguration.get(profileName.getString());
+ }
+
+ protected void init() {
+ this.optionsToggleList = new OptionsToggleList(this, this.minecraft, profileName.getString());
+ this.addWidget(this.optionsToggleList);
+
+ // buttons
+ this.addRenderableWidget(new Button(this.width / 2 - 155, this.height - 29, 150, 20, new TranslatableComponent("gui.optionsprofiles.save-current-options"), (button) -> {
+// Profiles.createProfile();
+ this.optionsToggleList.refreshEntries(false, false);
+ }));
+
+ this.addRenderableWidget(new Button(this.width / 2 + 5, this.height - 29, 150, 20, CommonComponents.GUI_DONE, (button) -> {
+ this.minecraft.setScreen(this.lastScreen);
+ }));
+ }
+
+ public void render(PoseStack poseStack, int mouseX, int mouseY, float delta) {
+ this.optionsToggleList.render(poseStack, mouseX, mouseY, delta);
+ GuiComponent.drawCenteredString(poseStack, this.font, this.title, this.width / 2, 8, 16777215);
+ super.render(poseStack, mouseX, mouseY, delta);
+ }
+}
diff --git a/common/src/main/java/com/axolotlmaid/optionsprofiles/gui/ProfilesList.java b/common/src/main/java/com/axolotlmaid/optionsprofiles/gui/ProfilesList.java
index 463f0fe..05892f2 100644
--- a/common/src/main/java/com/axolotlmaid/optionsprofiles/gui/ProfilesList.java
+++ b/common/src/main/java/com/axolotlmaid/optionsprofiles/gui/ProfilesList.java
@@ -25,7 +25,7 @@ public class ProfilesList extends ContainerObjectSelectionList {
+ this.addRenderableWidget(new Button(5, 5, 75, 20, new TranslatableComponent("gui.optionsprofiles.profiles-menu"), (button) -> {
this.minecraft.setScreen(new ProfilesScreen(this));
}));
}
diff --git a/common/src/main/java/com/axolotlmaid/optionsprofiles/profiles/ProfileConfiguration.java b/common/src/main/java/com/axolotlmaid/optionsprofiles/profiles/ProfileConfiguration.java
new file mode 100644
index 0000000..355ba86
--- /dev/null
+++ b/common/src/main/java/com/axolotlmaid/optionsprofiles/profiles/ProfileConfiguration.java
@@ -0,0 +1,77 @@
+package com.axolotlmaid.optionsprofiles.profiles;
+
+import com.axolotlmaid.optionsprofiles.OptionsProfilesMod;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+
+public class ProfileConfiguration {
+ private static final Path profilesDirectory = Profiles.PROFILES_DIRECTORY;
+ private static Path configurationFile;
+ private static String profileName;
+
+ public static int configurationVersion = 1; // Used to update configuration in later revisions
+ private int version = configurationVersion; // ^ same here - this variable is used to show it in the configuration.json file
+ private List optionsToLoad = new ArrayList<>();
+
+ public ProfileConfiguration save() {
+ ProfileConfiguration configuration = new ProfileConfiguration();
+
+ Gson gson = new GsonBuilder()
+ .setPrettyPrinting()
+ .create();
+
+ try (BufferedWriter writer = Files.newBufferedWriter(configurationFile)) {
+ gson.toJson(this, writer);
+ OptionsProfilesMod.LOGGER.info("[Profile '{}']: Profile configuration saved", profileName);
+ } catch (IOException e) {
+ OptionsProfilesMod.LOGGER.error("Unable to write configuration.json to profile!", e);
+ }
+
+ return configuration;
+ }
+
+ public static ProfileConfiguration get(String profile_name) {
+ ProfileConfiguration configuration = new ProfileConfiguration();
+
+ Path profile = profilesDirectory.resolve(profile_name);
+ configurationFile = profile.resolve("configuration.json");
+ profileName = profile_name;
+
+ if (Files.notExists(configurationFile)) {
+ configuration.save();
+ }
+
+ try (BufferedReader reader = Files.newBufferedReader(configurationFile)) {
+ Gson gson = new Gson();
+ configuration = gson.fromJson(reader, ProfileConfiguration.class);
+ } catch (IOException e) {
+ OptionsProfilesMod.LOGGER.error("[Profile '{}']: An error occurred when reading configuration.json", profileName, e);
+ }
+
+ return configuration;
+ }
+
+ public int getVersion() {
+ return version;
+ }
+
+ public void setVersion(int version) {
+ this.version = version;
+ }
+
+ public List getOptionsToLoad() {
+ return optionsToLoad;
+ }
+
+ public void setOptionsToLoad(List optionsToLoad) {
+ this.optionsToLoad = optionsToLoad;
+ }
+}
\ No newline at end of file
diff --git a/common/src/main/java/com/axolotlmaid/optionsprofiles/profiles/Profiles.java b/common/src/main/java/com/axolotlmaid/optionsprofiles/profiles/Profiles.java
index 1348b7a..d102698 100644
--- a/common/src/main/java/com/axolotlmaid/optionsprofiles/profiles/Profiles.java
+++ b/common/src/main/java/com/axolotlmaid/optionsprofiles/profiles/Profiles.java
@@ -1,197 +1,283 @@
package com.axolotlmaid.optionsprofiles.profiles;
-import dev.architectury.platform.Platform;
+import com.axolotlmaid.optionsprofiles.OptionsProfilesMod;
+import com.axolotlmaid.optionsprofiles.profiles.loaders.DistantHorizonsLoader;
+//import com.axolotlmaid.optionsprofiles.profiles.loaders.EmbeddiumLoader;
+//import com.axolotlmaid.optionsprofiles.profiles.loaders.SodiumExtraLoader;
+import com.axolotlmaid.optionsprofiles.profiles.loaders.SodiumLoader;
+import org.apache.commons.io.FileUtils;
-import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.nio.file.StandardOpenOption;
-import java.util.Comparator;
-import java.util.List;
+import java.nio.file.StandardCopyOption;
+import java.util.*;
+import java.util.function.Consumer;
import java.util.stream.Stream;
public class Profiles {
+ public static final Path PROFILES_DIRECTORY = Paths.get("options-profiles/");
+ public static final Path OPTIONS_FILE = Paths.get("options.txt");
+ public static final Path OPTIFINE_OPTIONS_FILE = Paths.get("optionsof.txt");
+ public static final Path SODIUM_OPTIONS_FILE = Paths.get("config/sodium-options.json");
+ public static final Path SODIUM_EXTRA_OPTIONS_FILE = Paths.get("config/sodium-extra-options.json");
+ public static final Path EMBEDDIUM_OPTIONS_FILE = Paths.get("config/embeddium-options.json");
+ public static final Path DISTANT_HORIZONS_OPTIONS_FILE = Paths.get("config/DistantHorizons.toml");
+
+ // This function goes through every profile and updates / adds the configuration file if it doesn't exist
+ public static void updateProfiles() {
+ try (Stream paths = Files.list(PROFILES_DIRECTORY)) {
+ paths.filter(Files::isDirectory)
+ .forEach(path -> {
+ String profileName = path.getFileName().toString();
+
+ // This gets the configuration but also creates the configuration file if it is not there
+ ProfileConfiguration profileConfiguration = ProfileConfiguration.get(profileName);
+ List optionsToLoad = profileConfiguration.getOptionsToLoad();
+
+ // Checks for updates to the configuration
+ if (profileConfiguration.getVersion() != ProfileConfiguration.configurationVersion) {
+ Path configurationFile = path.resolve("configuration.json");
+
+ try {
+ Files.delete(configurationFile);
+ } catch (IOException e) {
+ OptionsProfilesMod.LOGGER.error("[Profile '{}']: Error deleting configuration file", profileName, e);
+ }
+
+ // Create the configuration.json again thus updating it
+ profileConfiguration = ProfileConfiguration.get(profileName);
+
+ // Add player's old configuration
+ profileConfiguration.setOptionsToLoad(optionsToLoad);
+
+ // Save configuration
+ profileConfiguration.save();
+ }
+
+ OptionsProfilesMod.LOGGER.warn("[Profile '{}']: Profile configuration updated / added", profileName);
+ });
+ } catch (IOException e) {
+ OptionsProfilesMod.LOGGER.error("An error occurred when updating profiles", e);
+ }
+ }
+
public static void createProfile() {
String profileName = "Profile 1";
- Path profile = Paths.get("options-profiles/" + profileName);
+ Path profile = PROFILES_DIRECTORY.resolve(profileName);
+ // Increases the number in 'Profile 1' if it already exists
for (int i = 1; Files.exists(profile); i++) {
profileName = "Profile " + i;
- profile = Paths.get("options-profiles/" + profileName);
+ profile = Paths.get(PROFILES_DIRECTORY.toString(), profileName);
}
try {
Files.createDirectory(profile);
if (Files.exists(profile)) {
- System.out.println("Profile created.");
-
- writeOptionsFilesIntoProfile(profileName);
+ OptionsProfilesMod.LOGGER.info("[Profile '{}']: created", profileName);
+ writeProfile(profileName, false);
} else {
- System.out.println("Profile was not created successfully.");
+ OptionsProfilesMod.LOGGER.warn("[Profile '{}']: Profile already exists?", profileName);
}
} catch (IOException e) {
- System.out.println("An error occurred when creating a profile.");
- e.printStackTrace();
+ OptionsProfilesMod.LOGGER.error("[Profile '{}']: An error occurred when creating a profile", profileName, e);
}
}
- public static void writeOptionsFilesIntoProfile(String profileName) {
- Path profile = Paths.get("options-profiles/" + profileName);
+ private static void copyOptionFile(Path profile, Path options) {
+ if (Files.exists(options)) {
+ Path profileOptions = profile.resolve(options.getFileName());
- // options.txt
- Path options = Paths.get("options.txt");
- Path profileOptions = Paths.get(profile.toAbsolutePath() + "/options.txt");
+ try {
+ Files.copy(options, profileOptions);
+ } catch (IOException e) {
+ OptionsProfilesMod.LOGGER.error("[Profile '{}']: Unable to copy '{}'", profile.getFileName().toString(), options.getFileName().toString(), e);
+ }
+ }
+ }
- try (Stream paths = Files.lines(options)) {
- if (Files.exists(profileOptions))
- Files.newBufferedWriter(profileOptions, StandardOpenOption.TRUNCATE_EXISTING);
+ public static void writeProfile(String profileName, boolean overwriting) {
+ Path profile = PROFILES_DIRECTORY.resolve(profileName);
+ Path profileOptions = profile.resolve("options.txt");
- paths.forEach(line -> {
- try {
- Files.write(profileOptions, line.getBytes(), StandardOpenOption.CREATE, StandardOpenOption.APPEND);
- Files.write(profileOptions, "\n".getBytes(), StandardOpenOption.APPEND);
- } catch (IOException e) {
- System.out.println("An error occurred when writing a profile.");
- e.printStackTrace();
- }
- });
- } catch (IOException e) {
- System.out.println("An error occurred when reading options.txt.");
- e.printStackTrace();
+ ProfileConfiguration profileConfiguration = ProfileConfiguration.get(profileName);
+
+ if (overwriting) {
+ try {
+ // Removes old option files
+ FileUtils.cleanDirectory(profile.toFile());
+ } catch (IOException e) {
+ OptionsProfilesMod.LOGGER.error("[Profile '{}']: An error occurred when clearing old options files", profileName, e);
+ }
}
- // sodium-options.json
- if (Platform.isFabric()) {
- if (Platform.isModLoaded("sodium")) {
- Path sodiumConfiguration = Paths.get("config/sodium-options.json");
- Path sodiumConfigurationProfile = Paths.get(profile.toAbsolutePath() + "/sodium-options.json");
+ copyOptionFile(profile, OPTIONS_FILE);
+ copyOptionFile(profile, OPTIFINE_OPTIONS_FILE);
+ copyOptionFile(profile, SODIUM_OPTIONS_FILE);
+ copyOptionFile(profile, SODIUM_EXTRA_OPTIONS_FILE);
+ copyOptionFile(profile, EMBEDDIUM_OPTIONS_FILE);
+ copyOptionFile(profile, DISTANT_HORIZONS_OPTIONS_FILE);
- try (Stream paths = Files.lines(sodiumConfiguration)) {
- if (Files.exists(sodiumConfigurationProfile))
- Files.newBufferedWriter(sodiumConfigurationProfile, StandardOpenOption.TRUNCATE_EXISTING);
+ // Add every option value to configuration
+ try (Stream lines = Files.lines(profileOptions)) {
+ List optionsToLoad = profileConfiguration.getOptionsToLoad();
- paths.forEach(line -> {
- try {
- Files.write(sodiumConfigurationProfile, line.getBytes(), StandardOpenOption.CREATE, StandardOpenOption.APPEND);
- Files.write(sodiumConfigurationProfile, "\n".getBytes(), StandardOpenOption.APPEND);
- } catch (IOException e) {
- System.out.println("An error occurred when writing a profile.");
- e.printStackTrace();
- }
- });
- } catch (IOException e) {
- System.out.println("An error occurred when reading options.txt.");
- e.printStackTrace();
- }
- }
+ lines.forEach((line) -> {
+ String[] option = line.split(":");
+ optionsToLoad.add(option[0]);
+ });
+
+ profileConfiguration.save();
+ } catch (IOException e) {
+ OptionsProfilesMod.LOGGER.error("[Profile '{}']: An error occurred when adding options to the configuration file", profileName, e);
}
}
public static boolean isProfileLoaded(String profileName) {
- Path profile = Paths.get("options-profiles/" + profileName);
+ Path profile = PROFILES_DIRECTORY.resolve(profileName);
- Path options = Paths.get("options.txt");
- Path profileOptions = Paths.get(profile.toAbsolutePath() + "/options.txt");
+ List optionFiles = new ArrayList<>();
+ optionFiles.add(OPTIONS_FILE);
+ // The next few lines check if the specified file exists. If so, it adds it to the optionFiles ArrayList.
+ Optional.of(OPTIFINE_OPTIONS_FILE).filter(Files::exists).ifPresent(optionFiles::add);
+ Optional.of(SODIUM_OPTIONS_FILE).filter(Files::exists).ifPresent(optionFiles::add);
+ Optional.of(SODIUM_EXTRA_OPTIONS_FILE).filter(Files::exists).ifPresent(optionFiles::add);
+ Optional.of(EMBEDDIUM_OPTIONS_FILE).filter(Files::exists).ifPresent(optionFiles::add);
+ Optional.of(DISTANT_HORIZONS_OPTIONS_FILE).filter(Files::exists).ifPresent(optionFiles::add);
+
+ // Check if the original option file and the profile option file have the same content
try {
- List linesOptions = Files.readAllLines(options);
- List linesProfileOptions = Files.readAllLines(profileOptions);
-
- if (Platform.isFabric()) {
- if (Platform.isModLoaded("sodium")) {
- Path sodiumConfiguration = Paths.get("config/sodium-options.json");
- Path sodiumConfigurationProfile = Paths.get(profile.toAbsolutePath() + "/sodium-options.json");
-
- if (Files.exists(sodiumConfigurationProfile)) {
- List linesSodiumConfig = Files.readAllLines(sodiumConfiguration);
- List linesSodiumConfigProfile = Files.readAllLines(sodiumConfigurationProfile);
-
- return linesOptions.equals(linesProfileOptions) && linesSodiumConfig.equals(linesSodiumConfigProfile);
- }
+ for (Path optionFile : optionFiles) {
+ Path profileOptions = profile.resolve(optionFile.getFileName());
+ if (!FileUtils.contentEquals(optionFile.toFile(), profileOptions.toFile())) {
+ return false;
}
}
-
- return linesOptions.equals(linesProfileOptions);
} catch (IOException e) {
- e.printStackTrace();
+ OptionsProfilesMod.LOGGER.error("[Profile '{}']: An error occurred when checking if the profile is loaded", profileName, e);
+ return false;
}
- return false;
+ return true;
+ }
+
+ private static void loadOptionFile(String profileName, Path options) {
+ ProfileConfiguration profileConfiguration = ProfileConfiguration.get(profileName);
+
+ Path profile = PROFILES_DIRECTORY.resolve(profileName);
+ Path profileOptions = profile.resolve(options.getFileName());
+
+ if (Files.exists(profileOptions)) {
+ // This if statement is for loading specific options.
+ if (options.getFileName().toString().equals("options.txt")) { // If file is options.txt - only doing options.txt for now
+ Map optionsToWrite = new HashMap<>();
+
+ // Read options.txt
+ try (Stream lines = Files.lines(options)) {
+ lines.forEach(line -> {
+ String[] option = line.split(":"); // Split key and value
+
+ if (option.length > 1) {
+ optionsToWrite.put(option[0], option[1]); // Add them to the map
+ } else {
+ optionsToWrite.put(option[0], "");
+ }
+ });
+ } catch (IOException e) {
+ OptionsProfilesMod.LOGGER.error("[Profile '{}']: An error occurred reading options.txt to load the profile", profileName, e);
+ }
+
+ // Read profile options.txt
+ try (Stream lines = Files.lines(profileOptions)) {
+ lines.forEach(line -> {
+ String[] option = line.split(":"); // Split key and value
+
+ if (option.length > 1) {
+ if (profileConfiguration.getOptionsToLoad().contains(option[0])) {
+ optionsToWrite.put(option[0], option[1]); // Updates old value set by reading options.txt
+ }
+ }
+ });
+ } catch (IOException e) {
+ OptionsProfilesMod.LOGGER.error("[Profile '{}']: An error occurred reading profile options.txt to load the profile", profileName, e);
+ }
+
+ // Write into options.txt
+ try {
+ Files.write(options, () ->
+ optionsToWrite
+ .entrySet()
+ .stream()
+ .map(entry -> entry.getKey() + ":" + entry.getValue())
+ .iterator()
+ );
+
+ OptionsProfilesMod.LOGGER.info("[Profile '{}']: '{}' loaded with specific options", profileName, options.getFileName());
+ } catch (IOException e) {
+ OptionsProfilesMod.LOGGER.error("[Profile '{}']: An error occurred writing hashmap into options.txt", profileName, e);
+ }
+
+ return; // Return the function, thus not running the next few lines
+ }
+
+ try {
+ // Replaces the original option file with the profile option file
+ Files.copy(profileOptions, options, StandardCopyOption.REPLACE_EXISTING);
+ OptionsProfilesMod.LOGGER.info("[Profile '{}']: '{}' loaded by copying", profileName, options.getFileName());
+ } catch (IOException e) {
+ OptionsProfilesMod.LOGGER.error("[Profile '{}']: An error occurred when loading the profile", profileName, e);
+ }
+ }
+ }
+
+ private static void loadOptionFile(String profileName, Path options, Consumer loader) {
+ Path profile = PROFILES_DIRECTORY.resolve(profileName);
+ Path profileOptions = profile.resolve(options.getFileName());
+
+ if (Files.exists(profileOptions)) {
+ loader.accept(profileOptions);
+ OptionsProfilesMod.LOGGER.info("[Profile '{}']: '{}' loaded using loader class", profileName, options.getFileName());
+ }
}
public static void loadProfile(String profileName) {
- Path profile = Paths.get("options-profiles/" + profileName);
-
- // options.txt
- Path options = Paths.get("options.txt");
- Path profileOptions = Paths.get(profile.toAbsolutePath() + "/options.txt");
-
- try (Stream paths = Files.lines(profileOptions)) {
- Files.newBufferedWriter(options, StandardOpenOption.TRUNCATE_EXISTING);
-
- paths.forEach(line -> {
- try {
- Files.write(options, line.getBytes(), StandardOpenOption.APPEND);
- Files.write(options, "\n".getBytes(), StandardOpenOption.APPEND);
- } catch (IOException e) {
- System.out.println("An error occurred when loading a profile.");
- e.printStackTrace();
- }
- });
- } catch (IOException e) {
- System.out.println("An error occurred when loading a profile.");
- e.printStackTrace();
- }
-
- // sodium-options.json
- if (Platform.isFabric()) {
- if (Platform.isModLoaded("sodium")) {
- Path sodiumConfigurationProfile = Paths.get(profile.toAbsolutePath() + "/sodium-options.json");
-
- if (Files.exists(sodiumConfigurationProfile)) {
- SodiumConfigLoader.load(sodiumConfigurationProfile);
- }
- }
- }
+ loadOptionFile(profileName, OPTIONS_FILE);
+ loadOptionFile(profileName, OPTIFINE_OPTIONS_FILE);
+ loadOptionFile(profileName, SODIUM_OPTIONS_FILE, SodiumLoader::load);
+// loadOptionFile(profileName, SODIUM_EXTRA_OPTIONS_FILE, SodiumExtraLoader::load);
+// loadOptionFile(profileName, EMBEDDIUM_OPTIONS_FILE, EmbeddiumLoader::load);
+ loadOptionFile(profileName, DISTANT_HORIZONS_OPTIONS_FILE, DistantHorizonsLoader::load);
}
public static void renameProfile(String profileName, String newProfileName) {
- Path profile = Paths.get("options-profiles/" + profileName);
- Path newProfile = Paths.get("options-profiles/" + newProfileName);
+ Path profile = PROFILES_DIRECTORY.resolve(profileName);
+ Path newProfile = PROFILES_DIRECTORY.resolve(newProfileName);
- if (Files.exists(newProfile))
- System.out.println("New profile already exists!");
+ if (Files.exists(newProfile)) {
+ OptionsProfilesMod.LOGGER.warn("[Profile '{}']: A profile with that name already exists!", profileName);
+ return;
+ }
try {
Files.move(profile, newProfile);
-
- if (Files.exists(newProfile)) {
- System.out.println("Profile renamed.");
- } else {
- System.out.println("Profile was not renamed successfully.");
- }
+ OptionsProfilesMod.LOGGER.info("[Profile '{}']: renamed. Old name: {}", newProfileName, profileName);
} catch (IOException e) {
- System.out.println("Profile was not renamed successfully.");
- e.printStackTrace();
+ OptionsProfilesMod.LOGGER.error("[Profile '{}']: An error occurred when renaming the profile", profileName, e);
}
}
public static void deleteProfile(String profileName) {
- Path profile = Paths.get("options-profiles/" + profileName);
+ Path profile = PROFILES_DIRECTORY.resolve(profileName);
- try (Stream files = Files.walk(profile)) {
- files
- .sorted(Comparator.reverseOrder())
- .map(Path::toFile)
- .forEach(File::delete);
+ try {
+ FileUtils.deleteDirectory(profile.toFile());
+ OptionsProfilesMod.LOGGER.info("[Profile '{}']: deleted", profileName);
} catch (IOException e) {
- System.out.println("Profile was not deleted.");
- e.printStackTrace();
+ OptionsProfilesMod.LOGGER.error("[Profile '{}']: Profile was not deleted", profileName, e);
}
-
- System.out.println("Profile deleted.");
}
}
\ No newline at end of file
diff --git a/common/src/main/java/com/axolotlmaid/optionsprofiles/profiles/loaders/DistantHorizonsLoader.java b/common/src/main/java/com/axolotlmaid/optionsprofiles/profiles/loaders/DistantHorizonsLoader.java
new file mode 100644
index 0000000..64741ee
--- /dev/null
+++ b/common/src/main/java/com/axolotlmaid/optionsprofiles/profiles/loaders/DistantHorizonsLoader.java
@@ -0,0 +1,11 @@
+package com.axolotlmaid.optionsprofiles.profiles.loaders;
+
+import com.seibel.distanthorizons.core.config.ConfigBase;
+
+import java.nio.file.Path;
+
+public class DistantHorizonsLoader {
+ public static void load(Path file) {
+ ConfigBase.INSTANCE.configFileINSTANCE.loadFromFile();
+ }
+}
diff --git a/common/src/main/java/com/axolotlmaid/optionsprofiles/profiles/loaders/SodiumLoader.java b/common/src/main/java/com/axolotlmaid/optionsprofiles/profiles/loaders/SodiumLoader.java
new file mode 100644
index 0000000..d0867b0
--- /dev/null
+++ b/common/src/main/java/com/axolotlmaid/optionsprofiles/profiles/loaders/SodiumLoader.java
@@ -0,0 +1,87 @@
+package com.axolotlmaid.optionsprofiles.profiles.loaders;
+
+import com.axolotlmaid.optionsprofiles.OptionsProfilesMod;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import me.jellysquid.mods.sodium.client.SodiumClientMod;
+import me.jellysquid.mods.sodium.client.gui.SodiumGameOptions;
+
+import java.io.FileReader;
+import java.io.IOException;
+import java.nio.file.Path;
+
+public class SodiumLoader {
+ public static void load(Path file) {
+ try (FileReader reader = new FileReader(file.toFile())) {
+ Gson gson = new GsonBuilder().create();
+ Configuration configuration = gson.fromJson(reader, Configuration.class);
+
+ apply(configuration);
+ } catch (IOException e) {
+ OptionsProfilesMod.LOGGER.error("An error occurred when loading Sodium's configuration", e);
+ }
+ }
+
+ private static void apply(Configuration configuration) {
+ SodiumClientMod.options().quality.weatherQuality = SodiumGameOptions.GraphicsQuality.valueOf(configuration.quality.weather_quality);
+ SodiumClientMod.options().quality.leavesQuality = SodiumGameOptions.GraphicsQuality.valueOf(configuration.quality.leaves_quality);
+ SodiumClientMod.options().quality.enableVignette = configuration.quality.enable_vignette;
+
+ SodiumClientMod.options().advanced.arenaMemoryAllocator = SodiumGameOptions.ArenaMemoryAllocator.valueOf(configuration.advanced.arena_memory_allocator);
+ SodiumClientMod.options().advanced.allowDirectMemoryAccess = configuration.advanced.allow_direct_memory_access;
+ SodiumClientMod.options().advanced.enableMemoryTracing = configuration.advanced.enable_memory_tracing;
+ SodiumClientMod.options().advanced.useAdvancedStagingBuffers = configuration.advanced.use_advanced_staging_buffers;
+ SodiumClientMod.options().advanced.cpuRenderAheadLimit = configuration.advanced.cpu_render_ahead_limit;
+
+ SodiumClientMod.options().performance.chunkBuilderThreads = configuration.performance.chunk_builder_threads;
+ SodiumClientMod.options().performance.alwaysDeferChunkUpdates = configuration.performance.always_defer_chunk_updates;
+ SodiumClientMod.options().performance.animateOnlyVisibleTextures = configuration.performance.animate_only_visible_textures;
+ SodiumClientMod.options().performance.useEntityCulling = configuration.performance.use_entity_culling;
+ SodiumClientMod.options().performance.useParticleCulling = configuration.performance.use_particle_culling;
+ SodiumClientMod.options().performance.useFogOcclusion = configuration.performance.use_fog_occlusion;
+ SodiumClientMod.options().performance.useBlockFaceCulling = configuration.performance.use_block_face_culling;
+
+ SodiumClientMod.options().notifications.hideDonationButton = configuration.notifications.hide_donation_button;
+
+ try {
+ SodiumClientMod.options().writeChanges();
+ } catch (IOException e) {
+ OptionsProfilesMod.LOGGER.error("An error occurred when loading Sodium's configuration", e);
+ }
+ }
+
+ public static class Configuration {
+ public Quality quality;
+ public Advanced advanced;
+ public Performance performance;
+ public Notifications notifications;
+
+ public static class Quality {
+ public String weather_quality;
+ public String leaves_quality;
+ public boolean enable_vignette;
+ }
+
+ public static class Advanced {
+ public String arena_memory_allocator;
+ public boolean allow_direct_memory_access;
+ public boolean enable_memory_tracing;
+ public boolean use_advanced_staging_buffers;
+ public int cpu_render_ahead_limit;
+ }
+
+ public static class Performance {
+ public int chunk_builder_threads;
+ public boolean always_defer_chunk_updates;
+ public boolean animate_only_visible_textures;
+ public boolean use_entity_culling;
+ public boolean use_particle_culling;
+ public boolean use_fog_occlusion;
+ public boolean use_block_face_culling;
+ }
+
+ public static class Notifications {
+ public boolean hide_donation_button;
+ }
+ }
+}
\ No newline at end of file
diff --git a/common/src/main/resources/architectury.common.json b/common/src/main/resources/architectury.common.json
deleted file mode 100644
index 675ac01..0000000
--- a/common/src/main/resources/architectury.common.json
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "accessWidener": "optionsprofiles.accesswidener"
-}
\ No newline at end of file
diff --git a/common/src/main/resources/assets/optionsprofiles/lang/en_us.json b/common/src/main/resources/assets/optionsprofiles/lang/en_us.json
index 76abbc3..e3b4a31 100644
--- a/common/src/main/resources/assets/optionsprofiles/lang/en_us.json
+++ b/common/src/main/resources/assets/optionsprofiles/lang/en_us.json
@@ -7,6 +7,12 @@
"gui.optionsprofiles.editing-profile-title": "Editing Profile: ",
"gui.optionsprofiles.profile-name-text": "Profile Name",
"gui.optionsprofiles.overwrite-options": "Overwrite",
+ "gui.optionsprofiles.overwrite-options.tooltip": "Replaces the profile's options with your current options",
"gui.optionsprofiles.rename-profile": "Rename",
- "gui.optionsprofiles.delete-profile": "Delete"
+ "gui.optionsprofiles.delete-profile": "Delete",
+
+ "gui.optionsprofiles.options-toggle": "Select options to toggle",
+ "gui.optionsprofiles.options-toggle.tooltip": "Select the options you want to load in this profile",
+ "gui.optionsprofiles.all-on": "All ON",
+ "gui.optionsprofiles.all-off": "All OFF"
}
\ No newline at end of file
diff --git a/common/src/main/resources/assets/optionsprofiles/lang/ru_ru.json b/common/src/main/resources/assets/optionsprofiles/lang/ru_ru.json
index 4ffe547..d625136 100644
--- a/common/src/main/resources/assets/optionsprofiles/lang/ru_ru.json
+++ b/common/src/main/resources/assets/optionsprofiles/lang/ru_ru.json
@@ -7,9 +7,15 @@
"gui.optionsprofiles.editing-profile-title": "Изменение профиля: ",
"gui.optionsprofiles.profile-name-text": "Имя профиля",
"gui.optionsprofiles.overwrite-options": "Перезаписать",
+ "gui.optionsprofiles.overwrite-options.tooltip": "Заменяет параметры профиля на ваши текущие параметры",
"gui.optionsprofiles.rename-profile": "Переименовать",
"gui.optionsprofiles.delete-profile": "удалить",
+ "gui.optionsprofiles.options-toggle": "Выберите параметры для переключения",
+ "gui.optionsprofiles.options-toggle.tooltip": "Выберите параметры, которые вы хотите загрузить в этот профиль",
+ "gui.optionsprofiles.all-on": "Включи всё",
+ "gui.optionsprofiles.all-off": "Все выключить",
+
"modmenu.summaryTranslation.options-profiles": "Cохраняйте и загружайте профили настроек, не выходя из игры.",
"modmenu.descriptionTranslation.options-profiles": "Мод, позволяющий сохранять профили текущих настроек и загружать их, не выходя из игры."
}
\ No newline at end of file
diff --git a/common/src/main/resources/assets/optionsprofiles/lang/tt_ru.json b/common/src/main/resources/assets/optionsprofiles/lang/tt_ru.json
index 8314a93..652e987 100644
--- a/common/src/main/resources/assets/optionsprofiles/lang/tt_ru.json
+++ b/common/src/main/resources/assets/optionsprofiles/lang/tt_ru.json
@@ -7,9 +7,15 @@
"gui.optionsprofiles.editing-profile-title": "Профильне үзгәртү: ",
"gui.optionsprofiles.profile-name-text": "Профиль исеме",
"gui.optionsprofiles.overwrite-options": "перезапись",
+ "gui.optionsprofiles.overwrite-options.tooltip": "Профиль вариантларын хәзерге вариантларыгыз белән алыштыра",
"gui.optionsprofiles.rename-profile": "переименовывать",
"gui.optionsprofiles.delete-profile": "бетерү",
+ "gui.optionsprofiles.options-toggle": "Күчерү вариантларын сайлагыз",
+ "gui.optionsprofiles.options-toggle.tooltip": "Бу профильгә йөгерергә теләгән вариантларны сайлагыз",
+ "gui.optionsprofiles.all-on": "Барысын да кабызыгыз",
+ "gui.optionsprofiles.all-off": "Барысын да сүндерегез",
+
"modmenu.summaryTranslation.options-profiles": "Хәзерге көйләүләр профильләрен саклагыз һәм уеннан чыгусыз йөкләгез.",
"modmenu.descriptionTranslation.options-profiles": "Хәзерге көйләүләр профильләрен сакларга һәм уеннан чыгусыз йөкләргә рөхсәт итә торган мод."
}
diff --git a/common/src/main/resources/assets/optionsprofiles/lang/zh_cn.json b/common/src/main/resources/assets/optionsprofiles/lang/zh_cn.json
new file mode 100644
index 0000000..22b1010
--- /dev/null
+++ b/common/src/main/resources/assets/optionsprofiles/lang/zh_cn.json
@@ -0,0 +1,18 @@
+{
+ "gui.optionsprofiles.profiles-menu": "配置预设",
+ "gui.optionsprofiles.save-current-options": "保存当前配置",
+ "gui.optionsprofiles.load-profile": "✔(载入)",
+ "gui.optionsprofiles.edit-profile": "✎(编辑)",
+
+ "gui.optionsprofiles.editing-profile-title": "正在编辑:",
+ "gui.optionsprofiles.profile-name-text": "预设名",
+ "gui.optionsprofiles.overwrite-options": "覆盖",
+ "gui.optionsprofiles.overwrite-options.tooltip": "将配置文件选项替换为您当前的选项",
+ "gui.optionsprofiles.rename-profile": "重命名",
+ "gui.optionsprofiles.delete-profile": "删除",
+
+ "gui.optionsprofiles.options-toggle": "选择要切换的选项",
+ "gui.optionsprofiles.options-toggle.tooltip": "选择您要加载到此配置文件中的选项",
+ "gui.optionsprofiles.all-on": "全部开启",
+ "gui.optionsprofiles.all-off": "关掉一切"
+}
diff --git a/common/src/main/resources/assets/optionsprofiles/lang/zh_tw.json b/common/src/main/resources/assets/optionsprofiles/lang/zh_tw.json
new file mode 100644
index 0000000..99c2ce7
--- /dev/null
+++ b/common/src/main/resources/assets/optionsprofiles/lang/zh_tw.json
@@ -0,0 +1,18 @@
+{
+ "gui.optionsprofiles.profiles-menu": "配置檔",
+ "gui.optionsprofiles.save-current-options": "保存目前配置",
+ "gui.optionsprofiles.load-profile": "✔(載入)",
+ "gui.optionsprofiles.edit-profile": "✎(編輯)",
+
+ "gui.optionsprofiles.editing-profile-title": "正在編輯:",
+ "gui.optionsprofiles.profile-name-text": "預設名稱",
+ "gui.optionsprofiles.overwrite-options": "覆蓋",
+ "gui.optionsprofiles.overwrite-options.tooltip": "將配置文件選項替換為您目前的選項",
+ "gui.optionsprofiles.rename-profile": "重新命名",
+ "gui.optionsprofiles.delete-profile": "刪除",
+
+ "gui.optionsprofiles.options-toggle": "選擇要切換的選項",
+ "gui.optionsprofiles.options-toggle.tooltip": "選擇您要載入到此配置文件中的選項",
+ "gui.optionsprofiles.all-on": "全部 開啟",
+ "gui.optionsprofiles.all-off": "全部 關閉"
+}
diff --git a/common/src/main/resources/optionsprofiles.accesswidener b/common/src/main/resources/optionsprofiles.accesswidener
deleted file mode 100644
index 13268c3..0000000
--- a/common/src/main/resources/optionsprofiles.accesswidener
+++ /dev/null
@@ -1 +0,0 @@
-accessWidener v2 named
\ No newline at end of file
diff --git a/common/src/main/resources/optionsprofiles-common.mixins.json b/common/src/main/resources/optionsprofiles.mixins.json
similarity index 100%
rename from common/src/main/resources/optionsprofiles-common.mixins.json
rename to common/src/main/resources/optionsprofiles.mixins.json
diff --git a/fabric/build.gradle b/fabric/build.gradle
index 5ca331b..d9f3e92 100644
--- a/fabric/build.gradle
+++ b/fabric/build.gradle
@@ -1,5 +1,5 @@
plugins {
- id "com.github.johnrengelman.shadow" version "7.1.2"
+ id 'com.github.johnrengelman.shadow'
}
architectury {
@@ -7,71 +7,46 @@ architectury {
fabric()
}
-loom {
- accessWidenerPath = project(":common").loom.accessWidenerPath
-}
-
configurations {
- common
- shadowCommon // Don't use shadow from the shadow plugin since it *excludes* files.
+ common {
+ canBeResolved = true
+ canBeConsumed = false
+ }
compileClasspath.extendsFrom common
runtimeClasspath.extendsFrom common
developmentFabric.extendsFrom common
+
+ // Files in this configuration will be bundled into your mod using the Shadow plugin.
+ // Don't use the `shadow` configuration from the plugin itself as it's meant for excluding files.
+ shadowBundle {
+ canBeResolved = true
+ canBeConsumed = false
+ }
}
dependencies {
- modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
- modApi "net.fabricmc.fabric-api:fabric-api:${rootProject.fabric_api_version}"
- // Remove the next line if you don't want to depend on the API
- modApi "dev.architectury:architectury-fabric:${rootProject.architectury_version}"
+ modImplementation "net.fabricmc:fabric-loader:$rootProject.fabric_loader_version"
- common(project(path: ":common", configuration: "namedElements")) { transitive false }
- shadowCommon(project(path: ":common", configuration: "transformProductionFabric")) { transitive false }
+ // Fabric API. This is technically optional, but you probably want it anyway.
+ modImplementation "net.fabricmc.fabric-api:fabric-api:$rootProject.fabric_api_version"
+
+ common(project(path: ':common', configuration: 'namedElements')) { transitive false }
+ shadowBundle project(path: ':common', configuration: 'transformProductionFabric')
}
processResources {
- inputs.property "version", project.version
+ inputs.property 'version', project.version
- filesMatching("fabric.mod.json") {
- expand "version": project.version
+ filesMatching('fabric.mod.json') {
+ expand version: project.version
}
}
shadowJar {
- exclude "architectury.common.json"
-
- configurations = [project.configurations.shadowCommon]
- archiveClassifier = "dev-shadow"
+ configurations = [project.configurations.shadowBundle]
+ archiveClassifier = 'dev-shadow'
}
remapJar {
- injectAccessWidener = true
input.set shadowJar.archiveFile
- dependsOn shadowJar
-}
-
-sourcesJar {
- def commonSources = project(":common").sourcesJar
- dependsOn commonSources
- from commonSources.archiveFile.map { zipTree(it) }
-}
-
-components.java {
- withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) {
- skip()
- }
-}
-
-publishing {
- publications {
- mavenFabric(MavenPublication) {
- artifactId = rootProject.archives_base_name + "-" + project.name
- from components.java
- }
- }
-
- // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
- repositories {
- // Add repositories to publish to here.
- }
}
diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json
index ce6b6aa..f4ecc8c 100644
--- a/fabric/src/main/resources/fabric.mod.json
+++ b/fabric/src/main/resources/fabric.mod.json
@@ -21,12 +21,12 @@
]
},
"mixins": [
- "optionsprofiles.mixins.json",
- "optionsprofiles-common.mixins.json"
+ "optionsprofiles.mixins.json"
],
"depends": {
- "fabric": "*",
- "minecraft": ">=1.18.2",
- "architectury": ">=4.11.93"
+ "fabricloader": ">=0.15.11",
+ "minecraft": "~1.18.2",
+ "java": ">=17",
+ "fabric": "*"
}
}
\ No newline at end of file
diff --git a/fabric/src/main/resources/optionsprofiles.mixins.json b/fabric/src/main/resources/optionsprofiles.mixins.json
deleted file mode 100644
index 9d4e801..0000000
--- a/fabric/src/main/resources/optionsprofiles.mixins.json
+++ /dev/null
@@ -1,10 +0,0 @@
-{
- "required": true,
- "package": "com.axolotlmaid.optionsprofiles.mixin",
- "compatibilityLevel": "JAVA_17",
- "mixins": [
- ],
- "injectors": {
- "defaultRequire": 1
- }
-}
\ No newline at end of file
diff --git a/forge/build.gradle b/forge/build.gradle
index ce10b06..a00392b 100644
--- a/forge/build.gradle
+++ b/forge/build.gradle
@@ -1,5 +1,11 @@
plugins {
- id "com.github.johnrengelman.shadow" version "7.1.2"
+ id 'com.github.johnrengelman.shadow'
+}
+
+loom {
+ forge {
+ mixinConfig "optionsprofiles.mixins.json"
+ }
}
architectury {
@@ -7,78 +13,43 @@ architectury {
forge()
}
-loom {
- accessWidenerPath = project(":common").loom.accessWidenerPath
-
- forge {
- convertAccessWideners = true
- extraAccessWideners.add loom.accessWidenerPath.get().asFile.name
-
- mixinConfig "optionsprofiles-common.mixins.json"
- mixinConfig "optionsprofiles.mixins.json"
- }
-}
-
configurations {
- common
- shadowCommon // Don't use shadow from the shadow plugin since it *excludes* files.
+ common {
+ canBeResolved = true
+ canBeConsumed = false
+ }
compileClasspath.extendsFrom common
runtimeClasspath.extendsFrom common
developmentForge.extendsFrom common
+
+ // Files in this configuration will be bundled into your mod using the Shadow plugin.
+ // Don't use the `shadow` configuration from the plugin itself as it's meant for excluding files.
+ shadowBundle {
+ canBeResolved = true
+ canBeConsumed = false
+ }
}
dependencies {
- forge "net.minecraftforge:forge:${rootProject.forge_version}"
- // Remove the next line if you don't want to depend on the API
- modApi "dev.architectury:architectury-forge:${rootProject.architectury_version}"
+ forge "net.minecraftforge:forge:$rootProject.forge_version"
- common(project(path: ":common", configuration: "namedElements")) { transitive false }
- shadowCommon(project(path: ":common", configuration: "transformProductionForge")) { transitive = false }
+ common(project(path: ':common', configuration: 'namedElements')) { transitive false }
+ shadowBundle project(path: ':common', configuration: 'transformProductionForge')
}
processResources {
- inputs.property "version", project.version
+ inputs.property 'version', project.version
- filesMatching("META-INF/mods.toml") {
- expand "version": project.version
+ filesMatching('META-INF/mods.toml') {
+ expand version: project.version
}
}
shadowJar {
- exclude "fabric.mod.json"
- exclude "architectury.common.json"
-
- configurations = [project.configurations.shadowCommon]
- archiveClassifier = "dev-shadow"
+ configurations = [project.configurations.shadowBundle]
+ archiveClassifier = 'dev-shadow'
}
remapJar {
input.set shadowJar.archiveFile
- dependsOn shadowJar
-}
-
-sourcesJar {
- def commonSources = project(":common").sourcesJar
- dependsOn commonSources
- from commonSources.archiveFile.map { zipTree(it) }
-}
-
-components.java {
- withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) {
- skip()
- }
-}
-
-publishing {
- publications {
- mavenForge(MavenPublication) {
- artifactId = rootProject.archives_base_name + "-" + project.name
- from components.java
- }
- }
-
- // See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
- repositories {
- // Add repositories to publish to here.
- }
}
diff --git a/forge/src/main/resources/META-INF/mods.toml b/forge/src/main/resources/META-INF/mods.toml
index 17c8b66..707dddd 100644
--- a/forge/src/main/resources/META-INF/mods.toml
+++ b/forge/src/main/resources/META-INF/mods.toml
@@ -25,11 +25,4 @@ modId = "minecraft"
mandatory = true
versionRange = "[1.18.2,)"
ordering = "NONE"
-side = "BOTH"
-
-[[dependencies.optionsprofiles]]
-modId = "architectury"
-mandatory = true
-versionRange = "[4.11.93,)"
-ordering = "AFTER"
-side = "BOTH"
+side = "BOTH"
\ No newline at end of file
diff --git a/forge/src/main/resources/optionsprofiles.mixins.json b/forge/src/main/resources/optionsprofiles.mixins.json
deleted file mode 100644
index 5a28846..0000000
--- a/forge/src/main/resources/optionsprofiles.mixins.json
+++ /dev/null
@@ -1,13 +0,0 @@
-{
- "required": true,
- "package": "com.axolotlmaid.optionsprofiles.mixin.forge",
- "compatibilityLevel": "JAVA_17",
- "minVersion": "0.8",
- "client": [
- ],
- "mixins": [
- ],
- "injectors": {
- "defaultRequire": 1
- }
-}
\ No newline at end of file
diff --git a/forge/src/main/resources/pack.mcmeta b/forge/src/main/resources/pack.mcmeta
index 4efb538..a1536a9 100644
--- a/forge/src/main/resources/pack.mcmeta
+++ b/forge/src/main/resources/pack.mcmeta
@@ -1,6 +1,7 @@
{
"pack": {
"description": "Options Profiles",
- "pack_format": 15
+ "forge:data_pack_format": 9,
+ "pack_format": 8
}
-}
+}
\ No newline at end of file
diff --git a/gallery/options-toggle-menu.png b/gallery/options-toggle-menu.png
new file mode 100644
index 0000000..b50dbbb
Binary files /dev/null and b/gallery/options-toggle-menu.png differ
diff --git a/gradle.properties b/gradle.properties
index c7174a3..52f2edf 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,15 +1,17 @@
+# Done to increase the memory available to Gradle.
org.gradle.jvmargs=-Xmx6G
+org.gradle.parallel=true
-minecraft_version=1.18.2
+# Mod properties
+mod_version=1.3
+maven_group=com.axolotlmaid.optionsprofiles
+archives_name=optionsprofiles
enabled_platforms=fabric,forge
-archives_base_name=optionsprofiles
-mod_version=1.1
-maven_group=com.axolotlmaid.optionsprofiles
+# Minecraft properties
+minecraft_version = 1.18.2
-architectury_version=4.11.93
-
-fabric_loader_version=0.14.23
-fabric_api_version=0.76.0+1.18.2
-
-forge_version=1.18.2-40.2.10
\ No newline at end of file
+# Dependencies
+fabric_loader_version = 0.15.11
+fabric_api_version = 0.77.0+1.18.2
+forge_version = 1.18.2-40.2.21
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index 744c64d..dab2a01 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip
networkTimeout=10000
+validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
-zipStorePath=wrapper/dists
+zipStorePath=wrapper/dists
\ No newline at end of file
diff --git a/gradlew b/gradlew
index 79a61d4..1aa94a4 100644
--- a/gradlew
+++ b/gradlew
@@ -83,10 +83,8 @@ done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
-APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
-
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -133,10 +131,13 @@ location of your Java installation."
fi
else
JAVACMD=java
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
+ fi
fi
# Increase the maximum file descriptors if we can.
@@ -144,7 +145,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
case $MAX_FD in #(
max*)
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
- # shellcheck disable=SC3045
+ # shellcheck disable=SC2039,SC3045
MAX_FD=$( ulimit -H -n ) ||
warn "Could not query maximum file descriptor limit"
esac
@@ -152,7 +153,7 @@ if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
'' | soft) :;; #(
*)
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
- # shellcheck disable=SC3045
+ # shellcheck disable=SC2039,SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
@@ -197,11 +198,15 @@ if "$cygwin" || "$msys" ; then
done
fi
-# Collect all arguments for the java command;
-# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
-# shell script including quotes and variable substitutions, so put them in
-# double quotes to make sure that they get re-expanded; and
-# * put everything else in single quotes, so that it's not re-expanded.
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \
diff --git a/gradlew.bat b/gradlew.bat
index 93e3f59..25da30d 100644
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -43,11 +43,11 @@ set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if %ERRORLEVEL% equ 0 goto execute
-echo.
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
+echo. 1>&2
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
goto fail
@@ -57,11 +57,11 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
-echo.
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
-echo.
-echo Please set the JAVA_HOME variable in your environment to match the
-echo location of your Java installation.
+echo. 1>&2
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
+echo. 1>&2
+echo Please set the JAVA_HOME variable in your environment to match the 1>&2
+echo location of your Java installation. 1>&2
goto fail
diff --git a/settings.gradle b/settings.gradle
index 03230de..e1f7b7d 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -2,13 +2,13 @@ pluginManagement {
repositories {
maven { url "https://maven.fabricmc.net/" }
maven { url "https://maven.architectury.dev/" }
- maven { url "https://maven.minecraftforge.net/" }
+ maven { url "https://files.minecraftforge.net/maven/" }
gradlePluginPortal()
}
}
-include("common")
-include("fabric")
-include("forge")
+rootProject.name = 'optionsprofiles-v1.3-1.18.2'
-rootProject.name = "optionsprofiles-v1.1-1.18.2"
+include 'common'
+include 'fabric'
+include 'forge'