Compare commits

..

89 commits

Author SHA1 Message Date
b64f9b6741 fix: update mods and their loaders 2025-10-17 15:57:15 +01:00
0c767a4ba1 docs: update README and gallery 2025-10-16 17:42:27 +01:00
5df3f81fc6 feat: search filter for options toggle list 2025-10-15 22:30:56 +01:00
ee30c795a3 fix: change max length for servers text box 2025-10-15 22:30:30 +01:00
5ead7649af refactor: remove rename profile button 2025-10-15 22:30:09 +01:00
2c90b0af37 chore: bump version to v1.4.3 2025-10-15 21:24:07 +01:00
6b07a052f4 feat: profiles for specific servers (#43) 2025-10-15 21:23:11 +01:00
8859e89ae0 feat: 1.21.9 2025-10-05 11:29:56 +01:00
7457775bb8 chore: bump version 2025-07-31 19:59:27 +01:00
0bc9cd5fa2 fix: don't save if profile deleted 2025-07-31 19:59:22 +01:00
cc1dd4f766 fix: temporarily remove checking if profile is loaded
returns incorrect results.
2025-07-31 19:59:15 +01:00
5c933c5b07 feat: 1.21.6 2025-07-31 19:58:03 +01:00
738517594b chore: bump version 2025-05-21 22:16:02 +01:00
2f8b831a6b fix: update sodium loader (#38) 2025-05-21 22:13:17 +01:00
fd17833a16 fix: loading profiles on startup not loading correctly 2025-03-01 12:52:39 +00:00
05c49ad582 fix: optionsToLoad config resetting 2025-03-01 12:47:49 +00:00
24cb7d665d fix: set initial keybind index button value to config value 2025-03-01 12:38:25 +00:00
42bad1822b chore: bump version 2025-03-01 12:14:21 +00:00
698e793586 feat: load profiles through keybinds (#33) 2025-03-01 12:11:47 +00:00
1b8e17e02b feat: load profiles on startup (#17) 2025-03-01 11:12:52 +00:00
84b1eadf4a fix: delay opening screen by one tick in /optionsprofiles command 2025-03-01 10:18:08 +00:00
e56829232d feat: mod menu integration 2025-03-01 10:02:30 +00:00
aa206fc7e8 feat: settings screen 2025-03-01 10:02:21 +00:00
aa09edda1b fix: show only directories in profiles list 2025-03-01 09:54:51 +00:00
4eb068a2a1 feat: add mod configuration (#34) 2025-02-28 22:53:38 +00:00
ebc2948e0f feat: /optionsprofiles command (#34) 2025-02-28 22:33:14 +00:00
e44c57eca2 fix: loading option profiles without sodium (#35) 2025-02-28 22:13:11 +00:00
b5d8f25a83 fix: add architectury api 2025-02-28 22:12:59 +00:00
5f1a5c62bd refactor: update username 2025-02-28 22:06:13 +00:00
15263e8b74 fix: remove forge
architectury doesn't support forge anymore
2025-02-28 21:46:29 +00:00
422ef168f9
docs: add iris to mod support section and update information in README.md 2025-01-27 21:55:21 +00:00
3b91880e41 feat: iris support (#25) 2025-01-27 21:35:48 +00:00
trafficlunar
0d5b6be82f docs: remove Embeddium from README.md 2024-12-10 20:04:43 +00:00
trafficlunar
79ed571309 fix: add settings to sodium extra loader 2024-12-10 20:04:17 +00:00
trafficlunar
cc102b14de fix: sodium loader causing crash (#26) 2024-12-10 20:04:17 +00:00
trafficlunar
96c4d8eac8 fix: profile loading - check configuration to see if options to load are changed
worded horribly but just know it fixes annoyances
2024-12-10 20:02:25 +00:00
trafficlunar
60a2bcb853 chore: update project name 2024-12-10 19:59:48 +00:00
trafficlunar
44ab1a7f5e fix: rename getScrollbarPosition() to scrollBarX()
fixes game crashing
2024-12-07 13:21:06 +00:00
trafficlunar
fb1f1bb65b chore: remove embeddium (#27) 2024-12-07 13:21:06 +00:00
trafficlunar
f13e2f4dd3 chore: update versions 2024-12-07 13:21:06 +00:00
axolotlmaid
919fdc3486 Tiny code clean up
It was annoying me
2024-07-16 21:18:10 +01:00
axolotlmaid
3a8f3695f6 Add more logging to copying and deleting files 2024-07-16 20:53:04 +01:00
axolotlmaid
427b961fb0 Fix options not refreshing in the options screen without reopening (#22) 2024-07-16 12:36:23 +01:00
axolotlmaid
b38c3f7c57 Bump version up to 1.3.1 2024-07-14 02:41:01 +01:00
axolotlmaid
1526cb9694 Fix optionsToLoad being changed when overwriting profile 2024-07-14 02:07:34 +01:00
axolotlmaid
4d05bb4958 Fix Distant Horizons loading in 1.21 (#21) 2024-07-14 01:47:49 +01:00
axolotlmaid
be5efc2cf2 Forgotten code for commit ef4812a 2024-07-11 01:21:19 +01:00
axolotlmaid
ef4812ace4 Fix Distant Horizons loader causing crash (#18) 2024-07-06 23:10:03 +01:00
axolotlmaid
7401125cee
Merge pull request #16 from yichifauzi/1.21
Added Traditional Chinese (zh_tw.json)
2024-07-03 19:02:58 +01:00
dirtTW
7e7d9a3f56 Update zh_tw.json 2024-07-03 23:37:14 +07:00
dirtTW
98f3b2ffdd Added Traditional Chinese (zh_tw.json)
Added Traditional Chinese translations
2024-07-03 23:35:29 +07:00
axolotlmaid
ea1e7a3005 Add options toggle menu image to README.md
Also cleaned up the README and added a section for mod support
2024-07-03 16:35:59 +01:00
axolotlmaid
1b3e6ad354 Bump version up to 1.3 2024-07-03 16:34:34 +01:00
axolotlmaid
55e941b6f1 Change compatibility level in mixins.json to JAVA_17 for Forge 2024-07-03 16:32:22 +01:00
axolotlmaid
01ab8518f4 Update loom and gradle 2024-07-03 16:31:59 +01:00
axolotlmaid
1a96047b5e Add Embeddium and Distant Horizons support 2024-07-03 16:00:12 +01:00
axolotlmaid
e7d9ee1a21 Fix bug when checking profiles are loaded
bug: loading profiles do not check if other profiles are loaded which
will result in every load button to become disabled
2024-07-02 14:30:10 +01:00
axolotlmaid
f43edf9bbd Specific options profile loading (#15) 2024-07-02 02:19:27 +01:00
axolotlmaid
d960950df9 Add layouts to screens
Also minor changes and fixes:
- Localization and colors for "All ON" and "All OFF" buttons
- Code cleanup
- Change Y position for entries in list widgets
2024-07-02 01:45:08 +01:00
axolotlmaid
0b0a93dca7 Add checkbox in edit profile screen 2024-06-29 16:55:37 +01:00
axolotlmaid
b6480365ad Add profile configuration 2024-06-29 14:38:18 +01:00
axolotlmaid
6aa8d28d5a
Use relative image links 2024-06-15 16:00:01 +01:00
axolotlmaid
b150974eae Update to 1.21 2024-06-15 15:03:23 +01:00
axolotlmaid
30466aedc4
Merge pull request #13 from Rad586/patch-1
Create zh_cn.json
2024-06-07 12:48:50 +01:00
Rad
4dd8ba075b
Create zh_cn.json 2024-06-07 18:16:43 +08:00
axolotlmaid
159ebeefed
Remove yarn mappings from gradle.properties 2024-06-02 23:45:20 +01:00
axolotlmaid
2690515316 Add Neoforge and upgrade template
Forge is not working but I can't really do anything about it
2024-06-02 17:27:15 +01:00
axolotlmaid
f0cebb6252 Bump version down for consistency 2024-06-02 13:58:00 +01:00
axolotlmaid
4683c20c4b Remove Super Secret Settings from Sodium Extra 2024-05-31 22:48:46 +01:00
axolotlmaid
64eca1222a Upgrade everything
- Gradle
- Architectury Loom
- Mod implementations
- Versions
2024-05-31 22:48:27 +01:00
axolotlmaid
586db38dff Fix SodiumExtraConfigLoader.java (#11)
ConfigData is meant to look like 'sodium-extra-options.json'.

In other words, I forgot to make some variables lower case with underscores
2024-05-31 22:03:12 +01:00
axolotlmaid
8435350ee0 Fix and improve checking if profile is loaded
Other changes:
- Improved readability of logging
- Improved deleting profiles
- Added some comments
- Forgot to remove old classes in imports
2024-05-31 21:59:37 +01:00
AxolotlMaid
2ed45b5b99 Create SodiumExtraConfigLoader.java
Currently causing errors but will fix later
2024-05-29 23:47:55 +01:00
axolotlmaid
8b995955db Rewrite Profiles.java
Improves readability and logging
2024-05-29 22:34:46 +01:00
AxolotlMaid
1e1b19890a Forgot to replace some logging 2024-05-29 00:09:35 +01:00
AxolotlMaid
a4ab0aa35a Bump version up to 1.2.1 2024-05-28 23:59:21 +01:00
AxolotlMaid
2056f44b43 Replace logging with Log4j
Used to be logged with `System.out.println`
2024-05-28 23:59:12 +01:00
axolotlmaid
d43be9b51e
Update screenshots in README.md 2024-05-28 00:08:28 +01:00
AxolotlMaid
628c9a88b6 Retake screenshots to be more updated 2024-05-28 00:07:18 +01:00
axolotlmaid
bd51b1c6b1
Add Sodium Extra to build.gradle (#11) 2024-05-27 23:55:27 +01:00
axolotlmaid
a9eaaae9e9 Add version 1.2 features 2024-05-21 21:31:13 +01:00
axolotlmaid
34e6cc3020 Bump version to 1.2 2024-05-21 19:22:33 +01:00
axolotlmaid
b47336b04d Remove Architectury API 2024-05-21 19:22:21 +01:00
axolotlmaid
734d3d9d0c
Add FAQ to README.md 2024-05-20 14:02:08 +01:00
axolotlmaid
2b1331d756
Update README.md 2024-05-20 13:56:57 +01:00
axolotlmaid
ac9f0d59e4 Change mod version to 1.1.1 2024-05-11 17:01:20 +01:00
AxolotlMaid
330b6aef54 Fix #9 2024-04-18 00:30:01 +01:00
AxolotlMaid
6979ff543d Update to 1.20.4 2024-01-07 11:54:58 +00:00
AxolotlMaid
f55488ecf7
Update README.md 2023-12-24 14:13:06 +00:00
53 changed files with 1228 additions and 887 deletions

1
.gitignore vendored
View file

@ -1,3 +1,4 @@
.architectury-transformer/
build/ build/
*.ipr *.ipr
run/ run/

View file

@ -1,30 +1,35 @@
# [1.18.2] Options Profiles # Options Profiles
[![Modrinth](https://github.com/intergrav/devins-badges/blob/v3/assets/cozy/available/modrinth_64h.png?raw=true)](https://modrinth.com/mod/options-profiles) [![Modrinth](https://github.com/intergrav/devins-badges/blob/v3/assets/cozy/available/modrinth_64h.png?raw=true)](https://modrinth.com/mod/options-profiles)
[![Curseforge](https://github.com/intergrav/devins-badges/blob/v3/assets/cozy/available/curseforge_64h.png?raw=true)](https://curseforge.com/minecraft/mc-mods/options-profiles) [![Curseforge](https://github.com/intergrav/devins-badges/blob/v3/assets/cozy/available/curseforge_64h.png?raw=true)](https://curseforge.com/minecraft/mc-mods/options-profiles)
[![GitHub](https://github.com/intergrav/devins-badges/blob/v3/assets/cozy/available/git_64h.png?raw=true)](https://github.com/AxolotlMaid/options-profiles) [![GitHub](https://github.com/intergrav/devins-badges/blob/v3/assets/cozy/available/git_64h.png?raw=true)](https://github.com/trafficlunar/options-profiles)
Options Profiles is a Minecraft mod that lets you load and save your options as profiles from in-game. Options Profiles is a Minecraft mod that lets you load and save your options as profiles from in-game.
## Features ## Features
- Save and load profiles in-game - Save and load profiles in-game
- Load specific options (like only load keybinds, resource packs or FOV and GUI scale) - Load specific options (e.g. only load keybinds, resource packs, FOV, etc.)
- Load profiles when joining a certain server
- Edit profiles in-game (deleting, renaming, overwriting, pick options to only load) - Edit profiles in-game (deleting, renaming, overwriting, pick options to only load)
- Fabric and Forge support - Fabric, NeoForge support
- Third party mod support (see below) - Third party mod support (see below)
## Mod Support ## Mod Support
Options Profiles supports these mods which means you can create and load profiles with them and the mod will load their configuration. Options Profiles supports these mods which means you can create and load profiles with them and the mod will load their configuration.
- Sodium - Sodium
- Sodium Extra - Sodium Extra
- Embeddium - Iris
- Distant Horizons - Distant Horizons
- OptiFine
If you would like support for another mod, open an issue. If you would like support for another mod, open an issue.
## Frequently Asked Questions ## Frequently Asked Questions
- How to open profiles menu without going to options?
> You can open the profiles menu by using the command `/optionsprofiles` or by accessing it from Mod Menu
- Can you port [version]? - Can you port [version]?
> Open an issue in the GitHub repository. > Open an issue in the GitHub repository.
- Can I use this in my modpack? - Can I use this in my modpack?
@ -34,15 +39,15 @@ If you would like support for another mod, open an issue.
- Where can I find the source code for older versions? - Where can I find the source code for older versions?
> You can find them in the branches. > You can find them in the branches.
- Dependencies? - Dependencies?
> Versions 1.1 require Architectury API, however versions 1.2+ do not. > Architectury API and Fabric API (if on Fabric)
- For any other questions, create an issue or contact me at hello@axolotlmaid.com - For any other questions, create an issue or contact me at hello@trafficlunar.net
## Gallery ## Gallery
Profiles Menu | Edit Profile Screen | Profiles Menu | Edit Profile Screen |
:-------------------------:|:-------------------------: | :--------------------------------------------------------: | :--------------------------------------------------------------------: |
<img src="gallery/profiles-menu.png" alt="profiles list"/> | <img src="gallery/edit-profile-screen.png" alt="edit profile screen"/> | <img src="gallery/profiles-menu.png" alt="profiles list"/> | <img src="gallery/edit-profile-screen.png" alt="edit profile screen"/> |
Options Toggle Menu | Options Screen | Options Toggle Menu | Options Screen |
:-------------------------:|:-------------------------: | :--------------------------------------------------------------------: | :----------------------------------------------------------: |
<img src="gallery/options-toggle-menu.png" alt="options toggle menu"/> | <img src="gallery/options-screen.png" alt="options screen"/> | <img src="gallery/options-toggle-menu.png" alt="options toggle menu"/> | <img src="gallery/options-screen.png" alt="options screen"/> |

View file

@ -1,7 +1,7 @@
plugins { plugins {
id 'dev.architectury.loom' version '1.6-SNAPSHOT' apply false id 'dev.architectury.loom' version '1.11-SNAPSHOT' apply false
id 'architectury-plugin' version '3.4-SNAPSHOT' id 'architectury-plugin' version '3.4-SNAPSHOT'
id 'com.github.johnrengelman.shadow' version '8.1.1' apply false id 'com.gradleup.shadow' version '8.3.6' apply false
} }
architectury { architectury {
@ -46,12 +46,12 @@ subprojects {
// If you remove this line, sources will not be generated. // If you remove this line, sources will not be generated.
withSourcesJar() withSourcesJar()
sourceCompatibility = JavaVersion.VERSION_17 sourceCompatibility = JavaVersion.VERSION_21
targetCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_21
} }
tasks.withType(JavaCompile).configureEach { tasks.withType(JavaCompile).configureEach {
it.options.release = 17 it.options.release = 21
} }
// Configure Maven publishing. // Configure Maven publishing.

View file

@ -20,11 +20,15 @@ dependencies {
// We depend on Fabric Loader here to use the Fabric @Environment annotations, // We depend on Fabric Loader here to use the Fabric @Environment annotations,
// which get remapped to the correct annotations on each platform. // which get remapped to the correct annotations on each platform.
// Do NOT use other classes from Fabric Loader. // Do NOT use other classes from Fabric Loader.
modImplementation "net.fabricmc:fabric-loader:$rootProject.fabric_loader_version" modImplementation "net.fabricmc:fabric-loader:${rootProject.fabric_loader_version}"
// Architectury API
modImplementation "dev.architectury:architectury:$rootProject.architectury_api_version"
// Mod implementations // Mod implementations
modImplementation "maven.modrinth:sodium:mc1.18.2-0.4.1" // Sodium modImplementation "maven.modrinth:sodium:mc1.21.10-0.7.2-fabric" // Sodium
modImplementation "maven.modrinth:sodium-extra:mc1.18.2-0.4.18" // Sodium Extra modImplementation "maven.modrinth:sodium-extra:mc1.21.9-0.7.0+fabric" // Sodium Extra
modImplementation "maven.modrinth:embeddium:0.3.18+mc1.18.2" // Embeddium modImplementation "maven.modrinth:iris:1.9.6+1.21.10-fabric" // Iris
modImplementation "maven.modrinth:distanthorizons:2.1.2-a-1.18.2" // Distant Horizons modImplementation "maven.modrinth:distanthorizons:2.3.6-b-1.21.10" // Distant Horizons
modImplementation "maven.modrinth:controlify:2.4.2-fabric,1.21.9" // Controlify
} }

View file

@ -1,30 +0,0 @@
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;
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");
if (Files.notExists(profilesDirectory)) {
try {
Files.createDirectory(profilesDirectory);
} catch (IOException e) {
LOGGER.error("An error occurred when creating the 'options-profiles' directory.", e);
}
}
// Update / add configuration for existing profiles
Profiles.updateProfiles();
}
}

View file

@ -1,115 +0,0 @@
package com.axolotlmaid.optionsprofiles.gui;
import com.axolotlmaid.optionsprofiles.profiles.Profiles;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.GuiComponent;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import net.minecraft.network.chat.TranslatableComponent;
public class EditProfileScreen extends Screen {
private final Screen lastScreen;
private final Component profileName;
private EditBox profileNameEdit;
public EditProfileScreen(Screen screen, Component profileName) {
super(new TextComponent(new TranslatableComponent("gui.optionsprofiles.editing-profile-title").getString() + profileName.getString()));
this.lastScreen = screen;
this.profileName = profileName;
}
protected void init() {
this.profileNameEdit = new EditBox(
this.font,
this.width / 2 - 102,
70,
204,
20,
new TextComponent(Component.EMPTY.getString())
);
this.profileNameEdit.setValue(profileName.getString());
this.addRenderableWidget(this.profileNameEdit);
this.addRenderableWidget(
new Button(
this.width / 2 - 75,
100,
150,
20,
new TranslatableComponent("gui.optionsprofiles.overwrite-options"),
(button) -> {
Profiles.writeProfile(profileName.getString(), true);
this.minecraft.setScreen(this.lastScreen);
},
(button, poseStack, i, j) -> EditProfileScreen.this.renderTooltip(poseStack, new TranslatableComponent("gui.optionsprofiles.overwrite-options.tooltip"), i, j)
)
);
this.addRenderableWidget(
new Button(
this.width / 2 - 75,
121,
150,
20,
new TranslatableComponent("gui.optionsprofiles.rename-profile"),
(button) -> {
Profiles.renameProfile(profileName.getString(), this.profileNameEdit.getValue());
this.minecraft.setScreen(new EditProfileScreen(lastScreen, new TextComponent(this.profileNameEdit.getValue())));
}
)
);
this.addRenderableWidget(
new Button(
this.width / 2 - 75,
142,
150,
20,
new TranslatableComponent("gui.optionsprofiles.options-toggle").append("..."),
(button) -> {
this.minecraft.setScreen(new OptionsToggleScreen(this, profileName));
},
(button, poseStack, i, j) -> EditProfileScreen.this.renderTooltip(poseStack, new TranslatableComponent("gui.optionsprofiles.options-toggle.tooltip"), i, j)
)
);
this.addRenderableWidget(
new Button(
10,
this.height - 29,
50,
20,
new TranslatableComponent("gui.optionsprofiles.delete-profile").withStyle(ChatFormatting.RED),
(button) -> {
Profiles.deleteProfile(profileName.getString());
this.minecraft.setScreen(this.lastScreen);
}
)
);
this.addRenderableWidget(
new Button(
this.width / 2 - 100,
this.height - 29,
200,
20,
CommonComponents.GUI_DONE,
(button) -> this.minecraft.setScreen(this.lastScreen)
)
);
}
public void render(PoseStack poseStack, int mouseX, int mouseY, float delta) {
renderBackground(poseStack);
this.profileNameEdit.render(poseStack, mouseX, mouseY, delta);
GuiComponent.drawCenteredString(poseStack, this.font, this.title, this.width / 2, 8, 16777215);
GuiComponent.drawCenteredString(poseStack, this.font, new TranslatableComponent("gui.optionsprofiles.profile-name-text"), this.width / 2, 50, 16777215);
super.render(poseStack, mouseX, mouseY, delta);
}
}

View file

@ -1,73 +0,0 @@
package com.axolotlmaid.optionsprofiles.gui;
import com.axolotlmaid.optionsprofiles.profiles.ProfileConfiguration;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.ChatFormatting;
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.options-toggle").append(": ").append(profileName));
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);
this.addRenderableWidget(
new Button(
this.width / 2 - 80,
this.height - 29,
75,
20,
new TranslatableComponent("gui.optionsprofiles.all-off").withStyle(ChatFormatting.RED),
(button) -> this.optionsToggleList.refreshEntries(true, false)
)
);
this.addRenderableWidget(
new Button(
this.width / 2 - 155,
this.height - 29,
75,
20,
new TranslatableComponent("gui.optionsprofiles.all-on").withStyle(ChatFormatting.GREEN),
(button) -> this.optionsToggleList.refreshEntries(true, true)
)
);
this.addRenderableWidget(
new Button(
this.width / 2 + 5,
this.height - 29,
150,
20,
CommonComponents.GUI_DONE,
(button) -> {
profileConfiguration.save();
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);
}
}

View file

@ -1,147 +0,0 @@
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.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiComponent;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.ContainerObjectSelectionList;
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 net.minecraft.network.chat.TranslatableComponent;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class ProfilesList extends ContainerObjectSelectionList<ProfilesList.ProfileEntry> {
final ProfilesScreen profilesScreen;
public ProfilesList(ProfilesScreen profilesScreen, Minecraft minecraft) {
super(minecraft, profilesScreen.width + 45, profilesScreen.height, 20, profilesScreen.height - 32, 20);
this.profilesScreen = profilesScreen;
refreshEntries();
}
public void refreshEntries() {
this.clearEntries();
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Profiles.PROFILES_DIRECTORY)) {
List<Path> profileList = new ArrayList<>();
for (Path profile : directoryStream) {
profileList.add(profile);
}
// Sort the list alphabetically based on the profile names
profileList.sort(Comparator.comparing(p -> p.getFileName().toString()));
for (Path profile : profileList) {
this.addEntry(new ProfilesList.ProfileEntry(new TextComponent(profile.getFileName().toString())));
}
} catch (Exception e) {
OptionsProfilesMod.LOGGER.error("An error occurred when listing profiles", e);
}
checkEntriesLoaded();
}
public void checkEntriesLoaded() {
this.children().forEach(ProfileEntry::checkLoaded);
}
protected int getScrollbarPosition() {
return super.getScrollbarPosition() + 15;
}
public int getRowWidth() {
return 340;
}
public class ProfileEntry extends ContainerObjectSelectionList.Entry<ProfilesList.ProfileEntry> {
private final Component profileName;
private final Button editButton;
private final Button loadButton;
ProfileEntry(Component profileName) {
this.profileName = profileName;
this.editButton = new Button(
0,
0,
75,
20,
new TranslatableComponent("gui.optionsprofiles.edit-profile"),
(button) -> {
minecraft.setScreen(new EditProfileScreen(profilesScreen, profileName));
}
);
this.loadButton = new Button(
0,
0,
75,
20,
new TranslatableComponent("gui.optionsprofiles.load-profile"),
(button) -> {
Profiles.loadProfile(profileName.getString());
minecraft.options.load();
if (ProfileConfiguration.get(profileName.getString()).getOptionsToLoad().contains("resourcePacks")) {
minecraft.options.loadSelectedResourcePacks(minecraft.getResourcePackRepository());
minecraft.reloadResourcePacks();
}
minecraft.options.save();
ProfilesList.this.checkEntriesLoaded();
button.active = false;
}
);
this.loadButton.active = !Profiles.isProfileLoaded(profileName.getString());
}
@Override
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 = ProfilesList.this.minecraft.font;
int posX = ProfilesList.this.getScrollbarPosition() - this.loadButton.getWidth() - 10;
int posY = y - 2;
int textY = y + entryHeight / 2;
GuiComponent.drawString(poseStack, fontRenderer, this.profileName, x, textY - 9 / 2, 16777215);
this.editButton.x = posX - this.editButton.getWidth();
this.editButton.y = posY;
this.editButton.render(poseStack, mouseX, mouseY, tickDelta);
this.loadButton.x = posX;
this.loadButton.y = posY;
this.loadButton.render(poseStack, mouseX, mouseY, tickDelta);
}
public List<? extends GuiEventListener> children() {
return ImmutableList.of(this.editButton, this.loadButton);
}
public List<? extends NarratableEntry> narratables() {
return ImmutableList.of(this.editButton, this.loadButton);
}
protected void checkLoaded() {
this.loadButton.active = !Profiles.isProfileLoaded(profileName.getString());
}
}
}

View file

@ -1,56 +0,0 @@
package com.axolotlmaid.optionsprofiles.gui;
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.TranslatableComponent;
public class ProfilesScreen extends Screen {
private final Screen lastScreen;
private ProfilesList profilesList;
public ProfilesScreen(Screen screen) {
super(new TranslatableComponent("gui.optionsprofiles.profiles-menu"));
this.lastScreen = screen;
}
protected void init() {
this.profilesList = new ProfilesList(this, this.minecraft);
this.addWidget(this.profilesList);
this.addRenderableWidget(
new Button(
this.width / 2 - 155,
this.height - 29,
150,
20,
new TranslatableComponent("gui.optionsprofiles.save-current-options"),(button) -> {
Profiles.createProfile();
this.profilesList.refreshEntries();
}
)
);
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.profilesList.render(poseStack, mouseX, mouseY, delta);
GuiComponent.drawCenteredString(poseStack, this.font, this.title, this.width / 2, 8, 16777215);
super.render(poseStack, mouseX, mouseY, delta);
}
}

View file

@ -1,35 +0,0 @@
package com.axolotlmaid.optionsprofiles.mixin;
import com.axolotlmaid.optionsprofiles.gui.ProfilesScreen;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.screens.OptionsScreen;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TranslatableComponent;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(OptionsScreen.class)
public class MixinOptionsScreen extends Screen {
protected MixinOptionsScreen(Component component) {
super(component);
}
@Inject(at = @At("HEAD"), method = "init")
private void init(CallbackInfo info) {
this.addRenderableWidget(
new Button(
5,
5,
75,
20,
new TranslatableComponent("gui.optionsprofiles.profiles-menu"),
(button) -> {
this.minecraft.setScreen(new ProfilesScreen(this));
}
)
);
}
}

View file

@ -1,11 +0,0 @@
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();
}
}

View file

@ -1,71 +0,0 @@
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 EmbeddiumLoader {
public static void load(Path file) {
try (FileReader reader = new FileReader(file.toFile())) {
Gson gson = new GsonBuilder().create();
Configuration configData = gson.fromJson(reader, Configuration.class);
apply(configData);
} 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.disableIncompatibleModWarnings = configuration.advanced.disable_incompatible_mod_warnings;
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().performance.useCompactVertexFormat = configuration.performance.use_compact_vertex_format;
SodiumClientMod.options().performance.useTranslucentFaceSorting = configuration.performance.use_translucent_face_sorting;
SodiumClientMod.options().notifications.hideDonationButton = configuration.notifications.hide_donation_button;
try {
SodiumClientMod.options().writeChanges();
} catch (IOException e) {
OptionsProfilesMod.LOGGER.error("An error occurred when loading Embeddium's configuration", e);
}
}
public static class Configuration {
public SodiumLoader.Configuration.Quality quality;
public Advanced advanced;
public Performance performance;
public SodiumLoader.Configuration.Notifications notifications;
public static class Advanced extends SodiumLoader.Configuration.Advanced {
public boolean disable_incompatible_mod_warnings;
}
public static class Performance extends SodiumLoader.Configuration.Performance {
public boolean use_compact_vertex_format;
public boolean use_translucent_face_sorting;
}
}
}

View file

@ -0,0 +1,18 @@
package net.trafficlunar.optionsprofiles;
import dev.architectury.event.events.common.CommandRegistrationEvent;
import net.minecraft.client.Minecraft;
import net.trafficlunar.optionsprofiles.gui.ProfilesScreen;
public class Commands {
public static void init() {
CommandRegistrationEvent.EVENT.register(((dispatcher, buildContext, selection) -> dispatcher.register(
net.minecraft.commands.Commands
.literal("optionsprofiles")
.executes(context -> {
Minecraft.getInstance().execute(() -> Minecraft.getInstance().setScreen(new ProfilesScreen(null)));
return 1;
})
)));
}
}

View file

@ -0,0 +1,58 @@
package net.trafficlunar.optionsprofiles;
import com.mojang.blaze3d.platform.InputConstants;
import dev.architectury.event.events.client.ClientTickEvent;
import dev.architectury.registry.client.keymappings.KeyMappingRegistry;
import net.minecraft.client.KeyMapping;
import net.minecraft.client.Minecraft;
import net.minecraft.resources.ResourceLocation;
import net.trafficlunar.optionsprofiles.profiles.ProfileConfiguration;
import net.trafficlunar.optionsprofiles.profiles.Profiles;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Stream;
public class Keybinds {
private static final KeyMapping[] PROFILE_KEYMAPPINGS = new KeyMapping[3];
public static void init() {
KeyMapping.Category category = KeyMapping.Category.register(ResourceLocation.fromNamespaceAndPath(OptionsProfilesMod.MOD_ID, "keys"));
for (int i = 0; i < PROFILE_KEYMAPPINGS.length; i++) {
PROFILE_KEYMAPPINGS[i] = new KeyMapping(
"key.optionsprofiles.profile_" + (i + 1),
InputConstants.Type.KEYSYM,
-1,
category
);
KeyMappingRegistry.register(PROFILE_KEYMAPPINGS[i]);
}
ClientTickEvent.CLIENT_POST.register(minecraft -> {
for (int i = 0; i < PROFILE_KEYMAPPINGS.length; i++) {
while (PROFILE_KEYMAPPINGS[i].consumeClick()) {
loadProfilesByKeybind(i + 1);
}
}
});
}
private static void loadProfilesByKeybind(int keybindIndex) {
try (Stream<Path> paths = Files.list(Profiles.PROFILES_DIRECTORY)) {
paths.filter(Files::isDirectory)
.forEach(path -> {
String profileName = path.getFileName().toString();
ProfileConfiguration profileConfiguration = ProfileConfiguration.get(profileName);
if (profileConfiguration.getKeybindIndex() == keybindIndex) {
Profiles.loadProfile(profileName);
OptionsProfilesMod.LOGGER.warn("[Profile '{}']: Loaded through keybind", profileName);
}
});
} catch (IOException e) {
OptionsProfilesMod.LOGGER.error("An error occurred when loading profiles through keybinds", e);
}
}
}

View file

@ -0,0 +1,115 @@
package net.trafficlunar.optionsprofiles;
import dev.architectury.event.events.client.ClientLifecycleEvent;
import dev.architectury.event.events.client.ClientPlayerEvent;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.network.Connection;
import net.trafficlunar.optionsprofiles.profiles.ProfileConfiguration;
import net.trafficlunar.optionsprofiles.profiles.Profiles;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.stream.Stream;
public class OptionsProfilesMod {
public static final String MOD_ID = "optionsprofiles";
public static final Logger LOGGER = LogManager.getLogger("Options Profiles");
private static OptionsProfilesModConfiguration CONFIG;
public static void init() {
// Create options-profiles directory
Path profilesDirectory = Paths.get("options-profiles");
if (Files.notExists(profilesDirectory)) {
try {
Files.createDirectory(profilesDirectory);
} catch (IOException e) {
LOGGER.error("An error occurred when creating the 'options-profiles' directory.", e);
}
}
// Load mod config
CONFIG = OptionsProfilesModConfiguration.load();
// Load profiles marked to load on startup
ClientLifecycleEvent.CLIENT_STARTED.register(client -> {
try (Stream<Path> paths = Files.list(Profiles.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);
if (profileConfiguration.shouldLoadOnStartup()) {
Profiles.loadProfile(profileName);
OptionsProfilesMod.LOGGER.info("[Profile '{}']: Loaded on startup", profileName);
}
});
} catch (IOException e) {
OptionsProfilesMod.LOGGER.error("An error occurred when initializing", e);
}
});
// Load profiles marked to load on server join
ClientPlayerEvent.CLIENT_PLAYER_JOIN.register((LocalPlayer player) -> {
handleClientPlayerEvent(player, false);
});
// Load profiles marked to load on server leave
ClientPlayerEvent.CLIENT_PLAYER_QUIT.register((LocalPlayer player) -> {
handleClientPlayerEvent(player, true);
});
Keybinds.init();
Commands.init();
}
public static OptionsProfilesModConfiguration config() {
if (CONFIG == null) {
throw new IllegalStateException("Config not yet available");
} else {
return CONFIG;
}
}
private static void handleClientPlayerEvent(LocalPlayer player, boolean isOnLeave) {
if (player == null) return;
Connection connection = player.connection.getConnection();
// Check if it's not an integrated server
if (!connection.isMemoryConnection()) {
// Get IP address
SocketAddress address = connection.getRemoteAddress();
if (address instanceof InetSocketAddress inetAddress) {
String ip = inetAddress.getHostString().trim();
// Go through all profiles and check what profiles to load
try (Stream<Path> paths = Files.list(Profiles.PROFILES_DIRECTORY)) {
paths.filter(Files::isDirectory)
.forEach(path -> {
String profileName = path.getFileName().toString();
ProfileConfiguration profileConfiguration = ProfileConfiguration.get(profileName);
String[] servers = profileConfiguration.getServers().split(",");
if (servers.length == 0) return;
// Check if "leave" for the leave event or IP for the join event is in profile's servers
if (Arrays.asList(servers).contains(isOnLeave ? "leave" : ip)) {
Profiles.loadProfile(profileName);
OptionsProfilesMod.LOGGER.info("[Profile '{}']: Loaded on server ({})" + (isOnLeave ? "leave" : ""), profileName, ip);
}
});
} catch (IOException e) {
OptionsProfilesMod.LOGGER.error("An error occurred when initializing", e);
}
}
}
}
}

View file

@ -0,0 +1,59 @@
package net.trafficlunar.optionsprofiles;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import net.trafficlunar.optionsprofiles.profiles.Profiles;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class OptionsProfilesModConfiguration {
private static Path configurationFile;
private boolean showProfilesButton = true;
public OptionsProfilesModConfiguration save() {
OptionsProfilesModConfiguration configuration = new OptionsProfilesModConfiguration();
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.create();
try (BufferedWriter writer = Files.newBufferedWriter(configurationFile)) {
gson.toJson(this, writer);
OptionsProfilesMod.LOGGER.info("Main configuration saved");
} catch (IOException e) {
OptionsProfilesMod.LOGGER.error("Unable to write main configuration.json!", e);
}
return configuration;
}
public static OptionsProfilesModConfiguration load() {
OptionsProfilesModConfiguration configuration = new OptionsProfilesModConfiguration();
configurationFile = Profiles.PROFILES_DIRECTORY.resolve("configuration.json");
if (Files.notExists(configurationFile))
configuration.save();
try (BufferedReader reader = Files.newBufferedReader(configurationFile)) {
Gson gson = new Gson();
configuration = gson.fromJson(reader, OptionsProfilesModConfiguration.class);
} catch (IOException e) {
OptionsProfilesMod.LOGGER.error("An error occurred when reading the main configuration.json", e);
}
return configuration;
}
public boolean shouldShowProfilesButton() {
return showProfilesButton;
}
public void setShowProfilesButton(boolean showProfilesButton) {
this.showProfilesButton = showProfilesButton;
}
}

View file

@ -0,0 +1,138 @@
package net.trafficlunar.optionsprofiles.gui;
import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.components.*;
import net.minecraft.client.gui.layouts.HeaderAndFooterLayout;
import net.minecraft.client.gui.layouts.LayoutSettings;
import net.minecraft.client.gui.layouts.LinearLayout;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import net.trafficlunar.optionsprofiles.profiles.ProfileConfiguration;
import net.trafficlunar.optionsprofiles.profiles.Profiles;
public class EditProfileScreen extends Screen {
private final ProfilesScreen profilesScreen;
private final HeaderAndFooterLayout layout = new HeaderAndFooterLayout(this, 24, 33);
private final Component profileName;
private final ProfileConfiguration profileConfiguration;
private EditBox profileNameEdit;
private EditBox serversEdit;
public EditProfileScreen(ProfilesScreen profilesScreen, Component profileName) {
super(Component.literal(Component.translatable("gui.optionsprofiles.editing-profile-title").getString() + profileName.getString()));
this.profilesScreen = profilesScreen;
this.profileName = profileName;
this.profileConfiguration = ProfileConfiguration.get(profileName.getString());
}
protected void init() {
LinearLayout linearLayoutHeader = this.layout.addToHeader(LinearLayout.vertical());
linearLayoutHeader.addChild(new StringWidget(this.title, this.font), LayoutSettings::alignHorizontallyCenter);
this.profileNameEdit = new EditBox(this.font, this.width / 2 - 102, 116, 204, 20, Component.empty());
this.profileNameEdit.setValue(profileName.getString());
this.serversEdit = new EditBox(this.font, this.width / 2 - 102, 137, 204, 20, Component.empty());
this.serversEdit.setMaxLength(128);
this.serversEdit.setValue(this.profileConfiguration.getServers());
this.serversEdit.setHint(Component.translatable("gui.optionsprofiles.servers-hint").withStyle(ChatFormatting.GRAY));
this.serversEdit.setTooltip(Tooltip.create(Component.translatable("gui.optionsprofiles.servers.tooltip")));
LinearLayout linearLayoutContent = this.layout.addToContents(LinearLayout.vertical().spacing(12), LayoutSettings::alignHorizontallyCenter);
LinearLayout linearLayoutEditBox = linearLayoutContent.addChild(LinearLayout.vertical().spacing(3), LayoutSettings::alignHorizontallyCenter);
linearLayoutEditBox.addChild(new StringWidget(Component.translatable("gui.optionsprofiles.profile-name-text"), this.font), LayoutSettings::alignHorizontallyCenter);
linearLayoutEditBox.addChild(this.profileNameEdit);
linearLayoutEditBox.addChild(LinearLayout.vertical()); // add an extra spacing above edit box
linearLayoutEditBox.addChild(new StringWidget(Component.translatable("gui.optionsprofiles.servers-text"), this.font), LayoutSettings::alignHorizontallyCenter);
linearLayoutEditBox.addChild(this.serversEdit);
LinearLayout linearLayoutButtons = linearLayoutContent.addChild(LinearLayout.vertical().spacing(1), LayoutSettings::alignHorizontallyCenter);
linearLayoutButtons.addChild(
Button.builder(
Component.translatable("gui.optionsprofiles.overwrite-options"),
(button) -> {
Profiles.writeProfile(profileName.getString(), true);
this.onClose();
})
.size(150, 20)
.pos(this.width / 2 - 75, 145)
.tooltip(Tooltip.create(Component.translatable("gui.optionsprofiles.overwrite-options.tooltip")))
.build(),
LayoutSettings::alignHorizontallyCenter
);
linearLayoutButtons.addChild(
Button.builder(
Component.translatable("gui.optionsprofiles.options-toggle").append("..."),
(button) -> this.minecraft.setScreen(new OptionsToggleScreen(this, profileName, profileConfiguration)))
.size(150, 20)
.pos(this.width / 2 - 75, 187)
.tooltip(Tooltip.create(Component.translatable("gui.optionsprofiles.options-toggle.tooltip")))
.build(),
LayoutSettings::alignHorizontallyCenter
);
LinearLayout linearLayoutSettings = linearLayoutContent.addChild(LinearLayout.vertical().spacing(1), LayoutSettings::alignHorizontallyCenter);
linearLayoutSettings.addChild(
CycleButton.<Integer>builder(value -> Component.literal(value.toString()))
.withValues(0, 1, 2, 3)
.withInitialValue(this.profileConfiguration.getKeybindIndex())
.create(0, 0, 150, 20, Component.translatable("gui.optionsprofiles.keybind-index"), (button, keybindIndex) -> {
this.profileConfiguration.setKeybindIndex(keybindIndex);
}),
LayoutSettings::alignHorizontallyCenter
);
linearLayoutSettings.addChild(
CycleButton.onOffBuilder(this.profileConfiguration.shouldLoadOnStartup())
.create(0, 0, 150, 20, Component.translatable("gui.optionsprofiles.load-on-startup"), (button, boolean_) -> {
this.profileConfiguration.setLoadOnStartup(boolean_);
}),
LayoutSettings::alignHorizontallyCenter
);
this.layout.addToFooter(
Button.builder(
CommonComponents.GUI_DONE,
(button) -> this.onClose())
.width(200)
.build()
);
this.layout.addToFooter(
Button.builder(
Component.translatable("gui.optionsprofiles.delete-profile")
.withStyle(ChatFormatting.RED),
(button) -> {
Profiles.deleteProfile(profileName.getString());
this.onClose(true);
})
.width(50)
.build(),
(layoutSettings) -> layoutSettings.alignHorizontallyLeft().paddingLeft(5)
);
this.layout.visitWidgets(this::addRenderableWidget);
this.repositionElements();
}
protected void repositionElements() {
this.layout.arrangeElements();
}
@Override
public void onClose() {
this.onClose(false);
}
public void onClose(boolean deleted) {
if (!deleted) {
this.profileConfiguration.setServers(this.serversEdit.getValue());
this.profileConfiguration.save();
Profiles.renameProfile(profileName.getString(), this.profileNameEdit.getValue());
}
this.minecraft.setScreen(this.profilesScreen);
this.profilesScreen.profilesList.refreshEntries();
}
}

View file

@ -1,20 +1,23 @@
package com.axolotlmaid.optionsprofiles.gui; package net.trafficlunar.optionsprofiles.gui;
import com.axolotlmaid.optionsprofiles.OptionsProfilesMod; import net.fabricmc.api.EnvType;
import com.axolotlmaid.optionsprofiles.profiles.ProfileConfiguration; import net.fabricmc.api.Environment;
import com.axolotlmaid.optionsprofiles.profiles.Profiles; import net.minecraft.client.gui.screens.options.controls.KeyBindsList;
import net.trafficlunar.optionsprofiles.OptionsProfilesMod;
import net.trafficlunar.optionsprofiles.profiles.ProfileConfiguration;
import net.trafficlunar.optionsprofiles.profiles.Profiles;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font; import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiComponent; import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.ContainerObjectSelectionList; import net.minecraft.client.gui.components.ContainerObjectSelectionList;
import net.minecraft.client.gui.components.CycleButton; import net.minecraft.client.gui.components.CycleButton;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.components.Tooltip;
import net.minecraft.client.gui.components.events.GuiEventListener; import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.narration.NarratableEntry; import net.minecraft.client.gui.narration.NarratableEntry;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.TextComponent;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
@ -23,23 +26,40 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.stream.Stream; import java.util.stream.Stream;
public class OptionsToggleList extends ContainerObjectSelectionList<OptionsToggleList.Entry> { public class OptionsToggleList extends ContainerObjectSelectionList<OptionsToggleList.OptionEntry> {
private final String profileName; private final String profileName;
private final ProfileConfiguration profileConfiguration; private final ProfileConfiguration profileConfiguration;
private final OptionsToggleScreen optionsToggleScreen; private final EditBox searchBox;
private final List<OptionEntry> allEntries = new ArrayList<>();
public OptionsToggleList(OptionsToggleScreen optionsToggleScreen, Minecraft minecraft, String profileName) { public OptionsToggleList(OptionsToggleScreen optionsToggleScreen, Minecraft minecraft, String profileName, ProfileConfiguration profileConfiguration, EditBox searchBox) {
super(minecraft, optionsToggleScreen.width, optionsToggleScreen.height, 20, optionsToggleScreen.height - 32, 20); super(minecraft, optionsToggleScreen.width, optionsToggleScreen.layout.getContentHeight(), optionsToggleScreen.layout.getHeaderHeight(), 20);
this.profileConfiguration = profileConfiguration;
this.profileName = profileName; this.profileName = profileName;
this.profileConfiguration = optionsToggleScreen.profileConfiguration; this.searchBox = searchBox;
this.optionsToggleScreen = optionsToggleScreen;
this.searchBox.setResponder(this::filterEntries);
refreshEntries(false, false); refreshEntries(false, false);
} }
private void filterEntries(String searchText) {
this.clearEntries();
if (searchText.isEmpty()) {
allEntries.forEach(this::addEntry);
return;
}
String filter = searchText.toLowerCase();
allEntries.stream()
.filter(entry -> entry.key.toLowerCase().contains(filter))
.forEach(this::addEntry);
}
// If overriding boolean is set to true then this function will set every option in the list to overrideToggle (false or true) // 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) { public void refreshEntries(boolean overriding, boolean overrideToggle) {
this.clearEntries(); allEntries.clear();
Path profile = Profiles.PROFILES_DIRECTORY.resolve(profileName); Path profile = Profiles.PROFILES_DIRECTORY.resolve(profileName);
Path optionsFile = profile.resolve("options.txt"); Path optionsFile = profile.resolve("options.txt");
@ -63,34 +83,36 @@ public class OptionsToggleList extends ContainerObjectSelectionList<OptionsToggl
} }
// Add entry with option key and value and if the key is in the profile configuration // 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]))); allEntries.add(new OptionEntry(option[0], option[1], profileConfiguration.getOptionsToLoad().contains(option[0])));
} else { } else {
this.addEntry(new OptionEntry(option[0], "", profileConfiguration.getOptionsToLoad().contains(option[0]))); allEntries.add(new OptionEntry(option[0], "", profileConfiguration.getOptionsToLoad().contains(option[0])));
} }
}); });
} catch (IOException e) { } catch (IOException e) {
OptionsProfilesMod.LOGGER.error("An error occurred when listing options", e); OptionsProfilesMod.LOGGER.error("An error occurred when listing options", e);
} }
filterEntries(searchBox.getValue());
} }
protected int getScrollbarPosition() { protected int scrollBarX() {
return super.getScrollbarPosition() + 15; return super.scrollBarX() + 15;
} }
public int getRowWidth() { public int getRowWidth() {
return 340; return 340;
} }
public class OptionEntry extends Entry { public class OptionEntry extends ContainerObjectSelectionList.Entry<OptionEntry> {
private final String key;
private final Component optionKey; private final Component optionKey;
private final Component optionValue;
private final CycleButton<Boolean> toggleButton; private final CycleButton<Boolean> toggleButton;
OptionEntry(String optionKey, String optionValue, boolean toggled) { OptionEntry(String optionKey, String optionValue, boolean toggled) {
this.optionKey = new TextComponent(optionKey); this.key = optionKey;
this.optionValue = new TextComponent(optionValue); this.optionKey = Component.literal(optionKey);
this.toggleButton = CycleButton.onOffBuilder(toggled).displayOnlyValue().create(0, 0, 44, 20, TextComponent.EMPTY, (button, boolean_) -> { this.toggleButton = CycleButton.onOffBuilder(toggled).displayOnlyValue().create(0, 0, 44, 20, Component.empty(), (button, boolean_) -> {
List<String> optionsToLoad = profileConfiguration.getOptionsToLoad(); List<String> optionsToLoad = profileConfiguration.getOptionsToLoad();
// If toggled to true // If toggled to true
@ -105,6 +127,9 @@ public class OptionsToggleList extends ContainerObjectSelectionList<OptionsToggl
profileConfiguration.setOptionsToLoad(optionsToLoad); profileConfiguration.setOptionsToLoad(optionsToLoad);
}); });
// Set tooltip to the option value (e.g. "ao" will show "true")
this.toggleButton.setTooltip(Tooltip.create(Component.literal(optionValue)));
if (toggled) { if (toggled) {
this.toggleButton.setMessage(this.toggleButton.getMessage().copy().withStyle(ChatFormatting.GREEN)); // Set the button's color to green this.toggleButton.setMessage(this.toggleButton.getMessage().copy().withStyle(ChatFormatting.GREEN)); // Set the button's color to green
} else { } else {
@ -112,24 +137,14 @@ public class OptionsToggleList extends ContainerObjectSelectionList<OptionsToggl
} }
} }
public void render(PoseStack poseStack, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) { public void renderContent(GuiGraphics guiGraphics, int mouseX, int mouseY, boolean hovered, float tickDelta) {
Font fontRenderer = OptionsToggleList.this.minecraft.font; int posX = OptionsToggleList.this.scrollBarX() - this.toggleButton.getWidth() - 10;
int posY = this.getContentY() - 2;
int posX = OptionsToggleList.this.getScrollbarPosition() - this.toggleButton.getWidth() - 10; this.toggleButton.setPosition(posX, posY);
int posY = y - 2; this.toggleButton.render(guiGraphics, mouseX, mouseY, tickDelta);
int textY = y + entryHeight / 2;
GuiComponent.drawString(poseStack, fontRenderer, this.optionKey, x, textY - 9 / 2, 16777215); guiGraphics.drawString(OptionsToggleList.this.minecraft.font, this.optionKey, this.getContentX(), this.getContentYMiddle() - 4, -1);
this.toggleButton.x = posX;
this.toggleButton.y = posY;
this.toggleButton.render(poseStack, mouseX, mouseY, tickDelta);
this.toggleButton.renderToolTip(poseStack, mouseX, mouseY);
// Set tooltip to the option value (e.g. "ao" will show "true") | even though it's non-existent in this version
if (this.toggleButton.isHoveredOrFocused()) {
optionsToggleScreen.renderTooltip(poseStack, optionValue, mouseX, mouseY);
}
} }
public List<? extends GuiEventListener> children() { public List<? extends GuiEventListener> children() {
@ -140,9 +155,4 @@ public class OptionsToggleList extends ContainerObjectSelectionList<OptionsToggl
return ImmutableList.of(this.toggleButton); return ImmutableList.of(this.toggleButton);
} }
} }
public abstract static class Entry extends ContainerObjectSelectionList.Entry<OptionsToggleList.Entry> {
public Entry() {
}
}
} }

