feat: profiles for specific servers (#43)
This commit is contained in:
parent
8859e89ae0
commit
6b07a052f4
7 changed files with 114 additions and 60 deletions
|
|
@ -47,19 +47,7 @@ public class Keybinds {
|
||||||
|
|
||||||
ProfileConfiguration profileConfiguration = ProfileConfiguration.get(profileName);
|
ProfileConfiguration profileConfiguration = ProfileConfiguration.get(profileName);
|
||||||
if (profileConfiguration.getKeybindIndex() == keybindIndex) {
|
if (profileConfiguration.getKeybindIndex() == keybindIndex) {
|
||||||
Minecraft minecraft = Minecraft.getInstance();
|
|
||||||
|
|
||||||
Profiles.loadProfile(profileName);
|
Profiles.loadProfile(profileName);
|
||||||
minecraft.options.load();
|
|
||||||
|
|
||||||
if (ProfileConfiguration.get(profileName).getOptionsToLoad().contains("resourcePacks")) {
|
|
||||||
minecraft.options.loadSelectedResourcePacks(minecraft.getResourcePackRepository());
|
|
||||||
minecraft.reloadResourcePacks();
|
|
||||||
}
|
|
||||||
|
|
||||||
minecraft.options.save();
|
|
||||||
minecraft.levelRenderer.allChanged();
|
|
||||||
|
|
||||||
OptionsProfilesMod.LOGGER.warn("[Profile '{}']: Loaded through keybind", profileName);
|
OptionsProfilesMod.LOGGER.warn("[Profile '{}']: Loaded through keybind", profileName);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,22 @@
|
||||||
package net.trafficlunar.optionsprofiles;
|
package net.trafficlunar.optionsprofiles;
|
||||||
|
|
||||||
import dev.architectury.event.events.client.ClientLifecycleEvent;
|
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 net.trafficlunar.optionsprofiles.profiles.Profiles;
|
||||||
import org.apache.logging.log4j.LogManager;
|
import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.net.InetSocketAddress;
|
||||||
|
import java.net.SocketAddress;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public class OptionsProfilesMod {
|
public class OptionsProfilesMod {
|
||||||
public static final String MOD_ID = "optionsprofiles";
|
public static final String MOD_ID = "optionsprofiles";
|
||||||
|
|
@ -30,9 +38,33 @@ public class OptionsProfilesMod {
|
||||||
// Load mod config
|
// Load mod config
|
||||||
CONFIG = OptionsProfilesModConfiguration.load();
|
CONFIG = OptionsProfilesModConfiguration.load();
|
||||||
|
|
||||||
// Init profiles (for loading on startup)
|
// Load profiles marked to load on startup
|
||||||
ClientLifecycleEvent.CLIENT_STARTED.register(client -> {
|
ClientLifecycleEvent.CLIENT_STARTED.register(client -> {
|
||||||
Profiles.init();
|
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();
|
Keybinds.init();
|
||||||
|
|
@ -46,4 +78,38 @@ public class OptionsProfilesMod {
|
||||||
return CONFIG;
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ public class EditProfileScreen extends Screen {
|
||||||
private final Component profileName;
|
private final Component profileName;
|
||||||
private final ProfileConfiguration profileConfiguration;
|
private final ProfileConfiguration profileConfiguration;
|
||||||
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()));
|
||||||
|
|
@ -33,11 +34,19 @@ 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.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(6), LayoutSettings::alignHorizontallyCenter);
|
LinearLayout linearLayoutEditBox = linearLayoutContent.addChild(LinearLayout.vertical().spacing(3), LayoutSettings::alignHorizontallyCenter);
|
||||||
linearLayoutEditBox.addChild(new StringWidget(Component.translatable("gui.optionsprofiles.profile-name-text"), this.font), LayoutSettings::alignHorizontallyCenter);
|
linearLayoutEditBox.addChild(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(
|
||||||
|
|
@ -128,8 +137,10 @@ public class EditProfileScreen extends Screen {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onClose(boolean deleted) {
|
public void onClose(boolean deleted) {
|
||||||
if (!deleted)
|
if (!deleted) {
|
||||||
|
this.profileConfiguration.setServers(this.serversEdit.getValue());
|
||||||
this.profileConfiguration.save();
|
this.profileConfiguration.save();
|
||||||
|
}
|
||||||
this.minecraft.setScreen(this.profilesScreen);
|
this.minecraft.setScreen(this.profilesScreen);
|
||||||
this.profilesScreen.profilesList.refreshEntries();
|
this.profilesScreen.profilesList.refreshEntries();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -84,16 +84,7 @@ public class ProfilesList extends ContainerObjectSelectionList<ProfilesList.Prof
|
||||||
Component.translatable("gui.optionsprofiles.load-profile"),
|
Component.translatable("gui.optionsprofiles.load-profile"),
|
||||||
(button) -> {
|
(button) -> {
|
||||||
Profiles.loadProfile(profileName.getString());
|
Profiles.loadProfile(profileName.getString());
|
||||||
|
OptionsProfilesMod.LOGGER.warn("[Profile '{}']: Loaded through button", profileName);
|
||||||
minecraft.options.load();
|
|
||||||
|
|
||||||
if (ProfileConfiguration.get(profileName.getString()).getOptionsToLoad().contains("resourcePacks")) {
|
|
||||||
minecraft.options.loadSelectedResourcePacks(minecraft.getResourcePackRepository());
|
|
||||||
minecraft.reloadResourcePacks();
|
|
||||||
}
|
|
||||||
|
|
||||||
minecraft.options.save();
|
|
||||||
minecraft.levelRenderer.allChanged();
|
|
||||||
|
|
||||||
// ProfilesList.this.checkEntriesLoaded();
|
// ProfilesList.this.checkEntriesLoaded();
|
||||||
// button.active = false;
|
// button.active = false;
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ public class ProfileConfiguration {
|
||||||
private static String profileName;
|
private static String profileName;
|
||||||
|
|
||||||
private boolean loadOnStartup = false;
|
private boolean loadOnStartup = false;
|
||||||
|
private String servers = "";
|
||||||
private int keybindIndex = 0;
|
private int keybindIndex = 0;
|
||||||
private List<String> optionsToLoad = new ArrayList<>();
|
private List<String> optionsToLoad = new ArrayList<>();
|
||||||
|
|
||||||
|
|
@ -79,4 +80,12 @@ public class ProfileConfiguration {
|
||||||
public void setOptionsToLoad(List<String> optionsToLoad) {
|
public void setOptionsToLoad(List<String> optionsToLoad) {
|
||||||
this.optionsToLoad = optionsToLoad;
|
this.optionsToLoad = optionsToLoad;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getServers() {
|
||||||
|
return servers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setServers(String servers) {
|
||||||
|
this.servers = servers;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,8 +14,9 @@ import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.nio.file.StandardCopyOption;
|
import java.nio.file.StandardCopyOption;
|
||||||
import java.util.*;
|
import java.util.HashMap;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
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;
|
||||||
|
|
||||||
|
|
@ -28,35 +29,7 @@ public class Profiles {
|
||||||
public static final Path IRIS_OPTIONS_FILE = Paths.get("config/iris.properties");
|
public static final Path IRIS_OPTIONS_FILE = Paths.get("config/iris.properties");
|
||||||
public static final Path DISTANT_HORIZONS_OPTIONS_FILE = Paths.get("config/DistantHorizons.toml");
|
public static final Path DISTANT_HORIZONS_OPTIONS_FILE = Paths.get("config/DistantHorizons.toml");
|
||||||
|
|
||||||
public static void init() {
|
private static final Minecraft minecraft = Minecraft.getInstance();
|
||||||
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);
|
|
||||||
if (profileConfiguration.shouldLoadOnStartup()) {
|
|
||||||
Minecraft minecraft = Minecraft.getInstance();
|
|
||||||
loadProfile(profileName);
|
|
||||||
|
|
||||||
minecraft.options.load();
|
|
||||||
|
|
||||||
if (ProfileConfiguration.get(profileName).getOptionsToLoad().contains("resourcePacks")) {
|
|
||||||
minecraft.options.loadSelectedResourcePacks(minecraft.getResourcePackRepository());
|
|
||||||
minecraft.reloadResourcePacks();
|
|
||||||
}
|
|
||||||
|
|
||||||
minecraft.options.save();
|
|
||||||
minecraft.levelRenderer.allChanged();
|
|
||||||
|
|
||||||
OptionsProfilesMod.LOGGER.info("[Profile '{}']: Loaded on startup", profileName);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
} catch (IOException e) {
|
|
||||||
OptionsProfilesMod.LOGGER.error("An error occurred when initializing", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void createProfile() {
|
public static void createProfile() {
|
||||||
String profileName = "Profile 1";
|
String profileName = "Profile 1";
|
||||||
|
|
@ -145,7 +118,7 @@ public class Profiles {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean isProfileLoaded(String profileName) {
|
// public static boolean isProfileLoaded(String profileName) {
|
||||||
// TODO: rewrite/fix; returns incorrect results
|
// TODO: rewrite/fix; returns incorrect results
|
||||||
|
|
||||||
// Path profile = PROFILES_DIRECTORY.resolve(profileName);
|
// Path profile = PROFILES_DIRECTORY.resolve(profileName);
|
||||||
|
|
@ -198,8 +171,8 @@ public class Profiles {
|
||||||
// return false;
|
// return false;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
private static void loadOptionFile(String profileName, Path options) {
|
private static void loadOptionFile(String profileName, Path options) {
|
||||||
ProfileConfiguration profileConfiguration = ProfileConfiguration.get(profileName);
|
ProfileConfiguration profileConfiguration = ProfileConfiguration.get(profileName);
|
||||||
|
|
@ -294,6 +267,17 @@ public class Profiles {
|
||||||
loadOptionFile(profileName, DISTANT_HORIZONS_OPTIONS_FILE); // Overwrite / load original Disant Horizons option file
|
loadOptionFile(profileName, DISTANT_HORIZONS_OPTIONS_FILE); // Overwrite / load original Disant Horizons option file
|
||||||
loadOptionFile(profileName, DISTANT_HORIZONS_OPTIONS_FILE, DistantHorizonsLoader::load); // Tell Distant Horizons mod to reload configuration
|
loadOptionFile(profileName, DISTANT_HORIZONS_OPTIONS_FILE, DistantHorizonsLoader::load); // Tell Distant Horizons mod to reload configuration
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reload Minecraft options
|
||||||
|
minecraft.options.load();
|
||||||
|
|
||||||
|
if (ProfileConfiguration.get(profileName).getOptionsToLoad().contains("resourcePacks")) {
|
||||||
|
minecraft.options.loadSelectedResourcePacks(minecraft.getResourcePackRepository());
|
||||||
|
minecraft.reloadResourcePacks();
|
||||||
|
}
|
||||||
|
|
||||||
|
minecraft.options.save();
|
||||||
|
minecraft.levelRenderer.allChanged();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void renameProfile(String profileName, String newProfileName) {
|
public static void renameProfile(String profileName, String newProfileName) {
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,11 @@
|
||||||
|
|
||||||
"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",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue