diff options
author | Cow <cow@volloeko.de> | 2020-07-05 05:42:45 +0200 |
---|---|---|
committer | Cow <cow@volloeko.de> | 2020-07-05 05:42:45 +0200 |
commit | 1b446698398c648b38311975a6cfd54859ea5cfe (patch) | |
tree | 521ecc4ce9ad968281094eb8c5453dca606931e3 /src/main/java/eu/olli/cowlection/config | |
parent | edaca1fd41a612c71c526ceb20b89c5dec2d81b3 (diff) | |
download | Cowlection-1b446698398c648b38311975a6cfd54859ea5cfe.tar.gz Cowlection-1b446698398c648b38311975a6cfd54859ea5cfe.tar.bz2 Cowlection-1b446698398c648b38311975a6cfd54859ea5cfe.zip |
Renamed mod to Cowlection
Bumped version to 1.8.9-0.7.0
Diffstat (limited to 'src/main/java/eu/olli/cowlection/config')
3 files changed, 389 insertions, 0 deletions
diff --git a/src/main/java/eu/olli/cowlection/config/MooConfig.java b/src/main/java/eu/olli/cowlection/config/MooConfig.java new file mode 100644 index 0000000..ff54ab9 --- /dev/null +++ b/src/main/java/eu/olli/cowlection/config/MooConfig.java @@ -0,0 +1,274 @@ +package eu.olli.cowlection.config; + +import eu.olli.cowlection.Cowlection; +import eu.olli.cowlection.util.Utils; +import net.minecraft.client.Minecraft; +import net.minecraft.util.EnumChatFormatting; +import net.minecraft.util.Util; +import net.minecraftforge.common.ForgeModContainer; +import net.minecraftforge.common.MinecraftForge; +import net.minecraftforge.common.config.Configuration; +import net.minecraftforge.common.config.Property; +import net.minecraftforge.fml.client.FMLConfigGuiFactory; +import net.minecraftforge.fml.client.event.ConfigChangedEvent; +import net.minecraftforge.fml.common.eventhandler.EventPriority; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; + +import java.io.File; +import java.time.LocalDate; +import java.time.format.DateTimeParseException; +import java.time.temporal.ChronoUnit; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.regex.Pattern; + +/** + * Mod configuration via ingame gui + * <p> + * Based on <a href="https://github.com/TheGreyGhost/MinecraftByExample/blob/1-8-9final/src/main/java/minecraftbyexample/mbe70_configuration/MBEConfiguration.java">TheGreyGhost's MinecraftByExample</a> + * + * @see ForgeModContainer + * @see FMLConfigGuiFactory + */ +public class MooConfig { + static final String CATEGORY_LOGS_SEARCH = "logssearch"; + // main config + public static boolean doUpdateCheck; + public static boolean showBestFriendNotifications; + public static boolean showFriendNotifications; + public static boolean showGuildNotifications; + public static boolean showAdvancedTooltips; + public static String[] tabCompletableNamesCommands; + private static String numeralSystem; + // logs search config + public static String[] logsDirs; + private static String defaultStartDate; + // other stuff + public static String moo; + private static Configuration cfg = null; + private final Cowlection main; + private List<String> propOrderGeneral; + private List<String> propOrderLogsSearch; + + public MooConfig(Cowlection main, Configuration configuration) { + this.main = main; + cfg = configuration; + initConfig(); + } + + static Configuration getConfig() { + return cfg; + } + + private void initConfig() { + syncFromFile(); + MinecraftForge.EVENT_BUS.register(new ConfigEventHandler()); + } + + /** + * Load the configuration values from the configuration file + */ + private void syncFromFile() { + syncConfig(true, true); + } + + /** + * Save the GUI-altered values to disk + */ + private void syncFromGui() { + syncConfig(false, true); + } + + /** + * Save the Configuration variables (fields) to disk + */ + public void syncFromFields() { + syncConfig(false, false); + } + + public static LocalDate calculateStartDate() { + try { + // date format: yyyy-mm-dd + return LocalDate.parse(defaultStartDate); + } catch (DateTimeParseException e) { + // fallthrough + } + try { + int months = Integer.parseInt(defaultStartDate); + return LocalDate.now().minus(months, ChronoUnit.MONTHS); + } catch (NumberFormatException e) { + // default: 1 month + return LocalDate.now().minus(1, ChronoUnit.MONTHS); + } + } + + /** + * Synchronise the three copies of the data + * 1) loadConfigFromFile && readFieldsFromConfig -> initialise everything from the disk file + * 2) !loadConfigFromFile && readFieldsFromConfig -> copy everything from the config file (altered by GUI) + * 3) !loadConfigFromFile && !readFieldsFromConfig -> copy everything from the native fields + * + * @param loadConfigFromFile if true, load the config field from the configuration file on disk + * @param readFieldsFromConfig if true, reload the member variables from the config field + */ + private void syncConfig(boolean loadConfigFromFile, boolean readFieldsFromConfig) { + if (loadConfigFromFile) { + cfg.load(); + } + + // config section: main configuration + propOrderGeneral = new ArrayList<>(); + + Property propDoUpdateCheck = addConfigEntry(cfg.get(Configuration.CATEGORY_CLIENT, + "doUpdateCheck", true, "Check for mod updates?"), true); + Property propShowBestFriendNotifications = addConfigEntry(cfg.get(Configuration.CATEGORY_CLIENT, + "showBestFriendNotifications", true, "Set to true to receive best friends' login/logout messages, set to false hide them."), true); + Property propShowFriendNotifications = addConfigEntry(cfg.get(Configuration.CATEGORY_CLIENT, + "showFriendNotifications", true, "Set to true to receive friends' login/logout messages, set to false hide them."), true); + Property propShowGuildNotifications = addConfigEntry(cfg.get(Configuration.CATEGORY_CLIENT, + "showGuildNotifications", true, "Set to true to receive guild members' login/logout messages, set to false hide them."), true); + Property propShowAdvancedTooltips = addConfigEntry(cfg.get(Configuration.CATEGORY_CLIENT, + "showAdvancedTooltips", true, "Set to true to show advanced tooltips, set to false show default tooltips."), true); + Property propNumeralSystem = addConfigEntry(cfg.get(Configuration.CATEGORY_CLIENT, + "numeralSystem", "Arabic numerals: 1, 4, 10", "Use Roman or Arabic numeral system?", new String[]{"Arabic numerals: 1, 4, 10", "Roman numerals: I, IV, X"}), true); + Property propTabCompletableNamesCommands = addConfigEntry(cfg.get(Configuration.CATEGORY_CLIENT, + "tabCompletableNamesCommands", new String[]{"party", "p", "invite", "visit", "ah", "ignore", "msg", "tell", "w", "boop", "profile"}, "List of commands with a Tab-completable username argument."), true) + .setValidationPattern(Pattern.compile("^[A-Za-z]+$")); + Property propMoo = addConfigEntry(cfg.get(Configuration.CATEGORY_CLIENT, + "moo", "", "The answer to life the universe and everything. Don't edit this entry manually!", Utils.VALID_UUID_PATTERN), false); + + cfg.setCategoryPropertyOrder(Configuration.CATEGORY_CLIENT, propOrderGeneral); + + // config section: log files search + propOrderLogsSearch = new ArrayList<>(); + + Property propLogsDirs = addConfigEntry(cfg.get(CATEGORY_LOGS_SEARCH, + "logsDirs", resolveDefaultLogsDirs(), + "Directories with Minecraft log files"), true, CATEGORY_LOGS_SEARCH); + Property propDefaultStartDate = addConfigEntry(cfg.get(CATEGORY_LOGS_SEARCH, + "defaultStartDate", "3", "Default start date (a number means X months ago, alternatively a fixed date à la yyyy-mm-dd can be used)"), true) + .setValidationPattern(Pattern.compile("^[1-9][0-9]{0,2}|(2[0-9]{3}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01]))$")); + + cfg.setCategoryPropertyOrder(CATEGORY_LOGS_SEARCH, propOrderLogsSearch); + + // 'manual' replacement for propTabCompletableNamesCommands.hasChanged() + boolean modifiedTabCompletableCommandsList = false; + String[] tabCompletableCommandsPreChange = tabCompletableNamesCommands != null ? tabCompletableNamesCommands.clone() : null; + if (readFieldsFromConfig) { + // main config + doUpdateCheck = propDoUpdateCheck.getBoolean(); + showBestFriendNotifications = propShowBestFriendNotifications.getBoolean(); + showFriendNotifications = propShowFriendNotifications.getBoolean(); + showGuildNotifications = propShowGuildNotifications.getBoolean(); + showAdvancedTooltips = propShowAdvancedTooltips.getBoolean(); + numeralSystem = propNumeralSystem.getString(); + tabCompletableNamesCommands = propTabCompletableNamesCommands.getStringList(); + moo = propMoo.getString(); + + // logs search config + logsDirs = propLogsDirs.getStringList(); + defaultStartDate = propDefaultStartDate.getString().trim(); + + if (!Arrays.equals(tabCompletableCommandsPreChange, tabCompletableNamesCommands)) { + modifiedTabCompletableCommandsList = true; + } + } + + // main config + propDoUpdateCheck.set(doUpdateCheck); + propShowBestFriendNotifications.set(showBestFriendNotifications); + propShowFriendNotifications.set(showFriendNotifications); + propShowGuildNotifications.set(showGuildNotifications); + propShowAdvancedTooltips.set(showAdvancedTooltips); + propNumeralSystem.set(numeralSystem); + propTabCompletableNamesCommands.set(tabCompletableNamesCommands); + propMoo.set(moo); + + // logs search config + propLogsDirs.set(logsDirs); + propDefaultStartDate.set(defaultStartDate); + + if (cfg.hasChanged()) { + if (modifiedTabCompletableCommandsList && Minecraft.getMinecraft().thePlayer != null) { + main.getChatHelper().sendMessage(EnumChatFormatting.RED, "Added or removed commands with tab-completable usernames take effect after a game restart!"); + } + cfg.save(); + } + } + + private Property addConfigEntry(Property property, boolean showInGui, String category) { + if (showInGui) { + property.setLanguageKey(Cowlection.MODID + ".config." + property.getName()); + } else { + property.setShowInGui(false); + } + + if (CATEGORY_LOGS_SEARCH.equals(category)) { + propOrderLogsSearch.add(property.getName()); + } else { + // == Configuration.CATEGORY_CLIENT: + propOrderGeneral.add(property.getName()); + } + return property; + } + + private Property addConfigEntry(Property property, boolean showInGui) { + return addConfigEntry(property, showInGui, Configuration.CATEGORY_CLIENT); + } + + /** + * Tries to find/resolve default directories containing minecraft logfiles (in .log.gz format) + * + * @return list of /logs/ directories + */ + private String[] resolveDefaultLogsDirs() { + List<String> logsDirs = new ArrayList<>(); + File currentMcLogsDirFile = new File(Minecraft.getMinecraft().mcDataDir, "logs"); + if (currentMcLogsDirFile.exists() && currentMcLogsDirFile.isDirectory()) { + String currentMcLogsDir = Utils.toRealPath(currentMcLogsDirFile); + logsDirs.add(currentMcLogsDir); + } + + String defaultMcLogsDir = System.getProperty("user.home"); + Util.EnumOS osType = Util.getOSType(); + // default directories for .minecraft: https://minecraft.gamepedia.com/.minecraft + switch (osType) { + case WINDOWS: + defaultMcLogsDir += "\\AppData\\Roaming\\.minecraft\\logs"; + break; + case OSX: + defaultMcLogsDir += "/Library/Application Support/minecraft/logs"; + break; + default: + defaultMcLogsDir += "/.minecraft/logs"; + } + File defaultMcLogsDirFile = new File(defaultMcLogsDir); + if (defaultMcLogsDirFile.exists() && defaultMcLogsDirFile.isDirectory() && !currentMcLogsDirFile.equals(defaultMcLogsDirFile)) { + logsDirs.add(Utils.toRealPath(defaultMcLogsDirFile)); + } + return logsDirs.toArray(new String[]{}); + } + + /** + * Should login/logout notifications be modified and thus monitored? + * + * @return true if notifications should be monitored + */ + public static boolean doMonitorNotifications() { + return showBestFriendNotifications || !showFriendNotifications || !showGuildNotifications; + } + + public static boolean useRomanNumerals() { + return numeralSystem.startsWith("Roman"); + } + + public class ConfigEventHandler { + @SubscribeEvent(priority = EventPriority.NORMAL) + public void onEvent(ConfigChangedEvent.OnConfigChangedEvent e) { + if (Cowlection.MODID.equals(e.modID)) { + syncFromGui(); + } + } + } +} diff --git a/src/main/java/eu/olli/cowlection/config/MooGuiConfig.java b/src/main/java/eu/olli/cowlection/config/MooGuiConfig.java new file mode 100644 index 0000000..3692e48 --- /dev/null +++ b/src/main/java/eu/olli/cowlection/config/MooGuiConfig.java @@ -0,0 +1,86 @@ +package eu.olli.cowlection.config; + +import eu.olli.cowlection.Cowlection; +import eu.olli.cowlection.search.GuiTooltip; +import eu.olli.cowlection.util.Utils; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; +import net.minecraft.client.gui.GuiTextField; +import net.minecraft.client.resources.I18n; +import net.minecraft.util.EnumChatFormatting; +import net.minecraftforge.common.config.ConfigElement; +import net.minecraftforge.common.config.Configuration; +import net.minecraftforge.fml.client.config.GuiConfig; +import net.minecraftforge.fml.client.config.GuiConfigEntries; +import net.minecraftforge.fml.client.config.IConfigElement; +import org.apache.commons.lang3.reflect.FieldUtils; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class MooGuiConfig extends GuiConfig { + private GuiTooltip defaultStartDateTooltip; + private GuiTextField textFieldDefaultStartDate; + private String defaultStartDateTooltipText; + + public MooGuiConfig(GuiScreen parent) { + super(parent, + getConfigElements(), + Cowlection.MODID, + false, + false, + EnumChatFormatting.BOLD + "Configuration for " + Cowlection.MODNAME); + titleLine2 = EnumChatFormatting.GRAY + Utils.toRealPath(MooConfig.getConfig().getConfigFile()); + } + + private static List<IConfigElement> getConfigElements() { + List<IConfigElement> list = new ArrayList<>(new ConfigElement(MooConfig.getConfig().getCategory(Configuration.CATEGORY_CLIENT)).getChildElements()); + list.addAll(new ConfigElement(MooConfig.getConfig().getCategory(MooConfig.CATEGORY_LOGS_SEARCH)).getChildElements()); + return list; + } + + @Override + public void initGui() { + super.initGui(); + // optional: add buttons and initialize fields + for (GuiConfigEntries.IConfigEntry configEntry : entryList.listEntries) { + if ("defaultStartDate".equals(configEntry.getName()) && configEntry instanceof GuiConfigEntries.StringEntry) { + GuiConfigEntries.StringEntry entry = (GuiConfigEntries.StringEntry) configEntry; + defaultStartDateTooltipText = I18n.format(configEntry.getConfigElement().getLanguageKey() + ".tooltip"); + try { + textFieldDefaultStartDate = (GuiTextField) FieldUtils.readField(entry, "textFieldValue", true); + defaultStartDateTooltip = null; + } catch (IllegalAccessException e) { + // wasn't able to access textField, abort drawing tooltip + return; + } + } + } + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + super.drawScreen(mouseX, mouseY, partialTicks); + // optional: create animations, draw additional elements, etc. + + // add tooltip to defaultStartDate textField + if (textFieldDefaultStartDate != null) { + if (defaultStartDateTooltip == null) { + if (textFieldDefaultStartDate.yPosition == 0) { + return; + } + // create GuiTooltip here instead in initGui because y-position of textField is 0 inside initGui + defaultStartDateTooltip = new GuiTooltip(textFieldDefaultStartDate, Arrays.asList(defaultStartDateTooltipText.split("\\\\n"))); + } else if (defaultStartDateTooltip.checkHover(mouseX, mouseY)) { + drawHoveringText(defaultStartDateTooltip.getText(), mouseX, mouseY, fontRendererObj); + } + } + } + + @Override + protected void actionPerformed(GuiButton button) { + super.actionPerformed(button); + // optional: process any additional buttons added in initGui + } +} diff --git a/src/main/java/eu/olli/cowlection/config/MooGuiFactory.java b/src/main/java/eu/olli/cowlection/config/MooGuiFactory.java new file mode 100644 index 0000000..f876ec5 --- /dev/null +++ b/src/main/java/eu/olli/cowlection/config/MooGuiFactory.java @@ -0,0 +1,29 @@ +package eu.olli.cowlection.config; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiScreen; +import net.minecraftforge.fml.client.IModGuiFactory; + +import java.util.Set; + +public class MooGuiFactory implements IModGuiFactory { + @Override + public void initialize(Minecraft minecraftInstance) { + + } + + @Override + public Class<? extends GuiScreen> mainConfigGuiClass() { + return MooGuiConfig.class; + } + + @Override + public Set<RuntimeOptionCategoryElement> runtimeGuiCategories() { + return null; + } + + @Override + public RuntimeOptionGuiHandler getHandlerFor(RuntimeOptionCategoryElement element) { + return null; + } +} |