View file

@ -0,0 +1,80 @@
package net.trafficlunar.optionsprofiles.gui;
import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.EditBox;
import net.minecraft.client.gui.components.StringWidget;
import net.minecraft.client.gui.layouts.LinearLayout;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.options.OptionsSubScreen;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import net.trafficlunar.optionsprofiles.profiles.ProfileConfiguration;
public class OptionsToggleScreen extends OptionsSubScreen {
private final Component profileName;
private final ProfileConfiguration profileConfiguration;
private OptionsToggleList optionsToggleList;
private EditBox searchBox;
protected OptionsToggleScreen(Screen lastScreen, Component profileName, ProfileConfiguration profileConfiguration) {
super(lastScreen, null, Component.literal(Component.translatable("gui.optionsprofiles.options-toggle").append(": ").getString() + profileName.getString()));
this.profileName = profileName;
this.profileConfiguration = profileConfiguration;
}
protected void init() {
this.searchBox = new EditBox(this.minecraft.font, 0, 0, 200, 20, Component.empty());
this.searchBox.setHint(Component.translatable("gui.optionsprofiles.options-search-hint"));
super.init();
}
protected void addTitle() {
this.layout.addToHeader(new StringWidget(this.title, this.font), (settings) -> settings.alignVerticallyTop().paddingTop(6));
this.layout.addToHeader(this.searchBox, (settings) -> settings.alignVerticallyBottom().padding(4));
}
protected void addOptions() {}
protected void addContents() {
this.layout.setHeaderHeight(42);
this.optionsToggleList = this.layout.addToContents(new OptionsToggleList(this, this.minecraft, profileName.getString(), this.profileConfiguration, this.searchBox));
}
protected void addFooter() {
LinearLayout linearLayout = this.layout.addToFooter(LinearLayout.horizontal().spacing(8));
LinearLayout linearLayoutAllButtons = linearLayout.addChild(LinearLayout.horizontal().spacing(1));
linearLayoutAllButtons.addChild(
Button.builder(
Component.translatable("gui.optionsprofiles.all-off").withStyle(ChatFormatting.RED),
(button) -> this.optionsToggleList.refreshEntries(true, false))
.size(75, 20)
.build()
);
linearLayoutAllButtons.addChild(
Button.builder(
Component.translatable("gui.optionsprofiles.all-on").withStyle(ChatFormatting.GREEN),
(button) -> this.optionsToggleList.refreshEntries(true, true))
.size(75, 20)
.build()
);
linearLayout.addChild(
Button.builder(
CommonComponents.GUI_DONE,
(button -> this.onClose())
).build()
);
}
public void removed() {
this.profileConfiguration.save();
}
protected void repositionElements() {
this.layout.arrangeElements();
this.optionsToggleList.updateSize(this.width, this.layout);
}
}

