mirror of
https://github.com/trafficlunar/options-profiles.git
synced 2026-06-28 06:34:11 +00:00
Initial commit
This commit is contained in:
commit
7e5a9af3fe
23 changed files with 1649 additions and 0 deletions
|
|
@ -0,0 +1,11 @@
|
|||
package dev.axolotlmaid.optionsprofiles;
|
||||
|
||||
import net.fabricmc.api.ModInitializer;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class OptionsProfilesMod implements ModInitializer {
|
||||
@Override
|
||||
public void onInitialize() {}
|
||||
}
|
||||
182
src/main/java/dev/axolotlmaid/optionsprofiles/Profiles.java
Normal file
182
src/main/java/dev/axolotlmaid/optionsprofiles/Profiles.java
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
package dev.axolotlmaid.optionsprofiles;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import net.fabricmc.loader.api.FabricLoader;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.option.GameOptions;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.FileSystemException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class Profiles {
|
||||
public File getDirectory() {
|
||||
File profilesDirectory = new File("options-profiles");
|
||||
if (!profilesDirectory.exists()) {
|
||||
profilesDirectory.mkdirs();
|
||||
}
|
||||
|
||||
return profilesDirectory;
|
||||
}
|
||||
|
||||
public void createProfile() {
|
||||
try {
|
||||
File profilesDirectory = getDirectory();
|
||||
String path = profilesDirectory.getAbsolutePath() + "/";
|
||||
|
||||
String profileName = "Profile 1";
|
||||
File profile = new File(path + profileName + ".txt");
|
||||
|
||||
for (int i = 1; profile.exists(); i++) {
|
||||
profileName = "Profile " + i;
|
||||
profile = new File(path + profileName + ".txt");
|
||||
}
|
||||
|
||||
if (profile.createNewFile())
|
||||
System.out.println("Profile was created successfully.");
|
||||
|
||||
writeOptionsFileToProfile(profileName);
|
||||
} catch (IOException e) {
|
||||
System.out.println("An error occurred when creating a profile.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void writeOptionsFileToProfile(String profileName) {
|
||||
try {
|
||||
File profilesDirectory = getDirectory();
|
||||
String path = profilesDirectory.getAbsolutePath() + "/";
|
||||
|
||||
File options = new File("options.txt");
|
||||
File profile = new File(path + profileName + ".txt");
|
||||
|
||||
Scanner reader = new Scanner(options);
|
||||
FileWriter writer = new FileWriter(profile);
|
||||
|
||||
while (reader.hasNextLine()) {
|
||||
String data = reader.nextLine();
|
||||
writer.write(data);
|
||||
writer.write("\n");
|
||||
}
|
||||
|
||||
writer.close();
|
||||
reader.close();
|
||||
|
||||
// Sodium
|
||||
// The code below doesn't work
|
||||
// if (FabricLoader.getInstance().isModLoaded("sodium")) {
|
||||
// System.out.println("Found Sodium in mods.");
|
||||
//
|
||||
// File sodiumOptions = new File("config/sodium-options.json");
|
||||
// File sodiumOptionsProfile = new File(path + profileName + "-sodium-options" + ".json");
|
||||
//
|
||||
// if (sodiumOptionsProfile.createNewFile())
|
||||
// System.out.println("Sodium Options Profile was created successfully.");
|
||||
//
|
||||
// Scanner sodiumOptionsReader = new Scanner(sodiumOptions);
|
||||
// FileWriter sodiumOptionsWriter = new FileWriter(sodiumOptionsProfile);
|
||||
//
|
||||
// while (sodiumOptionsReader.hasNextLine()) {
|
||||
// String data = sodiumOptionsReader.nextLine();
|
||||
// sodiumOptionsWriter.write(data);
|
||||
// sodiumOptionsWriter.write("\n");
|
||||
// }
|
||||
//
|
||||
// sodiumOptionsWriter.close();
|
||||
// sodiumOptionsReader.close();
|
||||
// }
|
||||
} catch (IOException e) {
|
||||
System.out.println("An error occurred when writing a profile.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public void editProfile(String profileName, String newProfileName) {
|
||||
File profilesDirectory = getDirectory();
|
||||
String path = profilesDirectory.getAbsolutePath() + "/";
|
||||
|
||||
File profile = new File(path + profileName + ".txt");
|
||||
File newProfile = new File(path + newProfileName + ".txt");
|
||||
|
||||
if (newProfile.exists())
|
||||
System.out.println("New profile already exists!");
|
||||
|
||||
if (!profile.renameTo(newProfile))
|
||||
System.out.println("Profile was not renamed successfully.");
|
||||
|
||||
// Sodium
|
||||
// The code below doesn't work
|
||||
// if (FabricLoader.getInstance().isModLoaded("sodium")) {
|
||||
// File sodiumOptionsProfile = new File(path + profileName + "-sodium-options" + ".json");
|
||||
// File newSodiumOptionsProfile = new File(path + newProfileName + "-sodium-options" + ".json");
|
||||
//
|
||||
// if (newSodiumOptionsProfile.exists())
|
||||
// System.out.println("New Sodium options profile already exists!");
|
||||
//
|
||||
// if (!sodiumOptionsProfile.renameTo(newSodiumOptionsProfile))
|
||||
// System.out.println("Sodium options profile was not renamed successfully.");
|
||||
// }
|
||||
}
|
||||
|
||||
public void deleteProfile(String profileName) {
|
||||
File profilesDirectory = getDirectory();
|
||||
String path = profilesDirectory.getAbsolutePath() + "/";
|
||||
|
||||
File profile = new File(path + profileName + ".txt");
|
||||
|
||||
if (!profile.delete())
|
||||
System.out.println("Profile was not deleted successfully.");
|
||||
}
|
||||
|
||||
public void overwriteOptionsFile(String profileName) {
|
||||
try {
|
||||
File profilesDirectory = getDirectory();
|
||||
String path = profilesDirectory.getAbsolutePath() + "/";
|
||||
|
||||
File options = new File("options.txt");
|
||||
File profile = new File(path + profileName + ".txt");
|
||||
|
||||
Scanner reader = new Scanner(profile);
|
||||
FileWriter writer = new FileWriter(options);
|
||||
new FileWriter(options, false).close();
|
||||
|
||||
while (reader.hasNextLine()) {
|
||||
String data = reader.nextLine();
|
||||
writer.write(data);
|
||||
writer.write("\n");
|
||||
}
|
||||
|
||||
writer.close();
|
||||
reader.close();
|
||||
|
||||
// Sodium
|
||||
// The code below doesn't work
|
||||
// if (FabricLoader.getInstance().isModLoaded("sodium")) {
|
||||
// System.out.println("Found Sodium in mods.");
|
||||
//
|
||||
// File sodiumOptions = new File("config/sodium-options.json");
|
||||
// File sodiumOptionsProfile = new File(path + profileName + "-sodium-options" + ".json");
|
||||
//
|
||||
// Scanner sodiumOptionsReader = new Scanner(sodiumOptionsProfile);
|
||||
// FileWriter sodiumOptionsWriter = new FileWriter(sodiumOptions);
|
||||
//
|
||||
// while (sodiumOptionsReader.hasNextLine()) {
|
||||
// String data = sodiumOptionsReader.nextLine();
|
||||
// sodiumOptionsWriter.write(data);
|
||||
// sodiumOptionsWriter.write("\n");
|
||||
// }
|
||||
//
|
||||
// sodiumOptionsWriter.close();
|
||||
// sodiumOptionsReader.close();
|
||||
// }
|
||||
} catch (IOException e) {
|
||||
System.out.println("An error occurred when creating a profile.");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
package dev.axolotlmaid.optionsprofiles.gui;
|
||||
|
||||
import dev.axolotlmaid.optionsprofiles.Profiles;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.client.gui.widget.TextFieldWidget;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.screen.ScreenTexts;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
public class EditProfileScreen extends Screen {
|
||||
private final Screen parent;
|
||||
private final Text profileName;
|
||||
|
||||
public EditProfileScreen(Screen parent, Text profileName) {
|
||||
super(Text.translatable("gui.options-profiles.edit-profiles-screen-text"));
|
||||
this.parent = parent;
|
||||
this.profileName = profileName;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
TextFieldWidget textfield = new TextFieldWidget(textRenderer, this.width / 2 - 102, this.height / 4 + 24, 204, 20, Text.translatable("profile-name-text-field"));
|
||||
this.addDrawableChild(textfield);
|
||||
|
||||
this.addDrawableChild(new ButtonWidget(this.width / 2 - 50, this.height / 4 + 50, 100, 20, Text.translatable("gui.options-profiles.update-profile-text"), (button) -> {
|
||||
new Profiles().writeOptionsFileToProfile(profileName.getString());
|
||||
this.client.setScreen(this.parent);
|
||||
}));
|
||||
|
||||
this.addDrawableChild(new ButtonWidget(this.width / 2 - 100, this.height - 65, 200, 20, Text.translatable("gui.options-profiles.save-profile-text"), (button) -> {
|
||||
new Profiles().editProfile(profileName.getString(), textfield.getText());
|
||||
this.client.setScreen(this.parent);
|
||||
}));
|
||||
|
||||
this.addDrawableChild(new ButtonWidget(this.width / 2 - 100, this.height - 40, 200, 20, ScreenTexts.CANCEL, (button) -> {
|
||||
this.client.setScreen(this.parent);
|
||||
}));
|
||||
|
||||
this.addDrawableChild(new ButtonWidget(5, this.height - 25, 100, 20, Text.translatable("gui.options-profiles.delete-profile-text"), (button) -> {
|
||||
new Profiles().deleteProfile(profileName.getString());
|
||||
this.client.setScreen(this.parent);
|
||||
}));
|
||||
}
|
||||
|
||||
public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
||||
this.renderBackground(matrices);
|
||||
drawCenteredText(matrices, this.textRenderer, Text.of(this.title.getString() + profileName.getString()), this.width / 2 , 8, 16777215);
|
||||
drawCenteredText(matrices, this.textRenderer, "Profile Name", this.width / 2 - 70, this.height / 4 + 10, 16777215);
|
||||
super.render(matrices, mouseX, mouseY, delta);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
package dev.axolotlmaid.optionsprofiles.gui;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import dev.axolotlmaid.optionsprofiles.Profiles;
|
||||
import net.fabricmc.api.EnvType;
|
||||
import net.fabricmc.api.Environment;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.font.TextRenderer;
|
||||
import net.minecraft.client.gui.Element;
|
||||
import net.minecraft.client.gui.Selectable;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.client.gui.widget.ElementListWidget;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.text.Text;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.*;
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class ProfilesListWidget extends ElementListWidget<ProfilesListWidget.Entry> {
|
||||
final ProfilesScreen parent;
|
||||
|
||||
public void refreshEntries() {
|
||||
File profilesDirectory = new Profiles().getDirectory();
|
||||
|
||||
this.clearEntries();
|
||||
|
||||
for (File profile : Objects.requireNonNull(profilesDirectory.listFiles())) {
|
||||
String profileName = FilenameUtils.removeExtension(profile.getName());
|
||||
|
||||
// Sodium
|
||||
// This code doesn't work yet
|
||||
// if (!(profileName.contains("-sodium-options"))) {
|
||||
// this.addEntry(new ProfilesListWidget.ProfileEntry(Text.of(profileName)));
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
public ProfilesListWidget(ProfilesScreen parent, MinecraftClient client) {
|
||||
super(client, parent.width + 45, parent.height, 20, parent.height - 32, 20);
|
||||
this.parent = parent;
|
||||
|
||||
refreshEntries();
|
||||
}
|
||||
|
||||
protected int getScrollbarPositionX() {
|
||||
return super.getScrollbarPositionX() + 15;
|
||||
}
|
||||
|
||||
public int getRowWidth() {
|
||||
return super.getRowWidth() + 32;
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public class ProfileEntry extends ProfilesListWidget.Entry {
|
||||
private final ButtonWidget editButton;
|
||||
private final ButtonWidget loadButton;
|
||||
private final Text profileName;
|
||||
|
||||
ProfileEntry(final Text profileName) {
|
||||
this.profileName = profileName;
|
||||
this.editButton = new ButtonWidget(0, 0, 75, 20, Text.translatable("gui.options-profiles.edit-profile-text"), (button) -> {
|
||||
ProfilesListWidget.this.client.setScreen(new EditProfileScreen(parent, profileName));
|
||||
});
|
||||
this.loadButton = new ButtonWidget(0, 0, 75, 20, Text.translatable("gui.options-profiles.load-profile-text"), (button) -> {
|
||||
new Profiles().overwriteOptionsFile(profileName.getString());
|
||||
|
||||
client.options.load();
|
||||
client.worldRenderer.reload();
|
||||
client.getSoundManager().reloadSounds();
|
||||
});
|
||||
}
|
||||
|
||||
public void render(MatrixStack matrices, int index, int y, int x, int entryWidth, int entryHeight, int mouseX, int mouseY, boolean hovered, float tickDelta) {
|
||||
TextRenderer var10000 = ProfilesListWidget.this.client.textRenderer;
|
||||
|
||||
int var10004 = y + entryHeight / 2;
|
||||
|
||||
Objects.requireNonNull(ProfilesListWidget.this.client.textRenderer);
|
||||
var10000.draw(matrices, profileName, x, (float)(var10004 - 9 / 2), 16777215);
|
||||
|
||||
this.editButton.x = x + 115;
|
||||
this.editButton.y = y;
|
||||
this.editButton.render(matrices, mouseX, mouseY, tickDelta);
|
||||
|
||||
this.loadButton.x = x + 190;
|
||||
this.loadButton.y = y;
|
||||
this.loadButton.render(matrices, mouseX, mouseY, tickDelta);
|
||||
}
|
||||
|
||||
public List<? extends Element> children() {
|
||||
return ImmutableList.of(this.editButton, this.loadButton);
|
||||
}
|
||||
|
||||
public List<? extends Selectable> selectableChildren() {
|
||||
return ImmutableList.of(this.editButton, this.loadButton);
|
||||
}
|
||||
|
||||
public boolean mouseClicked(double mouseX, double mouseY, int button) {
|
||||
if (this.editButton.mouseClicked(mouseX, mouseY, button)) {
|
||||
return true;
|
||||
} else {
|
||||
return this.loadButton.mouseClicked(mouseX, mouseY, button);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean mouseReleased(double mouseX, double mouseY, int button) {
|
||||
return this.editButton.mouseReleased(mouseX, mouseY, button) || this.loadButton.mouseReleased(mouseX, mouseY, button);
|
||||
}
|
||||
}
|
||||
|
||||
@Environment(EnvType.CLIENT)
|
||||
public abstract static class Entry extends ElementListWidget.Entry<Entry> {
|
||||
public Entry() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
package dev.axolotlmaid.optionsprofiles.gui;
|
||||
|
||||
import dev.axolotlmaid.optionsprofiles.Profiles;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.client.util.math.MatrixStack;
|
||||
import net.minecraft.screen.ScreenTexts;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
public class ProfilesScreen extends Screen {
|
||||
private final Screen parent;
|
||||
private ProfilesListWidget profilesList;
|
||||
|
||||
public ProfilesScreen(Screen parent) {
|
||||
super(Text.translatable("gui.options-profiles.profiles-menu-text"));
|
||||
this.parent = parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void init() {
|
||||
this.profilesList = new ProfilesListWidget(this, this.client);
|
||||
this.addSelectableChild(this.profilesList);
|
||||
|
||||
// Bottom Buttons
|
||||
this.addDrawableChild(new ButtonWidget(this.width / 2 - 155, this.height - 29, 150, 20, Text.translatable("gui.options-profiles.save-current-options"), (button -> {
|
||||
new Profiles().createProfile();
|
||||
this.profilesList.refreshEntries();
|
||||
})));
|
||||
this.addDrawableChild(new ButtonWidget(this.width / 2 - 155 + 160, this.height - 29, 150, 20, ScreenTexts.DONE, (button) -> {
|
||||
this.client.setScreen(this.parent);
|
||||
}));
|
||||
}
|
||||
|
||||
public void render(MatrixStack matrices, int mouseX, int mouseY, float delta) {
|
||||
this.renderBackground(matrices);
|
||||
this.profilesList.render(matrices, mouseX, mouseY, delta);
|
||||
drawCenteredText(matrices, this.textRenderer, this.title, this.width / 2, 8, 16777215);
|
||||
super.render(matrices, mouseX, mouseY, delta);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package dev.axolotlmaid.optionsprofiles.mixin;
|
||||
|
||||
import dev.axolotlmaid.optionsprofiles.gui.ProfilesScreen;
|
||||
import net.minecraft.client.MinecraftClient;
|
||||
import net.minecraft.client.gui.screen.Screen;
|
||||
import net.minecraft.client.gui.screen.option.ControlsOptionsScreen;
|
||||
import net.minecraft.client.gui.screen.option.OptionsScreen;
|
||||
import net.minecraft.client.gui.widget.ButtonWidget;
|
||||
import net.minecraft.text.Text;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(OptionsScreen.class)
|
||||
public class OptionsScreenMixin extends Screen {
|
||||
protected OptionsScreenMixin(Text title) {
|
||||
super(title);
|
||||
}
|
||||
|
||||
@Inject(at = @At("TAIL"), method = "init")
|
||||
private void init(CallbackInfo info) {
|
||||
MinecraftClient minecraft = MinecraftClient.getInstance();
|
||||
this.addDrawableChild(new ButtonWidget(5, 5, 100, 20, Text.translatable("gui.options-profiles.profiles-menu-text"), (button -> {
|
||||
minecraft.setScreen(new ProfilesScreen(this));
|
||||
})));
|
||||
}
|
||||
}
|
||||
BIN
src/main/resources/assets/options-profiles/icon.png
Normal file
BIN
src/main/resources/assets/options-profiles/icon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.6 KiB |
10
src/main/resources/assets/options-profiles/lang/en_us.json
Normal file
10
src/main/resources/assets/options-profiles/lang/en_us.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"gui.options-profiles.profiles-menu-text": "Profiles Menu",
|
||||
"gui.options-profiles.edit-profiles-screen-text": "Editing Profile: ",
|
||||
"gui.options-profiles.delete-profile-text": "Delete Profile",
|
||||
"gui.options-profiles.save-profile-text": "Save Profile",
|
||||
"gui.options-profiles.update-profile-text": "Update Profile",
|
||||
"gui.options-profiles.save-current-options": "Save Current Options",
|
||||
"gui.options-profiles.load-profile-text": "Load",
|
||||
"gui.options-profiles.edit-profile-text": "Edit"
|
||||
}
|
||||
33
src/main/resources/fabric.mod.json
Normal file
33
src/main/resources/fabric.mod.json
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
{
|
||||
"schemaVersion": 1,
|
||||
"id": "options-profiles",
|
||||
"version": "${version}",
|
||||
"name": "Options Profiles",
|
||||
"description": "A Minecraft mod that lets you load and save your options from in-game.",
|
||||
"authors": [
|
||||
"AxolotlMaid"
|
||||
],
|
||||
"contact": {
|
||||
"homepage": "https://github.com/AxolotlMaid/options-profiles",
|
||||
"sources": "https://github.com/AxolotlMaid/options-profiles"
|
||||
},
|
||||
"license": "CC0-1.0",
|
||||
"icon": "assets/options-profiles/icon.png",
|
||||
"environment": "*",
|
||||
"entrypoints": {
|
||||
"main": [
|
||||
"dev.axolotlmaid.optionsprofiles.OptionsProfilesMod"
|
||||
]
|
||||
},
|
||||
"mixins": [
|
||||
"options-profiles.mixins.json"
|
||||
],
|
||||
"depends": {
|
||||
"fabricloader": ">=0.14.19",
|
||||
"minecraft": "~1.19",
|
||||
"java": ">=17"
|
||||
},
|
||||
"suggests": {
|
||||
"fabric-api": "*"
|
||||
}
|
||||
}
|
||||
11
src/main/resources/options-profiles.mixins.json
Normal file
11
src/main/resources/options-profiles.mixins.json
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"required": true,
|
||||
"package": "dev.axolotlmaid.optionsprofiles.mixin",
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"mixins": [
|
||||
"OptionsScreenMixin"
|
||||
],
|
||||
"injectors": {
|
||||
"defaultRequire": 1
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue