Initial commit

This commit is contained in:
AxolotlMaid 2023-04-23 10:49:17 +01:00
commit 7e5a9af3fe
23 changed files with 1649 additions and 0 deletions

View file

@ -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() {}
}

View 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();
}
}
}

View file

@ -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);
}
}

View file

@ -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() {
}
}
}

View file

@ -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);
}
}

View file

@ -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));
})));
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

View 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"
}

View 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": "*"
}
}

View file

@ -0,0 +1,11 @@
{
"required": true,
"package": "dev.axolotlmaid.optionsprofiles.mixin",
"compatibilityLevel": "JAVA_17",
"mixins": [
"OptionsScreenMixin"
],
"injectors": {
"defaultRequire": 1
}
}