View file

@ -0,0 +1,121 @@
package net.trafficlunar.optionsprofiles.gui;
import net.trafficlunar.optionsprofiles.OptionsProfilesMod;
import net.trafficlunar.optionsprofiles.profiles.ProfileConfiguration;
import net.trafficlunar.optionsprofiles.profiles.Profiles;
import com.google.common.collect.ImmutableList;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.ContainerObjectSelectionList;
import net.minecraft.client.gui.components.events.GuiEventListener;
import net.minecraft.client.gui.narration.NarratableEntry;
import net.minecraft.network.chat.Component;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
public class ProfilesList extends ContainerObjectSelectionList<ProfilesList.ProfileEntry> {
private final ProfilesScreen profilesScreen;
public ProfilesList(ProfilesScreen profilesScreen, Minecraft minecraft) {
super(minecraft, profilesScreen.width, profilesScreen.layout.getContentHeight(), profilesScreen.layout.getHeaderHeight(), 20);
this.profilesScreen = profilesScreen;
refreshEntries();
}
public void refreshEntries() {
this.clearEntries();
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Profiles.PROFILES_DIRECTORY)) {
List<Path> profileList = new ArrayList<>();
for (Path profile : directoryStream) {
if (Files.isDirectory(profile)) {
profileList.add(profile);
}
}
// Sort the list alphabetically based on the profile names
profileList.sort(Comparator.comparing(p -> p.getFileName().toString()));
for (Path profile : profileList) {
this.addEntry(new ProfilesList.ProfileEntry(Component.literal(profile.getFileName().toString())));
}
} catch (Exception e) {
OptionsProfilesMod.LOGGER.error("An error occurred when listing profiles", e);
}
// checkEntriesLoaded();
}
// public void checkEntriesLoaded() {
// this.children().forEach(ProfileEntry::checkLoaded);
// }
protected int scrollBarX() {
return super.scrollBarX() + 15;
}
public int getRowWidth() {
return 340;
}
public class ProfileEntry extends ContainerObjectSelectionList.Entry<ProfilesList.ProfileEntry> {
private final Component profileName;
private final Button editButton;
private final Button loadButton;
ProfileEntry(Component profileName) {
this.profileName = profileName;
this.editButton = Button.builder(
Component.translatable("gui.optionsprofiles.edit-profile"),
(button) -> minecraft.setScreen(new EditProfileScreen(profilesScreen, profileName)))
.size(75, 20)
.build();
this.loadButton = Button.builder(
Component.translatable("gui.optionsprofiles.load-profile"),
(button) -> {
Profiles.loadProfile(profileName.getString());
OptionsProfilesMod.LOGGER.warn("[Profile '{}']: Loaded through button", profileName);
// ProfilesList.this.checkEntriesLoaded();
// button.active = false;
})
.size(75, 20)
.build();
}
public void renderContent(GuiGraphics guiGraphics, int mouseX, int mouseY, boolean hovered, float tickDelta) {
int posX = ProfilesList.this.scrollBarX() - this.loadButton.getWidth() - 10;
int posY = this.getContentY() - 2;
this.editButton.setPosition(posX - this.editButton.getWidth(), posY);
this.editButton.render(guiGraphics, mouseX, mouseY, tickDelta);
this.loadButton.setPosition(posX, posY);
this.loadButton.render(guiGraphics, mouseX, mouseY, tickDelta);
guiGraphics.drawString(ProfilesList.this.minecraft.font, this.profileName, this.getContentX(), this.getContentYMiddle() - 4, -1);
}
public List<? extends GuiEventListener> children() {
return ImmutableList.of(this.editButton, this.loadButton);
}
public List<? extends NarratableEntry> narratables() {
return ImmutableList.of(this.editButton, this.loadButton);
}
// protected void checkLoaded() {
// this.loadButton.active = !Profiles.isProfileLoaded(profileName.getString());
// }
}
}

