diff --git a/README.md b/README.md index d99924b..7555116 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,56 @@ -# Extended Messages +# enhanmess -Minecraft Forge 1.8.9 mod that extends message length limit to 256 characters \ No newline at end of file +extends 100-character message limit of 1.8.9 up to 256 characters; queues regular messages & configured commands; adds long message splitting; increases default message history length; adds support for command & regular prefixes + +## usage + +to configure the mod execute `/em` (short for `/enhanmess`): + +![enhanmess settings gui](images/gui.png) + +or use commands instead: + +``` +/em toggle + +# message prefix +/em mp toggle +/em mp set + +# command prefix +/em cp toggle +/em cp set + +# message cooldown +/em mc set + +# command cooldown +/em cc set + +# history +/em h set +``` + +P.S. sending more than 100 chars in a single packet works only in singleplayer or on servers that support it, so message splitting is preferred + +## installation + +you can either install the `.jar` from the releases or build the mod yourself by cloning the repository and running: + +### windows + +```bat +.\gradlew.bat build +``` + +### linux + +```bash +./gradlew build +``` + +the built `.jar` will be inside `./build/libs` directory in both cases + +## contributions + +welcome \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts index 3d26f06..25cffad 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -12,10 +12,7 @@ plugins { val baseGroup: String by project val mcVersion: String by project -val version: String by project -val mixinGroup = "$baseGroup.mixin" val modid: String by project -val transformerFile = file("src/main/resources/accesstransformer.cfg") // Toolchains: java { @@ -34,7 +31,6 @@ tasks.withType().configureEach { loom { launchConfigs { "client" { - // If you don't want mixins, remove these lines property("mixin.debug", "true") arg("--tweakClass", "org.spongepowered.asm.launch.MixinTweaker") } @@ -52,10 +48,6 @@ loom { pack200Provider.set(dev.architectury.pack200.java.Pack200Adapter()) // If you don't want mixins, remove this lines mixinConfig("mixins.$modid.json") - if (transformerFile.exists()) { - println("Installing access transformer") - accessTransformer(transformerFile) - } } // If you don't want mixins, remove these lines mixin { @@ -103,7 +95,7 @@ tasks.withType(JavaCompile::class) { } tasks.withType(org.gradle.jvm.tasks.Jar::class) { - archiveBaseName.set(modid) + archiveBaseName.set("$modid-$mcVersion") manifest.attributes.run { this["FMLCorePluginContainsFMLMod"] = "true" this["ForceLoadAsMod"] = "true" @@ -111,8 +103,6 @@ tasks.withType(org.gradle.jvm.tasks.Jar::class) { // If you don't want mixins, remove these lines this["TweakClass"] = "org.spongepowered.asm.launch.MixinTweaker" this["MixinConfigs"] = "mixins.$modid.json" - if (transformerFile.exists()) - this["FMLAT"] = "${modid}_at.cfg" } } @@ -125,8 +115,6 @@ tasks.processResources { filesMatching(listOf("mcmod.info", "mixins.$modid.json")) { expand(inputs.properties) } - - rename("accesstransformer.cfg", "META-INF/${modid}_at.cfg") } @@ -150,9 +138,6 @@ tasks.shadowJar { println("Copying dependencies into mod: ${it.files}") } } - - // If you want to include other dependencies and shadow them, you can relocate them in here - fun relocate(name: String) = relocate(name, "$baseGroup.deps.$name") } tasks.assemble.get().dependsOn(tasks.remapJar) diff --git a/gradle.properties b/gradle.properties index c50b9cc..22a15be 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,6 +1,6 @@ loom.platform=forge org.gradle.jvmargs=-Xmx2g -baseGroup = com.github.cewko.extendedmessages +baseGroup = com.github.cewko.enhanmess mcVersion = 1.8.9 -modid = extendedmessages +modid = enhanmess version = 1.0.0 diff --git a/images/gui.png b/images/gui.png new file mode 100644 index 0000000..3b9ed9a Binary files /dev/null and b/images/gui.png differ diff --git a/settings.gradle.kts b/settings.gradle.kts index 5c52cd8..24d147f 100644 --- a/settings.gradle.kts +++ b/settings.gradle.kts @@ -23,4 +23,4 @@ plugins { } -rootProject.name = "extendedMessages" +rootProject.name = "enhanmess" diff --git a/src/main/java/com/github/cewko/enhanmess/EnhanMess.java b/src/main/java/com/github/cewko/enhanmess/EnhanMess.java new file mode 100644 index 0000000..e62f3f1 --- /dev/null +++ b/src/main/java/com/github/cewko/enhanmess/EnhanMess.java @@ -0,0 +1,254 @@ +package com.github.cewko.enhanmess; + +import com.github.cewko.enhanmess.config.EnhanMessConfig; +import com.github.cewko.enhanmess.messaging.MessageQueue; +import com.github.cewko.enhanmess.gui.GuiOpener; + +import net.minecraftforge.common.MinecraftForge; + +import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; +import net.minecraftforge.fml.common.Mod; +import net.minecraftforge.fml.common.event.FMLInitializationEvent; + +import net.minecraftforge.client.ClientCommandHandler; + +@Mod( + modid = Reference.MOD_ID, + name = Reference.NAME, + version = Reference.VERSION, + acceptedMinecraftVersions = Reference.ACCEPTED_VERSIONS, + clientSideOnly = true, + useMetadata = true +) +public class EnhanMess { + + private static boolean enabled = Reference.DEFAULT_ENABLED; + private static boolean splitEnabled = Reference.DEFAULT_SPLIT_ENABLED; + private static int messageDelaySeconds = Reference.DEFAULT_MESSAGE_DELAY_SECONDS; + private static int commandDelaySeconds = Reference.DEFAULT_COMMAND_DELAY_SECONDS; + + private static boolean messagePrefixEnabled = Reference.DEFAULT_MESSAGE_PREFIX_ENABLED; + private static String messagePrefix = Reference.DEFAULT_MESSAGE_PREFIX; + + private static boolean commandPrefixEnabled = Reference.DEFAULT_COMMAND_PREFIX_ENABLED; + private static String commandPrefix = Reference.DEFAULT_COMMAND_PREFIX; + + private static int messageHistoryLength = Reference.DEFAULT_MESSAGE_HISTORY_LENGTH; + + public static boolean isEnabled() { + return enabled; + } + + public static boolean isSplitEnabled() { + return splitEnabled; + } + + public static void setSplitEnabled(boolean value) { + if (splitEnabled == value) { + return; + } + + splitEnabled = value; + EnhanMessConfig.saveSplitEnabled(value); + + MessageQueue.getInstance().clear(); + } + + public static boolean toggleSplitEnabled() { + setSplitEnabled(!splitEnabled); + return splitEnabled; + } + + public static void setEnabled(boolean value) { + if (enabled == value) { + return; + } + + enabled = value; + EnhanMessConfig.saveEnabled(value); + + if (!enabled) { + MessageQueue.getInstance().clear(); + } + } + + public static boolean toggleEnabled() { + setEnabled(!enabled); + return enabled; + } + + public static int getMessageDelaySeconds() { + return messageDelaySeconds; + } + + public static void setMessageDelaySeconds(int seconds) { + SettingsValidation.validateDelaySeconds(seconds); + + if (messageDelaySeconds != seconds) { + messageDelaySeconds = seconds; + EnhanMessConfig.saveMessageDelaySeconds(seconds); + } + } + + public static int getCommandDelaySeconds() { + return commandDelaySeconds; + } + + public static void setCommandDelaySeconds(int seconds) { + SettingsValidation.validateDelaySeconds(seconds); + + if (commandDelaySeconds != seconds) { + commandDelaySeconds = seconds; + EnhanMessConfig.saveCommandDelaySeconds(seconds); + } + } + + public static boolean isMessagePrefixEnabled() { + return messagePrefixEnabled; + } + + public static String getMessagePrefix() { + return messagePrefix; + } + + public static boolean isCommandPrefixEnabled() { + return commandPrefixEnabled; + } + + public static String getCommandPrefix() { + return commandPrefix; + } + + public static void setMessagePrefixEnabled(boolean value) { + if (messagePrefixEnabled == value) { + return; + } + + messagePrefixEnabled = value; + EnhanMessConfig.saveMessagePrefixEnabled(value); + } + + public static boolean toggleMessagePrefixEnabled() { + setMessagePrefixEnabled(!messagePrefixEnabled); + return messagePrefixEnabled; + } + + public static void setMessagePrefix(String prefix) { + String normalized = SettingsValidation.normalizeMessagePrefix(prefix); + + if (!messagePrefix.equals(normalized)) { + messagePrefix = normalized; + EnhanMessConfig.saveMessagePrefix(normalized); + } + } + + public static void setCommandPrefixEnabled(boolean value) { + if (commandPrefixEnabled == value) { + return; + } + + commandPrefixEnabled = value; + EnhanMessConfig.saveCommandPrefixEnabled(value); + } + + public static boolean toggleCommandPrefixEnabled() { + setCommandPrefixEnabled(!commandPrefixEnabled); + return commandPrefixEnabled; + } + + public static void setCommandPrefix(String prefix) { + String normalized = SettingsValidation.normalizeCommandPrefix(prefix); + + if (!commandPrefix.equals(normalized)) { + commandPrefix = normalized; + EnhanMessConfig.saveCommandPrefix(normalized); + } + } + + public static int getCurrentMessageLimit() { + return enabled + ? Reference.EXTENDED_MESSAGE_LIMIT + : Reference.DEFAULT_MESSAGE_LIMIT; + } + + public static int getCurrentPacketMessageLimit() { + if (!enabled) { + return Reference.DEFAULT_MESSAGE_LIMIT; + } + + return splitEnabled + ? Reference.DEFAULT_MESSAGE_LIMIT + : Reference.EXTENDED_MESSAGE_LIMIT; + } + + public static int getMessageHistoryLength() { + return messageHistoryLength; + } + + public static void setMessageHistoryLength(int length) { + SettingsValidation.validateHistoryLength(length); + + if (messageHistoryLength != length) { + messageHistoryLength = length; + EnhanMessConfig.saveMessageHistoryLength(length); + } + } + + public static int getCurrentMessageHistoryLength() { + return enabled ? messageHistoryLength : Reference.VANILLA_MESSAGE_HISTORY_LENGTH; + } + + private static String loadMessagePrefix() { + try { + return SettingsValidation.normalizeMessagePrefix( + EnhanMessConfig.getMessagePrefix() + ); + } catch (IllegalArgumentException exception) { + return Reference.DEFAULT_MESSAGE_PREFIX; + } + } + + private static String loadCommandPrefix() { + try { + return SettingsValidation.normalizeCommandPrefix( + EnhanMessConfig.getCommandPrefix() + ); + } catch (IllegalArgumentException exception) { + return Reference.DEFAULT_COMMAND_PREFIX; + } + } + + @Mod.EventHandler + public void preInit(FMLPreInitializationEvent event) { + EnhanMessConfig.load(event.getSuggestedConfigurationFile()); + + enabled = EnhanMessConfig.getEnabled(); + splitEnabled = EnhanMessConfig.getSplitEnabled(); + + messageDelaySeconds = EnhanMessConfig.getMessageDelaySeconds(); + commandDelaySeconds = EnhanMessConfig.getCommandDelaySeconds(); + + messagePrefixEnabled = EnhanMessConfig.getMessagePrefixEnabled(); + commandPrefixEnabled = EnhanMessConfig.getCommandPrefixEnabled(); + + messagePrefix = loadMessagePrefix(); + commandPrefix = loadCommandPrefix(); + + EnhanMessConfig.saveMessagePrefix(messagePrefix); + EnhanMessConfig.saveCommandPrefix(commandPrefix); + + messageHistoryLength = EnhanMessConfig.getMessageHistoryLength(); + } + + @Mod.EventHandler + public void init(FMLInitializationEvent event) { + ClientCommandHandler.instance.registerCommand( + new EnhanMessCommand() + ); + + MinecraftForge.EVENT_BUS.register(MessageQueue.getInstance()); + MinecraftForge.EVENT_BUS.register(GuiOpener.getInstance()); + + System.out.println("[" + Reference.NAME + "] Mod has loaded :3"); + } +} diff --git a/src/main/java/com/github/cewko/enhanmess/EnhanMessCommand.java b/src/main/java/com/github/cewko/enhanmess/EnhanMessCommand.java new file mode 100644 index 0000000..3279a95 --- /dev/null +++ b/src/main/java/com/github/cewko/enhanmess/EnhanMessCommand.java @@ -0,0 +1,255 @@ +package com.github.cewko.enhanmess; + +import com.github.cewko.enhanmess.gui.GuiOpener; + +import java.util.Collections; +import java.util.List; +import java.util.function.BooleanSupplier; +import java.util.function.Consumer; +import java.util.function.IntConsumer; +import java.util.function.IntFunction; +import java.util.function.Supplier; + +import net.minecraft.command.CommandBase; +import net.minecraft.command.ICommandSender; +import net.minecraft.command.CommandException; +import net.minecraft.command.WrongUsageException; +import net.minecraft.util.ChatComponentText; +import net.minecraft.util.EnumChatFormatting; + +public final class EnhanMessCommand extends CommandBase { + private void handleIntSet( + ICommandSender sender, + String[] args, + String usage, + String displayName, + int min, + int max, + IntConsumer setter, + IntFunction formatter + ) throws CommandException { + if (args.length != 3 || !"set".equalsIgnoreCase(args[1])) { + throw new WrongUsageException(usage); + } + + int value = parseInt(args[2], min, max); + + try { + setter.accept(value); + } catch (IllegalArgumentException exception) { + throw new CommandException(exception.getMessage()); + } + + sendLine(sender, displayName + ": " + formatter.apply(value)); + } + + @Override + public String getCommandName() { + return Reference.COMMAND_NAME; + } + + @Override + public List getCommandAliases() { + return Collections.singletonList(Reference.COMMAND_ALIAS); + } + + @Override + public String getCommandUsage(ICommandSender sender) { + return "/em | /em toggle | /em mp >" + + " | /em cp >" + + " | /em mc set " + + " | /em cc set " + + " | /em h set "; + } + + @Override + public int getRequiredPermissionLevel() { + return 0; + } + + @Override + public void processCommand(ICommandSender sender, String[] args) + throws CommandException { + + if (args.length == 0) { + GuiOpener.getInstance().requestOpen(); + return; + } + + switch (args[0].toLowerCase()) { + case "toggle": + handleMainToggle(sender, args); + return; + case "mp": + handlePrefixSetting( + sender, + args, + "/em mp >", + "Message prefix", + EnhanMess::toggleMessagePrefixEnabled, + EnhanMess::setMessagePrefix, + EnhanMess::getMessagePrefix + ); + return; + case "cp": + handlePrefixSetting( + sender, + args, + "/em cp >", + "Command prefix", + EnhanMess::toggleCommandPrefixEnabled, + EnhanMess::setCommandPrefix, + EnhanMess::getCommandPrefix + ); + return; + case "mc": + handleIntSet( + sender, + args, + "/em mc set ", + "Message cooldown", + Reference.MIN_DELAY_SECONDS, + Reference.MAX_DELAY_SECONDS, + EnhanMess::setMessageDelaySeconds, + value -> EnumChatFormatting.AQUA + formatSeconds(value) + ); + return; + case "cc": + handleIntSet( + sender, + args, + "/em cc set ", + "Command cooldown", + Reference.MIN_DELAY_SECONDS, + Reference.MAX_DELAY_SECONDS, + EnhanMess::setCommandDelaySeconds, + value -> EnumChatFormatting.AQUA + formatSeconds(value) + ); + return; + case "h": + handleIntSet( + sender, + args, + "/em h set ", + "History length", + Reference.MIN_MESSAGE_HISTORY_LENGTH, + Reference.MAX_MESSAGE_HISTORY_LENGTH, + EnhanMess::setMessageHistoryLength, + value -> EnumChatFormatting.AQUA + + String.valueOf(value) + + EnumChatFormatting.GRAY + + " lines" + ); + return; + + default: + throw new WrongUsageException(getCommandUsage(sender)); + } + } + + private void handleMainToggle(ICommandSender sender, String[] args) + throws CommandException { + + if (args.length != 1) { + throw new WrongUsageException("/em toggle"); + } + + boolean enabled = EnhanMess.toggleEnabled(); + sendLine(sender, "Remove 100-character limit: " + formatState(enabled)); + } + + private void handlePrefixSetting( + ICommandSender sender, + String[] args, + String usage, + String displayName, + BooleanSupplier toggler, + Consumer setter, + Supplier getter + ) throws CommandException { + if (args.length < 2) { + throw new WrongUsageException(usage); + } + + switch (args[1].toLowerCase()) { + case "toggle": + if (args.length != 2) { + throw new WrongUsageException(usage); + } + + boolean enabled = toggler.getAsBoolean(); + sendLine(sender, displayName + ": " + formatState(enabled)); + return; + + case "set": + if (args.length < 3) { + throw new WrongUsageException(usage); + } + + handleTextSet(sender, args, displayName, setter, getter); + return; + + default: + throw new WrongUsageException(usage); + } + } + + private void handleTextSet( + ICommandSender sender, + String[] args, + String displayName, + Consumer setter, + Supplier getter + ) throws CommandException { + String value = joinArgs(args, 2); + String storedValue; + + try { + setter.accept(value); + storedValue = getter.get(); + } catch (IllegalArgumentException exception) { + throw new CommandException(exception.getMessage()); + } + + sendLine(sender, displayName + " set to " + formatValue(storedValue)); + } + + private String joinArgs(String[] args, int startIndex) { + StringBuilder result = new StringBuilder(); + + for (int i = startIndex; i < args.length; i++) { + if (i > startIndex) { + result.append(" "); + } + + result.append(args[i]); + } + + return result.toString(); + } + + private void sendLine(ICommandSender sender, String message) { + sender.addChatMessage(new ChatComponentText( + EnumChatFormatting.GRAY + + "[" + Reference.NAME + "] " + + message + )); + } + + private String formatState(boolean enabled) { + return enabled ? EnumChatFormatting.GREEN + "ON" : EnumChatFormatting.RED + "OFF"; + } + + private String formatSeconds(int seconds) { + return String.valueOf(seconds) + + EnumChatFormatting.GRAY + + (seconds == 1 ? " second" : " seconds"); + } + + private String formatValue(String value) { + if (value.isEmpty()) { + return EnumChatFormatting.DARK_GRAY + ""; + } + return EnumChatFormatting.AQUA + "\"" + value + "\""; + } +} diff --git a/src/main/java/com/github/cewko/extendedmessages/Reference.java b/src/main/java/com/github/cewko/enhanmess/Reference.java similarity index 50% rename from src/main/java/com/github/cewko/extendedmessages/Reference.java rename to src/main/java/com/github/cewko/enhanmess/Reference.java index 3e01757..d8c3f59 100644 --- a/src/main/java/com/github/cewko/extendedmessages/Reference.java +++ b/src/main/java/com/github/cewko/enhanmess/Reference.java @@ -1,22 +1,24 @@ -package com.github.cewko.extendedmessages; +package com.github.cewko.enhanmess; public final class Reference { - public static final String MOD_ID = "extendedmessages"; - public static final String NAME = "Extended Messages"; + public static final String MOD_ID = "enhanmess"; + public static final String NAME = "EnhanMess"; public static final String VERSION = "1.0.0"; public static final String ACCEPTED_VERSIONS = "[1.8.9]"; - public static final String COMMAND_NAME = "extendedmessages"; + public static final String COMMAND_NAME = "enhanmess"; public static final String COMMAND_ALIAS = "em"; public static final int DEFAULT_MESSAGE_LIMIT = 100; public static final int EXTENDED_MESSAGE_LIMIT = 256; - public static final int MIN_MESSAGE_DELAY_SECONDS = 1; - public static final int MAX_MESSAGE_DELAY_SECONDS = 30; + public static final int MIN_DELAY_SECONDS = 0; + public static final int MAX_DELAY_SECONDS = 120; public static final int DEFAULT_MESSAGE_DELAY_SECONDS = 3; + public static final int DEFAULT_COMMAND_DELAY_SECONDS = 1; + public static final long SEND_SAFETY_MARGIN_MILLIS = 50L; public static final boolean DEFAULT_ENABLED = false; public static final boolean DEFAULT_SPLIT_ENABLED = true; @@ -27,7 +29,15 @@ public final class Reference { public static final boolean DEFAULT_COMMAND_PREFIX_ENABLED = true; public static final String DEFAULT_COMMAND_PREFIX = "/pc"; + public static final int VANILLA_MESSAGE_HISTORY_LENGTH = 100; + public static final int MIN_MESSAGE_HISTORY_LENGTH = 100; + public static final int MAX_MESSAGE_HISTORY_LENGTH = 65536; + public static final int DEFAULT_MESSAGE_HISTORY_LENGTH = 1000; + + public static final int MAX_PREFIX_LENGTH = DEFAULT_MESSAGE_LIMIT - 2; + public static final int GUI_PREFIX_INPUT_LIMIT = MAX_PREFIX_LENGTH + 1; + private Reference() { // prevent creating instances } -} \ No newline at end of file +} diff --git a/src/main/java/com/github/cewko/enhanmess/SettingsValidation.java b/src/main/java/com/github/cewko/enhanmess/SettingsValidation.java new file mode 100644 index 0000000..c5a2afb --- /dev/null +++ b/src/main/java/com/github/cewko/enhanmess/SettingsValidation.java @@ -0,0 +1,74 @@ +package com.github.cewko.enhanmess; + +public final class SettingsValidation { + private SettingsValidation() { + } + + public static void validateDelaySeconds(int seconds) { + if (seconds < Reference.MIN_DELAY_SECONDS + || seconds > Reference.MAX_DELAY_SECONDS) { + throw new IllegalArgumentException( + "Delay must be between " + + Reference.MIN_DELAY_SECONDS + + " and " + + Reference.MAX_DELAY_SECONDS + + " secs" + ); + } + } + + public static void validateHistoryLength(int length) { + if (length < Reference.MIN_MESSAGE_HISTORY_LENGTH + || length > Reference.MAX_MESSAGE_HISTORY_LENGTH) { + throw new IllegalArgumentException( + "History length must be between " + + Reference.MIN_MESSAGE_HISTORY_LENGTH + + " and " + + Reference.MAX_MESSAGE_HISTORY_LENGTH + + " lines" + ); + } + } + + public static String normalizeMessagePrefix(String prefix) { + return normalizePrefix(prefix, "Message prefix", false); + } + + public static String normalizeCommandPrefix(String prefix) { + return normalizePrefix(prefix, "Command prefix", true); + } + + private static String normalizePrefix( + String prefix, + String displayName, + boolean command + ) { + if (prefix == null) { + throw new IllegalArgumentException(displayName + " cannot be null"); + } + + prefix = prefix.trim(); + + if (prefix.isEmpty()) { + throw new IllegalArgumentException(displayName + " is required"); + } + + if (command && !prefix.startsWith("/")) { + prefix = "/" + prefix; + } + + if (prefix.indexOf("\n") >= 0 || prefix.indexOf("\r") >= 0) { + throw new IllegalArgumentException(displayName + " cannot contain new lines"); + } + + if (prefix.length() > Reference.MAX_PREFIX_LENGTH) { + throw new IllegalArgumentException( + displayName + " must be at most " + + Reference.MAX_PREFIX_LENGTH + + " characters" + ); + } + + return prefix; + } +} diff --git a/src/main/java/com/github/cewko/extendedmessages/config/ExtendedMessagesConfig.java b/src/main/java/com/github/cewko/enhanmess/config/EnhanMessConfig.java similarity index 64% rename from src/main/java/com/github/cewko/extendedmessages/config/ExtendedMessagesConfig.java rename to src/main/java/com/github/cewko/enhanmess/config/EnhanMessConfig.java index 32fbb6b..c24aa77 100644 --- a/src/main/java/com/github/cewko/extendedmessages/config/ExtendedMessagesConfig.java +++ b/src/main/java/com/github/cewko/enhanmess/config/EnhanMessConfig.java @@ -1,17 +1,18 @@ -package com.github.cewko.extendedmessages.config; +package com.github.cewko.enhanmess.config; -import com.github.cewko.extendedmessages.Reference; +import com.github.cewko.enhanmess.Reference; import java.io.File; import net.minecraftforge.common.config.Configuration; import net.minecraftforge.common.config.Property; -public final class ExtendedMessagesConfig { +public final class EnhanMessConfig { private static final String KEY_ENABLED = "enabled"; private static final String KEY_SPLIT_ENABLED = "splitLongMessages"; private static final String KEY_MESSAGE_DELAY = "messageDelaySeconds"; + private static final String KEY_COMMAND_DELAY = "commandDelaySeconds"; private static final String KEY_MESSAGE_PREFIX_ENABLED = "messagePrefixEnabled"; private static final String KEY_MESSAGE_PREFIX = "messagePrefix"; @@ -19,11 +20,14 @@ public final class ExtendedMessagesConfig { private static final String KEY_COMMAND_PREFIX_ENABLED = "commandPrefixEnabled"; private static final String KEY_COMMAND_PREFIX = "commandPrefix"; + private static final String KEY_MESSAGE_HISTORY_LENGTH = "messageHistoryLength"; + private static Configuration configuration; private static Property enabledProperty; private static Property splitEnabledProperty; private static Property messageDelayProperty; + private static Property commandDelayProperty; private static Property messagePrefixEnabledProperty; private static Property messagePrefixProperty; @@ -31,10 +35,16 @@ public final class ExtendedMessagesConfig { private static Property commandPrefixEnabledProperty; private static Property commandPrefixProperty; - private ExtendedMessagesConfig() { + private static Property messageHistoryLengthProperty; + + private EnhanMessConfig() { // prevent creating instances } + private static int clamp(int value, int min, int max) { + return Math.max(min, Math.min(max, value)); + } + public static void load(File file) { configuration = new Configuration(file); configuration.load(); @@ -59,7 +69,14 @@ public static void load(File file) { Configuration.CATEGORY_GENERAL, KEY_MESSAGE_DELAY, Reference.DEFAULT_MESSAGE_DELAY_SECONDS, - "Delay in seconds between message chunks." + "Delay in seconds between regular message chunks." + ); + + commandDelayProperty = configuration.get( + Configuration.CATEGORY_GENERAL, + KEY_COMMAND_DELAY, + Reference.DEFAULT_COMMAND_DELAY_SECONDS, + "Delay in seconds between configured command message chunks." ); messagePrefixEnabledProperty = configuration.get( @@ -90,6 +107,13 @@ public static void load(File file) { "Message command repeated before every command message chunk" ); + messageHistoryLengthProperty = configuration.get( + Configuration.CATEGORY_GENERAL, + KEY_MESSAGE_HISTORY_LENGTH, + Reference.DEFAULT_MESSAGE_HISTORY_LENGTH, + "maximum number of message history length" + ); + saveIfChanged(); } @@ -109,9 +133,23 @@ public static int getMessageDelaySeconds() { int value = messageDelayProperty.getInt( Reference.DEFAULT_MESSAGE_DELAY_SECONDS ); - return Math.max( - Reference.MIN_MESSAGE_DELAY_SECONDS, - Math.min(Reference.MAX_MESSAGE_DELAY_SECONDS, value) + return clamp( + value, + Reference.MIN_DELAY_SECONDS, + Reference.MAX_DELAY_SECONDS + ); + } + + public static int getCommandDelaySeconds() { + ensureLoaded(); + + int value = commandDelayProperty.getInt( + Reference.DEFAULT_COMMAND_DELAY_SECONDS + ); + return clamp( + value, + Reference.MIN_DELAY_SECONDS, + Reference.MAX_DELAY_SECONDS ); } @@ -139,7 +177,21 @@ public static String getCommandPrefix() { return commandPrefixProperty.getString(); } - public static void ensureLoaded() { + public static int getMessageHistoryLength() { + ensureLoaded(); + + int value = messageHistoryLengthProperty.getInt( + Reference.DEFAULT_MESSAGE_HISTORY_LENGTH + ); + + return clamp( + value, + Reference.MIN_MESSAGE_HISTORY_LENGTH, + Reference.MAX_MESSAGE_HISTORY_LENGTH + ); + } + + private static void ensureLoaded() { if (configuration == null) { throw new IllegalStateException( Reference.NAME + " config has not been loaded" @@ -148,48 +200,60 @@ public static void ensureLoaded() { } public static void saveEnabled(boolean enabled) { - ensureLoaded(); - enabledProperty.set(enabled); - saveIfChanged(); + save(enabledProperty, enabled); } public static void saveSplitEnabled(boolean enabled) { - ensureLoaded(); - splitEnabledProperty.set(enabled); - saveIfChanged(); + save(splitEnabledProperty, enabled); } public static void saveMessageDelaySeconds(int seconds) { - ensureLoaded(); - messageDelayProperty.set(seconds); - saveIfChanged(); + save(messageDelayProperty, seconds); + } + + public static void saveCommandDelaySeconds(int seconds) { + save(commandDelayProperty, seconds); } public static void saveMessagePrefixEnabled(boolean enabled) { - ensureLoaded(); - messagePrefixEnabledProperty.set(enabled); - saveIfChanged(); + save(messagePrefixEnabledProperty, enabled); } public static void saveMessagePrefix(String prefix) { + save(messagePrefixProperty, prefix); + } + + public static void saveCommandPrefixEnabled(boolean enabled) { + save(commandPrefixEnabledProperty, enabled); + } + + public static void saveCommandPrefix(String prefix) { + save(commandPrefixProperty, prefix); + } + + public static void saveMessageHistoryLength(int length) { + save(messageHistoryLengthProperty, length); + } + + private static void save(Property property, boolean value) { ensureLoaded(); - messagePrefixProperty.set(prefix); + property.set(value); saveIfChanged(); } - public static void saveCommandPrefixEnabled(boolean enabled) { + private static void save(Property property, int value) { ensureLoaded(); - commandPrefixEnabledProperty.set(enabled); + property.set(value); saveIfChanged(); } - public static void saveCommandPrefix(String prefix) { + private static void save(Property property, String value) { ensureLoaded(); - commandPrefixProperty.set(prefix); + property.set(value); saveIfChanged(); } - public static void saveIfChanged() { + private static void saveIfChanged() { if (configuration.hasChanged()) { configuration.save(); } diff --git a/src/main/java/com/github/cewko/enhanmess/gui/EnhanMessGui.java b/src/main/java/com/github/cewko/enhanmess/gui/EnhanMessGui.java new file mode 100644 index 0000000..df74780 --- /dev/null +++ b/src/main/java/com/github/cewko/enhanmess/gui/EnhanMessGui.java @@ -0,0 +1,255 @@ +package com.github.cewko.enhanmess.gui; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +import com.github.cewko.enhanmess.Reference; +import com.github.cewko.enhanmess.gui.setting.GuiSetting; +import com.github.cewko.enhanmess.gui.setting.IntegerSetting; +import com.github.cewko.enhanmess.gui.setting.SliderSetting; +import com.github.cewko.enhanmess.gui.setting.TextSetting; +import com.github.cewko.enhanmess.gui.setting.ToggleSetting; + +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.gui.GuiScreen; + +public final class EnhanMessGui extends GuiScreen { + private static final int DONE_BUTTON_ID = 0; + + private final List settings = new ArrayList(); + private final List regularSettings = new ArrayList(); + private final List commandSettings = new ArrayList(); + + private final SettingsDraft draft; + + private GuiSetting mainSetting; + + private int nextControlId; + + public EnhanMessGui() { + draft = SettingsDraft.fromCurrentSettings(); + } + + @Override + public void initGui() { + buttonList.clear(); + settings.clear(); + regularSettings.clear(); + commandSettings.clear(); + nextControlId = 1; + + addSettings(); + + int panelX = width / 2 - GuiLayout.PANEL_WIDTH / 2; + int topY = GuiLayout.FIRST_ROW_Y; + int leftX = panelX; + int rightX = panelX + GuiLayout.COLUMN_WIDTH + GuiLayout.COLUMN_GAP; + int leftY = topY + GuiLayout.CONTROL_HEIGHT + GuiLayout.SECTION_GAP; + int rightY = topY + GuiLayout.CONTROL_HEIGHT + GuiLayout.SECTION_GAP; + + initSetting(mainSetting, panelX, topY, GuiLayout.PANEL_WIDTH); + + for (GuiSetting setting : regularSettings) { + initSetting(setting, leftX, leftY, GuiLayout.COLUMN_WIDTH); + leftY += setting.getHeight() + GuiLayout.ROW_SPACING; + } + + for (GuiSetting setting : commandSettings) { + initSetting(setting, rightX, rightY, GuiLayout.COLUMN_WIDTH); + rightY += setting.getHeight() + GuiLayout.ROW_SPACING; + } + + buttonList.add(new GuiButton( + DONE_BUTTON_ID, + width / 2 - GuiLayout.COLUMN_WIDTH / 2, + Math.max(leftY, rightY) + GuiLayout.SECTION_GAP, + GuiLayout.COLUMN_WIDTH, + GuiLayout.CONTROL_HEIGHT, + "Done" + )); + } + + private void initSetting(GuiSetting setting, int x, int y, int width) { + setting.init(buttonList, fontRendererObj, nextControlId++, x, y, width); + } + + private void addSettings() { + addMainSettings(); + addRegularSettings(); + addCommandSettings(); + } + + private void addMainSettings() { + mainSetting = new ToggleSetting( + "Remove 100-character limit", + draft::isEnabled, + draft::toggleEnabled + ); + + settings.add(mainSetting); + } + + private void addRegularSettings() { + addRegularSetting( + new ToggleSetting( + "Split long messages", + draft::isSplitEnabled, + draft::toggleSplitEnabled + ) + ); + + addRegularSetting( + new SliderSetting( + "Message cooldown", + Reference.MIN_DELAY_SECONDS, + Reference.MAX_DELAY_SECONDS, + draft::getMessageDelaySeconds, + draft::setMessageDelaySeconds + ) + ); + + addRegularSetting( + new ToggleSetting( + "Message prefix", + draft::isMessagePrefixEnabled, + draft::toggleMessagePrefixEnabled + ) + ); + + addRegularSetting( + new TextSetting( + "Message prefix", + Reference.GUI_PREFIX_INPUT_LIMIT, + draft::getMessagePrefix, + draft::setMessagePrefix + ) + ); + + addRegularSetting( + new IntegerSetting( + "History length", + Reference.MIN_MESSAGE_HISTORY_LENGTH, + Reference.MAX_MESSAGE_HISTORY_LENGTH, + draft::getMessageHistoryLength, + draft::setMessageHistoryLength + ) + ); + } + + private void addCommandSettings() { + addCommandSetting( + new ToggleSetting( + "Configured command", + draft::isCommandPrefixEnabled, + draft::toggleCommandPrefixEnabled + ) + ); + + addCommandSetting( + new SliderSetting( + "Command cooldown", + Reference.MIN_DELAY_SECONDS, + Reference.MAX_DELAY_SECONDS, + draft::getCommandDelaySeconds, + draft::setCommandDelaySeconds + ) + ); + + addCommandSetting( + new TextSetting( + "Command prefix", + Reference.GUI_PREFIX_INPUT_LIMIT, + draft::getCommandPrefix, + draft::setCommandPrefix + ) + ); + } + + private void addRegularSetting(GuiSetting setting) { + regularSettings.add(setting); + settings.add(setting); + } + + private void addCommandSetting(GuiSetting setting) { + commandSettings.add(setting); + settings.add(setting); + } + + @Override + protected void actionPerformed(GuiButton button) throws IOException { + if (button.id != DONE_BUTTON_ID) { + return; + } + + if (!validateSettings()) { + return; + } + + draft.apply(); + mc.displayGuiScreen(null); + } + + @Override + protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + super.mouseClicked(mouseX, mouseY, mouseButton); + + for (GuiSetting setting : settings) { + setting.mouseClicked(mouseX, mouseY, mouseButton); + } + } + + @Override + protected void keyTyped(char typedChar, int keyCode) throws IOException { + for (GuiSetting setting : settings) { + setting.keyTyped(typedChar, keyCode); + } + + super.keyTyped(typedChar, keyCode); + } + + private boolean validateSettings() { + boolean valid = true; + + for (GuiSetting setting : settings) { + if (!setting.validate()) { + valid = false; + } + } + + return valid; + } + + @Override + public void updateScreen() { + super.updateScreen(); + + for (GuiSetting setting : settings) { + setting.update(); + } + } + + @Override + public void drawScreen(int mouseX, int mouseY, float partialTicks) { + drawDefaultBackground(); + + drawCenteredString( + fontRendererObj, + Reference.NAME + " - v" + Reference.VERSION, + width / 2, + GuiLayout.TITLE_Y, + GuiColors.TEXT_PRIMARY + ); + + for (GuiSetting setting : settings) { + setting.draw(mc, mouseX, mouseY); + } + + super.drawScreen(mouseX, mouseY, partialTicks); + } + + @Override + public boolean doesGuiPauseGame() { + return false; + } +} diff --git a/src/main/java/com/github/cewko/enhanmess/gui/GuiColors.java b/src/main/java/com/github/cewko/enhanmess/gui/GuiColors.java new file mode 100644 index 0000000..7b25f71 --- /dev/null +++ b/src/main/java/com/github/cewko/enhanmess/gui/GuiColors.java @@ -0,0 +1,10 @@ +package com.github.cewko.enhanmess.gui; + +public final class GuiColors { + public static final int TEXT_PRIMARY = 0xFFFFFFFF; + public static final int TEXT_MUTED = 0xFFB0B0B0; + public static final int TEXT_ERROR = 0xFFFF5555; + + private GuiColors() { + } +} diff --git a/src/main/java/com/github/cewko/enhanmess/gui/GuiLayout.java b/src/main/java/com/github/cewko/enhanmess/gui/GuiLayout.java new file mode 100644 index 0000000..0f9968f --- /dev/null +++ b/src/main/java/com/github/cewko/enhanmess/gui/GuiLayout.java @@ -0,0 +1,29 @@ +package com.github.cewko.enhanmess.gui; + +public final class GuiLayout { + public static final int PANEL_WIDTH = 394; + public static final int COLUMN_WIDTH = 190; + public static final int COLUMN_GAP = 14; + + public static final int TITLE_Y = 20; + public static final int FIRST_ROW_Y = 44; + + public static final int CONTROL_HEIGHT = 20; + public static final int TOGGLE_ROW_HEIGHT = 22; + public static final int INPUT_ROW_HEIGHT = 42; + + public static final int ROW_SPACING = 6; + public static final int SECTION_GAP = 8; + + public static final int SETTING_LABEL_PADDING = 0; + public static final int SETTING_LABEL_Y_OFFSET = 0; + public static final int INPUT_FIELD_Y_OFFSET = 12; + + public static final int SLIDER_HANDLE_WIDTH = 8; + + public static final int TEXT_FIELD_PADDING = 4; + public static final int FONT_HEIGHT = 8; + + private GuiLayout() { + } +} diff --git a/src/main/java/com/github/cewko/enhanmess/gui/GuiOpener.java b/src/main/java/com/github/cewko/enhanmess/gui/GuiOpener.java new file mode 100644 index 0000000..7e40982 --- /dev/null +++ b/src/main/java/com/github/cewko/enhanmess/gui/GuiOpener.java @@ -0,0 +1,39 @@ +package com.github.cewko.enhanmess.gui; + +import net.minecraft.client.Minecraft; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +public final class GuiOpener { + private static final GuiOpener INSTANCE = new GuiOpener(); + + private boolean openRequested; + + private GuiOpener() { + } + + public static GuiOpener getInstance() { + return INSTANCE; + } + + public void requestOpen() { + openRequested = true; + } + + @SubscribeEvent + public void onClientTick(TickEvent.ClientTickEvent event) { + if (event.phase != TickEvent.Phase.END || !openRequested) { + return; + } + + openRequested = false; + + Minecraft minecraft = Minecraft.getMinecraft(); + + if (minecraft.thePlayer == null || minecraft.theWorld == null) { + return; + } + + minecraft.displayGuiScreen(new EnhanMessGui()); + } +} \ No newline at end of file diff --git a/src/main/java/com/github/cewko/enhanmess/gui/SettingsDraft.java b/src/main/java/com/github/cewko/enhanmess/gui/SettingsDraft.java new file mode 100644 index 0000000..4dded64 --- /dev/null +++ b/src/main/java/com/github/cewko/enhanmess/gui/SettingsDraft.java @@ -0,0 +1,145 @@ +package com.github.cewko.enhanmess.gui; + +import com.github.cewko.enhanmess.EnhanMess; +import com.github.cewko.enhanmess.SettingsValidation; + +public final class SettingsDraft { + private boolean enabled; + private boolean splitEnabled; + + private int messageDelaySeconds; + private int commandDelaySeconds; + + private boolean messagePrefixEnabled; + private String messagePrefix; + + private boolean commandPrefixEnabled; + private String commandPrefix; + + private int messageHistoryLength; + + private SettingsDraft() { + } + + public static SettingsDraft fromCurrentSettings() { + SettingsDraft draft = new SettingsDraft(); + + draft.enabled = EnhanMess.isEnabled(); + draft.splitEnabled = EnhanMess.isSplitEnabled(); + + draft.messageDelaySeconds = EnhanMess.getMessageDelaySeconds(); + draft.commandDelaySeconds = EnhanMess.getCommandDelaySeconds(); + + draft.messagePrefixEnabled = EnhanMess.isMessagePrefixEnabled(); + draft.messagePrefix = EnhanMess.getMessagePrefix(); + + draft.commandPrefixEnabled = EnhanMess.isCommandPrefixEnabled(); + draft.commandPrefix = EnhanMess.getCommandPrefix(); + + draft.messageHistoryLength = EnhanMess.getMessageHistoryLength(); + + return draft; + } + + public boolean isEnabled() { + return enabled; + } + + public void toggleEnabled() { + enabled = !enabled; + } + + public boolean isSplitEnabled() { + return splitEnabled; + } + + public void toggleSplitEnabled() { + splitEnabled = !splitEnabled; + } + + public int getMessageDelaySeconds() { + return messageDelaySeconds; + } + + public void setMessageDelaySeconds(int seconds) { + messageDelaySeconds = seconds; + } + + public int getCommandDelaySeconds() { + return commandDelaySeconds; + } + + public void setCommandDelaySeconds(int seconds) { + commandDelaySeconds = seconds; + } + + public boolean isMessagePrefixEnabled() { + return messagePrefixEnabled; + } + + public void toggleMessagePrefixEnabled() { + messagePrefixEnabled = !messagePrefixEnabled; + } + + public String getMessagePrefix() { + return messagePrefix; + } + + public void setMessagePrefix(String prefix) { + messagePrefix = prefix; + SettingsValidation.normalizeMessagePrefix(prefix); + } + + public boolean isCommandPrefixEnabled() { + return commandPrefixEnabled; + } + + public void toggleCommandPrefixEnabled() { + commandPrefixEnabled = !commandPrefixEnabled; + } + + public String getCommandPrefix() { + return commandPrefix; + } + + public void setCommandPrefix(String prefix) { + commandPrefix = prefix; + SettingsValidation.normalizeCommandPrefix(prefix); + } + + public int getMessageHistoryLength() { + return messageHistoryLength; + } + + public void setMessageHistoryLength(int length) { + messageHistoryLength = length; + } + + public void validate() { + SettingsValidation.normalizeMessagePrefix(messagePrefix); + SettingsValidation.normalizeCommandPrefix(commandPrefix); + SettingsValidation.validateDelaySeconds(messageDelaySeconds); + SettingsValidation.validateDelaySeconds(commandDelaySeconds); + SettingsValidation.validateHistoryLength(messageHistoryLength); + } + + public void apply() { + validate(); + + String normalizedMessagePrefix = + SettingsValidation.normalizeMessagePrefix(messagePrefix); + + String normalizedCommandPrefix = + SettingsValidation.normalizeCommandPrefix(commandPrefix); + + EnhanMess.setMessagePrefix(normalizedMessagePrefix); + EnhanMess.setCommandPrefix(normalizedCommandPrefix); + EnhanMess.setMessageDelaySeconds(messageDelaySeconds); + EnhanMess.setCommandDelaySeconds(commandDelaySeconds); + EnhanMess.setMessageHistoryLength(messageHistoryLength); + EnhanMess.setMessagePrefixEnabled(messagePrefixEnabled); + EnhanMess.setCommandPrefixEnabled(commandPrefixEnabled); + EnhanMess.setSplitEnabled(splitEnabled); + EnhanMess.setEnabled(enabled); + } +} diff --git a/src/main/java/com/github/cewko/enhanmess/gui/control/StyledIntegerSlider.java b/src/main/java/com/github/cewko/enhanmess/gui/control/StyledIntegerSlider.java new file mode 100644 index 0000000..c95ed62 --- /dev/null +++ b/src/main/java/com/github/cewko/enhanmess/gui/control/StyledIntegerSlider.java @@ -0,0 +1,132 @@ +package com.github.cewko.enhanmess.gui.control; + +import java.util.function.IntConsumer; +import java.util.function.IntSupplier; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; +import net.minecraft.client.renderer.GlStateManager; + +import com.github.cewko.enhanmess.gui.GuiLayout; + +public final class StyledIntegerSlider extends GuiButton { + private final String label; + private final int min; + private final int max; + private final IntSupplier getter; + private final IntConsumer setter; + + private boolean dragging; + + public StyledIntegerSlider( + int id, + int x, + int y, + int width, + int height, + String label, + int min, + int max, + IntSupplier getter, + IntConsumer setter + ) { + super(id, x, y, width, height, ""); + this.label = label; + this.min = min; + this.max = max; + this.getter = getter; + this.setter = setter; + updateText(); + } + + @Override + public boolean mousePressed(Minecraft minecraft, int mouseX, int mouseY) { + boolean pressed = super.mousePressed(minecraft, mouseX, mouseY); + + if (pressed) { + dragging = true; + updateValueFromMouse(mouseX); + } + + return pressed; + } + + @Override + public void mouseReleased(int mouseX, int mouseY) { + dragging = false; + } + + @Override + protected void mouseDragged(Minecraft minecraft, int mouseX, int mouseY) { + if (!visible) { + return; + } + + if (dragging) { + updateValueFromMouse(mouseX); + } + + minecraft.getTextureManager().bindTexture(buttonTextures); + GlStateManager.color(1.0F, 1.0F, 1.0F, 1.0F); + + int handleX = xPosition + Math.round( + getPercent() * (width - GuiLayout.SLIDER_HANDLE_WIDTH) + ); + + drawTexturedModalRect( + handleX, + yPosition, + 0, + 66, + GuiLayout.SLIDER_HANDLE_WIDTH / 2, + height + ); + + drawTexturedModalRect( + handleX + GuiLayout.SLIDER_HANDLE_WIDTH / 2, + yPosition, + 196, + 66, + GuiLayout.SLIDER_HANDLE_WIDTH / 2, + height + ); + } + + @Override + public void drawButton(Minecraft minecraft, int mouseX, int mouseY) { + updateText(); + super.drawButton(minecraft, mouseX, mouseY); + } + + @Override + protected int getHoverState(boolean mouseOver) { + return 0; + } + + private void updateValueFromMouse(int mouseX) { + float percent = ( + mouseX - xPosition - GuiLayout.SLIDER_HANDLE_WIDTH / 2.0F + ) / (float) (width - GuiLayout.SLIDER_HANDLE_WIDTH); + + percent = Math.max(0.0F, Math.min(1.0F, percent)); + + int newValue = Math.round(min + percent * (max - min)); + + if (newValue != getter.getAsInt()) { + setter.accept(newValue); + updateText(); + } + } + + private float getPercent() { + if (max == min) { + return 0.0F; + } + + return (float) (getter.getAsInt() - min) / (float) (max - min); + } + + private void updateText() { + displayString = label + ": " + getter.getAsInt() + "s"; + } +} diff --git a/src/main/java/com/github/cewko/enhanmess/gui/control/StyledTextField.java b/src/main/java/com/github/cewko/enhanmess/gui/control/StyledTextField.java new file mode 100644 index 0000000..c422f57 --- /dev/null +++ b/src/main/java/com/github/cewko/enhanmess/gui/control/StyledTextField.java @@ -0,0 +1,59 @@ +package com.github.cewko.enhanmess.gui.control; + +import com.github.cewko.enhanmess.gui.GuiColors; +import com.github.cewko.enhanmess.gui.GuiLayout; + +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiTextField; + +public final class StyledTextField extends GuiTextField { + private final FontRenderer fontRenderer; + private final int x; + private final int y; + private final int height; + + private String placeholder = ""; + + public StyledTextField( + int id, + FontRenderer fontRenderer, + int x, + int y, + int width, + int height + ) { + super(id, fontRenderer, x, y, width, height); + + this.fontRenderer = fontRenderer; + this.x = x; + this.y = y; + this.width = width; + this.height = height; + + setEnableBackgroundDrawing(true); + setTextColor(GuiColors.TEXT_PRIMARY); + setDisabledTextColour(GuiColors.TEXT_MUTED); + } + + public void setPlaceholder(String placeholder) { + this.placeholder = placeholder; + } + + @Override + public void drawTextBox() { + if (!getVisible()) { + return; + } + + super.drawTextBox(); + + if (getText().isEmpty() && !placeholder.isEmpty() && !isFocused()) { + fontRenderer.drawStringWithShadow( + placeholder, + x + GuiLayout.TEXT_FIELD_PADDING, + y + (height - GuiLayout.FONT_HEIGHT) / 2, + GuiColors.TEXT_MUTED + ); + } + } +} diff --git a/src/main/java/com/github/cewko/enhanmess/gui/control/StyledToggleButton.java b/src/main/java/com/github/cewko/enhanmess/gui/control/StyledToggleButton.java new file mode 100644 index 0000000..4806cdb --- /dev/null +++ b/src/main/java/com/github/cewko/enhanmess/gui/control/StyledToggleButton.java @@ -0,0 +1,55 @@ +package com.github.cewko.enhanmess.gui.control; + +import java.util.function.BooleanSupplier; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.GuiButton; + +public final class StyledToggleButton extends GuiButton { + private final String label; + private final BooleanSupplier getter; + private final Runnable toggler; + + public StyledToggleButton( + int id, + int x, + int y, + int width, + int height, + String label, + BooleanSupplier getter, + Runnable toggler + ) { + super(id, x, y, width, height, ""); + this.label = label; + this.getter = getter; + this.toggler = toggler; + updateText(); + } + + @Override + public boolean mousePressed(Minecraft minecraft, int mouseX, int mouseY) { + boolean pressed = super.mousePressed(minecraft, mouseX, mouseY); + + if (pressed) { + toggler.run(); + updateText(); + } + + return pressed; + } + + @Override + public void drawButton(Minecraft minecraft, int mouseX, int mouseY) { + updateText(); + super.drawButton(minecraft, mouseX, mouseY); + } + + private void updateText() { + displayString = label + + ": " + + (getter.getAsBoolean() + ? "\u00a7aON" + : "\u00a7cOFF"); + } +} diff --git a/src/main/java/com/github/cewko/enhanmess/gui/setting/GuiErrorLabel.java b/src/main/java/com/github/cewko/enhanmess/gui/setting/GuiErrorLabel.java new file mode 100644 index 0000000..8be64b0 --- /dev/null +++ b/src/main/java/com/github/cewko/enhanmess/gui/setting/GuiErrorLabel.java @@ -0,0 +1,16 @@ +package com.github.cewko.enhanmess.gui.setting; + +import com.github.cewko.enhanmess.gui.GuiColors; + +public final class GuiErrorLabel { + private GuiErrorLabel() { + } + + public static String text(String label, GuiValidationError error) { + return error == null ? label : label + " (" + error.getLabel() + ")"; + } + + public static int color(GuiValidationError error) { + return error == null ? GuiColors.TEXT_PRIMARY : GuiColors.TEXT_ERROR; + } +} \ No newline at end of file diff --git a/src/main/java/com/github/cewko/enhanmess/gui/setting/GuiSetting.java b/src/main/java/com/github/cewko/enhanmess/gui/setting/GuiSetting.java new file mode 100644 index 0000000..9f18e88 --- /dev/null +++ b/src/main/java/com/github/cewko/enhanmess/gui/setting/GuiSetting.java @@ -0,0 +1,37 @@ +package com.github.cewko.enhanmess.gui.setting; + +import java.io.IOException; +import java.util.List; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiButton; + +public interface GuiSetting { + int getHeight(); + + void init( + List buttons, + FontRenderer fontRenderer, + int id, + int x, + int y, + int width + ); + + default void draw(Minecraft minecraft, int mouseX, int mouseY) { + } + + default void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + } + + default void keyTyped(char typedChar, int keyCode) throws IOException { + } + + default void update() { + } + + default boolean validate() { + return true; + } +} diff --git a/src/main/java/com/github/cewko/enhanmess/gui/setting/GuiValidationError.java b/src/main/java/com/github/cewko/enhanmess/gui/setting/GuiValidationError.java new file mode 100644 index 0000000..fa6a2bb --- /dev/null +++ b/src/main/java/com/github/cewko/enhanmess/gui/setting/GuiValidationError.java @@ -0,0 +1,38 @@ +package com.github.cewko.enhanmess.gui.setting; + +public enum GuiValidationError { + REQUIRED("required"), + NUMBERS_ONLY("numbers only"), + OUT_OF_RANGE("out of range"), + TOO_LONG("too long"), + NO_NEW_LINES("no new lines"), + INVALID("invalid"); + + private final String label; + + GuiValidationError(String label) { + this.label = label; + } + + public String getLabel() { + return label; + } + + public static GuiValidationError fromException(IllegalArgumentException exception) { + String message = exception.getMessage().toLowerCase(); + + if (message.contains("required")) { + return REQUIRED; + } + + if (message.contains("at most")) { + return TOO_LONG; + } + + if (message.contains("new line")) { + return NO_NEW_LINES; + } + + return INVALID; + } +} \ No newline at end of file diff --git a/src/main/java/com/github/cewko/enhanmess/gui/setting/IntegerSetting.java b/src/main/java/com/github/cewko/enhanmess/gui/setting/IntegerSetting.java new file mode 100644 index 0000000..eb2513d --- /dev/null +++ b/src/main/java/com/github/cewko/enhanmess/gui/setting/IntegerSetting.java @@ -0,0 +1,135 @@ +package com.github.cewko.enhanmess.gui.setting; + +import java.io.IOException; +import java.util.List; +import java.util.function.IntConsumer; +import java.util.function.IntSupplier; + +import com.github.cewko.enhanmess.gui.GuiLayout; +import com.github.cewko.enhanmess.gui.control.StyledTextField; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiButton; + +public final class IntegerSetting implements GuiSetting { + private final String label; + private final int min; + private final int max; + private final IntSupplier getter; + private final IntConsumer setter; + + private FontRenderer fontRenderer; + private StyledTextField textField; + private GuiValidationError error; + private int x; + private int y; + + public IntegerSetting( + String label, + int min, + int max, + IntSupplier getter, + IntConsumer setter + ) { + this.label = label; + this.min = min; + this.max = max; + this.getter = getter; + this.setter = setter; + } + + @Override + public int getHeight() { + return GuiLayout.INPUT_ROW_HEIGHT; + } + + @Override + public void init( + List buttons, + FontRenderer fontRenderer, + int id, + int x, + int y, + int width + ) { + this.fontRenderer = fontRenderer; + this.x = x; + this.y = y; + + textField = new StyledTextField( + id, + fontRenderer, + x, + y + GuiLayout.INPUT_FIELD_Y_OFFSET, + width, + GuiLayout.CONTROL_HEIGHT + ); + + textField.setMaxStringLength(String.valueOf(max).length()); + textField.setText(String.valueOf(getter.getAsInt())); + textField.setPlaceholder(min + "-" + max); + } + + @Override + public void draw(Minecraft minecraft, int mouseX, int mouseY) { + fontRenderer.drawString( + GuiErrorLabel.text(label, error), + x + GuiLayout.SETTING_LABEL_PADDING, + y + GuiLayout.SETTING_LABEL_Y_OFFSET, + GuiErrorLabel.color(error) + ); + + textField.drawTextBox(); + } + + @Override + public void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + textField.mouseClicked(mouseX, mouseY, mouseButton); + } + + @Override + public void keyTyped(char typedChar, int keyCode) throws IOException { + if (textField.textboxKeyTyped(typedChar, keyCode)) { + saveIfValid(); + } + } + + @Override + public void update() { + textField.updateCursorCounter(); + } + + private boolean saveIfValid() { + String text = textField.getText().trim(); + + if (text.isEmpty()) { + error = GuiValidationError.REQUIRED; + return false; + } + + try { + int parsed = Integer.parseInt(text); + + if (parsed < min || parsed > max) { + error = GuiValidationError.OUT_OF_RANGE; + return false; + } + + setter.accept(parsed); + error = null; + return true; + } catch (NumberFormatException exception) { + error = GuiValidationError.NUMBERS_ONLY; + return false; + } catch (IllegalArgumentException exception) { + error = GuiValidationError.fromException(exception); + return false; + } + } + + @Override + public boolean validate() { + return saveIfValid(); + } +} diff --git a/src/main/java/com/github/cewko/enhanmess/gui/setting/SliderSetting.java b/src/main/java/com/github/cewko/enhanmess/gui/setting/SliderSetting.java new file mode 100644 index 0000000..d8b16a3 --- /dev/null +++ b/src/main/java/com/github/cewko/enhanmess/gui/setting/SliderSetting.java @@ -0,0 +1,61 @@ +package com.github.cewko.enhanmess.gui.setting; + +import java.util.List; +import java.util.function.IntConsumer; +import java.util.function.IntSupplier; + +import com.github.cewko.enhanmess.gui.GuiLayout; +import com.github.cewko.enhanmess.gui.control.StyledIntegerSlider; + +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiButton; + +public final class SliderSetting implements GuiSetting { + private final String label; + private final int min; + private final int max; + private final IntSupplier getter; + private final IntConsumer setter; + + public SliderSetting( + String label, + int min, + int max, + IntSupplier getter, + IntConsumer setter + ) { + this.label = label; + this.min = min; + this.max = max; + this.getter = getter; + this.setter = setter; + } + + @Override + public int getHeight() { + return GuiLayout.TOGGLE_ROW_HEIGHT; + } + + @Override + public void init( + List buttons, + FontRenderer fontRenderer, + int id, + int x, + int y, + int width + ) { + buttons.add(new StyledIntegerSlider( + id, + x, + y, + width, + GuiLayout.CONTROL_HEIGHT, + label, + min, + max, + getter, + setter + )); + } +} diff --git a/src/main/java/com/github/cewko/enhanmess/gui/setting/TextSetting.java b/src/main/java/com/github/cewko/enhanmess/gui/setting/TextSetting.java new file mode 100644 index 0000000..43aafc8 --- /dev/null +++ b/src/main/java/com/github/cewko/enhanmess/gui/setting/TextSetting.java @@ -0,0 +1,114 @@ +package com.github.cewko.enhanmess.gui.setting; + +import java.io.IOException; +import java.util.List; +import java.util.function.Consumer; +import java.util.function.Supplier; + +import com.github.cewko.enhanmess.gui.GuiLayout; +import com.github.cewko.enhanmess.gui.control.StyledTextField; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiButton; + +public final class TextSetting implements GuiSetting { + private final String label; + private final int maxLength; + private final Supplier getter; + private final Consumer setter; + + private FontRenderer fontRenderer; + private StyledTextField textField; + private GuiValidationError error; + private int x; + private int y; + + public TextSetting( + String label, + int maxLength, + Supplier getter, + Consumer setter + ) { + this.label = label; + this.maxLength = maxLength; + this.getter = getter; + this.setter = setter; + } + + @Override + public int getHeight() { + return GuiLayout.INPUT_ROW_HEIGHT; + } + + @Override + public void init( + List buttons, + FontRenderer fontRenderer, + int id, + int x, + int y, + int width + ) { + this.fontRenderer = fontRenderer; + this.x = x; + this.y = y; + + textField = new StyledTextField( + id, + fontRenderer, + x, + y + GuiLayout.INPUT_FIELD_Y_OFFSET, + width, + GuiLayout.CONTROL_HEIGHT + ); + + textField.setMaxStringLength(maxLength); + textField.setText(getter.get()); + } + + @Override + public void draw(Minecraft minecraft, int mouseX, int mouseY) { + fontRenderer.drawString( + GuiErrorLabel.text(label, error), + x + GuiLayout.SETTING_LABEL_PADDING, + y + GuiLayout.SETTING_LABEL_Y_OFFSET, + GuiErrorLabel.color(error) + ); + + textField.drawTextBox(); + } + + @Override + public void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException { + textField.mouseClicked(mouseX, mouseY, mouseButton); + } + + @Override + public void keyTyped(char typedChar, int keyCode) throws IOException { + if (textField.textboxKeyTyped(typedChar, keyCode)) { + saveIfValid(); + } + } + + @Override + public void update() { + textField.updateCursorCounter(); + } + + private boolean saveIfValid() { + try { + setter.accept(textField.getText()); + error = null; + return true; + } catch (IllegalArgumentException exception) { + error = GuiValidationError.fromException(exception); + return false; + } + } + + @Override + public boolean validate() { + return saveIfValid(); + } +} diff --git a/src/main/java/com/github/cewko/enhanmess/gui/setting/ToggleSetting.java b/src/main/java/com/github/cewko/enhanmess/gui/setting/ToggleSetting.java new file mode 100644 index 0000000..f68023b --- /dev/null +++ b/src/main/java/com/github/cewko/enhanmess/gui/setting/ToggleSetting.java @@ -0,0 +1,52 @@ +package com.github.cewko.enhanmess.gui.setting; + +import java.util.List; +import java.util.function.BooleanSupplier; + +import com.github.cewko.enhanmess.gui.GuiLayout; +import com.github.cewko.enhanmess.gui.control.StyledToggleButton; + +import net.minecraft.client.gui.FontRenderer; +import net.minecraft.client.gui.GuiButton; + +public final class ToggleSetting implements GuiSetting { + private final String label; + private final BooleanSupplier getter; + private final Runnable toggler; + + public ToggleSetting( + String label, + BooleanSupplier getter, + Runnable toggler + ) { + this.label = label; + this.getter = getter; + this.toggler = toggler; + } + + @Override + public int getHeight() { + return GuiLayout.TOGGLE_ROW_HEIGHT; + } + + @Override + public void init( + List buttons, + FontRenderer fontRenderer, + int id, + int x, + int y, + int width + ) { + buttons.add(new StyledToggleButton( + id, + x, + y, + width, + GuiLayout.CONTROL_HEIGHT, + label, + getter, + toggler + )); + } +} diff --git a/src/main/java/com/github/cewko/extendedmessages/init/AutoDiscoveryMixinPlugin.java b/src/main/java/com/github/cewko/enhanmess/init/AutoDiscoveryMixinPlugin.java similarity index 99% rename from src/main/java/com/github/cewko/extendedmessages/init/AutoDiscoveryMixinPlugin.java rename to src/main/java/com/github/cewko/enhanmess/init/AutoDiscoveryMixinPlugin.java index c9e3b50..a9a9f17 100644 --- a/src/main/java/com/github/cewko/extendedmessages/init/AutoDiscoveryMixinPlugin.java +++ b/src/main/java/com/github/cewko/enhanmess/init/AutoDiscoveryMixinPlugin.java @@ -1,4 +1,4 @@ -package com.github.cewko.extendedmessages.init; +package com.github.cewko.enhanmess.init; import org.spongepowered.asm.lib.tree.ClassNode; import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin; diff --git a/src/main/java/com/github/cewko/enhanmess/messaging/MessageQueue.java b/src/main/java/com/github/cewko/enhanmess/messaging/MessageQueue.java new file mode 100644 index 0000000..5e6a93f --- /dev/null +++ b/src/main/java/com/github/cewko/enhanmess/messaging/MessageQueue.java @@ -0,0 +1,164 @@ +package com.github.cewko.enhanmess.messaging; + +import com.github.cewko.enhanmess.EnhanMess; +import com.github.cewko.enhanmess.Reference; + +import java.util.ArrayDeque; +import java.util.Deque; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import net.minecraft.client.Minecraft; +import net.minecraft.world.World; +import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; +import net.minecraftforge.fml.common.gameevent.TickEvent; + +public final class MessageQueue { + private static final MessageQueue INSTANCE = new MessageQueue(); + + public enum Lane { + REGULAR, + CONFIGURED_COMMAND + } + + private final Deque regularLines = new ArrayDeque(); + private final Deque commandLines = new ArrayDeque(); + + private long nextRegularSendAtNanos; + private long nextCommandSendAtNanos; + + private World queuedWorld; + private boolean sendingQueuedMessage; + + private MessageQueue() { + } + + public static MessageQueue getInstance() { + return INSTANCE; + } + + public void enqueueLines(List lines, Lane lane) { + Minecraft minecraft = Minecraft.getMinecraft(); + + if (lines.isEmpty() || minecraft.thePlayer == null || minecraft.theWorld == null) { + return; + } + + if (queuedWorld != null && queuedWorld != minecraft.theWorld) { + clear(); + } + + queuedWorld = minecraft.theWorld; + getQueue(lane).addAll(lines); + + trySendReady(minecraft); + } + + private Deque getQueue(Lane lane) { + return lane == Lane.REGULAR ? regularLines : commandLines; + } + + private void trySendReady(Minecraft minecraft) { + trySendLane(minecraft, Lane.REGULAR); + trySendLane(minecraft, Lane.CONFIGURED_COMMAND); + } + + private void trySendLane(Minecraft minecraft, Lane lane) { + Deque queue = getQueue(lane); + long deadline = getNextSendAtNanos(lane); + long now = System.nanoTime(); + + if (queue.isEmpty() || (deadline != 0L && now - deadline < 0L)) { + return; + } + + String line = queue.pollFirst(); + + sendingQueuedMessage = true; + + try { + minecraft.thePlayer.sendChatMessage(line); + } finally { + sendingQueuedMessage = false; + } + + setNextSendAtNanos( + lane, + System.nanoTime() + getCooldownNanos(lane) + ); + } + + private long getNextSendAtNanos(Lane lane) { + return lane == Lane.REGULAR + ? nextRegularSendAtNanos + : nextCommandSendAtNanos; + } + + private void setNextSendAtNanos(Lane lane, long value) { + if (lane == Lane.REGULAR) { + nextRegularSendAtNanos = value; + } else { + nextCommandSendAtNanos = value; + } + } + + private long getCooldownNanos(Lane lane) { + int delaySeconds = getDelaySeconds(lane); + long cooldownNanos = TimeUnit.SECONDS.toNanos(delaySeconds); + + if (delaySeconds > 0) { + cooldownNanos += TimeUnit.MILLISECONDS.toNanos( + Reference.SEND_SAFETY_MARGIN_MILLIS + ); + } + + return cooldownNanos; + } + + private int getDelaySeconds(Lane lane) { + return lane == Lane.REGULAR + ? EnhanMess.getMessageDelaySeconds() + : EnhanMess.getCommandDelaySeconds(); + } + + @SubscribeEvent + public void onClientTick(TickEvent.ClientTickEvent event) { + if (event.phase != TickEvent.Phase.END) { + return; + } + + Minecraft minecraft = Minecraft.getMinecraft(); + + if (queuedWorld != null && minecraft.theWorld != queuedWorld) { + clear(); + } + + if (isEmpty()) { + return; + } + + if (minecraft.thePlayer == null || minecraft.theWorld == null + || minecraft.theWorld != queuedWorld || !EnhanMess.isEnabled()) { + clear(); + return; + } + + trySendReady(minecraft); + } + + private boolean isEmpty() { + return regularLines.isEmpty() && commandLines.isEmpty(); + } + + public void clear() { + regularLines.clear(); + commandLines.clear(); + queuedWorld = null; + nextRegularSendAtNanos = 0L; + nextCommandSendAtNanos = 0L; + } + + public boolean isSendingQueuedMessage() { + return sendingQueuedMessage; + } +} diff --git a/src/main/java/com/github/cewko/extendedmessages/messaging/OutgoingMessageProcessor.java b/src/main/java/com/github/cewko/enhanmess/messaging/OutgoingMessageProcessor.java similarity index 61% rename from src/main/java/com/github/cewko/extendedmessages/messaging/OutgoingMessageProcessor.java rename to src/main/java/com/github/cewko/enhanmess/messaging/OutgoingMessageProcessor.java index 6081978..aec1759 100644 --- a/src/main/java/com/github/cewko/extendedmessages/messaging/OutgoingMessageProcessor.java +++ b/src/main/java/com/github/cewko/enhanmess/messaging/OutgoingMessageProcessor.java @@ -1,7 +1,7 @@ -package com.github.cewko.extendedmessages.messaging; +package com.github.cewko.enhanmess.messaging; -import com.github.cewko.extendedmessages.ExtendedMessages; -import com.github.cewko.extendedmessages.Reference; +import com.github.cewko.enhanmess.EnhanMess; +import com.github.cewko.enhanmess.Reference; import java.util.ArrayList; import java.util.Collections; @@ -13,7 +13,16 @@ public final class OutgoingMessageProcessor { private OutgoingMessageProcessor() { + } + + private static final class ProcessedMessage { + private final List lines; + private final MessageQueue.Lane lane; + private ProcessedMessage(List lines, MessageQueue.Lane lane) { + this.lines = lines; + this.lane = lane; + } } public static boolean shouldBypass(String message) { @@ -33,7 +42,7 @@ public static boolean shouldBypass(String message) { return false; } - return message.length() <= ExtendedMessages.getCurrentPacketMessageLimit(); + return message.length() <= EnhanMess.getCurrentPacketMessageLimit(); } private static boolean startsWithCommand(String message, String command) { @@ -43,11 +52,11 @@ private static boolean startsWithCommand(String message, String command) { } private static boolean isConfiguredCommandMessage(String message) { - if (!ExtendedMessages.isCommandPrefixEnabled()) { + if (!EnhanMess.isCommandPrefixEnabled()) { return false; } - String commandPrefix = withTrailingSpace(ExtendedMessages.getCommandPrefix()); + String commandPrefix = withTrailingSpace(EnhanMess.getCommandPrefix()); return !commandPrefix.isEmpty() && message.regionMatches(true, 0, commandPrefix, 0, commandPrefix.length()) @@ -60,30 +69,53 @@ private static String withTrailingSpace(String prefix) { } public static void handle(Minecraft minecraft, String message) { - List lines = buildLines(minecraft, message); + ProcessedMessage processed = process(minecraft, message); - if (!lines.isEmpty()) { - MessageQueue.getInstance().enqueueLines(lines); + if (processed.lines.isEmpty()) { + return; } + + MessageQueue.getInstance().enqueueLines(processed.lines, processed.lane); } - private static List buildLines(Minecraft minecraft, String message) { + private static ProcessedMessage process(Minecraft minecraft, String message) { if (isConfiguredCommandMessage(message)) { - String commandPrefix = withTrailingSpace(ExtendedMessages.getCommandPrefix()); - String body = message.substring((commandPrefix.length())); - return buildSendableLines(minecraft, commandPrefix, body); + return processConfiguredCommand(minecraft, message); } if (message.startsWith("/")) { warn(minecraft, "long commands cannot be split safely"); - return Collections.emptyList(); + return new ProcessedMessage( + Collections.emptyList(), + MessageQueue.Lane.REGULAR + ); } - String messagePrefix = ExtendedMessages.isMessagePrefixEnabled() - ? withTrailingSpace(ExtendedMessages.getMessagePrefix()) + return processRegularMessage(minecraft, message); + } + + private static ProcessedMessage processRegularMessage(Minecraft minecraft, String message) { + String messagePrefix = EnhanMess.isMessagePrefixEnabled() + ? withTrailingSpace(EnhanMess.getMessagePrefix()) : ""; - return buildSendableLines(minecraft, messagePrefix, message); + return new ProcessedMessage( + buildSendableLines(minecraft, messagePrefix, message), + MessageQueue.Lane.REGULAR + ); + } + + private static ProcessedMessage processConfiguredCommand( + Minecraft minecraft, + String message + ) { + String commandPrefix = withTrailingSpace(EnhanMess.getCommandPrefix()); + String body = message.substring(commandPrefix.length()); + + return new ProcessedMessage( + buildSendableLines(minecraft, commandPrefix, body), + MessageQueue.Lane.CONFIGURED_COMMAND + ); } private static void warn(Minecraft minecraft, String message) { @@ -101,7 +133,7 @@ private static List buildSendableLines( String prefix, String body ) { - if (!ExtendedMessages.isSplitEnabled()) { + if (!EnhanMess.isSplitEnabled()) { String line = prefix + body; if (line.length() > Reference.EXTENDED_MESSAGE_LIMIT) { @@ -110,7 +142,7 @@ private static List buildSendableLines( + " chars" ); return Collections.emptyList(); - } + } return Collections.singletonList(line); } @@ -139,6 +171,4 @@ private static List splitWithPrefix( return lines; } - - } diff --git a/src/main/java/com/github/cewko/extendedmessages/mixin/MixinC01PacketChatMessage.java b/src/main/java/com/github/cewko/enhanmess/mixin/MixinC01PacketChatMessage.java similarity index 62% rename from src/main/java/com/github/cewko/extendedmessages/mixin/MixinC01PacketChatMessage.java rename to src/main/java/com/github/cewko/enhanmess/mixin/MixinC01PacketChatMessage.java index 085f83a..45a4362 100644 --- a/src/main/java/com/github/cewko/extendedmessages/mixin/MixinC01PacketChatMessage.java +++ b/src/main/java/com/github/cewko/enhanmess/mixin/MixinC01PacketChatMessage.java @@ -1,7 +1,7 @@ -package com.github.cewko.extendedmessages.mixin; +package com.github.cewko.enhanmess.mixin; -import com.github.cewko.extendedmessages.ExtendedMessages; -import com.github.cewko.extendedmessages.Reference; +import com.github.cewko.enhanmess.EnhanMess; +import com.github.cewko.enhanmess.Reference; import net.minecraft.network.play.client.C01PacketChatMessage; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.Constant; @@ -16,7 +16,7 @@ public abstract class MixinC01PacketChatMessage { require = 2 ) - private int extendedmessages$modifyOutgoingLimit(int defaultLimit) { - return ExtendedMessages.getCurrentPacketMessageLimit(); + private int enhanmess$modifyOutgoingLimit(int defaultLimit) { + return EnhanMess.getCurrentPacketMessageLimit(); } } diff --git a/src/main/java/com/github/cewko/extendedmessages/mixin/MixinEntityPlayerSP.java b/src/main/java/com/github/cewko/enhanmess/mixin/MixinEntityPlayerSP.java similarity index 73% rename from src/main/java/com/github/cewko/extendedmessages/mixin/MixinEntityPlayerSP.java rename to src/main/java/com/github/cewko/enhanmess/mixin/MixinEntityPlayerSP.java index 8362608..436503f 100644 --- a/src/main/java/com/github/cewko/extendedmessages/mixin/MixinEntityPlayerSP.java +++ b/src/main/java/com/github/cewko/enhanmess/mixin/MixinEntityPlayerSP.java @@ -1,8 +1,8 @@ -package com.github.cewko.extendedmessages.mixin; +package com.github.cewko.enhanmess.mixin; -import com.github.cewko.extendedmessages.ExtendedMessages; -import com.github.cewko.extendedmessages.messaging.OutgoingMessageProcessor; -import com.github.cewko.extendedmessages.messaging.MessageQueue; +import com.github.cewko.enhanmess.EnhanMess; +import com.github.cewko.enhanmess.messaging.OutgoingMessageProcessor; +import com.github.cewko.enhanmess.messaging.MessageQueue; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; @@ -21,7 +21,7 @@ public abstract class MixinEntityPlayerSP { cancellable = true, require = 1 ) - private void extendedmessages$interceptMessage( + private void enhanmess$interceptMessage( String message, CallbackInfo callback ) { @@ -31,7 +31,7 @@ public abstract class MixinEntityPlayerSP { return; } - if (!ExtendedMessages.isEnabled()) { + if (!EnhanMess.isEnabled()) { return; } diff --git a/src/main/java/com/github/cewko/extendedmessages/mixin/MixinGuiChat.java b/src/main/java/com/github/cewko/enhanmess/mixin/MixinGuiChat.java similarity index 65% rename from src/main/java/com/github/cewko/extendedmessages/mixin/MixinGuiChat.java rename to src/main/java/com/github/cewko/enhanmess/mixin/MixinGuiChat.java index 9714337..fb4a287 100644 --- a/src/main/java/com/github/cewko/extendedmessages/mixin/MixinGuiChat.java +++ b/src/main/java/com/github/cewko/enhanmess/mixin/MixinGuiChat.java @@ -1,7 +1,7 @@ -package com.github.cewko.extendedmessages.mixin; +package com.github.cewko.enhanmess.mixin; -import com.github.cewko.extendedmessages.ExtendedMessages; -import com.github.cewko.extendedmessages.Reference; +import com.github.cewko.enhanmess.EnhanMess; +import com.github.cewko.enhanmess.Reference; import net.minecraft.client.gui.GuiChat; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.Constant; @@ -13,9 +13,9 @@ public abstract class MixinGuiChat { method = "initGui", constant = @Constant(intValue = Reference.DEFAULT_MESSAGE_LIMIT) ) - private int extendedmessages$replaceVanillaChatLimit(int defaultLimit) { + private int enhanmess$replaceVanillaChatLimit(int defaultLimit) { // GuiChat.initGui creates chat input box with vanilla's 100 char limit // when mod is enabled we replace that limit with our extended one - return ExtendedMessages.getCurrentMessageLimit(); + return EnhanMess.getCurrentMessageLimit(); } } \ No newline at end of file diff --git a/src/main/java/com/github/cewko/enhanmess/mixin/MixinGuiNewChat.java b/src/main/java/com/github/cewko/enhanmess/mixin/MixinGuiNewChat.java new file mode 100644 index 0000000..1739ad7 --- /dev/null +++ b/src/main/java/com/github/cewko/enhanmess/mixin/MixinGuiNewChat.java @@ -0,0 +1,21 @@ +package com.github.cewko.enhanmess.mixin; + +import com.github.cewko.enhanmess.EnhanMess; +import com.github.cewko.enhanmess.Reference; +import net.minecraft.client.gui.GuiNewChat; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.Constant; +import org.spongepowered.asm.mixin.injection.ModifyConstant; + +@Mixin(GuiNewChat.class) +public abstract class MixinGuiNewChat { + @ModifyConstant( + method = "setChatLine", + constant = @Constant(intValue = Reference.VANILLA_MESSAGE_HISTORY_LENGTH), + require = 2 + ) + private int enhanmess$replaceMessageHistoryLength(int vanillaLimit) { + return EnhanMess.getCurrentMessageHistoryLength(); + } +} \ No newline at end of file diff --git a/src/main/java/com/github/cewko/extendedmessages/ExtendedMessages.java b/src/main/java/com/github/cewko/extendedmessages/ExtendedMessages.java deleted file mode 100644 index cbb7e2c..0000000 --- a/src/main/java/com/github/cewko/extendedmessages/ExtendedMessages.java +++ /dev/null @@ -1,209 +0,0 @@ -package com.github.cewko.extendedmessages; - -import com.github.cewko.extendedmessages.config.ExtendedMessagesConfig; -import com.github.cewko.extendedmessages.messaging.MessageQueue; - -import net.minecraftforge.common.MinecraftForge; - -import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; -import net.minecraftforge.fml.common.Mod; -import net.minecraftforge.fml.common.event.FMLInitializationEvent; - -import net.minecraftforge.client.ClientCommandHandler; - -@Mod( - modid = Reference.MOD_ID, - name = Reference.NAME, - version = Reference.VERSION, - acceptedMinecraftVersions = Reference.ACCEPTED_VERSIONS, - clientSideOnly = true, - useMetadata = true -) -public class ExtendedMessages { - - public static boolean enabled = Reference.DEFAULT_ENABLED; - private static boolean splitEnabled = Reference.DEFAULT_SPLIT_ENABLED; - private static int messageDelaySeconds = Reference.DEFAULT_MESSAGE_DELAY_SECONDS; - - private static boolean messagePrefixEnabled = Reference.DEFAULT_MESSAGE_PREFIX_ENABLED; - private static String messagePrefix = Reference.DEFAULT_MESSAGE_PREFIX; - - private static boolean commandPrefixEnabled = Reference.DEFAULT_COMMAND_PREFIX_ENABLED; - private static String commandPrefix = Reference.DEFAULT_COMMAND_PREFIX; - - public static boolean isEnabled() { - return enabled; - } - - public static boolean isSplitEnabled() { - return splitEnabled; - } - - public static boolean toggleSplitEnabled() { - splitEnabled = !splitEnabled; - ExtendedMessagesConfig.saveSplitEnabled(splitEnabled); - - MessageQueue.getInstance().clear(); - - return splitEnabled; - } - - public static boolean toggleEnabled() { - enabled = !enabled; - ExtendedMessagesConfig.saveEnabled(enabled); - - if (!enabled) { - MessageQueue.getInstance().clear(); - } - - return enabled; - } - - public static int getMessageDelaySeconds() { - return messageDelaySeconds; - } - - public static void setMessageDelaySeconds(int seconds) { - if (seconds < Reference.MIN_MESSAGE_DELAY_SECONDS - || seconds > Reference.MAX_MESSAGE_DELAY_SECONDS) { - throw new IllegalArgumentException( - "Message delay must be between " - + Reference.MIN_MESSAGE_DELAY_SECONDS - + " and " - + Reference.MAX_MESSAGE_DELAY_SECONDS - + " secs" - ); - } - - messageDelaySeconds = seconds; - ExtendedMessagesConfig.saveMessageDelaySeconds(seconds); - } - - public static boolean isMessagePrefixEnabled() { - return messagePrefixEnabled; - } - - public static String getMessagePrefix() { - return messagePrefix; - } - - public static boolean isCommandPrefixEnabled() { - return commandPrefixEnabled; - } - - public static String getCommandPrefix() { - return commandPrefix; - } - - public static boolean toggleMessagePrefixEnabled() { - messagePrefixEnabled = !messagePrefixEnabled; - - ExtendedMessagesConfig.saveMessagePrefixEnabled( - messagePrefixEnabled - ); - - return messagePrefixEnabled; - } - - public static void setMessagePrefix(String prefix) { - validatePrefix(prefix, "Message prefix"); - messagePrefix = prefix; - - ExtendedMessagesConfig.saveMessagePrefix( - messagePrefix - ); - } - - public static boolean toggleCommandPrefixEnabled() { - commandPrefixEnabled = !commandPrefixEnabled; - - ExtendedMessagesConfig.saveCommandPrefixEnabled( - commandPrefixEnabled - ); - - return commandPrefixEnabled; - } - - public static void setCommandPrefix(String prefix) { - if (prefix == null) { - throw new IllegalArgumentException("Command prefix cannot be null"); - } - - prefix = prefix.trim(); - - if (prefix.isEmpty()) { - throw new IllegalArgumentException("Command prefix cannot be empty"); - } - - if (!prefix.startsWith("/")) { - prefix = "/" + prefix; - } - - validatePrefix(prefix, "Command prefix"); - - commandPrefix = prefix; - - ExtendedMessagesConfig.saveCommandPrefix( - commandPrefix - ); - } - - private static void validatePrefix(String prefix, String displayName) { - if (prefix == null) { - throw new IllegalArgumentException(displayName + " cannot be null"); - } - - if (prefix.indexOf("\n") >= 0 || prefix.indexOf("\r") >= 0) { - throw new IllegalArgumentException(displayName + " cannot contain new lines"); - } - - if (prefix.length() >= Reference.DEFAULT_MESSAGE_LIMIT) { - throw new IllegalArgumentException( - displayName + " must be shorter than " + Reference.DEFAULT_MESSAGE_LIMIT); - } - } - - public static int getCurrentMessageLimit() { - return enabled - ? Reference.EXTENDED_MESSAGE_LIMIT - : Reference.DEFAULT_MESSAGE_LIMIT; - } - - public static int getCurrentPacketMessageLimit() { - if (!enabled) { - return Reference.DEFAULT_MESSAGE_LIMIT; - } - - return splitEnabled - ? Reference.DEFAULT_MESSAGE_LIMIT - : Reference.EXTENDED_MESSAGE_LIMIT; - } - - @Mod.EventHandler - public void preInit(FMLPreInitializationEvent event) { - ExtendedMessagesConfig.load( - event.getSuggestedConfigurationFile() - ); - - enabled = ExtendedMessagesConfig.getEnabled(); - splitEnabled = ExtendedMessagesConfig.getSplitEnabled(); - messageDelaySeconds = ExtendedMessagesConfig.getMessageDelaySeconds(); - - messagePrefixEnabled = ExtendedMessagesConfig.getMessagePrefixEnabled(); - messagePrefix = ExtendedMessagesConfig.getMessagePrefix(); - - commandPrefixEnabled = ExtendedMessagesConfig.getCommandPrefixEnabled(); - commandPrefix = ExtendedMessagesConfig.getCommandPrefix(); - } - - @Mod.EventHandler - public void init(FMLInitializationEvent event) { - ClientCommandHandler.instance.registerCommand( - new ExtendedMessagesCommand() - ); - - MinecraftForge.EVENT_BUS.register(MessageQueue.getInstance()); - - System.out.println("[" + Reference.NAME + "] Mod has loaded :3"); - } -} diff --git a/src/main/java/com/github/cewko/extendedmessages/ExtendedMessagesCommand.java b/src/main/java/com/github/cewko/extendedmessages/ExtendedMessagesCommand.java deleted file mode 100644 index 39804c5..0000000 --- a/src/main/java/com/github/cewko/extendedmessages/ExtendedMessagesCommand.java +++ /dev/null @@ -1,311 +0,0 @@ -package com.github.cewko.extendedmessages; - -import java.util.Collections; -import java.util.List; - -import net.minecraft.command.CommandBase; -import net.minecraft.command.ICommandSender; -import net.minecraft.command.CommandException; -import net.minecraft.command.WrongUsageException; -import net.minecraft.util.ChatComponentText; -import net.minecraft.util.EnumChatFormatting; - -public final class ExtendedMessagesCommand extends CommandBase { - - @Override - public String getCommandName() { - return "extendedmessages"; - } - - @Override - public List getCommandAliases() { - return Collections.singletonList("em"); - } - - @Override - public String getCommandUsage(ICommandSender sender) { - return "/em [toggle|split|delay <" - + Reference.MIN_MESSAGE_DELAY_SECONDS - + "-" - + Reference.MAX_MESSAGE_DELAY_SECONDS - + ">|prefix |party ]"; - } - - @Override - public int getRequiredPermissionLevel() { - return 0; - } - - @Override - public void processCommand(ICommandSender sender, String[] args) - throws CommandException { - - if (args.length == 0) { - showStatus(sender); - return; - } - - if (args.length == 1 && "toggle".equalsIgnoreCase(args[0])) { - boolean enabled = ExtendedMessages.toggleEnabled(); - sendLine(sender, "Remove 100-character limit: " + formatState(enabled)); - - return; - } - - if (args.length == 1 && "split".equalsIgnoreCase(args[0])) { - boolean enabled = ExtendedMessages.toggleSplitEnabled(); - - sendLine(sender, "Split long messages: " + formatState(enabled) - + formatSplitRisk(enabled) - ); - - return; - } - - if (args.length == 2 && "delay".equalsIgnoreCase(args[0])) { - - int seconds = parseInt( - args[1], - Reference.MIN_MESSAGE_DELAY_SECONDS, - Reference.MAX_MESSAGE_DELAY_SECONDS - ); - - ExtendedMessages.setMessageDelaySeconds(seconds); - - sendLine( - sender, - "Message delay: " - + EnumChatFormatting.AQUA - + seconds - + EnumChatFormatting.GRAY - + (seconds == 1 ? " second" : " seconds") - ); - - return; - } - - if ("prefix".equalsIgnoreCase(args[0])) { - handlePrefixCommand(sender, args); - return; - } - - if ("party".equalsIgnoreCase(args[0])) { - handlePartyCommand(sender, args); - return; - } - - throw new WrongUsageException(getCommandUsage(sender)); - } - - private void handlePrefixCommand( - ICommandSender sender, String[] args) throws CommandException { - - if (args.length == 1) { - showPrefixStatus(sender); - return; - } - - if (args.length == 2 && "toggle".equalsIgnoreCase(args[1])) { - boolean enabled = ExtendedMessages.toggleMessagePrefixEnabled(); - - sendLine(sender, "Message prefix: " + formatState(enabled)); - - return; - } - - if (args.length == 2 && "remove".equalsIgnoreCase(args[1])) { - ExtendedMessages.setMessagePrefix(""); - sendLine(sender, "Message prefix removed"); - return; - } - - if (args.length >= 3 && "set".equalsIgnoreCase(args[1])) { - String prefix = joinArgs(args, 2); - - try { - ExtendedMessages.setMessagePrefix(prefix); - } catch (IllegalArgumentException exception) { - throw new CommandException( - exception.getMessage() - ); - } - - sendLine(sender, - "Message prefix set to " + formatValue(ExtendedMessages.getMessagePrefix()) - ); - - return; - } - - throw new WrongUsageException( - "/em prefix [toggle|set |remove]" - ); - } - - private void handlePartyCommand( - ICommandSender sender, String[] args) throws CommandException { - - if (args.length == 1) { - showPartyStatus(sender); - return; - } - - if (args.length == 2 && "toggle".equalsIgnoreCase(args[1])) { - boolean enabled = ExtendedMessages.toggleCommandPrefixEnabled(); - sendLine(sender, "Party command: " + formatState(enabled)); - return; - } - - if (args.length >= 3 && "set".equalsIgnoreCase(args[1])) { - String commandPrefix = joinArgs(args, 2); - - try { - ExtendedMessages.setCommandPrefix(commandPrefix); - } catch (IllegalArgumentException exception) { - throw new CommandException( - exception.getMessage() - ); - } - - sendLine(sender, - "Party command set to " + formatValue( - ExtendedMessages.getCommandPrefix())); - - return; - } - - throw new WrongUsageException("/em party [toggle|set ]"); - } - - private String joinArgs(String[] args, int startIndex) { - StringBuilder result = new StringBuilder(); - - for (int i = startIndex; i < args.length; i++) { - if (i > startIndex) { - result.append(" "); - } - - result.append(args[i]); - } - - return result.toString(); - } - - private void showStatus(ICommandSender sender) { - sender.addChatMessage(new ChatComponentText( - EnumChatFormatting.AQUA - + "[" + Reference.NAME + "]" - )); - - sender.addChatMessage(new ChatComponentText( - EnumChatFormatting.GRAY - + "Remove 100-character limit: " - + formatState(ExtendedMessages.isEnabled()) - )); - - sender.addChatMessage(new ChatComponentText( - EnumChatFormatting.GRAY - + "Split long messages: " - + formatState(ExtendedMessages.isSplitEnabled()) - + formatSplitRisk(ExtendedMessages.isSplitEnabled()) - )); - - int delay = ExtendedMessages.getMessageDelaySeconds(); - - sender.addChatMessage(new ChatComponentText( - EnumChatFormatting.GRAY - + "Message delay: " - + EnumChatFormatting.AQUA - + delay - + EnumChatFormatting.GRAY - + (delay == 1 ? " second" : " seconds") - )); - - sender.addChatMessage(new ChatComponentText( - EnumChatFormatting.DARK_GRAY - + "/em toggle" - )); - - sender.addChatMessage(new ChatComponentText( - EnumChatFormatting.DARK_GRAY - + "/em split" - )); - - sender.addChatMessage(new ChatComponentText( - EnumChatFormatting.DARK_GRAY - + "/em delay " - )); - - sender.addChatMessage(new ChatComponentText( - EnumChatFormatting.GRAY + "Message prefix: " - + formatState(ExtendedMessages.isMessagePrefixEnabled()) - + EnumChatFormatting.GRAY - + " " - + formatValue(ExtendedMessages.getMessagePrefix()) - )); - - sender.addChatMessage(new ChatComponentText( - EnumChatFormatting.GRAY + "Party command: " - + formatState(ExtendedMessages.isCommandPrefixEnabled()) - + EnumChatFormatting.GRAY - + " " - + formatValue(ExtendedMessages.getCommandPrefix()) - )); - } - - private void showPrefixStatus(ICommandSender sender) { - sendLine(sender, "Message prefix: " - + formatState( - ExtendedMessages.isMessagePrefixEnabled() - ) - ); - - sendLine(sender, "Message prefix value: " - + formatValue( - ExtendedMessages.getMessagePrefix() - ) - ); - } - - private void showPartyStatus(ICommandSender sender) { - sendLine(sender, "Party command: " - + formatState( - ExtendedMessages.isCommandPrefixEnabled() - ) - ); - - sendLine(sender, "Party command value: " - + formatValue( - ExtendedMessages.getCommandPrefix() - ) - ); - } - - private void sendLine(ICommandSender sender, String message) { - sender.addChatMessage(new ChatComponentText( - EnumChatFormatting.GRAY - + "[" + Reference.NAME + "] " - + message - )); - } - - private String formatState(boolean enabled) { - return enabled ? EnumChatFormatting.GREEN + "ON" : EnumChatFormatting.RED + "OFF"; - } - - private String formatSplitRisk(boolean splitEnabled) { - if (splitEnabled) { - return ""; - } - - return EnumChatFormatting.RED - + " (unsafe; servers might kick you)"; - } - - private String formatValue(String value) { - if (value.isEmpty()) { - return EnumChatFormatting.DARK_GRAY + ""; - } - return EnumChatFormatting.AQUA + "\"" + value + "\""; - } -} diff --git a/src/main/java/com/github/cewko/extendedmessages/messaging/MessageQueue.java b/src/main/java/com/github/cewko/extendedmessages/messaging/MessageQueue.java deleted file mode 100644 index 2d1a531..0000000 --- a/src/main/java/com/github/cewko/extendedmessages/messaging/MessageQueue.java +++ /dev/null @@ -1,108 +0,0 @@ -package com.github.cewko.extendedmessages.messaging; - -import com.github.cewko.extendedmessages.ExtendedMessages; - -import java.util.ArrayDeque; -import java.util.Deque; -import java.util.List; - -import net.minecraft.client.Minecraft; -import net.minecraft.world.World; -import net.minecraftforge.fml.common.eventhandler.SubscribeEvent; -import net.minecraftforge.fml.common.gameevent.TickEvent; - -public final class MessageQueue { - private static final MessageQueue INSTANCE = new MessageQueue(); - private final Deque chunks = new ArrayDeque(); - - private World queuedWorld; - private long nextSendAtMillis; - private boolean sendingQueuedMessage; - - private MessageQueue() { - } - - public static MessageQueue getInstance() { - return INSTANCE; - } - - public void enqueueLines(List lines) { - Minecraft minecraft = Minecraft.getMinecraft(); - - if (lines.isEmpty() || minecraft.thePlayer == null || minecraft.theWorld == null) { - return; - } - - if (queuedWorld != null && queuedWorld != minecraft.theWorld) { - clear(); - } - - boolean sendImmediately = chunks.isEmpty() - && System.currentTimeMillis() >= nextSendAtMillis; - - queuedWorld = minecraft.theWorld; - chunks.addAll(lines); - - if (sendImmediately) { - sendNext(minecraft); - } - } - - @SubscribeEvent - public void onClientTick(TickEvent.ClientTickEvent event) { - if (event.phase != TickEvent.Phase.END || chunks.isEmpty()) { - return; - } - - Minecraft minecraft = Minecraft.getMinecraft(); - - if (minecraft.thePlayer == null || minecraft.theWorld == null - || minecraft.theWorld != queuedWorld || !ExtendedMessages.isEnabled()) { - clear(); - return; - } - - if (System.currentTimeMillis() >= nextSendAtMillis) { - sendNext(minecraft); - } - } - - public void clear() { - chunks.clear(); - queuedWorld = null; - nextSendAtMillis = 0L; - } - - private void sendNext(Minecraft minecraft) { - String chunk = chunks.pollFirst(); - - if (chunk == null) { - clear(); - return; - } - - sendingQueuedMessage = true; - - try { - minecraft.thePlayer.sendChatMessage(chunk); - } finally { - sendingQueuedMessage = false; - } - - nextSendAtMillis = System.currentTimeMillis() + ExtendedMessages.getMessageDelaySeconds() * 1000L; - - if (chunks.isEmpty()) { - queuedWorld = null; - return; - } - - } - - public boolean isSendingQueuedMessage() { - return sendingQueuedMessage; - } - - public boolean shouldQueueNewMessages() { - return !chunks.isEmpty() || System.currentTimeMillis() < nextSendAtMillis; - } -} diff --git a/src/main/resources/mcmod.info b/src/main/resources/mcmod.info index 07c6b39..d059306 100644 --- a/src/main/resources/mcmod.info +++ b/src/main/resources/mcmod.info @@ -1,11 +1,11 @@ [ { "modid": "${modid}", - "name": "Extended Messages", - "description": "extends Minecraft 1.8.9 message limit to 256 characters", + "name": "enhanmess", + "description": "adds 256-character message support, increased history length, configurable prefixes, cooldowns & message splitting", "version": "${version}", "mcversion": "${mcversion}", - "url": "", + "url": "https://github.com/cewko/enhanmess/", "updateUrl": "", "authorList": [ "cewko" diff --git a/src/main/resources/mixins.extendedmessages.json b/src/main/resources/mixins.enhanmess.json similarity index 100% rename from src/main/resources/mixins.extendedmessages.json rename to src/main/resources/mixins.enhanmess.json