Compare commits

..

4 commits

Author SHA1 Message Date
axolotlmaid
531e64fda2 fix: profile configuration being overwritten 2024-09-14 21:58:51 +01:00
axolotlmaid
8843ee8a53 work in progress 2024-09-14 21:56:01 +01:00
axolotlmaid
81a4370297 Add profile loading on startup (#17) 2024-08-12 14:16:27 +01:00
axolotlmaid
5ef62d174c Fix error when deleting profile 2024-08-12 14:15:04 +01:00
47 changed files with 589 additions and 831 deletions

View file

@ -2,34 +2,29 @@
[![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/trafficlunar/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)
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 (e.g. only load keybinds, resource packs, FOV, etc.) - Load specific options (like only load keybinds, resource packs or FOV and GUI scale)
- 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, NeoForge support - Fabric, NeoForge, Forge 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
- Iris - Embeddium
- 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?
@ -39,15 +34,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?
> Architectury API and Fabric API (if on Fabric) > Versions 1.1 require Architectury API, however versions 1.2+ do not.
- For any other questions, create an issue or contact me at hello@trafficlunar.net - For any other questions, create an issue or contact me at hello@axolotlmaid.com
## 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.11-SNAPSHOT' apply false id 'dev.architectury.loom' version '1.7-SNAPSHOT' apply false
id 'architectury-plugin' version '3.4-SNAPSHOT' id 'architectury-plugin' version '3.4-SNAPSHOT'
id 'com.gradleup.shadow' version '8.3.6' apply false id 'com.github.johnrengelman.shadow' version '8.1.1' apply false
} }
architectury { architectury {
@ -31,10 +31,6 @@ subprojects {
// for more information about repositories. // for more information about repositories.
} }
loom {
silentMojangMappingsLicense()
}
dependencies { dependencies {
minecraft "net.minecraft:minecraft:$rootProject.minecraft_version" minecraft "net.minecraft:minecraft:$rootProject.minecraft_version"
mappings loom.officialMojangMappings() mappings loom.officialMojangMappings()

View file

@ -14,6 +14,10 @@ repositories {
includeGroup "maven.modrinth" includeGroup "maven.modrinth"
} }
} }
maven {
url "https://maven.enjarai.nl/releases"
}
} }
dependencies { dependencies {
@ -22,13 +26,10 @@ dependencies {
// 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.21.10-0.7.2-fabric" // Sodium modImplementation "maven.modrinth:sodium:mc1.21-0.5.9" // Sodium
modImplementation "maven.modrinth:sodium-extra:mc1.21.9-0.7.0+fabric" // Sodium Extra modImplementation "maven.modrinth:sodium-extra:mc1.21-0.5.7" // Sodium Extra
modImplementation "maven.modrinth:iris:1.9.6+1.21.10-fabric" // Iris modImplementation "maven.modrinth:embeddium:1.0.2+mc1.21" // Embeddium
modImplementation "maven.modrinth:distanthorizons:2.3.6-b-1.21.10" // Distant Horizons modImplementation "maven.modrinth:distanthorizons:2.1.2-a-1.21" // Distant Horizons
modImplementation "maven.modrinth:controlify:2.4.2-fabric,1.21.9" // Controlify modImplementation "nl.enjarai:shared-resources-api:1.8.3" // Shared Resources
} }

View file

@ -0,0 +1,14 @@
package com.axolotlmaid.optionsprofiles;
import com.axolotlmaid.optionsprofiles.profiles.Profiles;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class OptionsProfilesMod {
public static final String MOD_ID = "optionsprofiles";
public static final Logger LOGGER = LogManager.getLogger("Options Profiles");
public static final Profiles PROFILES_INSTANCE = new Profiles();
public static void init() {}
}

View file

@ -1,5 +1,8 @@
package net.trafficlunar.optionsprofiles.gui; package com.axolotlmaid.optionsprofiles.gui;
import com.axolotlmaid.optionsprofiles.OptionsProfilesMod;
import com.axolotlmaid.optionsprofiles.profiles.ProfileConfiguration;
import com.axolotlmaid.optionsprofiles.profiles.Profiles;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.components.*; import net.minecraft.client.gui.components.*;
import net.minecraft.client.gui.layouts.HeaderAndFooterLayout; import net.minecraft.client.gui.layouts.HeaderAndFooterLayout;
@ -8,17 +11,16 @@ import net.minecraft.client.gui.layouts.LinearLayout;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.trafficlunar.optionsprofiles.profiles.ProfileConfiguration;
import net.trafficlunar.optionsprofiles.profiles.Profiles; import java.nio.file.Files;
public class EditProfileScreen extends Screen { public class EditProfileScreen extends Screen {
private final ProfilesScreen profilesScreen; private final ProfilesScreen profilesScreen;
private final HeaderAndFooterLayout layout = new HeaderAndFooterLayout(this, 24, 33); private final HeaderAndFooterLayout layout = new HeaderAndFooterLayout(this, 24, 33);
private final Component profileName;
private final ProfileConfiguration profileConfiguration; private final ProfileConfiguration profileConfiguration;
private final Component profileName;
private EditBox profileNameEdit; private EditBox profileNameEdit;
private EditBox serversEdit;
public EditProfileScreen(ProfilesScreen profilesScreen, Component profileName) { public EditProfileScreen(ProfilesScreen profilesScreen, Component profileName) {
super(Component.literal(Component.translatable("gui.optionsprofiles.editing-profile-title").getString() + profileName.getString())); super(Component.literal(Component.translatable("gui.optionsprofiles.editing-profile-title").getString() + profileName.getString()));
@ -34,62 +36,55 @@ public class EditProfileScreen extends Screen {
this.profileNameEdit = new EditBox(this.font, this.width / 2 - 102, 116, 204, 20, Component.empty()); this.profileNameEdit = new EditBox(this.font, this.width / 2 - 102, 116, 204, 20, Component.empty());
this.profileNameEdit.setValue(profileName.getString()); 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 linearLayoutContent = this.layout.addToContents(LinearLayout.vertical().spacing(12), LayoutSettings::alignHorizontallyCenter);
LinearLayout linearLayoutEditBox = linearLayoutContent.addChild(LinearLayout.vertical().spacing(3), LayoutSettings::alignHorizontallyCenter); LinearLayout linearLayoutEditBox = linearLayoutContent.addChild(LinearLayout.vertical().spacing(6), LayoutSettings::alignHorizontallyCenter);
linearLayoutEditBox.addChild(new StringWidget(Component.translatable("gui.optionsprofiles.profile-name-text"), this.font), LayoutSettings::alignHorizontallyCenter); linearLayoutEditBox.addChild(new StringWidget(Component.translatable("gui.optionsprofiles.profile-name-text"), this.font), LayoutSettings::alignHorizontallyCenter);
linearLayoutEditBox.addChild(this.profileNameEdit); 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); LinearLayout linearLayoutButtons = linearLayoutContent.addChild(LinearLayout.vertical().spacing(1), LayoutSettings::alignHorizontallyCenter);
linearLayoutButtons.addChild( linearLayoutButtons.addChild(
Button.builder( Button.builder(
Component.translatable("gui.optionsprofiles.overwrite-options"), Component.translatable("gui.optionsprofiles.overwrite-options"),
(button) -> { (button) -> {
Profiles.writeProfile(profileName.getString(), true); OptionsProfilesMod.PROFILES_INSTANCE.writeProfile(profileName.getString(), true);
this.onClose(); this.onClose();
}) })
.size(150, 20) .size(150, 20)
.pos(this.width / 2 - 75, 145)
.tooltip(Tooltip.create(Component.translatable("gui.optionsprofiles.overwrite-options.tooltip"))) .tooltip(Tooltip.create(Component.translatable("gui.optionsprofiles.overwrite-options.tooltip")))
.build(), .build(),
LayoutSettings::alignHorizontallyCenter LayoutSettings::alignHorizontallyCenter
); );
linearLayoutButtons.addChild(
Button.builder(
Component.translatable("gui.optionsprofiles.rename-profile"),
(button) -> {
OptionsProfilesMod.PROFILES_INSTANCE.renameProfile(profileName.getString(), this.profileNameEdit.getValue());
this.minecraft.setScreen(new EditProfileScreen(profilesScreen, Component.literal(this.profileNameEdit.getValue())));
})
.size(150, 20)
.build(),
LayoutSettings::alignHorizontallyCenter
);
linearLayoutButtons.addChild( linearLayoutButtons.addChild(
Button.builder( Button.builder(
Component.translatable("gui.optionsprofiles.options-toggle").append("..."), Component.translatable("gui.optionsprofiles.options-toggle").append("..."),
(button) -> this.minecraft.setScreen(new OptionsToggleScreen(this, profileName, profileConfiguration))) (button) -> this.minecraft.setScreen(new OptionsToggleScreen(this, profileName, profileConfiguration)))
.size(150, 20) .size(150, 20)
.pos(this.width / 2 - 75, 187)
.tooltip(Tooltip.create(Component.translatable("gui.optionsprofiles.options-toggle.tooltip"))) .tooltip(Tooltip.create(Component.translatable("gui.optionsprofiles.options-toggle.tooltip")))
.build(), .build(),
LayoutSettings::alignHorizontallyCenter LayoutSettings::alignHorizontallyCenter
); );
linearLayoutButtons.addChild(
LinearLayout linearLayoutSettings = linearLayoutContent.addChild(LinearLayout.vertical().spacing(1), LayoutSettings::alignHorizontallyCenter); Checkbox.builder(
linearLayoutSettings.addChild( Component.literal("Load on startup"),
CycleButton.<Integer>builder(value -> Component.literal(value.toString())) this.font
.withValues(0, 1, 2, 3) )
.withInitialValue(this.profileConfiguration.getKeybindIndex()) .selected(profileConfiguration.isLoadOnStartup())
.create(0, 0, 150, 20, Component.translatable("gui.optionsprofiles.keybind-index"), (button, keybindIndex) -> { .onValueChange((checkbox, value) -> profileConfiguration.setLoadOnStartup(value))
this.profileConfiguration.setKeybindIndex(keybindIndex); .build(),
}), (layoutSettings) -> layoutSettings.alignHorizontallyCenter().paddingTop(5)
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( this.layout.addToFooter(
@ -104,8 +99,8 @@ public class EditProfileScreen extends Screen {
Component.translatable("gui.optionsprofiles.delete-profile") Component.translatable("gui.optionsprofiles.delete-profile")
.withStyle(ChatFormatting.RED), .withStyle(ChatFormatting.RED),
(button) -> { (button) -> {
Profiles.deleteProfile(profileName.getString()); OptionsProfilesMod.PROFILES_INSTANCE.deleteProfile(profileName.getString());
this.onClose(true); this.onClose();
}) })
.width(50) .width(50)
.build(), .build(),
@ -120,19 +115,13 @@ public class EditProfileScreen extends Screen {
this.layout.arrangeElements(); this.layout.arrangeElements();
} }
@Override
public void onClose() { 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.minecraft.setScreen(this.profilesScreen);
this.profilesScreen.profilesList.refreshEntries(); this.profilesScreen.profilesList.refreshEntries();
// Checks if the configuration still exists and wasn't deleted
if (Files.exists(Profiles.PROFILES_DIRECTORY.resolve(profileName.getString()).resolve("configuration.json"))) {
this.profileConfiguration.save();
}
} }
} }

View file

@ -1,11 +1,8 @@
package net.trafficlunar.optionsprofiles.gui; package com.axolotlmaid.optionsprofiles.gui;
import net.fabricmc.api.EnvType; import com.axolotlmaid.optionsprofiles.OptionsProfilesMod;
import net.fabricmc.api.Environment; import com.axolotlmaid.optionsprofiles.profiles.ProfileConfiguration;
import net.minecraft.client.gui.screens.options.controls.KeyBindsList; import com.axolotlmaid.optionsprofiles.profiles.Profiles;
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 net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -13,7 +10,6 @@ import net.minecraft.client.gui.Font;
import net.minecraft.client.gui.GuiGraphics; 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.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;
@ -26,40 +22,21 @@ 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.OptionEntry> { public class OptionsToggleList extends ContainerObjectSelectionList<OptionsToggleList.Entry> {
private final String profileName; private final String profileName;
private final ProfileConfiguration profileConfiguration; private final ProfileConfiguration profileConfiguration;
private final EditBox searchBox;
private final List<OptionEntry> allEntries = new ArrayList<>();
public OptionsToggleList(OptionsToggleScreen optionsToggleScreen, Minecraft minecraft, String profileName, ProfileConfiguration profileConfiguration, EditBox searchBox) { public OptionsToggleList(OptionsToggleScreen optionsToggleScreen, Minecraft minecraft, String profileName) {
super(minecraft, optionsToggleScreen.width, optionsToggleScreen.layout.getContentHeight(), optionsToggleScreen.layout.getHeaderHeight(), 20); super(minecraft, optionsToggleScreen.width, optionsToggleScreen.layout.getContentHeight(), optionsToggleScreen.layout.getHeaderHeight(), 20);
this.profileConfiguration = profileConfiguration; this.profileConfiguration = optionsToggleScreen.profileConfiguration;
this.profileName = profileName; this.profileName = profileName;
this.searchBox = searchBox;
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) {
allEntries.clear(); this.clearEntries();
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");
@ -83,33 +60,29 @@ 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
allEntries.add(new OptionEntry(option[0], option[1], profileConfiguration.getOptionsToLoad().contains(option[0]))); this.addEntry(new OptionEntry(option[0], option[1], profileConfiguration.getOptionsToLoad().contains(option[0])));
} else { } else {
allEntries.add(new OptionEntry(option[0], "", profileConfiguration.getOptionsToLoad().contains(option[0]))); this.addEntry(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 scrollBarX() { protected int getScrollbarPosition() {
return super.scrollBarX() + 15; return super.getScrollbarPosition() + 15;
} }
public int getRowWidth() { public int getRowWidth() {
return 340; return 340;
} }
public class OptionEntry extends ContainerObjectSelectionList.Entry<OptionEntry> { public class OptionEntry extends Entry {
private final String key;
private final Component optionKey; private final Component optionKey;
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.key = optionKey;
this.optionKey = Component.literal(optionKey); this.optionKey = Component.literal(optionKey);
this.toggleButton = CycleButton.onOffBuilder(toggled).displayOnlyValue().create(0, 0, 44, 20, Component.empty(), (button, boolean_) -> { this.toggleButton = CycleButton.onOffBuilder(toggled).displayOnlyValue().create(0, 0, 44, 20, Component.empty(), (button, boolean_) -> {
@ -137,14 +110,17 @@ public class OptionsToggleList extends ContainerObjectSelectionList<OptionsToggl
} }
} }
public void renderContent(GuiGraphics guiGraphics, int mouseX, int mouseY, boolean hovered, float tickDelta) { public void render(GuiGraphics guiGraphics, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
int posX = OptionsToggleList.this.scrollBarX() - this.toggleButton.getWidth() - 10; Font fontRenderer = OptionsToggleList.this.minecraft.font;
int posY = this.getContentY() - 2;
int posX = OptionsToggleList.this.getScrollbarPosition() - this.toggleButton.getWidth() - 10;
int posY = y - 2;
int textY = y + entryHeight / 2;
guiGraphics.drawString(fontRenderer, this.optionKey, x, textY - 9 / 2, 16777215, false);
this.toggleButton.setPosition(posX, posY); this.toggleButton.setPosition(posX, posY);
this.toggleButton.render(guiGraphics, mouseX, mouseY, tickDelta); this.toggleButton.render(guiGraphics, mouseX, mouseY, tickDelta);
guiGraphics.drawString(OptionsToggleList.this.minecraft.font, this.optionKey, this.getContentX(), this.getContentYMiddle() - 4, -1);
} }
public List<? extends GuiEventListener> children() { public List<? extends GuiEventListener> children() {
@ -155,4 +131,9 @@ 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

@ -1,22 +1,18 @@
package net.trafficlunar.optionsprofiles.gui; package com.axolotlmaid.optionsprofiles.gui;
import com.axolotlmaid.optionsprofiles.profiles.ProfileConfiguration;
import net.minecraft.ChatFormatting; import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.components.Button; 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.layouts.LinearLayout;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.options.OptionsSubScreen; import net.minecraft.client.gui.screens.options.OptionsSubScreen;
import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.trafficlunar.optionsprofiles.profiles.ProfileConfiguration;
public class OptionsToggleScreen extends OptionsSubScreen { public class OptionsToggleScreen extends OptionsSubScreen {
private final Component profileName; private final Component profileName;
private final ProfileConfiguration profileConfiguration;
private OptionsToggleList optionsToggleList; private OptionsToggleList optionsToggleList;
private EditBox searchBox; public ProfileConfiguration profileConfiguration;
protected OptionsToggleScreen(Screen lastScreen, Component profileName, ProfileConfiguration profileConfiguration) { protected OptionsToggleScreen(Screen lastScreen, Component profileName, ProfileConfiguration profileConfiguration) {
super(lastScreen, null, Component.literal(Component.translatable("gui.optionsprofiles.options-toggle").append(": ").getString() + profileName.getString())); super(lastScreen, null, Component.literal(Component.translatable("gui.optionsprofiles.options-toggle").append(": ").getString() + profileName.getString()));
@ -24,22 +20,11 @@ public class OptionsToggleScreen extends OptionsSubScreen {
this.profileConfiguration = profileConfiguration; 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 addOptions() {}
protected void addContents() { protected void addContents() {
this.layout.setHeaderHeight(42); this.layout.setHeaderHeight(24);
this.optionsToggleList = this.layout.addToContents(new OptionsToggleList(this, this.minecraft, profileName.getString(), this.profileConfiguration, this.searchBox)); this.optionsToggleList = this.layout.addToContents(new OptionsToggleList(this, this.minecraft, profileName.getString()));
} }
protected void addFooter() { protected void addFooter() {
@ -70,7 +55,7 @@ public class OptionsToggleScreen extends OptionsSubScreen {
} }
public void removed() { public void removed() {
this.profileConfiguration.save(); profileConfiguration.save();
} }
protected void repositionElements() { protected void repositionElements() {

View file

@ -1,8 +1,8 @@
package net.trafficlunar.optionsprofiles.gui; package com.axolotlmaid.optionsprofiles.gui;
import net.trafficlunar.optionsprofiles.OptionsProfilesMod; import com.axolotlmaid.optionsprofiles.OptionsProfilesMod;
import net.trafficlunar.optionsprofiles.profiles.ProfileConfiguration; import com.axolotlmaid.optionsprofiles.profiles.ProfileConfiguration;
import net.trafficlunar.optionsprofiles.profiles.Profiles; import com.axolotlmaid.optionsprofiles.profiles.Profiles;
import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableList;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.Font; import net.minecraft.client.gui.Font;
@ -36,10 +36,8 @@ public class ProfilesList extends ContainerObjectSelectionList<ProfilesList.Prof
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Profiles.PROFILES_DIRECTORY)) { try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Profiles.PROFILES_DIRECTORY)) {
List<Path> profileList = new ArrayList<>(); List<Path> profileList = new ArrayList<>();
for (Path profile : directoryStream) { for (Path profile : directoryStream) {
if (Files.isDirectory(profile)) {
profileList.add(profile); profileList.add(profile);
} }
}
// Sort the list alphabetically based on the profile names // Sort the list alphabetically based on the profile names
profileList.sort(Comparator.comparing(p -> p.getFileName().toString())); profileList.sort(Comparator.comparing(p -> p.getFileName().toString()));
@ -51,15 +49,15 @@ public class ProfilesList extends ContainerObjectSelectionList<ProfilesList.Prof
OptionsProfilesMod.LOGGER.error("An error occurred when listing profiles", e); OptionsProfilesMod.LOGGER.error("An error occurred when listing profiles", e);
} }
// checkEntriesLoaded(); checkEntriesLoaded();
} }
// public void checkEntriesLoaded() { public void checkEntriesLoaded() {
// this.children().forEach(ProfileEntry::checkLoaded); this.children().forEach(ProfileEntry::checkLoaded);
// } }
protected int scrollBarX() { protected int getScrollbarPosition() {
return super.scrollBarX() + 15; return super.getScrollbarPosition() + 15;
} }
public int getRowWidth() { public int getRowWidth() {
@ -83,27 +81,38 @@ public class ProfilesList extends ContainerObjectSelectionList<ProfilesList.Prof
this.loadButton = Button.builder( this.loadButton = Button.builder(
Component.translatable("gui.optionsprofiles.load-profile"), Component.translatable("gui.optionsprofiles.load-profile"),
(button) -> { (button) -> {
Profiles.loadProfile(profileName.getString()); OptionsProfilesMod.PROFILES_INSTANCE.loadProfile(profileName.getString());
OptionsProfilesMod.LOGGER.warn("[Profile '{}']: Loaded through button", profileName);
// ProfilesList.this.checkEntriesLoaded(); minecraft.options.load();
// button.active = false;
if (ProfileConfiguration.get(profileName.getString()).getOptionsToLoad().contains("resourcePacks")) {
minecraft.options.loadSelectedResourcePacks(minecraft.getResourcePackRepository());
minecraft.reloadResourcePacks();
}
minecraft.options.save();
ProfilesList.this.checkEntriesLoaded();
button.active = false;
}) })
.size(75, 20) .size(75, 20)
.build(); .build();
} }
public void renderContent(GuiGraphics guiGraphics, int mouseX, int mouseY, boolean hovered, float tickDelta) { public void render(GuiGraphics guiGraphics, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
int posX = ProfilesList.this.scrollBarX() - this.loadButton.getWidth() - 10; Font fontRenderer = ProfilesList.this.minecraft.font;
int posY = this.getContentY() - 2;
int posX = ProfilesList.this.getScrollbarPosition() - this.loadButton.getWidth() - 10;
int posY = y - 2;
int textY = y + entryHeight / 2;
guiGraphics.drawString(fontRenderer, this.profileName, x, textY - 9 / 2, 16777215, false);
this.editButton.setPosition(posX - this.editButton.getWidth(), posY); this.editButton.setPosition(posX - this.editButton.getWidth(), posY);
this.editButton.render(guiGraphics, mouseX, mouseY, tickDelta); this.editButton.render(guiGraphics, mouseX, mouseY, tickDelta);
this.loadButton.setPosition(posX, posY); this.loadButton.setPosition(posX, posY);
this.loadButton.render(guiGraphics, mouseX, mouseY, tickDelta); 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() { public List<? extends GuiEventListener> children() {
@ -114,8 +123,8 @@ public class ProfilesList extends ContainerObjectSelectionList<ProfilesList.Prof
return ImmutableList.of(this.editButton, this.loadButton); return ImmutableList.of(this.editButton, this.loadButton);
} }
// protected void checkLoaded() { protected void checkLoaded() {
// this.loadButton.active = !Profiles.isProfileLoaded(profileName.getString()); this.loadButton.active = !OptionsProfilesMod.PROFILES_INSTANCE.isProfileLoaded(profileName.getString());
// } }
} }
} }

View file

@ -1,20 +1,22 @@
package net.trafficlunar.optionsprofiles.gui; package com.axolotlmaid.optionsprofiles.gui;
import com.axolotlmaid.optionsprofiles.OptionsProfilesMod;
import com.axolotlmaid.optionsprofiles.profiles.Profiles;
import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.layouts.LinearLayout; import net.minecraft.client.gui.layouts.LinearLayout;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.options.OptionsScreen;
import net.minecraft.client.gui.screens.options.OptionsSubScreen; import net.minecraft.client.gui.screens.options.OptionsSubScreen;
import net.minecraft.network.chat.CommonComponents; import net.minecraft.network.chat.CommonComponents;
import net.minecraft.network.chat.Component; import net.minecraft.network.chat.Component;
import net.trafficlunar.optionsprofiles.profiles.Profiles;
public class ProfilesScreen extends OptionsSubScreen { public class ProfilesScreen extends OptionsSubScreen {
private final Screen lastScreen; private final Screen optionsLastScreen;
public ProfilesList profilesList; public ProfilesList profilesList;
public ProfilesScreen(Screen lastScreen) { public ProfilesScreen(Screen lastScreen, Screen optionsLastScreen) {
super(lastScreen, null, Component.translatable("gui.optionsprofiles.profiles-menu")); super(lastScreen, null, Component.translatable("gui.optionsprofiles.profiles-menu"));
this.lastScreen = lastScreen; this.optionsLastScreen = optionsLastScreen;
} }
protected void addOptions() {} protected void addOptions() {}
@ -22,13 +24,6 @@ public class ProfilesScreen extends OptionsSubScreen {
protected void addContents() { protected void addContents() {
this.layout.setHeaderHeight(24); this.layout.setHeaderHeight(24);
this.profilesList = this.layout.addToContents(new ProfilesList(this, this.minecraft)); 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() { protected void addFooter() {
@ -37,7 +32,7 @@ public class ProfilesScreen extends OptionsSubScreen {
Button.builder( Button.builder(
Component.translatable("gui.optionsprofiles.save-current-options"), Component.translatable("gui.optionsprofiles.save-current-options"),
(button -> { (button -> {
Profiles.createProfile(); OptionsProfilesMod.PROFILES_INSTANCE.createProfile();
this.profilesList.refreshEntries(); this.profilesList.refreshEntries();
})) }))
.build() .build()
@ -51,7 +46,7 @@ public class ProfilesScreen extends OptionsSubScreen {
} }
public void onClose() { public void onClose() {
this.minecraft.setScreen(lastScreen); this.minecraft.setScreen(new OptionsScreen(optionsLastScreen, this.minecraft.options));
} }
protected void repositionElements() { protected void repositionElements() {

View file

@ -1,11 +1,10 @@
package net.trafficlunar.optionsprofiles.mixin; package com.axolotlmaid.optionsprofiles.mixin;
import com.axolotlmaid.optionsprofiles.gui.ProfilesScreen;
import net.minecraft.client.gui.components.Button; import net.minecraft.client.gui.components.Button;
import net.minecraft.client.gui.screens.Screen; import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.gui.screens.options.OptionsScreen; import net.minecraft.client.gui.screens.options.OptionsScreen;
import net.minecraft.network.chat.Component; 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.Final;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@ -23,15 +22,13 @@ public class MixinOptionsScreen extends Screen {
@Inject(at = @At("HEAD"), method = "init") @Inject(at = @At("HEAD"), method = "init")
private void init(CallbackInfo info) { private void init(CallbackInfo info) {
if (OptionsProfilesMod.config().shouldShowProfilesButton()) {
this.addRenderableWidget( this.addRenderableWidget(
Button.builder( Button.builder(
Component.translatable("gui.optionsprofiles.profiles-menu"), Component.translatable("gui.optionsprofiles.profiles-menu"),
(button) -> this.minecraft.setScreen(new ProfilesScreen(this))) (button) -> this.minecraft.setScreen(new ProfilesScreen(this, lastScreen)))
.width(75) .width(75)
.pos(5, 5) .pos(5, 5)
.build() .build()
); );
} }
} }
}

View file

@ -1,8 +1,8 @@
package net.trafficlunar.optionsprofiles.profiles; package com.axolotlmaid.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,11 @@ 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;
private boolean loadOnStartup = false; private boolean loadOnStartup = false;
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,11 +40,13 @@ 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();
configurationFile = Profiles.PROFILES_DIRECTORY.resolve(profile_name).resolve("configuration.json"); Path profile = profilesDirectory.resolve(profile_name);
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();
@ -57,7 +58,7 @@ public class ProfileConfiguration {
return configuration; return configuration;
} }
public boolean shouldLoadOnStartup() { public boolean isLoadOnStartup() {
return loadOnStartup; return loadOnStartup;
} }
@ -65,14 +66,6 @@ public class ProfileConfiguration {
this.loadOnStartup = loadOnStartup; this.loadOnStartup = loadOnStartup;
} }
public int getKeybindIndex() {
return keybindIndex;
}
public void setKeybindIndex(int keybindIndex) {
this.keybindIndex = keybindIndex;
}
public List<String> getOptionsToLoad() { public List<String> getOptionsToLoad() {
return optionsToLoad; return optionsToLoad;
} }
@ -80,12 +73,4 @@ 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,35 +1,98 @@
package net.trafficlunar.optionsprofiles.profiles; package com.axolotlmaid.optionsprofiles.profiles;
import dev.architectury.platform.Platform; import com.axolotlmaid.optionsprofiles.OptionsProfilesMod;
import net.minecraft.client.Minecraft; import com.axolotlmaid.optionsprofiles.profiles.loaders.DistantHorizonsLoader;
import net.trafficlunar.optionsprofiles.OptionsProfilesMod; import com.axolotlmaid.optionsprofiles.profiles.loaders.EmbeddiumLoader;
import net.trafficlunar.optionsprofiles.profiles.loaders.DistantHorizonsLoader; import com.axolotlmaid.optionsprofiles.profiles.loaders.SodiumExtraLoader;
import net.trafficlunar.optionsprofiles.profiles.loaders.IrisLoader; import com.axolotlmaid.optionsprofiles.profiles.loaders.SodiumLoader;
import net.trafficlunar.optionsprofiles.profiles.loaders.SodiumExtraLoader; import nl.enjarai.shared_resources.api.GameResourceHelper;
import net.trafficlunar.optionsprofiles.profiles.loaders.SodiumLoader; import nl.enjarai.shared_resources.util.GameResourceConfig;
import org.apache.commons.io.FileUtils; import org.apache.commons.io.FileUtils;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.*;
import java.nio.file.Path; import java.util.*;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
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;
public class Profiles { public class Profiles {
public static final Path PROFILES_DIRECTORY = Paths.get("options-profiles/"); public static Path PROFILES_DIRECTORY = Paths.get("options-profiles/");
public static final Path OPTIONS_FILE = Paths.get("options.txt"); public static Path OPTIONS_FILE = Paths.get("options.txt");
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 IRIS_OPTIONS_FILE = Paths.get("config/iris.properties"); public static final Path EMBEDDIUM_OPTIONS_FILE = Paths.get("config/embeddium-options.json");
public static final Path DISTANT_HORIZONS_OPTIONS_FILE = Paths.get("config/DistantHorizons.toml"); public static final Path DISTANT_HORIZONS_OPTIONS_FILE = Paths.get("config/DistantHorizons.toml");
public static void createProfile() { public Profiles() {
// Create profiles directory
PROFILES_DIRECTORY = Paths.get("options-profiles/");
if (Files.notExists(PROFILES_DIRECTORY)) {
try {
Files.createDirectory(PROFILES_DIRECTORY);
} catch (IOException e) {
OptionsProfilesMod.LOGGER.error("An error occurred when creating the 'options-profiles' directory.", e);
}
}
// Set profiles directory if Shared Resources mod is installed
Path sharedResourcesPath = GameResourceHelper.getPathFor(SharedResourcesProfiles.SHARED_RESOURCES_PROFILES_DIRECTORY);
if (sharedResourcesPath != null) {
PROFILES_DIRECTORY = sharedResourcesPath;
OPTIONS_FILE = sharedResourcesPath.getParent().resolve("options.txt");
}
// Goes through every profile and adds the configuration file if it doesn't exist
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);
Path profile = PROFILES_DIRECTORY.resolve(profileName);
Path profileOptions = profile.resolve(OPTIONS_FILE.getFileName());
// Add every option value to configuration
try (Stream<String> lines = Files.lines(profileOptions)) {
List<String> optionsToLoad = profileConfiguration.getOptionsToLoad();
lines.forEach((line) -> {
String[] option = line.split(":");
optionsToLoad.add(option[0]);
});
profileConfiguration.save();
} catch (IOException e) {
OptionsProfilesMod.LOGGER.error("[Profile '{}']: An error occurred when adding options to the configuration file", profileName, e);
}
OptionsProfilesMod.LOGGER.warn("[Profile '{}']: Profile configuration added", profileName);
});
} catch (IOException e) {
OptionsProfilesMod.LOGGER.error("An error occurred when updating profiles", e);
}
// Loading profiles on startup
try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(Profiles.PROFILES_DIRECTORY)) {
for (Path profile : directoryStream) {
String profileName = profile.getFileName().toString();
ProfileConfiguration profileConfiguration = ProfileConfiguration.get(profileName);
if (profileConfiguration.isLoadOnStartup()) {
OptionsProfilesMod.PROFILES_INSTANCE.loadProfile(profileName);
}
}
} catch (Exception e) {
OptionsProfilesMod.LOGGER.error("An error occurred when loading startup profiles", e);
}
return;
}
public void createProfile() {
String profileName = "Profile 1"; String profileName = "Profile 1";
Path profile = PROFILES_DIRECTORY.resolve(profileName); Path profile = PROFILES_DIRECTORY.resolve(profileName);
@ -53,7 +116,7 @@ public class Profiles {
} }
} }
private static void copyOptionFile(Path profile, Path options) { private void copyOptionFile(Path profile, Path options) {
if (Files.exists(options)) { if (Files.exists(options)) {
Path profileOptions = profile.resolve(options.getFileName()); Path profileOptions = profile.resolve(options.getFileName());
@ -66,7 +129,7 @@ public class Profiles {
} }
} }
public static void writeProfile(String profileName, boolean overwriting) { public void writeProfile(String profileName, boolean overwriting) {
Path profile = PROFILES_DIRECTORY.resolve(profileName); Path profile = PROFILES_DIRECTORY.resolve(profileName);
Path profileOptions = profile.resolve("options.txt"); Path profileOptions = profile.resolve("options.txt");
@ -88,13 +151,9 @@ 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);
if (Platform.isModLoaded("iris")) copyOptionFile(profile, EMBEDDIUM_OPTIONS_FILE);
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) {
@ -116,63 +175,36 @@ public class Profiles {
} }
} }
// public static boolean isProfileLoaded(String profileName) { public boolean isProfileLoaded(String profileName) {
// TODO: rewrite/fix; returns incorrect results Path profile = PROFILES_DIRECTORY.resolve(profileName);
// Path profile = PROFILES_DIRECTORY.resolve(profileName); List<Path> optionFiles = new ArrayList<>();
// ProfileConfiguration profileConfiguration = ProfileConfiguration.get(profileName); optionFiles.add(OPTIONS_FILE);
//
// 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;
// }
// return false; // These lines check if the specified file exists. If so, it adds it to the optionFiles ArrayList.
// } Optional.of(OPTIFINE_OPTIONS_FILE).filter(Files::exists).ifPresent(optionFiles::add);
Optional.of(SODIUM_OPTIONS_FILE).filter(Files::exists).ifPresent(optionFiles::add);
Optional.of(SODIUM_EXTRA_OPTIONS_FILE).filter(Files::exists).ifPresent(optionFiles::add);
Optional.of(EMBEDDIUM_OPTIONS_FILE).filter(Files::exists).ifPresent(optionFiles::add);
Optional.of(DISTANT_HORIZONS_OPTIONS_FILE).filter(Files::exists).ifPresent(optionFiles::add);
private static void loadOptionFile(String profileName, Path options) { // 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 void loadOptionFile(String profileName, Path options) {
ProfileConfiguration profileConfiguration = ProfileConfiguration.get(profileName); ProfileConfiguration profileConfiguration = ProfileConfiguration.get(profileName);
Path profile = PROFILES_DIRECTORY.resolve(profileName); Path profile = PROFILES_DIRECTORY.resolve(profileName);
@ -241,7 +273,7 @@ public class Profiles {
} }
} }
private static void loadOptionFile(String profileName, Path options, Consumer<Path> loader) { private void loadOptionFile(String profileName, Path options, Consumer<Path> loader) {
Path profile = PROFILES_DIRECTORY.resolve(profileName); Path profile = PROFILES_DIRECTORY.resolve(profileName);
Path profileOptions = profile.resolve(options.getFileName()); Path profileOptions = profile.resolve(options.getFileName());
@ -251,35 +283,18 @@ public class Profiles {
} }
} }
public static void loadProfile(String profileName) { public void loadProfile(String profileName) {
loadOptionFile(profileName, OPTIONS_FILE); loadOptionFile(profileName, OPTIONS_FILE);
loadOptionFile(profileName, OPTIFINE_OPTIONS_FILE); loadOptionFile(profileName, OPTIFINE_OPTIONS_FILE);
if (Platform.isModLoaded("sodium"))
loadOptionFile(profileName, SODIUM_OPTIONS_FILE, SodiumLoader::load); loadOptionFile(profileName, SODIUM_OPTIONS_FILE, SodiumLoader::load);
if (Platform.isModLoaded("sodium-extra"))
loadOptionFile(profileName, SODIUM_EXTRA_OPTIONS_FILE, SodiumExtraLoader::load); loadOptionFile(profileName, SODIUM_EXTRA_OPTIONS_FILE, SodiumExtraLoader::load);
if (Platform.isModLoaded("iris")) loadOptionFile(profileName, EMBEDDIUM_OPTIONS_FILE, EmbeddiumLoader::load);
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 public void renameProfile(String profileName, String newProfileName) {
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) {
Path profile = PROFILES_DIRECTORY.resolve(profileName); Path profile = PROFILES_DIRECTORY.resolve(profileName);
Path newProfile = PROFILES_DIRECTORY.resolve(newProfileName); Path newProfile = PROFILES_DIRECTORY.resolve(newProfileName);
@ -296,7 +311,7 @@ public class Profiles {
} }
} }
public static void deleteProfile(String profileName) { public void deleteProfile(String profileName) {
Path profile = PROFILES_DIRECTORY.resolve(profileName); Path profile = PROFILES_DIRECTORY.resolve(profileName);
try { try {

View file

@ -0,0 +1,21 @@
package com.axolotlmaid.optionsprofiles.profiles;
import net.minecraft.network.chat.Component;
import nl.enjarai.shared_resources.api.GameResourceRegistry;
import nl.enjarai.shared_resources.api.ResourceDirectory;
import nl.enjarai.shared_resources.api.ResourceDirectoryBuilder;
import nl.enjarai.shared_resources.api.SharedResourcesEntrypoint;
import net.minecraft.resources.ResourceLocation;
public class SharedResourcesProfiles implements SharedResourcesEntrypoint {
public static final ResourceDirectory SHARED_RESOURCES_PROFILES_DIRECTORY = new ResourceDirectoryBuilder("options-profiles")
.setDisplayName(Component.translatable("gui.optionsprofiles"))
.defaultEnabled(true)
.isExperimental()
.build();
@Override
public void registerResources(GameResourceRegistry registry) {
registry.register(ResourceLocation.fromNamespaceAndPath("optionsprofiles", "profiles_directory"), SHARED_RESOURCES_PROFILES_DIRECTORY);
}
}

View file

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

View file

@ -0,0 +1,70 @@
package com.axolotlmaid.optionsprofiles.profiles.loaders;
import com.axolotlmaid.optionsprofiles.OptionsProfilesMod;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.embeddedt.embeddium.impl.Embeddium;
import org.embeddedt.embeddium.impl.gui.EmbeddiumOptions;
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) {
Embeddium.options().quality.weatherQuality = EmbeddiumOptions.GraphicsQuality.valueOf(configuration.quality.weather_quality);
Embeddium.options().quality.leavesQuality = EmbeddiumOptions.GraphicsQuality.valueOf(configuration.quality.leaves_quality);
Embeddium.options().quality.enableVignette = configuration.quality.enable_vignette;
Embeddium.options().advanced.enableMemoryTracing = configuration.advanced.enable_memory_tracing;
Embeddium.options().advanced.useAdvancedStagingBuffers = configuration.advanced.use_advanced_staging_buffers;
Embeddium.options().advanced.disableIncompatibleModWarnings = configuration.advanced.disable_incompatible_mod_warnings;
Embeddium.options().advanced.cpuRenderAheadLimit = configuration.advanced.cpu_render_ahead_limit;
Embeddium.options().performance.chunkBuilderThreads = configuration.performance.chunk_builder_threads;
Embeddium.options().performance.alwaysDeferChunkUpdates = configuration.performance.always_defer_chunk_updates_v2;
Embeddium.options().performance.animateOnlyVisibleTextures = configuration.performance.animate_only_visible_textures;
Embeddium.options().performance.useEntityCulling = configuration.performance.use_entity_culling;
Embeddium.options().performance.useFogOcclusion = configuration.performance.use_fog_occlusion;
Embeddium.options().performance.useBlockFaceCulling = configuration.performance.use_block_face_culling;
Embeddium.options().performance.useCompactVertexFormat = configuration.performance.use_compact_vertex_format;
Embeddium.options().performance.useTranslucentFaceSorting = configuration.performance.use_translucent_face_sorting_v2;
Embeddium.options().performance.useNoErrorGLContext = configuration.performance.use_no_error_g_l_context;
Embeddium.options().notifications.hasClearedDonationButton = configuration.notifications.has_cleared_donation_button;
Embeddium.options().notifications.hasSeenDonationPrompt = configuration.notifications.has_seen_donation_prompt;
try {
EmbeddiumOptions.writeToDisk(Embeddium.options());
} 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_v2;
}
}
}

View file

@ -1,25 +1,21 @@
package net.trafficlunar.optionsprofiles.profiles.loaders; package com.axolotlmaid.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().registerTypeAdapter(ResourceLocation.class, new ResourceLocationSerializer()).create(); Gson gson = new GsonBuilder().create();
Configuration configuration = gson.fromJson(reader, Configuration.class); Configuration configuration = gson.fromJson(reader, Configuration.class);
apply(configuration); apply(configuration);
@ -44,15 +40,16 @@ 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.sun = configuration.detail_settings.sun; SodiumExtraClientMod.options().detailSettings.sunMoon = configuration.detail_settings.sun_moon;
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.globalFog = configuration.render_settings.global_fog; SodiumExtraClientMod.options().renderSettings.fogDistance = configuration.render_settings.fog_distance;
SodiumExtraClientMod.options().renderSettings.fogTypeConfig = configuration.render_settings.fog_type_config; SodiumExtraClientMod.options().renderSettings.fogStart = configuration.render_settings.fog_start;
SodiumExtraClientMod.options().renderSettings.multiDimensionFogControl = configuration.render_settings.multi_dimension_fog_control;
SodiumExtraClientMod.options().renderSettings.dimensionFogDistanceMap = configuration.render_settings.dimensionFogDistance;
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;
@ -72,6 +69,7 @@ public class SodiumExtraLoader {
SodiumExtraClientMod.options().extraSettings.reduceResolutionOnMac = configuration.extra_settings.reduce_resolution_on_mac; SodiumExtraClientMod.options().extraSettings.reduceResolutionOnMac = configuration.extra_settings.reduce_resolution_on_mac;
SodiumExtraClientMod.options().extraSettings.useAdaptiveSync = configuration.extra_settings.use_adaptive_sync; SodiumExtraClientMod.options().extraSettings.useAdaptiveSync = configuration.extra_settings.use_adaptive_sync;
SodiumExtraClientMod.options().extraSettings.cloudHeight = configuration.extra_settings.cloud_height; SodiumExtraClientMod.options().extraSettings.cloudHeight = configuration.extra_settings.cloud_height;
SodiumExtraClientMod.options().extraSettings.cloudDistance = configuration.extra_settings.cloud_distance;
SodiumExtraClientMod.options().extraSettings.toasts = configuration.extra_settings.toasts; SodiumExtraClientMod.options().extraSettings.toasts = configuration.extra_settings.toasts;
SodiumExtraClientMod.options().extraSettings.advancementToast = configuration.extra_settings.advancement_toast; SodiumExtraClientMod.options().extraSettings.advancementToast = configuration.extra_settings.advancement_toast;
SodiumExtraClientMod.options().extraSettings.recipeToast = configuration.extra_settings.recipe_toast; SodiumExtraClientMod.options().extraSettings.recipeToast = configuration.extra_settings.recipe_toast;
@ -112,8 +110,7 @@ public class SodiumExtraLoader {
public static class DetailSettings { public static class DetailSettings {
public boolean sky; public boolean sky;
public boolean sun; public boolean sun_moon;
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;
@ -121,8 +118,10 @@ public class SodiumExtraLoader {
} }
public static class RenderSettings { public static class RenderSettings {
public boolean global_fog; public int fog_distance;
public EnumMap<FogType, FogTypeConfig> fog_type_config; public int fog_start;
public boolean multi_dimension_fog_control;
public Map<ResourceLocation, Integer> dimensionFogDistance;
public boolean light_updates; public boolean light_updates;
public boolean item_frame; public boolean item_frame;
public boolean armor_stand; public boolean armor_stand;
@ -144,6 +143,7 @@ public class SodiumExtraLoader {
public boolean reduce_resolution_on_mac; public boolean reduce_resolution_on_mac;
public boolean use_adaptive_sync; public boolean use_adaptive_sync;
public int cloud_height; public int cloud_height;
public int cloud_distance;
public boolean toasts; public boolean toasts;
public boolean advancement_toast; public boolean advancement_toast;
public boolean recipe_toast; public boolean recipe_toast;

View file

@ -1,12 +1,10 @@
package net.trafficlunar.optionsprofiles.profiles.loaders; package com.axolotlmaid.optionsprofiles.profiles.loaders;
import net.caffeinemc.mods.sodium.client.render.chunk.DeferMode; import com.axolotlmaid.optionsprofiles.OptionsProfilesMod;
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 net.caffeinemc.mods.sodium.client.SodiumClientMod; import me.jellysquid.mods.sodium.client.SodiumClientMod;
import net.caffeinemc.mods.sodium.client.gui.SodiumGameOptions; import me.jellysquid.mods.sodium.client.gui.SodiumGameOptions;
import java.io.FileReader; import java.io.FileReader;
import java.io.IOException; import java.io.IOException;
@ -25,8 +23,8 @@ public class SodiumLoader {
} }
private static void apply(Configuration configuration) { private static void apply(Configuration configuration) {
SodiumClientMod.options().quality.weatherQuality = SodiumGameOptions.WeatherQuality.valueOf(configuration.quality.weather_quality); SodiumClientMod.options().quality.weatherQuality = SodiumGameOptions.GraphicsQuality.valueOf(configuration.quality.weather_quality);
SodiumClientMod.options().quality.leavesQuality = SodiumGameOptions.LeavesQuality.valueOf(configuration.quality.leaves_quality); SodiumClientMod.options().quality.leavesQuality = SodiumGameOptions.GraphicsQuality.valueOf(configuration.quality.leaves_quality);
SodiumClientMod.options().quality.enableVignette = configuration.quality.enable_vignette; SodiumClientMod.options().quality.enableVignette = configuration.quality.enable_vignette;
SodiumClientMod.options().advanced.enableMemoryTracing = configuration.advanced.enable_memory_tracing; SodiumClientMod.options().advanced.enableMemoryTracing = configuration.advanced.enable_memory_tracing;
@ -34,19 +32,16 @@ public class SodiumLoader {
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.chunkBuildDeferMode = configuration.performance.chunk_build_defer_mode; SodiumClientMod.options().performance.alwaysDeferChunkUpdates = configuration.performance.always_defer_chunk_updates_v2;
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.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.useNoErrorGLContext = configuration.performance.use_no_error_g_l_context;
SodiumClientMod.options().performance.quadSplittingMode = configuration.performance.quad_splitting_mode;
SodiumClientMod.options().notifications.hasClearedDonationButton = configuration.notifications.has_cleared_donation_button; SodiumClientMod.options().notifications.hasClearedDonationButton = configuration.notifications.has_cleared_donation_button;
SodiumClientMod.options().notifications.hasSeenDonationPrompt = configuration.notifications.has_seen_donation_prompt; SodiumClientMod.options().notifications.hasSeenDonationPrompt = configuration.notifications.has_seen_donation_prompt;
SodiumClientMod.options().debug.terrainSortingEnabled = configuration.debug.terrain_sorting_enabled;
try { try {
SodiumGameOptions.writeToDisk(SodiumClientMod.options()); SodiumGameOptions.writeToDisk(SodiumClientMod.options());
} catch (IOException e) { } catch (IOException e) {
@ -59,7 +54,6 @@ 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;
@ -75,22 +69,17 @@ public class SodiumLoader {
public static class Performance { public static class Performance {
public int chunk_builder_threads; public int chunk_builder_threads;
public DeferMode chunk_build_defer_mode; public boolean always_defer_chunk_updates_v2;
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_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 boolean use_no_error_g_l_context;
public QuadSplittingMode quad_splitting_mode;
} }
public static class Notifications { public static class Notifications {
public boolean has_cleared_donation_button; public boolean has_cleared_donation_button;
public boolean has_seen_donation_prompt; public boolean has_seen_donation_prompt;
} }
public static class Debug {
public boolean terrain_sorting_enabled;
}
} }
} }

View file

@ -1,18 +0,0 @@
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

@ -1,58 +0,0 @@
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

@ -1,115 +0,0 @@
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

@ -1,59 +0,0 @@
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

@ -1,57 +0,0 @@
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

@ -1,11 +0,0 @@
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

@ -1,35 +0,0 @@
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,4 +1,6 @@
{ {
"gui.optionsprofiles": "Options Profiles",
"gui.optionsprofiles.profiles-menu": "Profiles", "gui.optionsprofiles.profiles-menu": "Profiles",
"gui.optionsprofiles.save-current-options": "Save Current Options", "gui.optionsprofiles.save-current-options": "Save Current Options",
"gui.optionsprofiles.load-profile": "✔ (Load)", "gui.optionsprofiles.load-profile": "✔ (Load)",
@ -6,31 +8,13 @@
"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": "net.trafficlunar.optionsprofiles.mixin", "package": "com.axolotlmaid.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.gradleup.shadow' id 'com.github.johnrengelman.shadow'
} }
architectury { architectury {
@ -24,25 +24,12 @@ 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

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

View file

@ -1,12 +0,0 @@
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

@ -4,25 +4,32 @@
"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": ["trafficlunar"], "authors": [
"AxolotlMaid"
],
"contact": { "contact": {
"homepage": "https://github.com/trafficlunar/options-profiles", "homepage": "https://github.com/AxolotlMaid/options-profiles",
"sources": "https://github.com/trafficlunar/options-profiles", "sources": "https://github.com/AxolotlMaid/options-profiles",
"issues": "https://github.com/trafficlunar/options-profiles/issues" "issues": "https://github.com/AxolotlMaid/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": ["net.trafficlunar.optionsprofiles.fabric.OptionsProfilesModFabric"], "main": [
"modmenu": ["net.trafficlunar.optionsprofiles.fabric.ModMenuApiImpl"] "com.axolotlmaid.optionsprofiles.fabric.OptionsProfilesModFabric"
],
"shared-resources": [
"com.axolotlmaid.optionsprofiles.profiles.SharedResourcesProfiles"
]
}, },
"mixins": ["optionsprofiles.mixins.json"], "mixins": [
"optionsprofiles.mixins.json"
],
"depends": { "depends": {
"fabricloader": ">=0.17.2", "fabricloader": ">=0.15.11",
"minecraft": "~1.21", "minecraft": "~1.21",
"java": ">=21", "java": ">=21",
"architectury": ">=18.0.3",
"fabric-api": "*" "fabric-api": "*"
} }
} }

59
forge/build.gradle Normal file
View file

@ -0,0 +1,59 @@
plugins {
id 'com.github.johnrengelman.shadow'
}
loom {
forge {
mixinConfig "optionsprofiles.mixins.json"
}
}
architectury {
platformSetupLoomIde()
forge()
}
configurations {
common {
canBeResolved = true
canBeConsumed = false
}
compileClasspath.extendsFrom common
runtimeClasspath.extendsFrom common
developmentForge.extendsFrom common
// Files in this configuration will be bundled into your mod using the Shadow plugin.
// Don't use the `shadow` configuration from the plugin itself as it's meant for excluding files.
shadowBundle {
canBeResolved = true
canBeConsumed = false
}
}
configurations.all {
resolutionStrategy.force("net.sf.jopt-simple:jopt-simple:5.0.4")
}
dependencies {
forge "net.minecraftforge:forge:$rootProject.forge_version"
common(project(path: ':common', configuration: 'namedElements')) { transitive false }
shadowBundle project(path: ':common', configuration: 'transformProductionForge')
}
processResources {
inputs.property 'version', project.version
filesMatching('META-INF/mods.toml') {
expand version: project.version
}
}
shadowJar {
configurations = [project.configurations.shadowBundle]
archiveClassifier = 'dev-shadow'
}
remapJar {
input.set shadowJar.archiveFile
}

1
forge/gradle.properties Normal file
View file

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

View file

@ -0,0 +1,11 @@
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

@ -0,0 +1,28 @@
modLoader = "javafml"
loaderVersion = "[51,)"
#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 = "[51,)"
ordering = "NONE"
side = "BOTH"
[[dependencies.optionsprofiles]]
modId = "minecraft"
mandatory = true
versionRange = "[1.21,)"
ordering = "NONE"
side = "BOTH"

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View file

@ -0,0 +1,6 @@
{
"pack": {
"description": "Options Profiles",
"pack_format": 22
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 835 KiB

After

Width:  |  Height:  |  Size: 729 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 733 KiB

After

Width:  |  Height:  |  Size: 570 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 748 KiB

After

Width:  |  Height:  |  Size: 578 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 710 KiB

After

Width:  |  Height:  |  Size: 554 KiB

View file

@ -1,20 +1,16 @@
org.gradle.jvmargs=-Xmx6G org.gradle.jvmargs=-Xmx6G
org.gradle.parallel=true org.gradle.parallel=true
# Fixes errors caused by Loom version differences mod_version=1.3.1
loom.ignoreDependencyLoomVersionValidation=true maven_group=com.axolotlmaid.optionsprofiles
# Mod properties
mod_version=1.4.4
maven_group=net.trafficlunar.optionsprofiles
archives_name=optionsprofiles archives_name=optionsprofiles
enabled_platforms=fabric,neoforge enabled_platforms=fabric,forge,neoforge
# Minecraft properties minecraft_version=1.21
minecraft_version=1.21.9
# Dependencies fabric_loader_version=0.15.11
architectury_api_version = 18.0.3 fabric_api_version=0.100.1+1.21
fabric_loader_version=0.17.2
fabric_api_version=0.134.0+1.21.9 forge_version=1.21-51.0.7
neoforge_version=21.9.0-beta
neoforge_version=21.0.6-beta

View file

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

0
gradlew vendored Executable file → Normal file
View file

View file

@ -1,5 +1,5 @@
plugins { plugins {
id 'com.gradleup.shadow' id 'com.github.johnrengelman.shadow'
} }
architectury { architectury {
@ -34,9 +34,6 @@ repositories {
dependencies { dependencies {
neoForge "net.neoforged:neoforge:$rootProject.neoforge_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: 'transformProductionNeoForge') shadowBundle project(path: ':common', configuration: 'transformProductionNeoForge')
} }

View file

@ -1,6 +1,6 @@
package net.trafficlunar.optionsprofiles.neoforge; package com.axolotlmaid.optionsprofiles.forge;
import net.trafficlunar.optionsprofiles.OptionsProfilesMod; import com.axolotlmaid.optionsprofiles.OptionsProfilesMod;
import net.neoforged.fml.common.Mod; import net.neoforged.fml.common.Mod;
@Mod(OptionsProfilesMod.MOD_ID) @Mod(OptionsProfilesMod.MOD_ID)

View file

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

View file

@ -2,13 +2,14 @@ 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://maven.minecraftforge.net/" } maven { url "https://files.minecraftforge.net/maven/" }
gradlePluginPortal() gradlePluginPortal()
} }
} }
include("common") include("common")
include("fabric") include("fabric")
include("forge")
include("neoforge") include("neoforge")
rootProject.name = "optionsprofiles-v1.4.4-1.21.9" rootProject.name = "optionsprofiles-v1.3.1-1.21"