View file

@ -0,0 +1,61 @@
package net.trafficlunar.optionsprofiles.gui;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.layouts.LinearLayout;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.options.OptionsSubScreen;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import net.trafficlunar.optionsprofiles.profiles.Profiles;
public class ProfilesScreen extends OptionsSubScreen {
private final Screen lastScreen;
public ProfilesList profilesList;
public ProfilesScreen(Screen lastScreen) {
super(lastScreen, null, Component.translatable("gui.optionsprofiles.profiles-menu"));
this.lastScreen = lastScreen;
}
protected void addOptions() {}
protected void addContents() {
this.layout.setHeaderHeight(24);
this.profilesList = this.layout.addToContents(new ProfilesList(this, this.minecraft));
this.addRenderableWidget(Button.builder(
Component.translatable("gui.optionsprofiles.settings-button"),
(button) -> this.minecraft.setScreen(new SettingsScreen(this)))
.width(75)
.pos(1, 1)
.build());
}
protected void addFooter() {
LinearLayout linearLayout = this.layout.addToFooter(LinearLayout.horizontal().spacing(8));
linearLayout.addChild(
Button.builder(
Component.translatable("gui.optionsprofiles.save-current-options"),
(button -> {
Profiles.createProfile();
this.profilesList.refreshEntries();
}))
.build()
);
linearLayout.addChild(
Button.builder(
CommonComponents.GUI_DONE,
(button -> this.onClose()))
.build()
);
}
public void onClose() {
this.minecraft.setScreen(lastScreen);
}
protected void repositionElements() {
this.layout.arrangeElements();
this.profilesList.updateSize(this.width, this.layout);
}
}

View file

@ -0,0 +1,57 @@
package net.trafficlunar.optionsprofiles.gui;
import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.components.CycleButton;
import net.minecraft.client.gui.components.StringWidget;
import net.minecraft.client.gui.components.Tooltip;
import net.minecraft.client.gui.layouts.HeaderAndFooterLayout;
import net.minecraft.client.gui.layouts.LayoutSettings;
import net.minecraft.client.gui.layouts.LinearLayout;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component;
import net.trafficlunar.optionsprofiles.OptionsProfilesMod;
public class SettingsScreen extends Screen {
private final Screen lastScreen;
private final HeaderAndFooterLayout layout = new HeaderAndFooterLayout(this, 24, 33);
public SettingsScreen(Screen lastScreen) {
super(Component.translatable("gui.optionsprofiles.settings-menu"));
this.lastScreen = lastScreen;
}
protected void init() {
LinearLayout linearLayoutHeader = this.layout.addToHeader(LinearLayout.vertical());
linearLayoutHeader.addChild(new StringWidget(this.title, this.font), LayoutSettings::alignHorizontallyCenter);
CycleButton<Boolean> showProfilesButtonButton = CycleButton.onOffBuilder(OptionsProfilesMod.config().shouldShowProfilesButton())
.create(0, 0, 150, 20, Component.translatable("gui.optionsprofiles.show-profiles-button"), (button, boolean_) -> {
OptionsProfilesMod.config().setShowProfilesButton(boolean_);
});
showProfilesButtonButton.setTooltip(Tooltip.create(Component.translatable("gui.optionsprofiles.show-profiles-button.tooltip")));
this.layout.addToContents(showProfilesButtonButton);
this.layout.addToFooter(
Button.builder(
CommonComponents.GUI_DONE,
(button) -> this.onClose())
.width(200)
.build()
);
this.layout.visitWidgets(this::addRenderableWidget);
this.repositionElements();
}
protected void repositionElements() {
this.layout.arrangeElements();
}
public void onClose() {
this.minecraft.setScreen(this.lastScreen);
OptionsProfilesMod.config().save();
}
}

View file

@ -0,0 +1,37 @@
package net.trafficlunar.optionsprofiles.mixin;
import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.options.OptionsScreen;
import net.minecraft.network.chat.Component;
import net.trafficlunar.optionsprofiles.OptionsProfilesMod;
import net.trafficlunar.optionsprofiles.gui.ProfilesScreen;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(OptionsScreen.class)
public class MixinOptionsScreen extends Screen {
@Shadow @Final private Screen lastScreen;
protected MixinOptionsScreen(Component component) {
super(component);
}
@Inject(at = @At("HEAD"), method = "init")
private void init(CallbackInfo info) {
if (OptionsProfilesMod.config().shouldShowProfilesButton()) {
this.addRenderableWidget(
Button.builder(
Component.translatable("gui.optionsprofiles.profiles-menu"),
(button) -> this.minecraft.setScreen(new ProfilesScreen(this)))
.width(75)
.pos(5, 5)
.build()
);
}
}
}

View file

@ -1,8 +1,8 @@
package com.axolotlmaid.optionsprofiles.profiles; package net.trafficlunar.optionsprofiles.profiles;
import com.axolotlmaid.optionsprofiles.OptionsProfilesMod;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import net.trafficlunar.optionsprofiles.OptionsProfilesMod;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.BufferedWriter; import java.io.BufferedWriter;
@ -13,12 +13,12 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
public class ProfileConfiguration { public class ProfileConfiguration {
private static final Path profilesDirectory = Profiles.PROFILES_DIRECTORY;
private static Path configurationFile; private static Path configurationFile;
private static String profileName; private static String profileName;
public static int configurationVersion = 1; // Used to update configuration in later revisions private boolean loadOnStartup = false;
private int version = configurationVersion; // ^ same here - this variable is used to show it in the configuration.json file private String servers = "";
private int keybindIndex = 0;
private List<String> optionsToLoad = new ArrayList<>(); private List<String> optionsToLoad = new ArrayList<>();
public ProfileConfiguration save() { public ProfileConfiguration save() {
@ -41,13 +41,11 @@ public class ProfileConfiguration {
public static ProfileConfiguration get(String profile_name) { public static ProfileConfiguration get(String profile_name) {
ProfileConfiguration configuration = new ProfileConfiguration(); ProfileConfiguration configuration = new ProfileConfiguration();
Path profile = profilesDirectory.resolve(profile_name); configurationFile = Profiles.PROFILES_DIRECTORY.resolve(profile_name).resolve("configuration.json");
configurationFile = profile.resolve("configuration.json");
profileName = profile_name; profileName = profile_name;
if (Files.notExists(configurationFile)) { if (Files.notExists(configurationFile))
configuration.save(); configuration.save();
}
try (BufferedReader reader = Files.newBufferedReader(configurationFile)) { try (BufferedReader reader = Files.newBufferedReader(configurationFile)) {
Gson gson = new Gson(); Gson gson = new Gson();
@ -59,12 +57,20 @@ public class ProfileConfiguration {
return configuration; return configuration;
} }
public int getVersion() { public boolean shouldLoadOnStartup() {
return version; return loadOnStartup;
} }
public void setVersion(int version) { public void setLoadOnStartup(boolean loadOnStartup) {
this.version = version; this.loadOnStartup = loadOnStartup;
}
public int getKeybindIndex() {
return keybindIndex;
}
public void setKeybindIndex(int keybindIndex) {
this.keybindIndex = keybindIndex;
} }
public List<String> getOptionsToLoad() { public List<String> getOptionsToLoad() {
@ -74,4 +80,12 @@ public class ProfileConfiguration {
public void setOptionsToLoad(List<String> optionsToLoad) { public void setOptionsToLoad(List<String> optionsToLoad) {
this.optionsToLoad = optionsToLoad; this.optionsToLoad = optionsToLoad;
} }
public String getServers() {
return servers;
}
public void setServers(String servers) {
this.servers = servers;
}
} }

View file

@ -1,10 +1,12 @@
package com.axolotlmaid.optionsprofiles.profiles; package net.trafficlunar.optionsprofiles.profiles;
import com.axolotlmaid.optionsprofiles.OptionsProfilesMod; import dev.architectury.platform.Platform;
import com.axolotlmaid.optionsprofiles.profiles.loaders.DistantHorizonsLoader; import net.minecraft.client.Minecraft;
import com.axolotlmaid.optionsprofiles.profiles.loaders.EmbeddiumLoader; import net.trafficlunar.optionsprofiles.OptionsProfilesMod;
import com.axolotlmaid.optionsprofiles.profiles.loaders.SodiumExtraLoader; import net.trafficlunar.optionsprofiles.profiles.loaders.DistantHorizonsLoader;
import com.axolotlmaid.optionsprofiles.profiles.loaders.SodiumLoader; import net.trafficlunar.optionsprofiles.profiles.loaders.IrisLoader;
import net.trafficlunar.optionsprofiles.profiles.loaders.SodiumExtraLoader;
import net.trafficlunar.optionsprofiles.profiles.loaders.SodiumLoader;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import java.io.IOException; import java.io.IOException;
@ -12,7 +14,9 @@ import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.nio.file.StandardCopyOption; import java.nio.file.StandardCopyOption;
import java.util.*; import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.stream.Stream; import java.util.stream.Stream;
@ -22,47 +26,9 @@ public class Profiles {
public static final Path OPTIFINE_OPTIONS_FILE = Paths.get("optionsof.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_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 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 IRIS_OPTIONS_FILE = Paths.get("config/iris.properties");
public static final Path DISTANT_HORIZONS_OPTIONS_FILE = Paths.get("config/DistantHorizons.toml"); 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<Path> 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<String> 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() { public static void createProfile() {
String profileName = "Profile 1"; String profileName = "Profile 1";
Path profile = PROFILES_DIRECTORY.resolve(profileName); Path profile = PROFILES_DIRECTORY.resolve(profileName);
@ -122,9 +88,13 @@ public class Profiles {
copyOptionFile(profile, OPTIONS_FILE); copyOptionFile(profile, OPTIONS_FILE);
copyOptionFile(profile, OPTIFINE_OPTIONS_FILE); copyOptionFile(profile, OPTIFINE_OPTIONS_FILE);
if (Platform.isModLoaded("sodium"))
copyOptionFile(profile, SODIUM_OPTIONS_FILE); copyOptionFile(profile, SODIUM_OPTIONS_FILE);
if (Platform.isModLoaded("sodium-extra"))
copyOptionFile(profile, SODIUM_EXTRA_OPTIONS_FILE); copyOptionFile(profile, SODIUM_EXTRA_OPTIONS_FILE);
copyOptionFile(profile, EMBEDDIUM_OPTIONS_FILE); if (Platform.isModLoaded("iris"))
copyOptionFile(profile, IRIS_OPTIONS_FILE);
if (Platform.isModLoaded("distanthorizons"))
copyOptionFile(profile, DISTANT_HORIZONS_OPTIONS_FILE); copyOptionFile(profile, DISTANT_HORIZONS_OPTIONS_FILE);
if (!overwriting) { if (!overwriting) {
@ -146,34 +116,61 @@ public class Profiles {
} }
} }
public static boolean isProfileLoaded(String profileName) { // public static boolean isProfileLoaded(String profileName) {
Path profile = PROFILES_DIRECTORY.resolve(profileName); // TODO: rewrite/fix; returns incorrect results
List<Path> optionFiles = new ArrayList<>(); // Path profile = PROFILES_DIRECTORY.resolve(profileName);
optionFiles.add(OPTIONS_FILE); // ProfileConfiguration profileConfiguration = ProfileConfiguration.get(profileName);
//
// List<Path> 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(file -> Platform.isModLoaded("sodium")).ifPresent(optionFiles::add);
// Optional.of(SODIUM_EXTRA_OPTIONS_FILE).filter(file -> Platform.isModLoaded("sodium-extra")).ifPresent(optionFiles::add);
// Optional.of(IRIS_OPTIONS_FILE).filter(file -> Platform.isModLoaded("iris")).ifPresent(optionFiles::add);
// Optional.of(DISTANT_HORIZONS_OPTIONS_FILE).filter(file -> Platform.isModLoaded("distanthorizons")).ifPresent(optionFiles::add);
//
// // Check if the original option file and the profile option file have the same content
// try {
// for (Path optionFile : optionFiles) {
// Path profileOptions = profile.resolve(optionFile.getFileName());
//
// if (optionFile.getFileName().equals(OPTIONS_FILE)) {
// try (Stream<String> lines = Files.lines(optionFile)) {
// List<String> optionsToLoad = profileConfiguration.getOptionsToLoad();
// AtomicBoolean loaded = new AtomicBoolean(false);
//
// lines.forEach((line) -> {
// String[] option = line.split(":");
//
// if (optionsToLoad.contains(option[0])) {
// try (Stream<String> profileLines = Files.lines(profileOptions)) {
// loaded.set(profileLines.anyMatch(profileLine -> profileLine.equals(line)));
// } catch (IOException e) {
// OptionsProfilesMod.LOGGER.error("[Profile '{}']: An error occurred when checking each line in options.txt if the profiles is loaded", profileName, e);
// }
// }
// });
//
// return loaded.get();
// } catch (IOException e) {
// OptionsProfilesMod.LOGGER.error("[Profile '{}']: An error occurred when opening options.txt to check if the profile is loaded", profileName, e);
// }
// } else {
// if (!FileUtils.contentEquals(optionFile.toFile(), profileOptions.toFile())) {
// return false;
// }
// }
// }
// } catch (IOException e) {
// OptionsProfilesMod.LOGGER.error("[Profile '{}']: An error occurred when checking if the profile is loaded", profileName, e);
// return false;
// }
// The next few lines check if the specified file exists. If so, it adds it to the optionFiles ArrayList. // return false;
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 {
for (Path optionFile : optionFiles) {
Path profileOptions = profile.resolve(optionFile.getFileName());
if (!FileUtils.contentEquals(optionFile.toFile(), profileOptions.toFile())) {
return false;
}
}
} catch (IOException e) {
OptionsProfilesMod.LOGGER.error("[Profile '{}']: An error occurred when checking if the profile is loaded", profileName, e);
return false;
}
return true;
}
private static void loadOptionFile(String profileName, Path options) { private static void loadOptionFile(String profileName, Path options) {
ProfileConfiguration profileConfiguration = ProfileConfiguration.get(profileName); ProfileConfiguration profileConfiguration = ProfileConfiguration.get(profileName);
@ -257,14 +254,31 @@ public class Profiles {
public static void loadProfile(String profileName) { public static void loadProfile(String profileName) {
loadOptionFile(profileName, OPTIONS_FILE); loadOptionFile(profileName, OPTIONS_FILE);
loadOptionFile(profileName, OPTIFINE_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);
if (Platform.isModLoaded("sodium"))
loadOptionFile(profileName, SODIUM_OPTIONS_FILE, SodiumLoader::load);
if (Platform.isModLoaded("sodium-extra"))
loadOptionFile(profileName, SODIUM_EXTRA_OPTIONS_FILE, SodiumExtraLoader::load);
if (Platform.isModLoaded("iris"))
loadOptionFile(profileName, IRIS_OPTIONS_FILE, IrisLoader::load);
if (Platform.isModLoaded("distanthorizons")) {
loadOptionFile(profileName, DISTANT_HORIZONS_OPTIONS_FILE); // Overwrite / load original Disant Horizons option file loadOptionFile(profileName, DISTANT_HORIZONS_OPTIONS_FILE); // Overwrite / load original Disant Horizons option file
loadOptionFile(profileName, DISTANT_HORIZONS_OPTIONS_FILE, DistantHorizonsLoader::load); // Tell Distant Horizons mod to reload configuration loadOptionFile(profileName, DISTANT_HORIZONS_OPTIONS_FILE, DistantHorizonsLoader::load); // Tell Distant Horizons mod to reload configuration
} }
// Reload Minecraft options
Minecraft minecraft = Minecraft.getInstance();
minecraft.options.load();
if (ProfileConfiguration.get(profileName).getOptionsToLoad().contains("resourcePacks")) {
minecraft.options.loadSelectedResourcePacks(minecraft.getResourcePackRepository());
minecraft.reloadResourcePacks();
}
minecraft.options.save();
minecraft.levelRenderer.allChanged();
}
public static void renameProfile(String profileName, String newProfileName) { public static void renameProfile(String profileName, String newProfileName) {
Path profile = PROFILES_DIRECTORY.resolve(profileName); Path profile = PROFILES_DIRECTORY.resolve(profileName);
Path newProfile = PROFILES_DIRECTORY.resolve(newProfileName); Path newProfile = PROFILES_DIRECTORY.resolve(newProfileName);

View file

@ -0,0 +1,11 @@
package net.trafficlunar.optionsprofiles.profiles.loaders;
import com.seibel.distanthorizons.core.config.ConfigHandler;
import java.nio.file.Path;
public class DistantHorizonsLoader {
public static void load(Path file) {
ConfigHandler.INSTANCE.configFileHandler.loadFromFile();
}
}

View file

@ -0,0 +1,35 @@
package net.trafficlunar.optionsprofiles.profiles.loaders;
import net.trafficlunar.optionsprofiles.OptionsProfilesMod;
import net.irisshaders.iris.Iris;
import net.irisshaders.iris.api.v0.IrisApi;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Properties;
public class IrisLoader {
public static void load(Path file) {
try (FileReader reader = new FileReader(file.toFile())) {
Properties properties = new Properties();
properties.load(reader);
apply(properties);
} catch (IOException e) {
OptionsProfilesMod.LOGGER.error("An error occurred when reading and loading Iris's configuration", e);
}
}
private static void apply(Properties properties) {
Iris.getIrisConfig().setShaderPackName(properties.getProperty("shaderPack"));
Iris.getIrisConfig().setDebugEnabled("true".equals(properties.getProperty("enableDebugOptions")));
IrisApi.getInstance().getConfig().setShadersEnabledAndApply("true".equals(properties.getProperty("enableShaders")));
try {
Iris.getIrisConfig().save();
} catch (IOException e) {
OptionsProfilesMod.LOGGER.error("An error occurred when loading Sodium's configuration", e);
}
}
}

View file

@ -1,26 +1,30 @@
package com.axolotlmaid.optionsprofiles.profiles.loaders; package net.trafficlunar.optionsprofiles.profiles.loaders;
import com.axolotlmaid.optionsprofiles.OptionsProfilesMod;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import me.flashyreese.mods.sodiumextra.client.SodiumExtraClientMod; import me.flashyreese.mods.sodiumextra.client.SodiumExtraClientMod;
import me.flashyreese.mods.sodiumextra.client.gui.FogTypeConfig;
import me.flashyreese.mods.sodiumextra.client.gui.SodiumExtraGameOptions; import me.flashyreese.mods.sodiumextra.client.gui.SodiumExtraGameOptions;
import me.flashyreese.mods.sodiumextra.common.util.ResourceLocationSerializer;
import net.minecraft.resources.ResourceLocation; import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.material.FogType;
import net.trafficlunar.optionsprofiles.OptionsProfilesMod;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.EnumMap;
import java.util.Map; import java.util.Map;
public class SodiumExtraLoader { public class SodiumExtraLoader {
public static void load(Path file) { public static void load(Path file) {
try (FileReader reader = new FileReader(file.toFile())) { try (FileReader reader = new FileReader(file.toFile())) {
Gson gson = new GsonBuilder().create(); Gson gson = new GsonBuilder().registerTypeAdapter(ResourceLocation.class, new ResourceLocationSerializer()).create();
Configuration configuration = gson.fromJson(reader, Configuration.class); Configuration configuration = gson.fromJson(reader, Configuration.class);
apply(configuration); apply(configuration);
} catch (IOException e) { } catch (IOException e) {
OptionsProfilesMod.LOGGER.error("An error occurred when loading Sodium's configuration", e); OptionsProfilesMod.LOGGER.error("An error occurred when loading Sodium Extra's configuration", e);
} }
} }
@ -40,23 +44,22 @@ public class SodiumExtraLoader {
SodiumExtraClientMod.options().particleSettings.otherMap = configuration.particle_settings.other; SodiumExtraClientMod.options().particleSettings.otherMap = configuration.particle_settings.other;
SodiumExtraClientMod.options().detailSettings.sky = configuration.detail_settings.sky; SodiumExtraClientMod.options().detailSettings.sky = configuration.detail_settings.sky;
SodiumExtraClientMod.options().detailSettings.sunMoon = configuration.detail_settings.sun_moon; SodiumExtraClientMod.options().detailSettings.sun = configuration.detail_settings.sun;
SodiumExtraClientMod.options().detailSettings.moon = configuration.detail_settings.moon;
SodiumExtraClientMod.options().detailSettings.stars = configuration.detail_settings.stars; SodiumExtraClientMod.options().detailSettings.stars = configuration.detail_settings.stars;
SodiumExtraClientMod.options().detailSettings.rainSnow = configuration.detail_settings.rain_snow; SodiumExtraClientMod.options().detailSettings.rainSnow = configuration.detail_settings.rain_snow;
SodiumExtraClientMod.options().detailSettings.biomeColors = configuration.detail_settings.biome_colors; SodiumExtraClientMod.options().detailSettings.biomeColors = configuration.detail_settings.biome_colors;
SodiumExtraClientMod.options().detailSettings.skyColors = configuration.detail_settings.sky_colors; SodiumExtraClientMod.options().detailSettings.skyColors = configuration.detail_settings.sky_colors;
SodiumExtraClientMod.options().renderSettings.fogDistance = configuration.render_settings.fog_distance; SodiumExtraClientMod.options().renderSettings.globalFog = configuration.render_settings.global_fog;
SodiumExtraClientMod.options().renderSettings.fogStart = configuration.render_settings.fog_start; SodiumExtraClientMod.options().renderSettings.fogTypeConfig = configuration.render_settings.fog_type_config;
SodiumExtraClientMod.options().renderSettings.multiDimensionFogControl = configuration.render_settings.multi_dimension_fog_control;
SodiumExtraClientMod.options().renderSettings.dimensionFogDistanceMap = configuration.render_settings.dimensionFogDistance;
SodiumExtraClientMod.options().renderSettings.useLinearFlatColorBlender = configuration.render_settings.use_linear_flat_color_blender;
SodiumExtraClientMod.options().renderSettings.lightUpdates = configuration.render_settings.light_updates; SodiumExtraClientMod.options().renderSettings.lightUpdates = configuration.render_settings.light_updates;
SodiumExtraClientMod.options().renderSettings.itemFrame = configuration.render_settings.item_frame; SodiumExtraClientMod.options().renderSettings.itemFrame = configuration.render_settings.item_frame;
SodiumExtraClientMod.options().renderSettings.armorStand = configuration.render_settings.armor_stand; SodiumExtraClientMod.options().renderSettings.armorStand = configuration.render_settings.armor_stand;
SodiumExtraClientMod.options().renderSettings.painting = configuration.render_settings.painting; SodiumExtraClientMod.options().renderSettings.painting = configuration.render_settings.painting;
SodiumExtraClientMod.options().renderSettings.piston = configuration.render_settings.piston; SodiumExtraClientMod.options().renderSettings.piston = configuration.render_settings.piston;
SodiumExtraClientMod.options().renderSettings.beaconBeam = configuration.render_settings.beacon_beam; SodiumExtraClientMod.options().renderSettings.beaconBeam = configuration.render_settings.beacon_beam;
SodiumExtraClientMod.options().renderSettings.limitBeaconBeamHeight = configuration.render_settings.limit_beacon_beam_height;
SodiumExtraClientMod.options().renderSettings.enchantingTableBook = configuration.render_settings.enchanting_table_book; SodiumExtraClientMod.options().renderSettings.enchantingTableBook = configuration.render_settings.enchanting_table_book;
SodiumExtraClientMod.options().renderSettings.itemFrameNameTag = configuration.render_settings.item_frame_name_tag; SodiumExtraClientMod.options().renderSettings.itemFrameNameTag = configuration.render_settings.item_frame_name_tag;
SodiumExtraClientMod.options().renderSettings.playerNameTag = configuration.render_settings.player_name_tag; SodiumExtraClientMod.options().renderSettings.playerNameTag = configuration.render_settings.player_name_tag;
@ -76,14 +79,8 @@ public class SodiumExtraLoader {
SodiumExtraClientMod.options().extraSettings.tutorialToast = configuration.extra_settings.tutorial_toast; SodiumExtraClientMod.options().extraSettings.tutorialToast = configuration.extra_settings.tutorial_toast;
SodiumExtraClientMod.options().extraSettings.instantSneak = configuration.extra_settings.instant_sneak; SodiumExtraClientMod.options().extraSettings.instantSneak = configuration.extra_settings.instant_sneak;
SodiumExtraClientMod.options().extraSettings.preventShaders = configuration.extra_settings.prevent_shaders; SodiumExtraClientMod.options().extraSettings.preventShaders = configuration.extra_settings.prevent_shaders;
SodiumExtraClientMod.options().extraSettings.useFastRandom = configuration.extra_settings.use_fast_random; SodiumExtraClientMod.options().extraSettings.steadyDebugHud = configuration.extra_settings.steady_debug_hud;
SodiumExtraClientMod.options().extraSettings.steadyDebugHudRefreshInterval = configuration.extra_settings.steady_debug_hud_refresh_interval;
SodiumExtraClientMod.options().notificationSettings.hideRSORecommendation = configuration.notification_settings.hide_r_s_o_recommendation;
SodiumExtraClientMod.options().superSecretSettings.fetchSodiumExtraCrowdinTranslations = configuration.super_secret_settings.fetch_sodium_extra_crowdin_translations;
SodiumExtraClientMod.options().superSecretSettings.sodiumExtraCrowdinProjectIdentifier = configuration.super_secret_settings.sodium_extra_crowdin_project_identifier;
SodiumExtraClientMod.options().superSecretSettings.fetchSodiumCrowdinTranslations = configuration.super_secret_settings.fetch_sodium_crowdin_translations;
SodiumExtraClientMod.options().superSecretSettings.sodiumCrowdinProjectIdentifier = configuration.super_secret_settings.sodium_crowdin_project_identifier;
SodiumExtraClientMod.options().writeChanges(); SodiumExtraClientMod.options().writeChanges();
} }
@ -94,8 +91,6 @@ public class SodiumExtraLoader {
public DetailSettings detail_settings; public DetailSettings detail_settings;
public RenderSettings render_settings; public RenderSettings render_settings;
public ExtraSettings extra_settings; public ExtraSettings extra_settings;
public NotificationSettings notification_settings;
public SuperSecretSettings super_secret_settings;
public static class AnimationSettings { public static class AnimationSettings {
public boolean animation; public boolean animation;
@ -117,7 +112,8 @@ public class SodiumExtraLoader {
public static class DetailSettings { public static class DetailSettings {
public boolean sky; public boolean sky;
public boolean sun_moon; public boolean sun;
public boolean moon;
public boolean stars; public boolean stars;
public boolean rain_snow; public boolean rain_snow;
public boolean biome_colors; public boolean biome_colors;
@ -125,17 +121,15 @@ public class SodiumExtraLoader {
} }
public static class RenderSettings { public static class RenderSettings {
public int fog_distance; public boolean global_fog;
public int fog_start; public EnumMap<FogType, FogTypeConfig> fog_type_config;
public boolean multi_dimension_fog_control;
public Map<ResourceLocation, Integer> dimensionFogDistance;
public boolean use_linear_flat_color_blender;
public boolean light_updates; public boolean light_updates;
public boolean item_frame; public boolean item_frame;
public boolean armor_stand; public boolean armor_stand;
public boolean painting; public boolean painting;
public boolean piston; public boolean piston;
public boolean beacon_beam; public boolean beacon_beam;
public boolean limit_beacon_beam_height;
public boolean enchanting_table_book; public boolean enchanting_table_book;
public boolean item_frame_name_tag; public boolean item_frame_name_tag;
public boolean player_name_tag; public boolean player_name_tag;
@ -157,18 +151,8 @@ public class SodiumExtraLoader {
public boolean tutorial_toast; public boolean tutorial_toast;
public boolean instant_sneak; public boolean instant_sneak;
public boolean prevent_shaders; public boolean prevent_shaders;
public boolean use_fast_random; public boolean steady_debug_hud;
} public int steady_debug_hud_refresh_interval;
public static class NotificationSettings {
public boolean hide_r_s_o_recommendation;
}
public static class SuperSecretSettings {
public boolean fetch_sodium_extra_crowdin_translations;
public String sodium_extra_crowdin_project_identifier;
public boolean fetch_sodium_crowdin_translations;
public String sodium_crowdin_project_identifier;
} }
} }
} }

View file

@ -1,10 +1,12 @@
package com.axolotlmaid.optionsprofiles.profiles.loaders; package net.trafficlunar.optionsprofiles.profiles.loaders;
import com.axolotlmaid.optionsprofiles.OptionsProfilesMod; import net.caffeinemc.mods.sodium.client.render.chunk.DeferMode;
import net.caffeinemc.mods.sodium.client.render.chunk.translucent_sorting.QuadSplittingMode;
import net.trafficlunar.optionsprofiles.OptionsProfilesMod;
import com.google.gson.Gson; import com.google.gson.Gson;
import com.google.gson.GsonBuilder; import com.google.gson.GsonBuilder;
import me.jellysquid.mods.sodium.client.SodiumClientMod; import net.caffeinemc.mods.sodium.client.SodiumClientMod;
import me.jellysquid.mods.sodium.client.gui.SodiumGameOptions; import net.caffeinemc.mods.sodium.client.gui.SodiumGameOptions;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
@ -23,28 +25,30 @@ public class SodiumLoader {
} }
private static void apply(Configuration configuration) { private static void apply(Configuration configuration) {
SodiumClientMod.options().quality.weatherQuality = SodiumGameOptions.GraphicsQuality.valueOf(configuration.quality.weather_quality); SodiumClientMod.options().quality.weatherQuality = SodiumGameOptions.WeatherQuality.valueOf(configuration.quality.weather_quality);
SodiumClientMod.options().quality.leavesQuality = SodiumGameOptions.GraphicsQuality.valueOf(configuration.quality.leaves_quality); SodiumClientMod.options().quality.leavesQuality = SodiumGameOptions.LeavesQuality.valueOf(configuration.quality.leaves_quality);
SodiumClientMod.options().quality.enableVignette = configuration.quality.enable_vignette; 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.enableMemoryTracing = configuration.advanced.enable_memory_tracing;
SodiumClientMod.options().advanced.useAdvancedStagingBuffers = configuration.advanced.use_advanced_staging_buffers; SodiumClientMod.options().advanced.useAdvancedStagingBuffers = configuration.advanced.use_advanced_staging_buffers;
SodiumClientMod.options().advanced.cpuRenderAheadLimit = configuration.advanced.cpu_render_ahead_limit; SodiumClientMod.options().advanced.cpuRenderAheadLimit = configuration.advanced.cpu_render_ahead_limit;
SodiumClientMod.options().performance.chunkBuilderThreads = configuration.performance.chunk_builder_threads; SodiumClientMod.options().performance.chunkBuilderThreads = configuration.performance.chunk_builder_threads;
SodiumClientMod.options().performance.alwaysDeferChunkUpdates = configuration.performance.always_defer_chunk_updates; SodiumClientMod.options().performance.chunkBuildDeferMode = configuration.performance.chunk_build_defer_mode;
SodiumClientMod.options().performance.animateOnlyVisibleTextures = configuration.performance.animate_only_visible_textures; SodiumClientMod.options().performance.animateOnlyVisibleTextures = configuration.performance.animate_only_visible_textures;
SodiumClientMod.options().performance.useEntityCulling = configuration.performance.use_entity_culling; 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.useFogOcclusion = configuration.performance.use_fog_occlusion;
SodiumClientMod.options().performance.useBlockFaceCulling = configuration.performance.use_block_face_culling; SodiumClientMod.options().performance.useBlockFaceCulling = configuration.performance.use_block_face_culling;
SodiumClientMod.options().performance.useNoErrorGLContext = configuration.performance.use_no_error_g_l_context;
SodiumClientMod.options().performance.quadSplittingMode = configuration.performance.quad_splitting_mode;
SodiumClientMod.options().notifications.hideDonationButton = configuration.notifications.hide_donation_button; SodiumClientMod.options().notifications.hasClearedDonationButton = configuration.notifications.has_cleared_donation_button;
SodiumClientMod.options().notifications.hasSeenDonationPrompt = configuration.notifications.has_seen_donation_prompt;
SodiumClientMod.options().debug.terrainSortingEnabled = configuration.debug.terrain_sorting_enabled;
try { try {
SodiumClientMod.options().writeChanges(); SodiumGameOptions.writeToDisk(SodiumClientMod.options());
} catch (IOException e) { } catch (IOException e) {
OptionsProfilesMod.LOGGER.error("An error occurred when loading Sodium's configuration", e); OptionsProfilesMod.LOGGER.error("An error occurred when loading Sodium's configuration", e);
} }
@ -55,6 +59,7 @@ public class SodiumLoader {
public Advanced advanced; public Advanced advanced;
public Performance performance; public Performance performance;
public Notifications notifications; public Notifications notifications;
public Debug debug;
public static class Quality { public static class Quality {
public String weather_quality; public String weather_quality;
@ -63,8 +68,6 @@ public class SodiumLoader {
} }
public static class Advanced { public static class Advanced {
public String arena_memory_allocator;
public boolean allow_direct_memory_access;
public boolean enable_memory_tracing; public boolean enable_memory_tracing;
public boolean use_advanced_staging_buffers; public boolean use_advanced_staging_buffers;
public int cpu_render_ahead_limit; public int cpu_render_ahead_limit;
@ -72,16 +75,22 @@ public class SodiumLoader {
public static class Performance { public static class Performance {
public int chunk_builder_threads; public int chunk_builder_threads;
public boolean always_defer_chunk_updates; public DeferMode chunk_build_defer_mode;
public boolean animate_only_visible_textures; public boolean animate_only_visible_textures;
public boolean use_entity_culling; public boolean use_entity_culling;
public boolean use_particle_culling;
public boolean use_fog_occlusion; public boolean use_fog_occlusion;
public boolean use_block_face_culling; public boolean use_block_face_culling;
public boolean use_no_error_g_l_context;
public QuadSplittingMode quad_splitting_mode;
} }
public static class Notifications { public static class Notifications {
public boolean hide_donation_button; public boolean has_cleared_donation_button;
public boolean has_seen_donation_prompt;
}
public static class Debug {
public boolean terrain_sorting_enabled;
} }
} }
} }

View file

@ -6,13 +6,31 @@
"gui.optionsprofiles.editing-profile-title": "Editing Profile: ", "gui.optionsprofiles.editing-profile-title": "Editing Profile: ",
"gui.optionsprofiles.profile-name-text": "Profile Name", "gui.optionsprofiles.profile-name-text": "Profile Name",
"gui.optionsprofiles.servers-text": "Server List",
"gui.optionsprofiles.servers-hint": "mc.hypixel.net, play.mccis...",
"gui.optionsprofiles.servers.tooltip": "List servers (comma-separated) to load this profile on join. Add 'leave' to load on server leave.",
"gui.optionsprofiles.overwrite-options": "Overwrite", "gui.optionsprofiles.overwrite-options": "Overwrite",
"gui.optionsprofiles.overwrite-options.tooltip": "Replaces the profile's options with your current options", "gui.optionsprofiles.overwrite-options.tooltip": "Replaces the profile's options with your current options",
"gui.optionsprofiles.rename-profile": "Rename", "gui.optionsprofiles.rename-profile": "Rename",
"gui.optionsprofiles.delete-profile": "Delete", "gui.optionsprofiles.delete-profile": "Delete",
"gui.optionsprofiles.keybind-index": "Keybind index",
"gui.optionsprofiles.load-on-startup": "Load on startup",
"gui.optionsprofiles.options-toggle": "Select options to toggle", "gui.optionsprofiles.options-toggle": "Select options to toggle",
"gui.optionsprofiles.options-search-hint": "Search options...",
"gui.optionsprofiles.options-toggle.tooltip": "Select the options you want to load in this profile", "gui.optionsprofiles.options-toggle.tooltip": "Select the options you want to load in this profile",
"gui.optionsprofiles.all-on": "All ON", "gui.optionsprofiles.all-on": "All ON",
"gui.optionsprofiles.all-off": "All OFF" "gui.optionsprofiles.all-off": "All OFF",
"gui.optionsprofiles.settings-button": "Settings",
"gui.optionsprofiles.settings-menu": "Options Profiles Settings",
"gui.optionsprofiles.show-profiles-button": "Show Profiles Button",
"gui.optionsprofiles.show-profiles-button.tooltip": "Toggle to remove the profiles button in Options. Access profiles through /optionsprofiles.",
"key.category.optionsprofiles.keys": "Options Profiles",
"key.optionsprofiles.profile_1": "Profile 1",
"key.optionsprofiles.profile_2": "Profile 2",
"key.optionsprofiles.profile_3": "Profile 3"
} }

View file

@ -1,6 +1,6 @@
{ {
"required": true, "required": true,
"package": "com.axolotlmaid.optionsprofiles.mixin", "package": "net.trafficlunar.optionsprofiles.mixin",
"compatibilityLevel": "JAVA_17", "compatibilityLevel": "JAVA_17",
"minVersion": "0.8", "minVersion": "0.8",
"client": [ "client": [

View file

@ -1,5 +1,5 @@
plugins { plugins {
id 'com.github.johnrengelman.shadow' id 'com.gradleup.shadow'
} }
architectury { architectury {
@ -24,12 +24,25 @@ configurations {
} }
} }
repositories {
maven {
name = "Terraformers"
url = "https://maven.terraformersmc.com/"
}
}
dependencies { dependencies {
modImplementation "net.fabricmc:fabric-loader:$rootProject.fabric_loader_version" modImplementation "net.fabricmc:fabric-loader:$rootProject.fabric_loader_version"
// Fabric API. This is technically optional, but you probably want it anyway. // Fabric API. This is technically optional, but you probably want it anyway.
modImplementation "net.fabricmc.fabric-api:fabric-api:$rootProject.fabric_api_version" modImplementation "net.fabricmc.fabric-api:fabric-api:$rootProject.fabric_api_version"
// Architectury API
modImplementation "dev.architectury:architectury-fabric:$rootProject.architectury_api_version"
// Mod Menu API
modImplementation("com.terraformersmc:modmenu:16.0.0-rc.1")
common(project(path: ':common', configuration: 'namedElements')) { transitive false } common(project(path: ':common', configuration: 'namedElements')) { transitive false }
shadowBundle project(path: ':common', configuration: 'transformProductionFabric') shadowBundle project(path: ':common', configuration: 'transformProductionFabric')
} }

View file

@ -0,0 +1,12 @@
package net.trafficlunar.optionsprofiles.fabric;
import com.terraformersmc.modmenu.api.ConfigScreenFactory;
import com.terraformersmc.modmenu.api.ModMenuApi;
import net.trafficlunar.optionsprofiles.gui.ProfilesScreen;
public class ModMenuApiImpl implements ModMenuApi {
@Override
public ConfigScreenFactory<?> getModConfigScreenFactory() {
return ProfilesScreen::new;
}
}

View file

@ -1,6 +1,6 @@
package com.axolotlmaid.optionsprofiles.fabric; package net.trafficlunar.optionsprofiles.fabric;
import com.axolotlmaid.optionsprofiles.OptionsProfilesMod; import net.trafficlunar.optionsprofiles.OptionsProfilesMod;
import net.fabricmc.api.ModInitializer; import net.fabricmc.api.ModInitializer;
public class OptionsProfilesModFabric implements ModInitializer { public class OptionsProfilesModFabric implements ModInitializer {

View file

@ -4,29 +4,25 @@
"version": "${version}", "version": "${version}",
"name": "Options Profiles", "name": "Options Profiles",
"description": "Load and save your options from in-game.", "description": "Load and save your options from in-game.",
"authors": [ "authors": ["trafficlunar"],
"AxolotlMaid"
],
"contact": { "contact": {
"homepage": "https://github.com/AxolotlMaid/options-profiles", "homepage": "https://github.com/trafficlunar/options-profiles",
"sources": "https://github.com/AxolotlMaid/options-profiles", "sources": "https://github.com/trafficlunar/options-profiles",
"issues": "https://github.com/AxolotlMaid/options-profiles/issues" "issues": "https://github.com/trafficlunar/options-profiles/issues"
}, },
"license": "GNU GPL 3.0", "license": "GNU GPL 3.0",
"icon": "assets/optionsprofiles/icon.png", "icon": "assets/optionsprofiles/icon.png",
"environment": "*", "environment": "*",
"entrypoints": { "entrypoints": {
"main": [ "main": ["net.trafficlunar.optionsprofiles.fabric.OptionsProfilesModFabric"],
"com.axolotlmaid.optionsprofiles.fabric.OptionsProfilesModFabric" "modmenu": ["net.trafficlunar.optionsprofiles.fabric.ModMenuApiImpl"]
]
}, },
"mixins": [ "mixins": ["optionsprofiles.mixins.json"],
"optionsprofiles.mixins.json"
],
"depends": { "depends": {
"fabricloader": ">=0.15.11", "fabricloader": ">=0.17.2",
"minecraft": "~1.18.2", "minecraft": "~1.21",
"java": ">=17", "java": ">=21",
"fabric": "*" "architectury": ">=18.0.3",
"fabric-api": "*"
} }
} }

View file

@ -1 +0,0 @@
loom.platform=forge

View file

@ -1,11 +0,0 @@
package com.axolotlmaid.optionsprofiles.forge;
import com.axolotlmaid.optionsprofiles.OptionsProfilesMod;
import net.minecraftforge.fml.common.Mod;
@Mod(OptionsProfilesMod.MOD_ID)
public class OptionsProfilesModForge {
public OptionsProfilesModForge() {
OptionsProfilesMod.init();
}
}

View file

@ -1,28 +0,0 @@
modLoader = "javafml"
loaderVersion = "[40,)"
#issueTrackerURL = ""
license = "GNU GPL 3.0"
[[mods]]
modId = "optionsprofiles"
version = "${version}"
displayName = "Options Profiles"
authors = "AxolotlMaid"
description = '''
Load and save your options from in-game.
'''
logoFile = "icon.png"
[[dependencies.optionsprofiles]]
modId = "forge"
mandatory = true
versionRange = "[40,)"
ordering = "NONE"
side = "BOTH"
[[dependencies.optionsprofiles]]
modId = "minecraft"
mandatory = true
versionRange = "[1.18.2,)"
ordering = "NONE"
side = "BOTH"

View file

@ -1,7 +0,0 @@
{
"pack": {
"description": "Options Profiles",
"forge:data_pack_format": 9,
"pack_format": 8
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 383 KiB

After

Width:  |  Height:  |  Size: 835 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 414 KiB

After

Width:  |  Height:  |  Size: 733 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 578 KiB

After

Width:  |  Height:  |  Size: 748 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 407 KiB

After

Width:  |  Height:  |  Size: 710 KiB

View file

@ -1,17 +1,20 @@
# Done to increase the memory available to Gradle.
org.gradle.jvmargs=-Xmx6G org.gradle.jvmargs=-Xmx6G
org.gradle.parallel=true org.gradle.parallel=true
# Fixes errors caused by Loom version differences
loom.ignoreDependencyLoomVersionValidation=true
# Mod properties # Mod properties
mod_version=1.3.1 mod_version=1.4.4
maven_group=com.axolotlmaid.optionsprofiles maven_group=net.trafficlunar.optionsprofiles
archives_name=optionsprofiles archives_name=optionsprofiles
enabled_platforms=fabric,forge enabled_platforms=fabric,neoforge
# Minecraft properties # Minecraft properties
minecraft_version = 1.18.2 minecraft_version=1.21.9
# Dependencies # Dependencies
fabric_loader_version = 0.15.11 architectury_api_version = 18.0.3
fabric_api_version = 0.77.0+1.18.2 fabric_loader_version=0.17.2
forge_version = 1.18.2-40.2.21 fabric_api_version=0.134.0+1.21.9
neoforge_version=21.9.0-beta

View file

@ -1,7 +1,6 @@
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.8-bin.zip distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip
networkTimeout=10000 networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists

8
gradlew vendored Normal file → Executable file
View file

@ -84,7 +84,7 @@ done
# shellcheck disable=SC2034 # shellcheck disable=SC2034
APP_BASE_NAME=${0##*/} APP_BASE_NAME=${0##*/}
# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) # 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 APP_HOME=$( cd "${APP_HOME:-./}.." > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value. # Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum MAX_FD=maximum
@ -112,7 +112,7 @@ case "$( uname )" in #(
NONSTOP* ) nonstop=true ;; NONSTOP* ) nonstop=true ;;
esac esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar CLASSPATH=$APP_HOME/lib/gradle-launcher-8.7.jar
# Determine the Java command to use to start the JVM. # Determine the Java command to use to start the JVM.
@ -200,7 +200,7 @@ fi
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. # 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"' DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'" \"-javaagent:$APP_HOME/lib/agents/gradle-instrumentation-agent-8.7.jar\""
# Collect all arguments for the java command: # Collect all arguments for the java command:
# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, # * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
@ -211,7 +211,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
set -- \ set -- \
"-Dorg.gradle.appname=$APP_BASE_NAME" \ "-Dorg.gradle.appname=$APP_BASE_NAME" \
-classpath "$CLASSPATH" \ -classpath "$CLASSPATH" \
org.gradle.wrapper.GradleWrapperMain \ org.gradle.launcher.GradleMain \
"$@" "$@"
# Stop when "xargs" is not available. # Stop when "xargs" is not available.

8
gradlew.bat vendored
View file

@ -28,13 +28,13 @@ set DIRNAME=%~dp0
if "%DIRNAME%"=="" set DIRNAME=. if "%DIRNAME%"=="" set DIRNAME=.
@rem This is normally unused @rem This is normally unused
set APP_BASE_NAME=%~n0 set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME% set APP_HOME=%DIRNAME%..
@rem Resolve any "." and ".." in APP_HOME to make it shorter. @rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" "-javaagent:%APP_HOME%/lib/agents/gradle-instrumentation-agent-8.7.jar"
@rem Find java.exe @rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome if defined JAVA_HOME goto findJavaFromJavaHome
@ -68,11 +68,11 @@ goto fail
:execute :execute
@rem Setup the command line @rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar set CLASSPATH=%APP_HOME%\lib\gradle-launcher-8.7.jar
@rem Execute Gradle @rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.launcher.GradleMain %*
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell

View file

@ -1,16 +1,10 @@
plugins { plugins {
id 'com.github.johnrengelman.shadow' id 'com.gradleup.shadow'
}
loom {
forge {
mixinConfig "optionsprofiles.mixins.json"
}
} }
architectury { architectury {
platformSetupLoomIde() platformSetupLoomIde()
forge() neoForge()
} }
configurations { configurations {
@ -20,7 +14,7 @@ configurations {
} }
compileClasspath.extendsFrom common compileClasspath.extendsFrom common
runtimeClasspath.extendsFrom common runtimeClasspath.extendsFrom common
developmentForge.extendsFrom common developmentNeoForge.extendsFrom common
// Files in this configuration will be bundled into your mod using the Shadow plugin. // 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. // Don't use the `shadow` configuration from the plugin itself as it's meant for excluding files.
@ -30,17 +24,27 @@ configurations {
} }
} }
repositories {
maven {
name = 'NeoForged'
url = 'https://maven.neoforged.net/releases'
}
}
dependencies { dependencies {
forge "net.minecraftforge:forge:$rootProject.forge_version" neoForge "net.neoforged:neoforge:$rootProject.neoforge_version"
// Architectury API
modImplementation "dev.architectury:architectury-neoforge:$rootProject.architectury_api_version"
common(project(path: ':common', configuration: 'namedElements')) { transitive false } common(project(path: ':common', configuration: 'namedElements')) { transitive false }
shadowBundle project(path: ':common', configuration: 'transformProductionForge') shadowBundle project(path: ':common', configuration: 'transformProductionNeoForge')
} }
processResources { processResources {
inputs.property 'version', project.version inputs.property 'version', project.version
filesMatching('META-INF/mods.toml') { filesMatching('META-INF/neoforge.mods.toml') {
expand version: project.version expand version: project.version
} }
} }

View file

@ -0,0 +1 @@
loom.platform = neoforge

View file

@ -0,0 +1,11 @@
package net.trafficlunar.optionsprofiles.neoforge;
import net.trafficlunar.optionsprofiles.OptionsProfilesMod;
import net.neoforged.fml.common.Mod;
@Mod(OptionsProfilesMod.MOD_ID)
public class OptionsProfilesModNeoForge {
public OptionsProfilesModNeoForge() {
OptionsProfilesMod.init();
}
}

View file

@ -0,0 +1,38 @@
modLoader = "javafml"
loaderVersion = "[10,)"
issueTrackerURL = "https://github.com/trafficlunar/options-profiles/issues"
license = "GNU GPL 3.0"
[[mods]]
modId = "optionsprofiles"
version = "${version}"
displayName = "Options Profiles"
authors = "trafficlunar"
description = '''
Load and save your options from in-game.
'''
logoFile = "icon.png"
[[dependencies.optionsprofiles]]
modId = "neoforge"
type = "required"
versionRange = "[21.9.0-beta,)"
ordering = "NONE"
side = "BOTH"
[[dependencies.optionsprofiles]]
modId = "minecraft"
type = "required"
versionRange = "[1.21,)"
ordering = "NONE"
side = "BOTH"
[[dependencies.optionsprofiles]]
modId = "architectury"
type = "required"
versionRange = "[18.0.3,)"
ordering = "AFTER"
side = "BOTH"
[[mixins]]
config = "optionsprofiles.mixins.json"

View file

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

View file

@ -2,13 +2,13 @@ pluginManagement {
repositories { repositories {
maven { url "https://maven.fabricmc.net/" } maven { url "https://maven.fabricmc.net/" }
maven { url "https://maven.architectury.dev/" } maven { url "https://maven.architectury.dev/" }
maven { url "https://files.minecraftforge.net/maven/" } maven { url "https://maven.minecraftforge.net/" }
gradlePluginPortal() gradlePluginPortal()
} }
} }
rootProject.name = 'optionsprofiles-v1.3.1-1.18.2' include("common")
include("fabric")
include("neoforge")
include 'common' rootProject.name = "optionsprofiles-v1.4.4-1.21.9"
include 'fabric'
include 'forge'