├── .github ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── PULL_REQUEST_TEMPLATE │ └── documentation.md └── workflows │ ├── discord_publish.yml │ └── publish.yml ├── .gitignore ├── HEADER.txt ├── LICENSE.txt ├── README.md ├── build.gradle ├── docs ├── _config.yml ├── chatBox │ ├── assets │ │ └── images │ │ │ ├── ACC-ChatBox_Icon.png │ │ │ ├── calculatorMASS.png │ │ │ ├── colorCode.png │ │ │ ├── colorShowcaseMASS.png │ │ │ ├── shortcutMASS.png │ │ │ └── spellCheck.png │ └── chatBox.md ├── chatHUD │ ├── ChatHUD.md │ └── assets │ │ └── images │ │ ├── ACC-ChatHUD_Icon.png │ │ ├── ChatButtons.png │ │ ├── ChatColoring.png │ │ ├── ChatHUDTab.png │ │ ├── ChatHeadsDisplay.png │ │ ├── ChatHxW.png │ │ ├── ChatLineStyle.png │ │ ├── ChatPaddingUI.png │ │ ├── ChatRightSideTabBtn.png │ │ ├── ChatStrippedMsg.png │ │ ├── ChatTabsTab.png │ │ ├── ChatUnreadMsg.png │ │ └── RightClickContextMenu.png ├── chatLog │ ├── assets │ │ └── images │ │ │ ├── ACC-ChatLog_Icon.png │ │ │ ├── LogTAB.png │ │ │ ├── logGUI.png │ │ │ └── logView.png │ └── chatLog.md ├── commonKnowledge │ ├── commonKnowledgeCOLOR.md │ ├── commonKnowledgeMATH.md │ ├── commonKnowledgeREGEX.md │ └── index.md ├── core │ ├── core_configuration.md │ └── index.md ├── filters │ ├── common_filters.md │ ├── images │ │ └── filterconfig.png │ ├── index.md │ └── tutorial.md ├── index.md └── modules │ ├── assets │ └── images │ │ ├── ACC-ChatBox_Icon.png │ │ ├── ACC-ChatFilters_Icon.png │ │ ├── ACC-ChatHUD_Icon.png │ │ ├── ACC-ChatLog_Icon.png │ │ ├── ACC-ChatMacros_Icon.png │ │ └── AdvancedChatCore_Icon.png │ └── modulesOverview.md ├── gradle.properties ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── icon - original.png ├── jitpack.yml ├── settings.gradle └── src └── main ├── java └── io │ └── github │ └── darkkronicle │ └── advancedchatcore │ ├── AdvancedChatCore.java │ ├── InitHandler.java │ ├── Module.java │ ├── ModuleHandler.java │ ├── chat │ ├── AdvancedChatScreen.java │ ├── AdvancedSleepingChatScreen.java │ ├── AdvancedTextField.java │ ├── ChatHistory.java │ ├── ChatHistoryProcessor.java │ ├── ChatMessage.java │ ├── ChatScreenSectionHolder.java │ ├── DefaultChatSuggestor.java │ ├── MessageDispatcher.java │ ├── MessageOwner.java │ └── MessageSender.java │ ├── config │ ├── ConfigStorage.java │ ├── SaveableConfig.java │ ├── gui │ │ ├── GuiConfig.java │ │ ├── GuiConfigHandler.java │ │ ├── ModMenuImpl.java │ │ ├── OnOffListListener.java │ │ ├── TabSupplier.java │ │ └── widgets │ │ │ ├── WidgetColor.java │ │ │ ├── WidgetIntBox.java │ │ │ ├── WidgetLabelHoverable.java │ │ │ ├── WidgetListRegistryOption.java │ │ │ ├── WidgetRegistryOptionEntry.java │ │ │ └── WidgetToggle.java │ └── options │ │ └── ConfigColor.java │ ├── finder │ ├── CustomFinder.java │ ├── LiteralFinder.java │ ├── PatternFinder.java │ ├── RegexFinder.java │ ├── UpperLowerFinder.java │ └── custom │ │ └── ProfanityFinder.java │ ├── gui │ ├── CleanButton.java │ ├── ConfigGuiListBase.java │ ├── ContextMenu.java │ ├── CoreGuiListBase.java │ ├── IconButton.java │ ├── WidgetConfigList.java │ ├── WidgetConfigListEntry.java │ └── buttons │ │ ├── BackButtonListener.java │ │ ├── Buttons.java │ │ ├── ConfigTabsButtonListener.java │ │ └── NamedSimpleButton.java │ ├── hotkeys │ └── InputHandler.java │ ├── interfaces │ ├── AdvancedChatScreenSection.java │ ├── ConfigRegistryOption.java │ ├── IChatMessageProcessor.java │ ├── IClosable.java │ ├── IFinder.java │ ├── IJsonApplier.java │ ├── IJsonSave.java │ ├── IMatchProcessor.java │ ├── IMessageFilter.java │ ├── IMessageProcessor.java │ ├── IScreenSupplier.java │ ├── IStringFilter.java │ ├── RegistryOption.java │ └── Translatable.java │ ├── konstruct │ ├── AdvancedChatKonstruct.java │ └── StringMatchObject.java │ ├── mixin │ ├── MixinChatHud.java │ ├── MixinChatHudInvoker.java │ ├── MixinChatScreen.java │ ├── MixinClientPlayerEntity.java │ ├── MixinKeyboard.java │ ├── MixinMessageIndicator.java │ ├── MixinMinecraftClient.java │ └── MixinSleepingChatScreen.java │ └── util │ ├── AbstractRegistry.java │ ├── Color.java │ ├── ColorUtil.java │ ├── Colors.java │ ├── EasingMethod.java │ ├── FindPair.java │ ├── FindType.java │ ├── LimitedInteger.java │ ├── ProfanityUtil.java │ ├── RawText.java │ ├── RowList.java │ ├── SearchResult.java │ ├── SearchUtils.java │ ├── StringInsert.java │ ├── StringMatch.java │ ├── StyleFormatter.java │ ├── SyncTaskQueue.java │ ├── TextBuilder.java │ ├── TextUtil.java │ └── TomlUtil.java └── resources ├── advancedchatcore.mixins.json ├── assets └── advancedchatcore │ ├── icon.png │ ├── lang │ ├── en_us.json │ └── zh_cn.json │ └── textures │ └── gui │ └── settings.png ├── colors.toml └── fabric.mod.json /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: "[BUG]" 5 | labels: bug 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **Minecraft Info** 14 | Minecraft information: 15 | - AdvancedChat version [e.g. AdvancedChat-2.0.0-beta] 16 | 17 | **To Reproduce** 18 | Steps to reproduce the behavior: 19 | 1. Go to '...' 20 | 2. Click on '....' 21 | 3. Scroll down to '....' 22 | 4. See error 23 | 24 | **Expected behavior** 25 | A clear and concise description of what you expected to happen. 26 | 27 | **Screenshots** 28 | If applicable, add screenshots to help explain your problem. 29 | 30 | **Additional context** 31 | Add any other context about the problem here. This could be a mods list, server, etc. 32 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: "[FEATURE]" 5 | labels: feature 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Additional context** 17 | Add any other context or screenshots about the feature request here. 18 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE/documentation.md: -------------------------------------------------------------------------------- 1 | ## Key Topics 2 | 3 | What key topics did you update/add? -------------------------------------------------------------------------------- /.github/workflows/discord_publish.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - main 5 | jobs: 6 | build: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - uses: actions/checkout@main 10 | - name: Set up JDK 17 11 | uses: actions/setup-java@v1 12 | with: 13 | java-version: 17 14 | - name: Upload to Discord 15 | run: ./gradlew discord --stacktrace 16 | if: | 17 | !contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.pull_request.title, '[ci skip]') 18 | env: 19 | discord_webhook: ${{ secrets.DISCORD_WEBHOOK }} 20 | action_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }} 21 | - name: Capture build artifacts 22 | uses: actions/upload-artifact@v2 23 | with: 24 | name: Artifacts 25 | path: build/libs/ -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | on: 2 | workflow_dispatch: 3 | inputs: 4 | previousVersion: 5 | description: 'Previous Version (Do not include v prefix, must be same as the last version tag! Example: 1.4.1)' 6 | required: true 7 | version: 8 | description: 'Version (Do not include v prefix! Example: 1.4.2)' 9 | required: true 10 | jobs: 11 | build: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@main 15 | - name: Fetch tags 16 | run: git fetch --tags 17 | - name: Set up JDK 17 18 | uses: actions/setup-java@v1 19 | with: 20 | java-version: 17 21 | - name: Upload to websites 22 | run: ./gradlew publishThirdParty --stacktrace -PlastTag="v${{ github.event.inputs.previousVersion }}" -PcurrentTag="v${{ github.event.inputs.version }}" 23 | if: | 24 | !contains(github.event.head_commit.message, '[ci skip]') && !contains(github.event.pull_request.title, '[ci skip]') 25 | env: 26 | modrinth_token: ${{ secrets.MODRINTH_TOKEN }} 27 | curseforge_token: ${{ secrets.CURSEFORGE_TOKEN }} 28 | github_token: ${{ secrets.GH_API_KEY }} 29 | discord_release_webhook: ${{ secrets.DISCORD_RELEASE_WEBHOOK }} 30 | - name: Capture build artifacts 31 | uses: actions/upload-artifact@v2 32 | with: 33 | name: Artifacts 34 | path: build/libs/ -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | *.iml 3 | *.ipr 4 | *.iws 5 | lib/ 6 | run/ 7 | out/ 8 | bin/ 9 | build/ 10 | .gradle/ 11 | classes/ 12 | lombok.config 13 | extra.properties 14 | swear_words.csv -------------------------------------------------------------------------------- /HEADER.txt: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) $YEAR DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # AdvancedChatCore 2 | 3 | This is the base mod of all AdvancedChat modules and features. This mod provides the necessary foundation and framework for AdvancedChat mod's to work. 4 | 5 | This mod primarily adds internal features used by other modules, as well as the ability to display the time that a message was sent. 6 | 7 | ## Dependencies 8 | [MaLiLib](https://www.curseforge.com/minecraft/mc-mods/malilib) and [Fabric API](https://www.curseforge.com/minecraft/mc-mods/fabric-api/) are **required** for this mod to run 9 | 10 | [Mod Menu](https://www.curseforge.com/minecraft/mc-mods/modmenu) is strongly recommended, as it allows you to easily edit the config 11 | 12 | 13 | ## Configuration 14 | 15 | You can either manually edit the config file, located in `~.minecraft/config/advancedchat/advancedchatcore.json`, or you can open the configuration screen using mod menu (see **Dependencies**) 16 | 17 | 18 | ## About AdvancedChat Modules 19 | 20 | AdvancedChat Modules splits the features of [AdvancedChat](https://www.curseforge.com/minecraft/mc-mods/advancedchat/) into several different mods, all of which depend on AdvancedChatCore. This simplifies development, and also allows for the user to pick-and-choose what features of AdvancedChat they want or don't want. The main AdvancedChat mod will eventually serve as a bundle of all AdvancedChat modules. [Full list](https://github.com/DarkKronicle/AdvancedChatCore/wiki/Modules-List) 21 | 22 | ## Developers 23 | 24 | To use AdvancedChatCore within your own mod you can use [jitpack](https://jitpack.io/) with maven to download and implement it. 25 | 26 | ``` 27 | allprojects { 28 | repositories { 29 | ... 30 | maven { url 'https://jitpack.io' } 31 | } 32 | } 33 | ``` 34 | 35 | ``` 36 | dependencies { 37 | modImplementation 'com.github.DarkKronicle:AdvancedChatCore:VERSION' 38 | } 39 | ``` 40 | 41 | To have the core reference the mod as a module, int `fabric.mod.json` in `custom` put `"acmodule: true"` 42 | 43 | ```JSON 44 | { 45 | ... 46 | "custom": { 47 | "acmodule": true 48 | } 49 | } 50 | ``` 51 | 52 | Reference the [example mod](https://github.com/DarkKronicle/AdvancedChatModuleTemplate) for individual use cases. 53 | 54 | ## Development 55 | 56 | To develop, all dependencies should automatically be processed through gradle. 57 | 58 | ## Credits n' more 59 | 60 | Code & Mastermind: DarkKronicle 61 | 62 | Update to 1.16.3: lmichaelis 63 | 64 | Logo & Proofreading: Chronos22 65 | 66 | Libraries: 67 | - [MathParser](http://mathparser.org/) 68 | - [OwO](https://github.com/maowcraft/owo) 69 | 70 | For more help join the [Discord](https://discord.gg/WnaE3uZxDA) 71 | -------------------------------------------------------------------------------- /build.gradle: -------------------------------------------------------------------------------- 1 | plugins { 2 | id 'fabric-loom' version '1.0-SNAPSHOT' 3 | id 'maven-publish' 4 | id "io.freefair.lombok" version "6.0.0-m2" 5 | } 6 | 7 | apply from: 'https://raw.githubusercontent.com/DarkKronicle/GradleScripts/main/gradle/publish.gradle' 8 | 9 | sourceCompatibility = JavaVersion.VERSION_17 10 | targetCompatibility = JavaVersion.VERSION_17 11 | 12 | archivesBaseName = project.archives_base_name 13 | version = "${project.minecraft_version}-${project.mod_version}" 14 | group = project.maven_group 15 | 16 | Properties additionalProperties = new Properties() 17 | if (file("extra.properties").exists()) { 18 | additionalProperties.load(file("extra.properties").newReader()) 19 | } 20 | 21 | repositories { 22 | mavenCentral() 23 | maven { url 'https://masa.dy.fi/maven' } 24 | maven { url 'https://maven.terraformersmc.com/releases/' } 25 | maven { url 'https://jitpack.io' } 26 | maven { url 'https://maven.wispforest.io' } 27 | } 28 | 29 | dependencies { 30 | minecraft "com.mojang:minecraft:${project.minecraft_version}" 31 | mappings "net.fabricmc:yarn:${project.yarn_mappings}:v2" 32 | modImplementation "net.fabricmc:fabric-loader:${project.loader_version}" 33 | modImplementation "net.fabricmc.fabric-api:fabric-api:${project.fabric_api_version}" 34 | modImplementation "fi.dy.masa.malilib:malilib-fabric-1.20.2:${project.malilib_version}" 35 | modCompileOnly "com.terraformersmc:modmenu:${project.modmenu_version}" 36 | 37 | implementation "com.github.DarkKronicle.Konstruct:addons:${project.konstruct_version}" 38 | implementation "com.github.DarkKronicle.Konstruct:core:${project.konstruct_version}" 39 | 40 | implementation 'com.electronwill.night-config:toml:3.6.5' 41 | // Transitive 42 | include 'com.electronwill.night-config:toml:3.6.5' 43 | include 'com.electronwill.night-config:core:3.6.5' 44 | 45 | 46 | include "com.github.DarkKronicle.Konstruct:addons:${project.konstruct_version}" 47 | include "com.github.DarkKronicle.Konstruct:core:${project.konstruct_version}" 48 | 49 | implementation "org.mariuszgromada.math:MathParser.org-mXparser:${project.mxparser_version}" 50 | include "org.mariuszgromada.math:MathParser.org-mXparser:${project.mxparser_version}" 51 | 52 | implementation "io.github.maowimpl:owo:${project.owo_version}" 53 | include "io.github.maowimpl:owo:${project.owo_version}" 54 | 55 | implementation 'org.apache.commons:commons-csv:1.8' 56 | include 'org.apache.commons:commons-csv:1.8' 57 | 58 | } 59 | 60 | processResources { 61 | inputs.property "version", project.version 62 | 63 | filesMatching("fabric.mod.json") { 64 | expand "version": project.version 65 | } 66 | } 67 | 68 | tasks.withType(JavaCompile).configureEach { 69 | it.options.encoding = "UTF-8" 70 | it.options.release = 17 71 | } 72 | 73 | task sourcesJar(type: Jar, dependsOn: classes) { 74 | classifier = "sources" 75 | from sourceSets.main.allSource 76 | } 77 | 78 | jar { 79 | from "LICENSE.txt" 80 | } 81 | 82 | tasks.register('downloadExtra') { 83 | def f = new File('./src/main/resources/swear_words.csv') 84 | if (!f.exists()) { 85 | new URL('https://raw.githubusercontent.com/surge-ai/profanity/main/profanity_en.csv').withInputStream{ i -> f.withOutputStream{ it << i }} 86 | } 87 | } 88 | 89 | assemble { 90 | dependsOn 'downloadExtra' 91 | } 92 | 93 | // configure the maven publication 94 | publishing { 95 | publications { 96 | mavenJava(MavenPublication) { 97 | // add all the jars that should be included when publishing to maven 98 | artifact(remapJar) { 99 | builtBy remapJar 100 | } 101 | artifact(sourcesJar) { 102 | builtBy remapSourcesJar 103 | } 104 | } 105 | } 106 | 107 | // select the repositories you want to publish to 108 | repositories { 109 | // uncomment to publish to the local maven 110 | // mavenLocal() 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /docs/_config.yml: -------------------------------------------------------------------------------- 1 | remote_theme: pmarsceill/just-the-docs 2 | color_scheme: dark 3 | title: AdvancedChat 4 | description: Documentation for AdvancedChat 5 | aux_links: 6 | "AdvancedChat on GitHub": 7 | - "https://github.com/DarkKronicle/AdvancedChatCore" 8 | gh_edit_link: true 9 | gh_edit_link_text: "Edit this page on GitHub" 10 | gh_edit_repository: "https://github.com/DarkKronicle/AdvancedChatCore" 11 | gh_edit_branch: "main" 12 | gh_edit_source: docs 13 | gh_edit_view_mode: "tree" 14 | 15 | search_enabled: true 16 | search: 17 | heading_level: 2 18 | previews: 2 19 | preview_words_before: 5 20 | preview_words_after: 5 21 | tokenizer_separator: /[\s\-/]+/ 22 | rel_url: true 23 | button: true -------------------------------------------------------------------------------- /docs/chatBox/assets/images/ACC-ChatBox_Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/chatBox/assets/images/ACC-ChatBox_Icon.png -------------------------------------------------------------------------------- /docs/chatBox/assets/images/calculatorMASS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/chatBox/assets/images/calculatorMASS.png -------------------------------------------------------------------------------- /docs/chatBox/assets/images/colorCode.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/chatBox/assets/images/colorCode.png -------------------------------------------------------------------------------- /docs/chatBox/assets/images/colorShowcaseMASS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/chatBox/assets/images/colorShowcaseMASS.png -------------------------------------------------------------------------------- /docs/chatBox/assets/images/shortcutMASS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/chatBox/assets/images/shortcutMASS.png -------------------------------------------------------------------------------- /docs/chatBox/assets/images/spellCheck.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/chatBox/assets/images/spellCheck.png -------------------------------------------------------------------------------- /docs/chatHUD/assets/images/ACC-ChatHUD_Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/chatHUD/assets/images/ACC-ChatHUD_Icon.png -------------------------------------------------------------------------------- /docs/chatHUD/assets/images/ChatButtons.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/chatHUD/assets/images/ChatButtons.png -------------------------------------------------------------------------------- /docs/chatHUD/assets/images/ChatColoring.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/chatHUD/assets/images/ChatColoring.png -------------------------------------------------------------------------------- /docs/chatHUD/assets/images/ChatHUDTab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/chatHUD/assets/images/ChatHUDTab.png -------------------------------------------------------------------------------- /docs/chatHUD/assets/images/ChatHeadsDisplay.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/chatHUD/assets/images/ChatHeadsDisplay.png -------------------------------------------------------------------------------- /docs/chatHUD/assets/images/ChatHxW.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/chatHUD/assets/images/ChatHxW.png -------------------------------------------------------------------------------- /docs/chatHUD/assets/images/ChatLineStyle.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/chatHUD/assets/images/ChatLineStyle.png -------------------------------------------------------------------------------- /docs/chatHUD/assets/images/ChatPaddingUI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/chatHUD/assets/images/ChatPaddingUI.png -------------------------------------------------------------------------------- /docs/chatHUD/assets/images/ChatRightSideTabBtn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/chatHUD/assets/images/ChatRightSideTabBtn.png -------------------------------------------------------------------------------- /docs/chatHUD/assets/images/ChatStrippedMsg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/chatHUD/assets/images/ChatStrippedMsg.png -------------------------------------------------------------------------------- /docs/chatHUD/assets/images/ChatTabsTab.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/chatHUD/assets/images/ChatTabsTab.png -------------------------------------------------------------------------------- /docs/chatHUD/assets/images/ChatUnreadMsg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/chatHUD/assets/images/ChatUnreadMsg.png -------------------------------------------------------------------------------- /docs/chatHUD/assets/images/RightClickContextMenu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/chatHUD/assets/images/RightClickContextMenu.png -------------------------------------------------------------------------------- /docs/chatLog/assets/images/ACC-ChatLog_Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/chatLog/assets/images/ACC-ChatLog_Icon.png -------------------------------------------------------------------------------- /docs/chatLog/assets/images/LogTAB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/chatLog/assets/images/LogTAB.png -------------------------------------------------------------------------------- /docs/chatLog/assets/images/logGUI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/chatLog/assets/images/logGUI.png -------------------------------------------------------------------------------- /docs/chatLog/assets/images/logView.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/chatLog/assets/images/logView.png -------------------------------------------------------------------------------- /docs/chatLog/chatLog.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Log 4 | nav_order: 5 5 | has_children: false 6 | --- 7 | 8 | # AdvancedChat ChatLog Overview 9 |
10 | 11 | Table of contents 12 | 13 | {: .text-delta } 14 | 1. TOC 15 | {:toc} 16 |
17 | 18 | --- 19 | ![ACC-ChatLogIcon](./assets/images/ACC-ChatLog_Icon.png) 20 | ### AdvancedChatLog 21 | - View, store and sort through mass amounts of previous messages. 22 | 23 | --- 24 | ### Overview 25 | {:toc} 26 | The information on this page is for the features of the **ChatLog** module of AdvancedChat. 27 | Once the mod is installed a **Chat Log** tab will be added to the AdvancedChat Config Menu, as well as a button in the chat GUI that looks like 3 stacked bars. 28 | 29 | **A bit of information** 30 | This mod allows you to not only store messages typed in game to a local file, but also allows the ability to leave the game either to the menu or to the desktop, and come back to your world with your previously sent messages. 31 | You can configure how many lines of chat are stored, as well as how many of those stored lines will be saved in order to be loaded the next time you play. Plus you can also search those saved lines in game via a chat GUI button. 32 | 33 | --- 34 | ### Available Tabs and Settings 35 | {:toc} 36 | The following section will go over all the available tabs and settings in each tab that you can modify. This information can also be found [here](https://darkkronicle.github.io/AdvancedChatCore/modules/modulesOverview.html), in the Modules Overview section. As well as overviews for all other modules available as of January 31st 2022. 37 | 38 | **In Game Buttons** 39 | - The Chatlog module adds an additional button to the right of the UI that looks like 3 stacked bars once the chat is opened. That is used to view and search chat. The search options use the **Filter Type** button that cycles the options; 40 | - **Literal**, exact match. 41 | - **Upper-Lower**, literal but not case-sensitive. 42 | - **RegEx**, Parses the strings as Regular Expression. 43 | - **Custom**, Allows for custom search parameters. 44 | 45 | ![Log GUI](./assets/images/logGUI.png) 46 | 47 | ***Chat Log Tab*** 48 | - Stored Lines - This value dictates how many lines of information are saved to the log file. Fair warning, large numbers may result in out of memory errors. 49 | - Saved - Lines - The amount of stored lines that are loaded when the game starts. 50 | - Clean Saved Lines - When true this will make it so that the log doesn't save things like mouse clicks and movements to help reduce the logs file size. 51 | 52 | ![Log Tab](./assets/images/LogTAB.png) 53 | 54 | **Output File** 55 | - It should be noted that the location of the log output file is in your .minecraft folder, either in the directory in the 'chatlogs' folder or in your profiles 'chatlogs' folder. (*~/.minecraft/chatlogs/ -OR- ~/.minecraft/MC_Profile_Name/chatlogs/*) 56 | 57 | ![Log Output View](./assets/images/logView.png) 58 | 59 | 60 | -------------------------------------------------------------------------------- /docs/commonKnowledge/commonKnowledgeCOLOR.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Color 4 | nav_order: 2 5 | parent: Common Knowledge 6 | --- 7 | 8 | # Common Knowledge - Color 9 |
10 | 11 | Table of contents 12 | 13 | {: .text-delta } 14 | 1. TOC 15 | {:toc} 16 |
17 | 18 | --- 19 | ## Color in AdvancedChat 20 | {:toc} 21 | AdvancedChat Project, the name given to encompass all of the AdvancedChat mods(Core, HUD, Box, Log, and Filters), has the option to change the color of certain things. Anytime you encounter the option to change the color of a setting it will use HEX values. Some will only use the 6 character format and others may use the 8 character format. The difference between these two is the alpha channel aka the opacity of your color. 22 | 23 | A normal HEX code looks something like this #FF0000, which is bright red. The FF indicates the hue of the the RGB channels which are represented by the four zeros. But when using an 8 character HEX suddenly you unlock an additional two characters at the front of the string that represent opacity also called transparency. 24 | 25 | The proper format is #AARRGGBB where the A is alpha channels, R is red, G is green and B is blue. Which is why HEX+Alpha is sometimes referred to ARGB but has fallen out of style a bit due to ARGB referring to Addressable RGB lights. 26 | 27 | So knowing all that; #CCFF0000 would be an 80% opacity to our bright red mentioned earlier making it a slightly lighter red. As 100% opacity would be our default value of bright red. 28 | 29 | --- 30 | ## Resources 31 | {:toc} 32 | Here is a dumb of useful links to help get you on your way; 33 | - Learning 34 | - Incase you would like to learn more [here](https://learn.sparkfun.com/tutorials/hexadecimal/all) is a link to an article on HEX itself 35 | - As well as [this](https://www.codeconquest.com/hex-color-codes/) one for HEX color specifically. 36 | - Coloring 37 | - Color pallet [picker](https://coolors.co/c6c5b9-62929e-4a6d7c-393a10-475657) randomizer that has a fair few customization options. Just load the page and if you don't like the choices hit SPACE. 38 | - Have a specific color you like in an image? [This](https://imagecolorpicker.com/en) site allows you to figure out what it is. 39 | - Looking for something popular? We got you covered with [this](https://www.color-hex.com/popular-colors.php) site. 40 | - What's that you want a palette and to be popular? Well alright [here](https://www.color-hex.com/color-palettes/popular.php) you go. 41 | - If you don't want to google around for a decent HEX color picker [here](https://htmlcolorcodes.com/color-picker/) is my go to that offers HSL, CYMYK, RGB, and our needed HEX. 42 | It also has some information on things like color theory and shading. Pick your color and then just use the section below to add opacity if you'd like. 43 | 44 | --- 45 | ## HEX Opacity Table 46 | {:toc} 47 | Here is a complete table from 0% opacity all the way up to 100% opacity at single percent increments...It should be noted that you wont see much of a difference from say 1% to 3%. You more than likely will see the best result when working at 5% increments. I included 1% increments incase you want to dial it in after getting in the ball park of where youd like it. Remember! The **closer** to 100% the value is the **less** transparent it is. 48 | 49 |
50 | Click here to show the Opacity Table 51 | 52 | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 53 | | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | --- | 54 | |Opacity% | 0% | 1% | 2% | 3% | 4% | 5% | 6% | 7% | 8% | 9% | 10% | 11% | 12% | 13% | 14% | 15% | 16% | 17% | 18% | 19% | 20% | 21% | 22% | 23% | 24% | 25% | 26% | 27% | 28% | 29% | 30% | 31% | 32% | 33% | 34% | 35% | 36% | 37% | 38% | 39% | 40% | 41% | 42% | 43% | 44% | 45% | 46% | 47% | 48% | 49% | 50% | 51% | 52% | 53% | 54% | 55% | 56% | 57% | 58% | 59% | 60% | 61% | 62% | 63% | 64% | 65% | 66% | 67% | 68% | 69% | 70% | 71% | 72% | 73% | 74% | 75% | 76% | 77% | 78% | 79% | 80% | 81% | 82% | 83% | 84% | 85% | 86% | 87% | 88% | 89% | 90% | 91% | 92% | 93% | 94% | 95% | 96% | 97% | 98% | 99% | 100% | 55 | |Hex# | 00 | 02 | 05 | 07 | 0C | 0C | 0F | 11 | 14 | 16 | 19 | 1C | 1E | 21 | 23 | 26 | 28 | 2B | 2D | 30 | 33 | 35 | 38 | 3A | 3D | 3F | 42 | 44 | 47 | 49 | 4C | 4F | 51 | 54 | 56 | 59 | 5B | 5E | 60 | 63 | 66 | 68 | 6B | 6D | 70 | 72 | 75 | 77 | 7A | 7C | 7F | 82 | 84 | 87 | 89 | 8C | 8E | 91 | 93 | 96 | 99 | 9B | 9E | A0 | A3 | A5 | A8 | AA | AD | AF | B2 | B5 | B7 | BA | BC | 8F | C1 | C4 | C6 | C9 | CC | CE | D1 | D3 | D6 | D8 | DB | DD | E0 | E2 | E5 | E8 | EA | ED | EF | F2 | F4 | F7 | F9 | FC | FF | 56 | 57 |
58 | 59 | 60 | -------------------------------------------------------------------------------- /docs/commonKnowledge/commonKnowledgeMATH.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Math 4 | nav_order: 1 5 | parent: Common Knowledge 6 | --- 7 | 8 | # Common Knowledge - Math 9 |
10 | 11 | Table of contents 12 | 13 | {: .text-delta } 14 | 1. TOC 15 | {:toc} 16 |
17 | 18 | --- 19 | ## Calculator 20 | {:toc} 21 | AdvancedChat [ChatBox]() has the available option to use an in game calculator. It uses [mXparser](https://mathparser.org/) to do its business. (*Those who are more technically inclined should probably just explore the link.*) 22 | 23 | - For those needing a basic run down. 24 | - mXparser is basically just a library of information that can be used by a programmer to create code that can dip its toes into the library for any information it may need. 25 | 26 | In this case we are using it in Minecraft as a calculator. Simply put you can put into chat something simple like `1+2` or something as complex as `int( sqrt(1-x^2), x, -1, 1)`. Though for the average user what you need to know is that you don't need to worry about parentheses for longer equations. 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /docs/commonKnowledge/commonKnowledgeREGEX.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: RegEx 4 | nav_order: 3 5 | parent: Common Knowledge 6 | --- 7 | 8 | # RegEx 9 | 10 | AdvancedChat provides a lot of support for Regular Expressions (RegEx) to allow for more complex matching, filtering, and searching. 11 | 12 | ## Overview 13 | 14 | Regular Expressions are a tool to find matches within a string. They can come off as very complex, confusing, and hard to learn. 9/10 times a simple regular expression will be easy to create and easy to understand. 15 | 16 | - RegEx parser (HIGHLY RECOMMEND) - https://regex101.com/ 17 | - Interactive Tutorial - https://regexone.com/ 18 | - Visualizer - https://extendsclass.com/regex-tester.html#java 19 | - Cheat Sheet - https://cheatography.com/davechild/cheat-sheets/regular-expressions/ 20 | - Basics Video - https://www.youtube.com/watch?v=sXQxhojSdZM 21 | 22 | ## AdvancedChat Specific RegEx 23 | 24 | AdvancedChat (in specific situations) allows for matching for colors/links/other text properties within RegEx. This is supported in filters and is rolling out to other modules. 25 | 26 | How do you do it? RegEx group names. 27 | 28 | You can create a RegEx group name by using the syntax `(?)`. An example is `(?.)`. It creates a group named `eachCharacter that is applied to every character that it matches. 29 | 30 | AdvancedChat takes these names and checks to see if any start with `adv`. If they do you can apply filtering conditions making it so that AdvancedChat won't match unless the condition is met. This is a second layer, so the RegEx won't be reprocessed so `or` conditions can be a bit confusing. 31 | 32 | ## Color Example 33 | 34 | You can use any built in Minecraft color `0-9`, `a-f` to compare to as well as `o`, `l`, `m`, `n`. Let's say I only want to match to dark blue `DarkKronicle`. I would use the regex `(?DarkKronicle)`. The `adv0` specifies function 0 for AdvancedChat. Any character specified after that functions as an `or` condition. This one is only `9` which is the color code for dark blue. For example, if I did `9al` it would match dark blue, green, or bold. If an `and` condition is wanted there can be nested groups. 35 | 36 | Custom types: 37 | 38 | - `z` - A clickable link 39 | - `x` - Copy to clipboard 40 | - `y` - Open file 41 | - `w` - Run command 42 | - `v` - Suggest command 43 | - `h` - Hover text 44 | -------------------------------------------------------------------------------- /docs/commonKnowledge/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Common Knowledge 4 | nav_order: 2 5 | has_children: true 6 | --- 7 | 8 | --- 9 | # Common Knowledge 10 | 11 | These series of pages are dedicated to the aspects of the AdvancedChat project that to some are common knowledge or should be known to those using the mod(s) to some degree. 12 | 13 |
14 | 15 | Table of contents 16 | 17 | {: .text-delta } 18 | 1. TOC 19 | {:toc} 20 |
-------------------------------------------------------------------------------- /docs/core/core_configuration.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Core Configuration 4 | parent: AdvancedChatCore 5 | nav_order: 0 6 | --- 7 | 8 | # AdvancedChatCore -------------------------------------------------------------------------------- /docs/core/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Core 4 | nav_order: 1 5 | has_children: true 6 | --- 7 | 8 | # AdvancedChatCore 9 | 10 |
11 | 12 | Table of contents 13 | 14 | {: .text-delta } 15 | 1. TOC 16 | {:toc} 17 |
-------------------------------------------------------------------------------- /docs/filters/common_filters.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Common Filters 4 | nav_order: 1 5 | parent: AdvancedChatFilters 6 | --- 7 | 8 | # Common Filters 9 | 10 | To import these go to filters then click import and paste in the JSON data from this page. 11 | 12 | ## Underline Links 13 | 14 | Underline links in chat 15 | 16 | ``` 17 | {"name":"Underline Links","active":true,"stripColors":true,"findString":"(?\u003cadv0z\u003e.)","findType":"regex","replaceType":"onlymatch","replaceTo":"\u0026n$1\u0026r","replaceTextColor":false,"textColor":"#FFFFFFFF","replaceBackgroundColor":false,"backgroundColor":"#FFFFFFFF","processors":{"forward":{"active":true},"actionbar":{"active":false},"sound":{"active":false,"notifySound":"none","soundPitch":1.0,"soundVolume":1.0},"narrator":{"active":false,"message":"$1"},"konstruct":{"active":false,"nodeData":""}},"order":0} 18 | ``` 19 | 20 | ## Markdown Formatting 21 | 22 | Provides support for discord-like formatting within chat. All 5 need to be imported. 23 | 24 | 1 25 | ``` 26 | {"name":"Markdown Underline","active":true,"stripColors":true,"findString":"__([^_]*?)__","findType":"regex","replaceType":"onlymatch","replaceTo":"\u0026n$1","replaceTextColor":false,"textColor":"#FFFFFFFF","replaceBackgroundColor":false,"backgroundColor":"#FFFFFFFF","processors":{"forward":{"active":true},"actionbar":{"active":false},"sound":{"active":false,"notifySound":"none","soundPitch":1.0,"soundVolume":1.0},"narrator":{"active":false,"message":"$1"},"konstruct":{"active":false,"nodeData":""}},"order":1} 27 | ``` 28 | 2 29 | ``` 30 | {"name":"Markdown Strikethrough","active":true,"stripColors":true,"findString":"~~([^\\*]*?)~~","findType":"regex","replaceType":"onlymatch","replaceTo":"\u0026m$1","replaceTextColor":false,"textColor":"#FFFFFFFF","replaceBackgroundColor":false,"backgroundColor":"#FFFFFFFF","processors":{"forward":{"active":true},"actionbar":{"active":false},"sound":{"active":false,"notifySound":"none","soundPitch":1.0,"soundVolume":1.0},"narrator":{"active":false,"message":"$1"},"konstruct":{"active":false,"nodeData":""}},"order":2} 31 | ``` 32 | 3 33 | ``` 34 | {"name":"Markdown Bold Italic","active":true,"stripColors":true,"findString":"\\*\\*\\*([^\\*]*?)\\*\\*\\*","findType":"regex","replaceType":"onlymatch","replaceTo":"\u0026o\u0026l$1","replaceTextColor":false,"textColor":"#FFFFFFFF","replaceBackgroundColor":false,"backgroundColor":"#FFFFFFFF","processors":{"forward":{"active":true},"actionbar":{"active":false},"sound":{"active":false,"notifySound":"none","soundPitch":1.0,"soundVolume":1.0},"narrator":{"active":false,"message":"$1"},"konstruct":{"active":false,"nodeData":""}},"order":3} 35 | ``` 36 | 4 37 | ``` 38 | {"name":"Markdown Bold","active":true,"stripColors":true,"findString":"(?\u003c!\\*)\\*\\*([^\\*]*?)\\*\\*(?!\\*)","findType":"regex","replaceType":"onlymatch","replaceTo":"\u0026o$1","replaceTextColor":false,"textColor":"#FFFFFFFF","replaceBackgroundColor":false,"backgroundColor":"#FFFFFFFF","processors":{"forward":{"active":true},"actionbar":{"active":false},"sound":{"active":false,"notifySound":"none","soundPitch":1.0,"soundVolume":1.0},"narrator":{"active":false,"message":"$1"},"konstruct":{"active":false,"nodeData":""}},"order":4} 39 | ``` 40 | 5 41 | ``` 42 | {"name":"Markdown Italic","active":true,"stripColors":true,"findString":"(?\u003c!\\*)\\*([^\\*]*?)\\*(?!\\*)","findType":"regex","replaceType":"onlymatch","replaceTo":"\u0026o$1","replaceTextColor":false,"textColor":"#FFFFFFFF","replaceBackgroundColor":false,"backgroundColor":"#FFFFFFFF","processors":{"forward":{"active":true},"actionbar":{"active":false},"sound":{"active":false,"notifySound":"none","soundPitch":1.0,"soundVolume":1.0},"narrator":{"active":false,"message":"$1"},"konstruct":{"active":false,"nodeData":""}},"order":5} 43 | ``` 44 | 45 | ## Pig Latin 46 | 47 | Enable Pig Latin. Not perfect, but really close. 48 | 49 | ``` 50 | {"name":"Pig Latin","active":true,"stripColors":true,"findString":"(?\u003c\u003d\\W?)([aeiouy]?[^aeiouy\\W]+?)([aeiouy]\\w*)","findType":"regex","replaceType":"onlymatch","replaceTo":"$2$1ay","replaceTextColor":false,"textColor":"#FFBBFFFF","replaceBackgroundColor":false,"backgroundColor":"#FFFFFFFF","processors":{"forward":{"active":true},"actionbar":{"active":false},"sound":{"active":false,"notifySound":"none","soundPitch":1.0,"soundVolume":1.0},"narrator":{"active":false,"message":"$1"},"konstruct":{"active":false,"nodeData":""},"macro":{"active":false,"command":"po|gers","delay":68,"parseAsKonstruct":false}},"order":0} 51 | ``` 52 | -------------------------------------------------------------------------------- /docs/filters/images/filterconfig.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/filters/images/filterconfig.png -------------------------------------------------------------------------------- /docs/filters/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: AdvancedChatFilters 4 | nav_order: 2 5 | has_children: true 6 | --- 7 | 8 | Chat, but **filtered** 9 | -------------------------------------------------------------------------------- /docs/filters/tutorial.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Filters Tutorial 4 | parent: AdvancedChatFilters 5 | nav_order: 0 6 | --- 7 | # Basic Filters 8 | 9 | AC Filters let you take control of your chat. Let's take a look at how to make your own filters. 10 | Recall that the String to Find box contains the string to filter for. The treatment is specified by the Filter Type property. 11 | 12 | ## Name Highlights 13 | 14 | A common use for filters is to highlight your name in chat. The easiest way to do this is to edit the `Text Color` property. Change the color value to what you want make sure to turn on `Replace Text Color`. Keep the other values at default for now. 15 | What if you wanted to make it trigger regardless of casing? You can simply change the `Filter Type` property to Upper-Lower. You can experiment with this and change different properties. 16 | 17 | ## Profanity 18 | 19 | Let's try something a little harder. What about filtering profanity? You may think you need to check for *every* single profane word, but DarkKronicle makes this easy for us. Set the `Filter Type` to Custom, and set the search string to `profanity`. You can then set the Replace String to something more friendly. 20 | 21 | We encourage you to mess around with these examples and try things on your own. 22 | 23 | # Message Processor 24 | 25 | ACF offers a lot more options with the matched chat message. The Message Processor section allows you to configure what happens to the chat message. You can control if it goes to the chat, it goes to the Action Bar, the Narrator says it, or if a sound is played. (psst... that would be great for the name highlights we mentioned before!). You can also add Konstruct filters, which are pretty advanced. 26 | 27 | # Regular Expressions 28 | 29 | Regular expressions are one of the best ways to implement find and replace searches. Fortunately, ACF contains RegEx support in `Filter Type`. We recommend a few tools to help you out. 30 | 1. [Regex Parser - Extremely useful](https://regex101.com) 31 | 2. [Interactive Tutorial](https://regexone.com/) 32 | 3. [Visualizer](https://extendsclass.com/regex-tester.html#java) 33 | 4. [Cheat Sheet](https://cheatography.com/davechild/cheat-sheets/regular-expressions/) 34 | 5. [Basics Video](https://www.youtube.com/watch?v=sXQxhojSdZM]) 35 | 36 | Keep in mind that the code runs on Java 8, so make sure to select that option while testing regex. 37 | Currently, the regex does not support `/regex/flags` syntax. Use `(?flags)regex` instead. 38 | 39 | Let's go over some quick regex tips. 40 | 41 | ## Players 42 | 43 | Oftentimes with ACF we find the need for regex that matches any valid playername. `[A-Za-z0-9_§]{3,16}` matches valid playernames. You can use this for [message regex](FILE SOON) and more. 44 | 45 | Another thing we can do with regex is make more complicated name highlights. This will vary for everyone, but the regex for me is `(?i)furr?y(?:[_ ]?101)?`. 46 | 47 | --- 48 | 49 | That's all the basic tutorial has to offer. Consider looking at our [filter examples](FILES SOON) before moving onto advanced filters. 50 | 51 | 52 | 53 | Questions? Comments? Concerns? Join the discord for more help or just to hang out. 54 | 55 | Poke Fury if something is wrong with the page 56 | -------------------------------------------------------------------------------- /docs/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | layout: default 3 | title: Home 4 | nav_order: 0 5 | has_children: false 6 | --- 7 | 8 | # AdvancedChat 9 | 10 | Chat, but **epic**. 11 | 12 |
13 | 14 | Table of contents 15 | 16 | {: .text-delta } 17 | 1. TOC 18 | {:toc} 19 |
-------------------------------------------------------------------------------- /docs/modules/assets/images/ACC-ChatBox_Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/modules/assets/images/ACC-ChatBox_Icon.png -------------------------------------------------------------------------------- /docs/modules/assets/images/ACC-ChatFilters_Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/modules/assets/images/ACC-ChatFilters_Icon.png -------------------------------------------------------------------------------- /docs/modules/assets/images/ACC-ChatHUD_Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/modules/assets/images/ACC-ChatHUD_Icon.png -------------------------------------------------------------------------------- /docs/modules/assets/images/ACC-ChatLog_Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/modules/assets/images/ACC-ChatLog_Icon.png -------------------------------------------------------------------------------- /docs/modules/assets/images/ACC-ChatMacros_Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/modules/assets/images/ACC-ChatMacros_Icon.png -------------------------------------------------------------------------------- /docs/modules/assets/images/AdvancedChatCore_Icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/docs/modules/assets/images/AdvancedChatCore_Icon.png -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | org.gradle.jvmargs=-Xmx1G 2 | 3 | minecraft_version=1.20.4 4 | yarn_mappings=1.20.4+build.3 5 | loader_version=0.15.3 6 | fabric_api_version=0.92.0+1.20.4 7 | 8 | mod_version=1.5.10 9 | maven_group=io.github.darkkronicle 10 | archives_base_name=AdvancedChatCore 11 | 12 | malilib_version=0.17.0 13 | konstruct_version=2.0.3-build1 14 | mxparser_version=4.4.2 15 | owo_version=2.0.0 16 | modmenu_version=7.1.0 17 | 18 | # Uploading data 19 | curseforge_slug=advancedchatcore 20 | curseforge_id=537853 21 | 22 | modrinth_slug=advancedchatcore 23 | modrinth_id=1l6k9gvT 24 | 25 | # default_release_type can be stable, beta, or alpha 26 | default_release_type=stable 27 | project_name=AdvancedChatCore 28 | project_url=https://modrinth.com/mod/advancedchatcore 29 | project_logo=https://raw.githubusercontent.com/DarkKronicle/AdvancedChatCore/main/src/main/resources/assets/advancedchatcore/icon.png 30 | project_color=0x134bff 31 | changelog_hide_unimportant_commits=true 32 | changelog_max_commit_search=200 33 | discord_webhook_changelog_line_limit=10 -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega -------------------------------------------------------------------------------- /icon - original.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/medisant/AdvancedChatCore/f38f9f82de7e7ba29a5ac6f9a02b07840216416f/icon - original.png -------------------------------------------------------------------------------- /jitpack.yml: -------------------------------------------------------------------------------- 1 | before_install: 2 | - sdk install java 17.0.2-open 3 | - sdk use java 17.0.2-open -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | pluginManagement { 2 | repositories { 3 | maven { 4 | name = 'Fabric' 5 | url = 'https://maven.fabricmc.net/' 6 | } 7 | gradlePluginPortal() 8 | mavenCentral() 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/AdvancedChatCore.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021-2022 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore; 9 | 10 | import fi.dy.masa.malilib.event.InitializationHandler; 11 | import fi.dy.masa.malilib.gui.GuiBase; 12 | import io.github.darkkronicle.advancedchatcore.chat.AdvancedSleepingChatScreen; 13 | import io.github.darkkronicle.advancedchatcore.util.Colors; 14 | import io.github.darkkronicle.advancedchatcore.util.SyncTaskQueue; 15 | import java.io.FileInputStream; 16 | import java.io.IOException; 17 | import java.io.InputStream; 18 | import java.net.URI; 19 | import java.net.URISyntaxException; 20 | import java.nio.file.Paths; 21 | import java.util.Random; 22 | import net.fabricmc.api.ClientModInitializer; 23 | import net.fabricmc.api.EnvType; 24 | import net.fabricmc.api.Environment; 25 | import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; 26 | import net.minecraft.client.MinecraftClient; 27 | import org.apache.logging.log4j.LogManager; 28 | import org.apache.logging.log4j.Logger; 29 | 30 | @Environment(EnvType.CLIENT) 31 | public class AdvancedChatCore implements ClientModInitializer { 32 | 33 | public static final String MOD_ID = "advancedchatcore"; 34 | 35 | /** 36 | * Whether or not messages should be sent to the HUD. Used for other modules overwriting HUD. 37 | */ 38 | public static boolean FORWARD_TO_HUD = true; 39 | 40 | /** 41 | * Whether or not the default chat suggestor should be created. Used for modules overwriting the 42 | * suggestor. 43 | */ 44 | public static boolean CREATE_SUGGESTOR = true; 45 | 46 | public static final Logger LOGGER = LogManager.getLogger(MOD_ID); 47 | 48 | private static final Random RANDOM = new Random(); 49 | 50 | private static final String[] RANDOM_STRINGS = { 51 | "yes", "maybe", "no", "potentially", "hello", "goodbye", "tail", "pop", "water", 52 | "headphone", "head", "scissor", "paper", "burger", "clock", "peg", "speaker", 53 | "computer", "mouse", "mat", "keyboard", "soda", "mac", "cheese", "home", 54 | "pillow", "couch", "drums", "drumstick", "math", "Euler", "Chronos", "DarkKronicle", 55 | "Kron", "pain", "suffer", "bridge", "Annevdl", "MaLiLib", "pog", "music", 56 | "pants", "glockenspiel", "marimba", "chimes", "vibraphone", "vibe", "snare", 57 | "monkeymode", "shades", "cactus", "shaker", "pit", "band", "percussion", 58 | "foot", "leg", "Kurt", "bruh", "gamer", "gaming" 59 | }; 60 | 61 | @Override 62 | public void onInitializeClient() { 63 | // Important to get first since configuration options depend on colors 64 | Colors.getInstance().load(); 65 | InitializationHandler.getInstance().registerInitializationHandler(new InitHandler()); 66 | MinecraftClient client = MinecraftClient.getInstance(); 67 | ClientTickEvents.START_CLIENT_TICK.register( 68 | s -> { 69 | // Allow for delayed tasks to be added 70 | SyncTaskQueue.getInstance().update(s.inGameHud.getTicks()); 71 | // Make sure we're not in the sleeping screen while awake 72 | if (client.currentScreen instanceof AdvancedSleepingChatScreen 73 | && !client.player.isSleeping()) { 74 | GuiBase.openGui(null); 75 | } 76 | }); 77 | } 78 | 79 | /** 80 | * Get's a resource from src/resources. Works in a emulated environment. 81 | * 82 | * @param path Path from the resources to get 83 | * @return Stream of the resource 84 | * @throws URISyntaxException If the resource doesn't exist 85 | * @throws IOException Can't be opened 86 | */ 87 | public static InputStream getResource(String path) throws URISyntaxException, IOException { 88 | URI uri = Thread.currentThread().getContextClassLoader().getResource(path).toURI(); 89 | if (!uri.getScheme().equals("file")) { 90 | // it's not a file 91 | return Thread.currentThread().getContextClassLoader().getResourceAsStream(path); 92 | } else { 93 | // it's a file - try to access it directly! 94 | return new FileInputStream(Paths.get(uri).toFile()); 95 | } 96 | } 97 | 98 | /** 99 | * Get's a random string. 100 | * 101 | * @return Random generated string. 102 | */ 103 | public static String getRandomString() { 104 | return RANDOM_STRINGS[RANDOM.nextInt(RANDOM_STRINGS.length)]; 105 | } 106 | 107 | /** 108 | * Returns the server address that the client is currently connected to. 109 | * @return The server address if connected, 'singleplayer' if singleplayer, 'none' if none. 110 | */ 111 | public static String getServer() { 112 | MinecraftClient client = MinecraftClient.getInstance(); 113 | if (client.isInSingleplayer()) { 114 | return "singleplayer"; 115 | } 116 | if (client.getCurrentServerEntry() == null) { 117 | return "none"; 118 | } 119 | return client.getCurrentServerEntry().address; 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/Module.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore; 9 | 10 | import java.util.Collection; 11 | import lombok.Value; 12 | import net.fabricmc.loader.api.metadata.Person; 13 | 14 | @Value 15 | public class Module { 16 | 17 | /** The Mod ID of the module */ 18 | String modId; 19 | 20 | /** A {@link Collection} of {@link Person}'s */ 21 | Collection authors; 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/ModuleHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore; 9 | 10 | import java.util.ArrayList; 11 | import java.util.Collections; 12 | import java.util.List; 13 | import java.util.Optional; 14 | 15 | import fi.dy.masa.malilib.interfaces.IInitializationHandler; 16 | import lombok.AllArgsConstructor; 17 | import lombok.Getter; 18 | import lombok.Value; 19 | import net.fabricmc.loader.api.FabricLoader; 20 | import net.fabricmc.loader.api.ModContainer; 21 | import net.fabricmc.loader.api.metadata.CustomValue; 22 | 23 | public class ModuleHandler { 24 | 25 | private static final ModuleHandler INSTANCE = new ModuleHandler(); 26 | 27 | @Getter private final List modules = new ArrayList<>(); 28 | 29 | private ModuleHandler() {} 30 | 31 | private List toLoad = new ArrayList<>(); 32 | 33 | public static ModuleHandler getInstance() { 34 | return INSTANCE; 35 | } 36 | 37 | public void registerModules() { 38 | modules.clear(); 39 | for (ModContainer mod : FabricLoader.getInstance().getAllMods()) { 40 | // Check if in "custom" it has "acmodule": true 41 | CustomValue acData = mod.getMetadata().getCustomValue("acmodule"); 42 | if (acData == null) { 43 | continue; 44 | } 45 | if (acData.getType() == CustomValue.CvType.BOOLEAN && acData.getAsBoolean()) { 46 | // Add the module 47 | modules.add(new Module(mod.getMetadata().getId(), mod.getMetadata().getAuthors())); 48 | } 49 | } 50 | } 51 | 52 | public void registerInitHandler(String name, int priority, IInitializationHandler handler) { 53 | toLoad.add(new LoadOrder(name, priority, handler)); 54 | } 55 | 56 | /** Do not call */ 57 | public void load() { 58 | Collections.sort(toLoad); 59 | for (LoadOrder load : toLoad) { 60 | load.getHandler().registerModHandlers(); 61 | } 62 | toLoad = null; 63 | } 64 | 65 | /** 66 | * Retrieves a {@link Module} based off of a mod ID. 67 | * 68 | *

This is useful for incompatible features or enabling others. 69 | * 70 | * @param modID Mod id of the mod 71 | * @return An optional containing the module if found. 72 | */ 73 | public Optional fromId(String modID) { 74 | for (Module m : modules) { 75 | if (m.getModId().equals(modID)) { 76 | return Optional.of(m); 77 | } 78 | } 79 | return Optional.empty(); 80 | } 81 | 82 | @AllArgsConstructor 83 | @Value 84 | public static class LoadOrder implements Comparable { 85 | String name; 86 | Integer order; 87 | IInitializationHandler handler; 88 | 89 | @Override 90 | public int compareTo(ModuleHandler.LoadOrder o) { 91 | int compared = order.compareTo(o.order); 92 | if (compared == 0) { 93 | return name.compareTo(o.getName()); 94 | } 95 | return compared; 96 | } 97 | } 98 | } 99 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/chat/AdvancedSleepingChatScreen.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021-2022 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.chat; 9 | 10 | import fi.dy.masa.malilib.gui.GuiBase; 11 | import fi.dy.masa.malilib.gui.button.ButtonGeneric; 12 | import fi.dy.masa.malilib.util.KeyCodes; 13 | import fi.dy.masa.malilib.util.StringUtils; 14 | import net.minecraft.client.network.ClientPlayNetworkHandler; 15 | import net.minecraft.network.packet.c2s.play.ClientCommandC2SPacket; 16 | 17 | public class AdvancedSleepingChatScreen extends AdvancedChatScreen { 18 | 19 | public AdvancedSleepingChatScreen() { 20 | super(""); 21 | } 22 | 23 | public void initGui() { 24 | super.initGui(); 25 | ButtonGeneric stopSleep = 26 | new ButtonGeneric( 27 | this.width / 2 - 100, 28 | this.height - 40, 29 | 200, 30 | 20, 31 | StringUtils.translate("multiplayer.stopSleeping")); 32 | this.addButton(stopSleep, (button, mouseButton) -> stopSleeping()); 33 | } 34 | 35 | public void onClose() { 36 | this.stopSleeping(); 37 | } 38 | 39 | public boolean keyPressed(int keyCode, int scanCode, int modifiers) { 40 | if (keyCode == KeyCodes.KEY_ESCAPE) { 41 | this.stopSleeping(); 42 | } else if (keyCode == KeyCodes.KEY_ENTER || keyCode == KeyCodes.KEY_KP_ENTER) { 43 | String string = this.chatField.getText().trim(); 44 | if (!string.isEmpty()) { 45 | MessageSender.getInstance().sendMessage(string); 46 | } 47 | 48 | this.chatField.setText(""); 49 | this.client.inGameHud.getChatHud().resetScroll(); 50 | // Prevents really weird interactions with chat history 51 | resetCurrentMessage(); 52 | return true; 53 | } 54 | 55 | return super.keyPressed(keyCode, scanCode, modifiers); 56 | } 57 | 58 | private void stopSleeping() { 59 | ClientPlayNetworkHandler clientPlayNetworkHandler = this.client.player.networkHandler; 60 | clientPlayNetworkHandler.sendPacket( 61 | new ClientCommandC2SPacket( 62 | this.client.player, ClientCommandC2SPacket.Mode.STOP_SLEEPING)); 63 | GuiBase.openGui(null); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/chat/ChatHistory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.chat; 9 | 10 | import io.github.darkkronicle.advancedchatcore.config.ConfigStorage; 11 | import io.github.darkkronicle.advancedchatcore.interfaces.IChatMessageProcessor; 12 | import java.util.ArrayList; 13 | import java.util.List; 14 | import java.util.stream.Collectors; 15 | import lombok.Getter; 16 | import lombok.Setter; 17 | import net.fabricmc.api.EnvType; 18 | import net.fabricmc.api.Environment; 19 | 20 | /** A utility class to maintain the storage of the chat. */ 21 | @Environment(EnvType.CLIENT) 22 | public class ChatHistory { 23 | 24 | private static final ChatHistory INSTANCE = new ChatHistory(); 25 | 26 | /** Stored lines */ 27 | @Getter private final List messages = new ArrayList<>(); 28 | 29 | /** Maximum lines for storage */ 30 | @Getter @Setter private int maxLines = 500; 31 | 32 | /** Runnable's to run when chat history is cleared */ 33 | @Getter private final List onClear = new ArrayList<>(); 34 | 35 | /** {@link IChatMessageProcessor} for when history is updated. */ 36 | @Getter private final List onUpdate = new ArrayList<>(); 37 | 38 | public static ChatHistory getInstance() { 39 | return INSTANCE; 40 | } 41 | 42 | private ChatHistory() {} 43 | 44 | /** 45 | * Add's a runnable that will trigger when all chat messages should be cleared. 46 | * 47 | * @param runnable Runnable to run 48 | */ 49 | public void addOnClear(Runnable runnable) { 50 | onClear.add(runnable); 51 | } 52 | 53 | /** 54 | * Add's a {@link IChatMessageProcessor} that get's called on new messages, added messages, 55 | * stacked messages, or removed messages. 56 | * 57 | * @param processor Processor ot add 58 | */ 59 | public void addOnUpdate(IChatMessageProcessor processor) { 60 | onUpdate.add(processor); 61 | } 62 | 63 | /** Goes through and clears all message data from everywhere. */ 64 | public void clearAll() { 65 | this.messages.clear(); 66 | for (Runnable r : onClear) { 67 | r.run(); 68 | } 69 | } 70 | 71 | /** Clear's all the chat messages from the history */ 72 | public void clear() { 73 | messages.clear(); 74 | } 75 | 76 | private void sendUpdate(ChatMessage message, IChatMessageProcessor.UpdateType type) { 77 | for (IChatMessageProcessor consumer : onUpdate) { 78 | consumer.onMessageUpdate(message, type); 79 | } 80 | } 81 | 82 | /** 83 | * Add's a chat message to the history. 84 | * 85 | * @param message 86 | */ 87 | public boolean add(ChatMessage message) { 88 | sendUpdate(message, IChatMessageProcessor.UpdateType.NEW); 89 | for (int i = 0; 90 | i < ConfigStorage.General.CHAT_STACK.config.getIntegerValue() 91 | && i < messages.size(); 92 | i++) { 93 | // Check for stacks 94 | ChatMessage chatLine = messages.get(i); 95 | if (message.isSimilar(chatLine)) { 96 | chatLine.setStacks(chatLine.getStacks() + 1); 97 | sendUpdate(chatLine, IChatMessageProcessor.UpdateType.STACK); 98 | return false; 99 | } 100 | } 101 | sendUpdate(message, IChatMessageProcessor.UpdateType.ADDED); 102 | messages.add(0, message); 103 | while (this.messages.size() > maxLines) { 104 | sendUpdate( 105 | this.messages.remove(this.messages.size() - 1), 106 | IChatMessageProcessor.UpdateType.REMOVE); 107 | } 108 | return true; 109 | } 110 | 111 | /** 112 | * Remove's a message based off of it's messageId. 113 | * 114 | * @param messageId Message ID to find and remove 115 | */ 116 | public void removeMessage(int messageId) { 117 | List toRemove = 118 | this.messages.stream() 119 | .filter(line -> line.getId() == messageId) 120 | .collect(Collectors.toList()); 121 | this.messages.removeAll(toRemove); 122 | for (ChatMessage m : toRemove) { 123 | sendUpdate(m, IChatMessageProcessor.UpdateType.REMOVE); 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/chat/ChatHistoryProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021-2022 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.chat; 9 | 10 | import io.github.darkkronicle.advancedchatcore.AdvancedChatCore; 11 | import io.github.darkkronicle.advancedchatcore.config.ConfigStorage; 12 | import io.github.darkkronicle.advancedchatcore.interfaces.IMessageProcessor; 13 | import io.github.darkkronicle.advancedchatcore.mixin.MixinChatHudInvoker; 14 | import io.github.darkkronicle.advancedchatcore.util.Color; 15 | import io.github.darkkronicle.advancedchatcore.util.SearchUtils; 16 | import java.time.LocalTime; 17 | import java.time.format.DateTimeFormatter; 18 | import net.fabricmc.api.EnvType; 19 | import net.fabricmc.api.Environment; 20 | import net.minecraft.client.MinecraftClient; 21 | import net.minecraft.client.gui.hud.MessageIndicator; 22 | import net.minecraft.network.message.MessageSignatureData; 23 | import net.minecraft.text.Style; 24 | import net.minecraft.text.Text; 25 | import net.minecraft.text.TextColor; 26 | import org.jetbrains.annotations.Nullable; 27 | 28 | @Environment(EnvType.CLIENT) 29 | public class ChatHistoryProcessor implements IMessageProcessor { 30 | 31 | private static boolean sendToHud(Text text, @Nullable MessageSignatureData signature, MessageIndicator indicator) { 32 | if (AdvancedChatCore.FORWARD_TO_HUD) { 33 | ((MixinChatHudInvoker) MinecraftClient.getInstance().inGameHud.getChatHud()).invokeAddMessage( 34 | text, signature, MinecraftClient.getInstance().inGameHud.getTicks(), indicator, false); 35 | return true; 36 | } 37 | return false; 38 | } 39 | 40 | @Override 41 | public boolean process(Text text, @Nullable Text unfiltered) { 42 | return process(text, unfiltered, null, MessageIndicator.system()); 43 | } 44 | 45 | @Override 46 | public boolean process(Text text, @Nullable Text unfiltered, @Nullable MessageSignatureData signature, @Nullable MessageIndicator indicator) { 47 | if (unfiltered == null) { 48 | unfiltered = text; 49 | } 50 | 51 | // Put the time in 52 | LocalTime time = LocalTime.now(); 53 | boolean showtime = ConfigStorage.General.SHOW_TIME.config.getBooleanValue(); 54 | // Store original so we can get stuff without the time 55 | Text original = text.copy(); 56 | if (showtime) { 57 | DateTimeFormatter format = 58 | DateTimeFormatter.ofPattern( 59 | ConfigStorage.General.TIME_FORMAT.config.getStringValue()); 60 | String replaceFormat = 61 | ConfigStorage.General.TIME_TEXT_FORMAT.config.getStringValue().replaceAll("&", "§"); 62 | Color color = ConfigStorage.General.TIME_COLOR.config.get(); 63 | Style style = Style.EMPTY; 64 | TextColor textColor = TextColor.fromRgb(color.color()); 65 | style = style.withColor(textColor); 66 | text.getSiblings().add(0, Text.literal(replaceFormat.replaceAll("%TIME%", time.format(format))).fillStyle(style)); 67 | } 68 | 69 | int width = 0; 70 | // Find player 71 | MessageOwner player = 72 | SearchUtils.getAuthor( 73 | MinecraftClient.getInstance().getNetworkHandler(), unfiltered.getString()); 74 | ChatMessage line = ChatMessage.builder() 75 | .displayText(text) 76 | .originalText(original) 77 | .owner(player) 78 | .id(0) 79 | .width(width) 80 | .creationTick(MinecraftClient.getInstance().inGameHud.getTicks()) 81 | .time(time) 82 | .backgroundColor(null) 83 | .build(); 84 | if (ChatHistory.getInstance().add(line)) { 85 | sendToHud(line.getDisplayText(), line.getSignature(), line.getIndicator()); 86 | } 87 | return true; 88 | } 89 | } 90 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/chat/ChatScreenSectionHolder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.chat; 9 | 10 | import io.github.darkkronicle.advancedchatcore.interfaces.AdvancedChatScreenSection; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | import java.util.function.Function; 14 | import lombok.Getter; 15 | 16 | /** 17 | * A class to handle the construction and distribution of {@link AdvancedChatScreenSection} when 18 | * {@link AdvancedChatScreen} is created. 19 | */ 20 | public class ChatScreenSectionHolder { 21 | 22 | private static final ChatScreenSectionHolder INSTANCE = new ChatScreenSectionHolder(); 23 | 24 | /** All suppliers for the sections */ 25 | @Getter 26 | private final List> sectionSuppliers = 27 | new ArrayList<>(); 28 | 29 | public static ChatScreenSectionHolder getInstance() { 30 | return INSTANCE; 31 | } 32 | 33 | private ChatScreenSectionHolder() {} 34 | 35 | public void addSectionSupplier( 36 | Function sectionSupplier) { 37 | sectionSuppliers.add(sectionSupplier); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/chat/DefaultChatSuggestor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.chat; 9 | 10 | import io.github.darkkronicle.advancedchatcore.interfaces.AdvancedChatScreenSection; 11 | import net.fabricmc.api.EnvType; 12 | import net.fabricmc.api.Environment; 13 | import net.minecraft.client.MinecraftClient; 14 | import net.minecraft.client.gui.DrawContext; 15 | import net.minecraft.client.gui.screen.ChatInputSuggestor; 16 | import net.minecraft.client.util.math.MatrixStack; 17 | 18 | /** Handles the CommandSuggestor for the chat */ 19 | @Environment(EnvType.CLIENT) 20 | public class DefaultChatSuggestor extends AdvancedChatScreenSection { 21 | 22 | private ChatInputSuggestor commandSuggestor; 23 | 24 | public DefaultChatSuggestor(AdvancedChatScreen screen) { 25 | super(screen); 26 | } 27 | 28 | @Override 29 | public void onChatFieldUpdate(String chatText, String text) { 30 | this.commandSuggestor.setWindowActive(!text.equals(getScreen().getOriginalChatText())); 31 | this.commandSuggestor.refresh(); 32 | } 33 | 34 | @Override 35 | public boolean keyPressed(int keyCode, int scanCode, int modifiers) { 36 | return this.commandSuggestor.keyPressed(keyCode, scanCode, modifiers); 37 | } 38 | 39 | @Override 40 | public void render(DrawContext context, int mouseX, int mouseY, float partialTicks) { 41 | this.commandSuggestor.render(context, mouseX, mouseY); 42 | } 43 | 44 | @Override 45 | public void setChatFromHistory(String hist) { 46 | this.commandSuggestor.setWindowActive(false); 47 | } 48 | 49 | @Override 50 | public boolean mouseScrolled(double mouseX, double mouseY, double amount) { 51 | return this.commandSuggestor.mouseScrolled(amount); 52 | } 53 | 54 | @Override 55 | public boolean mouseClicked(double mouseX, double mouseY, int button) { 56 | return this.commandSuggestor.mouseClicked(mouseX, mouseY, button); 57 | } 58 | 59 | @Override 60 | public void resize(int width, int height) { 61 | this.commandSuggestor.refresh(); 62 | } 63 | 64 | @Override 65 | public void initGui() { 66 | MinecraftClient client = MinecraftClient.getInstance(); 67 | AdvancedChatScreen screen = getScreen(); 68 | this.commandSuggestor = 69 | new ChatInputSuggestor( 70 | client, 71 | screen, 72 | screen.chatField, 73 | client.textRenderer, 74 | false, 75 | false, 76 | 1, 77 | 10, 78 | true, 79 | -805306368); 80 | this.commandSuggestor.refresh(); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/chat/MessageOwner.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.chat; 9 | 10 | import lombok.AllArgsConstructor; 11 | import lombok.Data; 12 | import lombok.Value; 13 | import net.fabricmc.api.EnvType; 14 | import net.fabricmc.api.Environment; 15 | import net.minecraft.client.network.PlayerListEntry; 16 | import net.minecraft.util.Identifier; 17 | 18 | /** Stores data about a message owner */ 19 | @Data 20 | @Value 21 | @AllArgsConstructor 22 | @Environment(EnvType.CLIENT) 23 | public class MessageOwner { 24 | 25 | /** Player name */ 26 | String name; 27 | 28 | /** Entry that has player data */ 29 | PlayerListEntry entry; 30 | 31 | /** 32 | * The texture of the player's skin 33 | * 34 | * @return Identifier with texture data 35 | */ 36 | public Identifier getTexture() { 37 | return entry.getSkinTextures().texture(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/chat/MessageSender.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.chat; 9 | 10 | import io.github.darkkronicle.advancedchatcore.AdvancedChatCore; 11 | import io.github.darkkronicle.advancedchatcore.interfaces.IStringFilter; 12 | import net.minecraft.client.MinecraftClient; 13 | import org.apache.logging.log4j.Level; 14 | 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | import java.util.Optional; 18 | 19 | public class MessageSender { 20 | 21 | private static final MessageSender INSTANCE = new MessageSender(); 22 | private final MinecraftClient client = MinecraftClient.getInstance(); 23 | 24 | public static MessageSender getInstance() { 25 | return INSTANCE; 26 | } 27 | 28 | private MessageSender() {} 29 | 30 | private final List filters = new ArrayList<>(); 31 | 32 | public void addFilter(IStringFilter filter) { 33 | filters.add(filter); 34 | } 35 | 36 | public void addFilter(IStringFilter filter, int index) { 37 | filters.add(index, filter); 38 | } 39 | 40 | public void sendMessage(String string) { 41 | String unfiltered = string; 42 | for (IStringFilter filter : filters) { 43 | Optional filtered = filter.filter(string); 44 | if (filtered.isPresent()) { 45 | string = filtered.get().strip(); 46 | } 47 | } 48 | if (string.length() > 256) { 49 | string = string.substring(0, 256); 50 | } 51 | this.client.inGameHud.getChatHud().addToMessageHistory(unfiltered); 52 | 53 | if (string.length() == 0) { 54 | AdvancedChatCore.LOGGER.log(Level.WARN, "Blank message was attempted to be sent. " + unfiltered); 55 | return; 56 | } 57 | 58 | if (client.player != null) { 59 | if (string.startsWith("/")) { 60 | this.client.getNetworkHandler().sendChatCommand(string.substring(1)); 61 | } else { 62 | this.client.getNetworkHandler().sendChatMessage(string); 63 | } 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/config/SaveableConfig.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.config; 9 | 10 | import fi.dy.masa.malilib.config.IConfigBase; 11 | 12 | public class SaveableConfig { 13 | 14 | public final T config; 15 | public final String key; 16 | 17 | private SaveableConfig(String key, T config) { 18 | this.key = key; 19 | this.config = config; 20 | } 21 | 22 | public static SaveableConfig fromConfig(String key, C config) { 23 | return new SaveableConfig<>(key, config); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/config/gui/ModMenuImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.config.gui; 9 | 10 | import com.terraformersmc.modmenu.api.ConfigScreenFactory; 11 | import com.terraformersmc.modmenu.api.ModMenuApi; 12 | import net.fabricmc.api.EnvType; 13 | import net.fabricmc.api.Environment; 14 | 15 | @Environment(EnvType.CLIENT) 16 | public class ModMenuImpl implements ModMenuApi { 17 | 18 | @Override 19 | public ConfigScreenFactory getModConfigScreenFactory() { 20 | return parent -> GuiConfigHandler.getInstance().getDefaultScreen(); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/config/gui/OnOffListListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.config.gui; 9 | 10 | import fi.dy.masa.malilib.gui.button.ButtonBase; 11 | import fi.dy.masa.malilib.gui.button.ButtonGeneric; 12 | import fi.dy.masa.malilib.gui.button.IButtonActionListener; 13 | import io.github.darkkronicle.advancedchatcore.config.gui.widgets.WidgetToggle; 14 | import io.github.darkkronicle.advancedchatcore.interfaces.Translatable; 15 | import java.util.ArrayList; 16 | import java.util.HashMap; 17 | import java.util.List; 18 | import java.util.Map; 19 | 20 | public class OnOffListListener implements IButtonActionListener { 21 | 22 | private final ButtonGeneric button; 23 | private final WidgetToggle toggle; 24 | private T current; 25 | private HashMap onOff; 26 | private final List order; 27 | 28 | public OnOffListListener(ButtonGeneric button, WidgetToggle toggle, HashMap onOff) { 29 | this.button = button; 30 | this.toggle = toggle; 31 | this.onOff = new HashMap<>(onOff); 32 | this.order = new ArrayList<>(onOff.keySet()); 33 | next(); 34 | } 35 | 36 | public IButtonActionListener getButtonListener() { 37 | return (button1, mouseButton) -> { 38 | onToggled(); 39 | }; 40 | } 41 | 42 | private void onToggled() { 43 | onOff.put(current, toggle.isCurrentlyOn()); 44 | } 45 | 46 | private void next() { 47 | int i = order.indexOf(current) + 1; 48 | if (i >= order.size()) { 49 | i = 0; 50 | } 51 | current = order.get(i); 52 | button.setDisplayString(current.translate()); 53 | toggle.setOn(onOff.get(current)); 54 | } 55 | 56 | public List getOn() { 57 | ArrayList list = new ArrayList<>(); 58 | for (Map.Entry entry : onOff.entrySet()) { 59 | if (entry.getValue()) { 60 | list.add(entry.getKey()); 61 | } 62 | } 63 | return list; 64 | } 65 | 66 | public static HashMap getOnOff( 67 | List all, List active) { 68 | HashMap map = new HashMap<>(); 69 | for (T a : all) { 70 | map.put(a, active.contains(a)); 71 | } 72 | return map; 73 | } 74 | 75 | @Override 76 | public void actionPerformedWithButton(ButtonBase button, int mouseButton) { 77 | next(); 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/config/gui/TabSupplier.java: -------------------------------------------------------------------------------- 1 | package io.github.darkkronicle.advancedchatcore.config.gui; 2 | 3 | import fi.dy.masa.malilib.config.IConfigBase; 4 | import fi.dy.masa.malilib.util.StringUtils; 5 | import lombok.Getter; 6 | import lombok.Setter; 7 | import net.minecraft.client.gui.screen.Screen; 8 | 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | public class TabSupplier { 13 | 14 | @Getter 15 | private final String name; 16 | 17 | private final String translationKey; 18 | 19 | @Getter 20 | @Setter 21 | private TabSupplier nestedSelection = null; 22 | 23 | @Getter 24 | private List children = new ArrayList<>(); 25 | 26 | public TabSupplier(String name, String translationKey) { 27 | this.name = name; 28 | this.translationKey = translationKey; 29 | } 30 | 31 | public String getDisplayName() { 32 | return StringUtils.translate(translationKey); 33 | } 34 | 35 | public List getOptions() { 36 | return null; 37 | } 38 | 39 | public Screen getScreen(Screen parent) { 40 | return null; 41 | } 42 | 43 | public boolean isSelectable() { 44 | return true; 45 | } 46 | 47 | @Override 48 | public boolean equals(Object obj) { 49 | if (!(obj instanceof TabSupplier)) { 50 | return false; 51 | } 52 | return (((TabSupplier) obj).getName().equals(getName())); 53 | } 54 | 55 | public void addChild(TabSupplier supplier) { 56 | if (nestedSelection == null) { 57 | if (supplier.isSelectable()) { 58 | nestedSelection = supplier; 59 | } 60 | } 61 | this.children.add(supplier); 62 | } 63 | 64 | public TabSupplier get(String name) { 65 | for (TabSupplier child : children) { 66 | if (name.equals(child.getName())) { 67 | return child; 68 | } 69 | } 70 | return null; 71 | } 72 | 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/config/gui/widgets/WidgetColor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.config.gui.widgets; 9 | 10 | import fi.dy.masa.malilib.gui.GuiTextFieldGeneric; 11 | import fi.dy.masa.malilib.render.RenderUtils; 12 | import fi.dy.masa.malilib.util.StringUtils; 13 | import io.github.darkkronicle.advancedchatcore.util.Color; 14 | import io.github.darkkronicle.advancedchatcore.util.Colors; 15 | import java.util.Optional; 16 | import net.minecraft.client.font.TextRenderer; 17 | import net.minecraft.client.gui.DrawContext; 18 | import net.minecraft.client.util.math.MatrixStack; 19 | 20 | public class WidgetColor extends GuiTextFieldGeneric { 21 | 22 | private int colorX; 23 | private Color currentColor; 24 | 25 | public WidgetColor( 26 | int x, int y, int width, int height, Color color, TextRenderer textRenderer) { 27 | super(x, y, width - 22, height, textRenderer); 28 | this.colorX = x + width - 20; 29 | this.currentColor = color; 30 | setText(String.format("#%08X", this.currentColor.color())); 31 | } 32 | 33 | @Override 34 | public void renderWidget(DrawContext context, int mouseX, int mouseY, float delta) { 35 | super.renderWidget(context, mouseX, mouseY, delta); 36 | int y = this.y; 37 | RenderUtils.drawRect(this.colorX, y, 19, 19, 0xFFFFFFFF); 38 | RenderUtils.drawRect(this.colorX + 1, y + 1, 17, 17, 0xFF000000); 39 | RenderUtils.drawRect(this.colorX + 2, y + 2, 15, 15, this.currentColor.color()); 40 | } 41 | 42 | @Override 43 | public void write(String text) { 44 | super.write(text); 45 | getAndRefreshColor4f(); 46 | } 47 | 48 | @Override 49 | public int getWidth() { 50 | return super.getWidth() + 22; 51 | } 52 | 53 | public Color getAndRefreshColor4f() { 54 | Optional color = Colors.getInstance().getColor(getText()); 55 | if (color.isPresent()) { 56 | this.currentColor = color.get(); 57 | return this.currentColor; 58 | } 59 | this.currentColor = new Color(StringUtils.getColor(getText(), 0)); 60 | return this.currentColor; 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/config/gui/widgets/WidgetIntBox.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.config.gui.widgets; 9 | 10 | import fi.dy.masa.malilib.gui.GuiTextFieldGeneric; 11 | import io.github.darkkronicle.advancedchatcore.util.FindType; 12 | import io.github.darkkronicle.advancedchatcore.util.SearchUtils; 13 | import io.github.darkkronicle.advancedchatcore.util.StringMatch; 14 | import java.util.List; 15 | import java.util.Optional; 16 | import lombok.Getter; 17 | import lombok.Setter; 18 | import net.minecraft.client.font.TextRenderer; 19 | 20 | public class WidgetIntBox extends GuiTextFieldGeneric { 21 | 22 | @Setter @Getter private Runnable apply = null; 23 | 24 | public WidgetIntBox(int x, int y, int width, int height, TextRenderer textRenderer) { 25 | super(x, y, width, height, textRenderer); 26 | this.setTextPredicate( 27 | text -> { 28 | if (text.equals("")) { 29 | return true; 30 | } 31 | try { 32 | // Only allow numbers! 33 | Integer.valueOf(text); 34 | } catch (NumberFormatException e) { 35 | return false; 36 | } 37 | return true; 38 | }); 39 | this.setDrawsBackground(true); 40 | } 41 | 42 | public Integer getInt() { 43 | String text = this.getText(); 44 | if (text == null || text.length() == 0) { 45 | return null; 46 | } 47 | try { 48 | return Integer.parseInt(text); 49 | } catch (NumberFormatException e) { 50 | // Extra catch 51 | Optional> omatches = 52 | SearchUtils.findMatches(text, "[0-9]+", FindType.REGEX); 53 | if (!omatches.isPresent()) { 54 | return null; 55 | } 56 | for (StringMatch m : omatches.get()) { 57 | try { 58 | return Integer.parseInt(m.match); 59 | } catch (NumberFormatException err) { 60 | return null; 61 | } 62 | } 63 | } 64 | return null; 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/config/gui/widgets/WidgetLabelHoverable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.config.gui.widgets; 9 | 10 | import fi.dy.masa.malilib.gui.widgets.WidgetLabel; 11 | import fi.dy.masa.malilib.render.RenderUtils; 12 | import java.util.Arrays; 13 | import java.util.List; 14 | 15 | import net.minecraft.client.gui.DrawContext; 16 | import net.minecraft.client.util.math.MatrixStack; 17 | 18 | public class WidgetLabelHoverable extends WidgetLabel { 19 | 20 | private List hoverLines = null; 21 | 22 | public WidgetLabelHoverable( 23 | int x, int y, int width, int height, int textColor, List lines) { 24 | super(x, y, width, height, textColor, lines); 25 | } 26 | 27 | public WidgetLabelHoverable( 28 | int x, int y, int width, int height, int textColor, String... text) { 29 | super(x, y, width, height, textColor, text); 30 | } 31 | 32 | public void setHoverLines(String... hoverLines) { 33 | this.hoverLines = Arrays.asList(hoverLines); 34 | } 35 | 36 | @Override 37 | public void postRenderHovered( 38 | int mouseX, int mouseY, boolean selected, DrawContext context) { 39 | super.postRenderHovered(mouseX, mouseY, selected, context); 40 | 41 | if (hoverLines == null) { 42 | return; 43 | } 44 | 45 | if (mouseX >= this.x 46 | && mouseX < this.x + this.width 47 | && mouseY >= this.y 48 | && mouseY <= this.y + this.height) { 49 | RenderUtils.drawHoverText(mouseX, mouseY, this.hoverLines, context); 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/config/gui/widgets/WidgetListRegistryOption.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.config.gui.widgets; 9 | 10 | import fi.dy.masa.malilib.gui.interfaces.ISelectionListener; 11 | import fi.dy.masa.malilib.gui.widgets.WidgetListBase; 12 | import io.github.darkkronicle.advancedchatcore.interfaces.ConfigRegistryOption; 13 | import io.github.darkkronicle.advancedchatcore.util.AbstractRegistry; 14 | import java.util.Collection; 15 | import java.util.stream.Collectors; 16 | import net.minecraft.client.gui.screen.Screen; 17 | import org.jetbrains.annotations.Nullable; 18 | 19 | public class WidgetListRegistryOption> 20 | extends WidgetListBase> { 21 | 22 | private final AbstractRegistry registry; 23 | 24 | public WidgetListRegistryOption( 25 | int x, 26 | int y, 27 | int width, 28 | int height, 29 | @Nullable ISelectionListener selectionListener, 30 | AbstractRegistry registry, 31 | Screen parent) { 32 | super(x, y, width, height, selectionListener); 33 | this.browserEntryHeight = 22; 34 | this.setParent(parent); 35 | this.registry = registry; 36 | } 37 | 38 | @Override 39 | protected WidgetRegistryOptionEntry createListEntryWidget( 40 | int x, int y, int listIndex, boolean isOdd, T entry) { 41 | return new WidgetRegistryOptionEntry( 42 | x, 43 | y, 44 | this.browserEntryWidth, 45 | this.getBrowserEntryHeightFor(entry), 46 | isOdd, 47 | entry, 48 | listIndex, 49 | this); 50 | } 51 | 52 | @Override 53 | protected Collection getAllEntries() { 54 | return registry.getAll().stream() 55 | .filter(option -> !option.isHidden()) 56 | .collect(Collectors.toList()); 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/config/gui/widgets/WidgetToggle.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.config.gui.widgets; 9 | 10 | import fi.dy.masa.malilib.gui.button.ButtonOnOff; 11 | import lombok.Getter; 12 | 13 | public class WidgetToggle extends ButtonOnOff { 14 | 15 | @Getter private boolean currentlyOn; 16 | 17 | public WidgetToggle( 18 | int x, 19 | int y, 20 | int width, 21 | boolean rightAlign, 22 | String translationKey, 23 | boolean isCurrentlyOn, 24 | String... hoverStrings) { 25 | super(x, y, width, rightAlign, translationKey, isCurrentlyOn, hoverStrings); 26 | this.currentlyOn = isCurrentlyOn; 27 | } 28 | 29 | @Override 30 | protected boolean onMouseClickedImpl(int mouseX, int mouseY, int mouseButton) { 31 | this.currentlyOn = !this.currentlyOn; 32 | this.updateDisplayString(this.currentlyOn); 33 | return super.onMouseClickedImpl(mouseX, mouseY, mouseButton); 34 | } 35 | 36 | public void setOn(boolean on) { 37 | this.currentlyOn = on; 38 | this.updateDisplayString(on); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/config/options/ConfigColor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021-2022 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.config.options; 9 | 10 | import com.google.gson.JsonElement; 11 | import com.google.gson.JsonPrimitive; 12 | import fi.dy.masa.malilib.MaLiLib; 13 | import fi.dy.masa.malilib.util.StringUtils; 14 | import io.github.darkkronicle.advancedchatcore.util.Color; 15 | import io.github.darkkronicle.advancedchatcore.util.Colors; 16 | import java.util.Optional; 17 | import net.fabricmc.api.EnvType; 18 | import net.fabricmc.api.Environment; 19 | 20 | @Environment(EnvType.CLIENT) 21 | public class ConfigColor extends fi.dy.masa.malilib.config.options.ConfigColor { 22 | private Color color; 23 | private final String defaultReference; 24 | private String reference = null; 25 | 26 | public ConfigColor(String name, Color defaultValue, String comment) { 27 | super(name, defaultValue.getString(), comment); 28 | this.color = defaultValue; 29 | this.defaultReference = null; 30 | } 31 | 32 | public ConfigColor(String name, String referenceDefault, String comment) { 33 | super(name, Colors.getInstance().getColorOrWhite(referenceDefault).toString(), comment); 34 | this.color = Colors.getInstance().getColorOrWhite(referenceDefault); 35 | this.defaultReference = referenceDefault; 36 | } 37 | 38 | @Override 39 | public void resetToDefault() { 40 | if (defaultReference != null) { 41 | this.setValueFromString(defaultReference); 42 | } else { 43 | this.setValueFromString(new Color(defaultValue).getString()); 44 | } 45 | onValueChanged(); 46 | } 47 | 48 | @Override 49 | public String getDefaultStringValue() { 50 | if (defaultReference == null) { 51 | return super.getDefaultStringValue(); 52 | } 53 | return defaultReference; 54 | } 55 | 56 | @Override 57 | public void setValueFromString(String value) { 58 | Optional color = Colors.getInstance().getColor(value); 59 | if (color.isPresent()) { 60 | this.setIntegerValue(color.get().color()); 61 | this.reference = value; 62 | this.setColor(); 63 | return; 64 | } 65 | this.reference = null; 66 | super.setValueFromString(value); 67 | this.setColor(); 68 | } 69 | 70 | @Override 71 | public String getStringValue() { 72 | if (reference != null) { 73 | return this.reference; 74 | } 75 | return super.getStringValue(); 76 | } 77 | 78 | private void setColor() { 79 | this.color = new Color(getIntegerValue()); 80 | } 81 | 82 | @Override 83 | public void setValueFromJsonElement(JsonElement element) { 84 | try { 85 | if (element.isJsonPrimitive()) { 86 | String value = element.getAsString(); 87 | Optional color = Colors.getInstance().getColor(value); 88 | if (color.isPresent()) { 89 | this.setIntegerValue(color.get().color()); 90 | this.reference = value; 91 | this.setColor(); 92 | return; 93 | } 94 | this.value = this.getClampedValue(StringUtils.getColor(value, 0)); 95 | this.setIntegerValue(this.value); 96 | this.setColor(); 97 | } else { 98 | MaLiLib.logger.warn( 99 | "Failed to set config value for '{}' from the JSON element '{}'", 100 | this.getName(), 101 | element); 102 | } 103 | } catch (Exception e) { 104 | MaLiLib.logger.warn( 105 | "Failed to set config value for '{}' from the JSON element '{}'", 106 | this.getName(), 107 | element, 108 | e); 109 | } 110 | } 111 | 112 | @Override 113 | public JsonElement getAsJsonElement() { 114 | return new JsonPrimitive(getStringValue()); 115 | } 116 | 117 | public Color get() { 118 | return color; 119 | } 120 | } 121 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/finder/CustomFinder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.finder; 9 | 10 | import io.github.darkkronicle.advancedchatcore.AdvancedChatCore; 11 | import io.github.darkkronicle.advancedchatcore.interfaces.IFinder; 12 | import io.github.darkkronicle.advancedchatcore.interfaces.RegistryOption; 13 | import io.github.darkkronicle.advancedchatcore.util.AbstractRegistry; 14 | import io.github.darkkronicle.advancedchatcore.util.StringMatch; 15 | import java.util.ArrayList; 16 | import java.util.List; 17 | import java.util.Optional; 18 | import java.util.function.Supplier; 19 | import net.fabricmc.api.EnvType; 20 | import net.fabricmc.api.Environment; 21 | import org.apache.logging.log4j.Level; 22 | 23 | @Environment(EnvType.CLIENT) 24 | public class CustomFinder extends AbstractRegistry 25 | implements IFinder { 26 | 27 | private static final CustomFinder INSTANCE = new CustomFinder(); 28 | 29 | public static CustomFinder getInstance() { 30 | return INSTANCE; 31 | } 32 | 33 | private CustomFinder() {} 34 | 35 | public static final String NAME = "customfind"; 36 | 37 | @Override 38 | public boolean isMatch(String input, String toMatch) { 39 | Optional option = getFinder(toMatch); 40 | if (option.isEmpty()) { 41 | // Invalid :( 42 | AdvancedChatCore.LOGGER.log(Level.WARN, getHelp(toMatch)); 43 | return false; 44 | } 45 | return option.get().isMatch(input, toMatch); 46 | } 47 | 48 | private String getHelp(String toMatch) { 49 | StringBuilder builder = 50 | new StringBuilder() 51 | .append("Custom find type was used but the match ") 52 | .append(toMatch) 53 | .append(" does not exist in the registry! Possible correct options: "); 54 | for (CustomFinderOption o : getAll()) { 55 | builder.append(o.saveString).append(", "); 56 | } 57 | return builder.substring(0, builder.length() - 2); 58 | } 59 | 60 | @Override 61 | public List getMatches(String input, String toMatch) { 62 | Optional option = getFinder(toMatch); 63 | if (option.isEmpty()) { 64 | // Invalid :( 65 | AdvancedChatCore.LOGGER.log(Level.WARN, getHelp(toMatch)); 66 | return new ArrayList<>(); 67 | } 68 | return option.get().getMatches(input, toMatch); 69 | } 70 | 71 | public Optional getFinder(String toMatch) { 72 | for (CustomFinderOption o : getAll()) { 73 | if (toMatch.startsWith(o.saveString)) { 74 | return Optional.of(o.getOption()); 75 | } 76 | } 77 | return Optional.empty(); 78 | } 79 | 80 | @Override 81 | public CustomFinder clone() { 82 | CustomFinder finder = new CustomFinder(); 83 | for (CustomFinderOption o : getAll()) { 84 | finder.add(o.copy(this)); 85 | } 86 | return finder; 87 | } 88 | 89 | @Override 90 | public CustomFinderOption constructOption( 91 | Supplier type, 92 | String saveString, 93 | String translation, 94 | String infoTranslation, 95 | boolean active, 96 | boolean setDefault, 97 | boolean hidden) { 98 | return new CustomFinderOption( 99 | type, saveString, translation, infoTranslation, active, hidden, this); 100 | } 101 | 102 | public static class CustomFinderOption implements RegistryOption { 103 | 104 | private final IFinder finder; 105 | private final String saveString; 106 | private final String translation; 107 | private final CustomFinder registry; 108 | private final String infoTranslation; 109 | private final boolean hidden; 110 | private final boolean active; 111 | 112 | private CustomFinderOption( 113 | Supplier finder, 114 | String saveString, 115 | String translation, 116 | String infoTranslation, 117 | boolean active, 118 | boolean hidden, 119 | CustomFinder registry) { 120 | this(finder.get(), saveString, translation, infoTranslation, active, hidden, registry); 121 | } 122 | 123 | // Only register 124 | private CustomFinderOption( 125 | IFinder finder, 126 | String saveString, 127 | String translation, 128 | String infoTranslation, 129 | boolean active, 130 | boolean hidden, 131 | CustomFinder registry) { 132 | this.finder = finder; 133 | this.saveString = saveString; 134 | this.translation = translation; 135 | this.registry = registry; 136 | this.infoTranslation = infoTranslation; 137 | this.hidden = hidden; 138 | this.active = active; 139 | } 140 | 141 | @Override 142 | public IFinder getOption() { 143 | return finder; 144 | } 145 | 146 | @Override 147 | public boolean isActive() { 148 | return active; 149 | } 150 | 151 | @Override 152 | public String getSaveString() { 153 | return saveString; 154 | } 155 | 156 | @Override 157 | public CustomFinderOption copy(AbstractRegistry registry) { 158 | return new CustomFinderOption( 159 | finder, 160 | saveString, 161 | translation, 162 | infoTranslation, 163 | isActive(), 164 | isHidden(), 165 | registry == null ? this.registry : (CustomFinder) registry); 166 | } 167 | } 168 | } 169 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/finder/LiteralFinder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.finder; 9 | 10 | import java.util.regex.Pattern; 11 | 12 | public class LiteralFinder extends PatternFinder { 13 | @Override 14 | public Pattern getPattern(String toMatch) { 15 | return Pattern.compile(Pattern.quote(toMatch)); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/finder/PatternFinder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.finder; 9 | 10 | import io.github.darkkronicle.advancedchatcore.interfaces.IFinder; 11 | import io.github.darkkronicle.advancedchatcore.util.StringMatch; 12 | import org.jetbrains.annotations.Nullable; 13 | 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | import java.util.regex.Matcher; 17 | import java.util.regex.Pattern; 18 | 19 | public abstract class PatternFinder implements IFinder { 20 | 21 | @Nullable 22 | public abstract Pattern getPattern(String toMatch); 23 | 24 | @Override 25 | public boolean isMatch(String input, String toMatch) { 26 | Pattern pattern = getPattern(toMatch); 27 | if (pattern == null) { 28 | return false; 29 | } 30 | return pattern.matcher(input).find(); 31 | } 32 | 33 | @Override 34 | public List getMatches(String input, String toMatch) { 35 | List matches = new ArrayList<>(); 36 | Pattern pattern = getPattern(toMatch); 37 | if (pattern == null) { 38 | return matches; 39 | } 40 | Matcher matcher = pattern.matcher(input); 41 | while (matcher.find()) { 42 | matches.add(new StringMatch(matcher.group(), matcher.start(), matcher.end())); 43 | } 44 | matcher.reset(); 45 | return matches; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/finder/UpperLowerFinder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.finder; 9 | 10 | import java.util.regex.Pattern; 11 | 12 | public class UpperLowerFinder extends PatternFinder { 13 | @Override 14 | public Pattern getPattern(String toMatch) { 15 | return Pattern.compile(Pattern.quote(toMatch), Pattern.CASE_INSENSITIVE); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/finder/custom/ProfanityFinder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.finder.custom; 9 | 10 | import io.github.darkkronicle.advancedchatcore.config.ConfigStorage; 11 | import io.github.darkkronicle.advancedchatcore.interfaces.IFinder; 12 | import io.github.darkkronicle.advancedchatcore.util.ProfanityUtil; 13 | import io.github.darkkronicle.advancedchatcore.util.StringMatch; 14 | import java.util.List; 15 | import net.fabricmc.api.EnvType; 16 | import net.fabricmc.api.Environment; 17 | 18 | @Environment(EnvType.CLIENT) 19 | public class ProfanityFinder implements IFinder { 20 | @Override 21 | public boolean isMatch(String input, String toMatch) { 22 | return getMatches(input, toMatch).size() != 0; 23 | } 24 | 25 | @Override 26 | public List getMatches(String input, String toMatch) { 27 | return ProfanityUtil.getInstance().getBadWords(input, (float) ConfigStorage.General.PROFANITY_ABOVE.config.getDoubleValue(), ConfigStorage.General.PROFANITY_ON_WORD_BOUNDARIES.config.getBooleanValue()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/gui/CleanButton.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.gui; 9 | 10 | import fi.dy.masa.malilib.gui.button.ButtonBase; 11 | import fi.dy.masa.malilib.render.RenderUtils; 12 | import io.github.darkkronicle.advancedchatcore.util.Color; 13 | import io.github.darkkronicle.advancedchatcore.util.Colors; 14 | import lombok.EqualsAndHashCode; 15 | import lombok.ToString; 16 | import net.fabricmc.api.EnvType; 17 | import net.fabricmc.api.Environment; 18 | import net.minecraft.client.MinecraftClient; 19 | import net.minecraft.client.gui.DrawContext; 20 | import net.minecraft.client.util.math.MatrixStack; 21 | 22 | /** A simple button */ 23 | @EqualsAndHashCode(callSuper = false) 24 | @ToString 25 | @Environment(EnvType.CLIENT) 26 | public class CleanButton extends ButtonBase { 27 | 28 | protected Color baseColor; 29 | 30 | private MinecraftClient client = MinecraftClient.getInstance(); 31 | 32 | /** 33 | * Constructs a new simple clean button 34 | * 35 | * @param x X 36 | * @param y Y 37 | * @param width Width 38 | * @param height Height 39 | * @param baseColor Color that it should render when not hovered 40 | * @param text Text to render 41 | */ 42 | public CleanButton(int x, int y, int width, int height, Color baseColor, String text) { 43 | super(x, y, width, height, text); 44 | this.x = x; 45 | this.y = y; 46 | this.baseColor = baseColor; 47 | } 48 | 49 | @Override 50 | public void render(int mouseX, int mouseY, boolean selected, DrawContext context) { 51 | int relMX = mouseX - x; 52 | int relMY = mouseY - y; 53 | hovered = relMX >= 0 && relMX <= width && relMY >= 0 && relMY <= height; 54 | Color color = baseColor; 55 | if (hovered) { 56 | color = Colors.getInstance().getColor("white").get().withAlpha(color.alpha()); 57 | } 58 | RenderUtils.drawRect(x, y, width, height, color.color()); 59 | drawCenteredString( 60 | (x + (width / 2)), 61 | (y + (height / 2) - 3), 62 | Colors.getInstance().getColorOrWhite("white").color(), 63 | displayString, 64 | context); 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/gui/ConfigGuiListBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.gui; 9 | 10 | import fi.dy.masa.malilib.gui.widgets.WidgetListBase; 11 | import fi.dy.masa.malilib.gui.widgets.WidgetListEntryBase; 12 | import io.github.darkkronicle.advancedchatcore.config.gui.GuiConfig; 13 | import io.github.darkkronicle.advancedchatcore.config.gui.GuiConfigHandler; 14 | import java.util.List; 15 | 16 | /** GUI list base to work in a configuration screen */ 17 | public abstract class ConfigGuiListBase< 18 | TYPE, 19 | WIDGET extends WidgetListEntryBase, 20 | WIDGETLIST extends WidgetListBase> 21 | extends CoreGuiListBase { 22 | 23 | public ConfigGuiListBase(List tabButtons) { 24 | this(10, 60, tabButtons); 25 | } 26 | 27 | public ConfigGuiListBase() { 28 | this(10, 60, null); 29 | } 30 | 31 | public ConfigGuiListBase(int listX, int listY, List tabButtons) { 32 | super(listX, listY); 33 | } 34 | 35 | @Override 36 | public void initGui() { 37 | super.initGui(); 38 | 39 | int x = 10; 40 | int y = 26; 41 | 42 | y += (22 * GuiConfig.addTabButtons(this, 10, y)); 43 | if (GuiConfig.TAB.getChildren() != null && GuiConfig.TAB.getChildren().size() > 0) { 44 | y += (22 * GuiConfig.addAllChildrenButtons(this, GuiConfig.TAB, 10, y)); 45 | } 46 | this.setListPosition(this.getListX(), y); 47 | this.reCreateListWidget(); 48 | this.getListWidget().refreshEntries(); 49 | 50 | y += 24; 51 | 52 | initGuiConfig(x, y); 53 | } 54 | 55 | /** Method when the GUI is initialized. This one takes an X,Y that is away from the buttons */ 56 | public void initGuiConfig(int x, int y) {} 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/gui/ContextMenu.java: -------------------------------------------------------------------------------- 1 | package io.github.darkkronicle.advancedchatcore.gui; 2 | 3 | import fi.dy.masa.malilib.gui.widgets.WidgetBase; 4 | import io.github.darkkronicle.advancedchatcore.util.Color; 5 | import io.github.darkkronicle.advancedchatcore.util.TextUtil; 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | import net.minecraft.client.MinecraftClient; 9 | import net.minecraft.client.gui.DrawContext; 10 | import net.minecraft.text.Text; 11 | 12 | import java.util.LinkedHashMap; 13 | 14 | public class ContextMenu extends WidgetBase { 15 | 16 | private final LinkedHashMap options; 17 | private Text hoveredEntry = null; 18 | 19 | @Getter 20 | private final int contextX; 21 | 22 | @Getter 23 | private final int contextY; 24 | 25 | @Getter 26 | @Setter 27 | private Runnable close; 28 | 29 | @Setter 30 | @Getter 31 | private Color background; 32 | 33 | @Setter 34 | @Getter 35 | private Color hover; 36 | 37 | public ContextMenu(int x, int y, LinkedHashMap options, Runnable close) { 38 | this(x, y, options, close, new Color(0, 0, 0, 200), new Color(255, 255, 255, 100)); 39 | } 40 | 41 | public ContextMenu(int x, int y, LinkedHashMap options, Runnable close, Color background, Color hover) { 42 | super(x, y, 10, 10); 43 | this.contextX = x; 44 | this.contextY = y; 45 | this.options = options; 46 | updateDimensions(); 47 | this.close = close; 48 | this.background = background; 49 | this.hover = hover; 50 | } 51 | 52 | public void updateDimensions() { 53 | setWidth(TextUtil.getMaxLengthString(options.keySet().stream().map(Text::getString).toList()) + 4); 54 | setHeight(options.size() * (textRenderer.fontHeight + 2)); 55 | int windowWidth = MinecraftClient.getInstance().getWindow().getScaledWidth(); 56 | int windowHeight = MinecraftClient.getInstance().getWindow().getScaledHeight(); 57 | if (x + width > windowWidth) { 58 | x = windowWidth - width; 59 | } 60 | if (y + height > windowHeight) { 61 | y = windowHeight - height; 62 | } 63 | } 64 | 65 | @Override 66 | public boolean onMouseClicked(int mouseX, int mouseY, int mouseButton) { 67 | boolean success = super.onMouseClicked(mouseX, mouseY, mouseButton); 68 | if (success) { 69 | return true; 70 | } 71 | // Didn't click on this 72 | close.run(); 73 | return false; 74 | } 75 | 76 | @Override 77 | protected boolean onMouseClickedImpl(int mouseX, int mouseY, int mouseButton) { 78 | if (mouseButton != 0) { 79 | return false; 80 | } 81 | if (hoveredEntry == null) { 82 | return false; 83 | } 84 | options.get(hoveredEntry).takeAction(contextX, contextY); 85 | close.run(); 86 | return true; 87 | } 88 | 89 | @Override 90 | public void render(int mouseX, int mouseY, boolean selected, DrawContext context) { 91 | drawRect(context, x, y, width, height, background.color()); 92 | int rX = x + 2; 93 | int rY = y + 2; 94 | hoveredEntry = null; 95 | for (Text option : options.keySet()) { 96 | if (mouseX >= x && mouseX <= x + width && mouseY >= rY - 2 && mouseY < rY + fontHeight + 1) { 97 | hoveredEntry = option; 98 | drawRect(context, rX - 2, rY - 2, width, textRenderer.fontHeight + 2, hover.color()); 99 | } 100 | context.drawTextWithShadow(textRenderer, option, rX, rY, -1); 101 | rY += textRenderer.fontHeight + 2; 102 | } 103 | } 104 | 105 | private static void drawRect(DrawContext context, int x, int y, int width, int height, int color) { 106 | context.fill(x, y, x + width, y + height, color); 107 | } 108 | 109 | public interface ContextConsumer { 110 | void takeAction(int x, int y); 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/gui/CoreGuiListBase.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.gui; 9 | 10 | import fi.dy.masa.malilib.gui.GuiListBase; 11 | import fi.dy.masa.malilib.gui.button.ButtonBase; 12 | import fi.dy.masa.malilib.gui.interfaces.ISelectionListener; 13 | import fi.dy.masa.malilib.gui.widgets.WidgetListBase; 14 | import fi.dy.masa.malilib.gui.widgets.WidgetListEntryBase; 15 | import io.github.darkkronicle.advancedchatcore.interfaces.IClosable; 16 | 17 | public abstract class CoreGuiListBase< 18 | TYPE, 19 | WIDGET extends WidgetListEntryBase, 20 | WIDGETLIST extends WidgetListBase> 21 | extends GuiListBase 22 | implements ISelectionListener, IClosable { 23 | 24 | public CoreGuiListBase(int listX, int listY) { 25 | super(listX, listY); 26 | } 27 | 28 | @Override 29 | protected WIDGETLIST createListWidget(int listX, int listY) { 30 | return null; 31 | } 32 | 33 | @Override 34 | protected int getBrowserWidth() { 35 | return this.width - 20; 36 | } 37 | 38 | @Override 39 | protected int getBrowserHeight() { 40 | return this.height - 6 - this.getListY(); 41 | } 42 | 43 | @Override 44 | public void onSelectionChange(TYPE entry) {} 45 | 46 | @Override 47 | public void close(ButtonBase button) { 48 | this.closeGui(true); 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/gui/IconButton.java: -------------------------------------------------------------------------------- 1 | package io.github.darkkronicle.advancedchatcore.gui; 2 | 3 | import fi.dy.masa.malilib.render.RenderUtils; 4 | import io.github.darkkronicle.advancedchatcore.util.Color; 5 | import io.github.darkkronicle.advancedchatcore.util.Colors; 6 | import lombok.Getter; 7 | import lombok.Setter; 8 | import net.minecraft.client.MinecraftClient; 9 | import net.minecraft.client.gui.DrawContext; 10 | import net.minecraft.client.sound.PositionedSoundInstance; 11 | import net.minecraft.client.util.math.MatrixStack; 12 | import net.minecraft.sound.SoundEvents; 13 | import net.minecraft.util.Identifier; 14 | 15 | import java.util.function.Consumer; 16 | 17 | public class IconButton extends CleanButton { 18 | 19 | @Setter 20 | @Getter 21 | private int padding; 22 | 23 | @Setter 24 | @Getter 25 | private Identifier icon; 26 | 27 | @Setter 28 | @Getter 29 | private int iconWidth; 30 | 31 | @Setter 32 | @Getter 33 | private int iconHeight; 34 | 35 | @Setter 36 | @Getter 37 | private Consumer onClick; 38 | 39 | @Getter 40 | @Setter 41 | private String onHover; 42 | 43 | public IconButton(int x, int y, int sideLength, int iconLength, Identifier icon, Consumer mouseClick) { 44 | this(x, y, sideLength, sideLength, iconLength, iconLength, icon, mouseClick); 45 | } 46 | 47 | public IconButton(int x, int y, int width, int height, int iconWidth, int iconHeight, Identifier icon, Consumer mouseClick) { 48 | this(x, y, width, height, 2, iconWidth, iconHeight, icon, mouseClick, null); 49 | } 50 | 51 | public IconButton(int x, int y, int width, int height, int padding, int iconWidth, int iconHeight, Identifier icon, Consumer mouseClick, String onHover) { 52 | super(x, y, width, height, null, null); 53 | this.padding = padding; 54 | this.iconWidth = iconWidth; 55 | this.iconHeight = iconHeight; 56 | this.icon = icon; 57 | this.onClick = mouseClick; 58 | this.onHover = onHover; 59 | } 60 | 61 | @Override 62 | public void render(int mouseX, int mouseY, boolean unused, DrawContext context) { 63 | int relMX = mouseX - x; 64 | int relMY = mouseY - y; 65 | hovered = relMX >= 0 && relMX <= width && relMY >= 0 && relMY <= height; 66 | 67 | Color plusBack = Colors.getInstance().getColorOrWhite("background").withAlpha(100); 68 | if (hovered) { 69 | plusBack = Colors.getInstance().getColorOrWhite("hover").withAlpha(plusBack.alpha()); 70 | } 71 | 72 | RenderUtils.drawRect(x, y, width, height, plusBack.color()); 73 | 74 | RenderUtils.color(1, 1, 1, 1); 75 | RenderUtils.bindTexture(icon); 76 | context.drawTexture(icon, x + padding, y + padding, width - (padding * 2), height - (padding * 2), 77 | 0, 0, iconWidth, iconHeight, iconWidth, iconHeight); 78 | 79 | if (hovered && onHover != null) { 80 | context.drawCenteredTextWithShadow( 81 | MinecraftClient.getInstance().textRenderer, 82 | onHover, 83 | mouseX + 4, 84 | mouseY - 16, 85 | Colors.getInstance().getColorOrWhite("white").color()); 86 | } 87 | } 88 | 89 | @Override 90 | protected boolean onMouseClickedImpl(int mouseX, int mouseY, int mouseButton) { 91 | this.mc.getSoundManager().play(PositionedSoundInstance.master(SoundEvents.UI_BUTTON_CLICK, 1.0F)); 92 | onClick.accept(this); 93 | return true; 94 | } 95 | 96 | } 97 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/gui/WidgetConfigList.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.gui; 9 | 10 | import fi.dy.masa.malilib.gui.GuiTextFieldGeneric; 11 | import fi.dy.masa.malilib.gui.interfaces.ISelectionListener; 12 | import fi.dy.masa.malilib.gui.widgets.WidgetListBase; 13 | import fi.dy.masa.malilib.gui.wrappers.TextFieldWrapper; 14 | import java.util.ArrayList; 15 | import java.util.List; 16 | import net.minecraft.client.gui.screen.Screen; 17 | 18 | public abstract class WidgetConfigList> 19 | extends WidgetListBase { 20 | 21 | protected List> textFields = new ArrayList<>(); 22 | 23 | public WidgetConfigList( 24 | int x, 25 | int y, 26 | int width, 27 | int height, 28 | ISelectionListener selectionListener, 29 | Screen parent) { 30 | super(x, y, width, height, selectionListener); 31 | this.browserEntryHeight = 22; 32 | this.setParent(parent); 33 | } 34 | 35 | @Override 36 | protected void reCreateListEntryWidgets() { 37 | textFields.clear(); 38 | super.reCreateListEntryWidgets(); 39 | } 40 | 41 | public void addTextField(TextFieldWrapper text) { 42 | textFields.add(text); 43 | } 44 | 45 | protected void clearTextFieldFocus() { 46 | for (TextFieldWrapper field : this.textFields) { 47 | GuiTextFieldGeneric textField = field.getTextField(); 48 | 49 | if (textField.isFocused()) { 50 | textField.setFocused(false); 51 | break; 52 | } 53 | } 54 | } 55 | 56 | @Override 57 | public boolean onMouseClicked(int mouseX, int mouseY, int mouseButton) { 58 | clearTextFieldFocus(); 59 | return super.onMouseClicked(mouseX, mouseY, mouseButton); 60 | } 61 | 62 | @Override 63 | public boolean onKeyTyped(int keyCode, int scanCode, int modifiers) { 64 | for (WidgetConfigListEntry widget : this.listWidgets) { 65 | if (widget.onKeyTyped(keyCode, scanCode, modifiers)) { 66 | return true; 67 | } 68 | } 69 | return super.onKeyTyped(keyCode, scanCode, modifiers); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/gui/buttons/BackButtonListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.gui.buttons; 9 | 10 | import fi.dy.masa.malilib.gui.button.ButtonBase; 11 | import fi.dy.masa.malilib.gui.button.IButtonActionListener; 12 | import io.github.darkkronicle.advancedchatcore.interfaces.IClosable; 13 | 14 | public class BackButtonListener implements IButtonActionListener { 15 | 16 | private final IClosable closable; 17 | 18 | public BackButtonListener(IClosable closable) { 19 | this.closable = closable; 20 | } 21 | 22 | @Override 23 | public void actionPerformedWithButton(ButtonBase button, int mouseButton) { 24 | this.closable.close(button); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/gui/buttons/Buttons.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.gui.buttons; 9 | 10 | import fi.dy.masa.malilib.util.StringUtils; 11 | 12 | public enum Buttons { 13 | BACK("advancedchat.gui.button.back"); 14 | 15 | private final String translationString; 16 | 17 | Buttons(String translationString) { 18 | this.translationString = translationString; 19 | } 20 | 21 | public NamedSimpleButton createButton(int x, int y) { 22 | return new NamedSimpleButton(x, y, StringUtils.translate(translationString)); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/gui/buttons/ConfigTabsButtonListener.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.gui.buttons; 9 | 10 | import fi.dy.masa.malilib.gui.GuiBase; 11 | import fi.dy.masa.malilib.gui.button.ButtonBase; 12 | import fi.dy.masa.malilib.gui.button.IButtonActionListener; 13 | import io.github.darkkronicle.advancedchatcore.config.gui.GuiConfig; 14 | import io.github.darkkronicle.advancedchatcore.config.gui.GuiConfigHandler; 15 | import net.fabricmc.api.EnvType; 16 | import net.fabricmc.api.Environment; 17 | 18 | @Deprecated 19 | @Environment(EnvType.CLIENT) 20 | public class ConfigTabsButtonListener implements IButtonActionListener { 21 | 22 | private final GuiConfigHandler.TabButton tabButton; 23 | 24 | public ConfigTabsButtonListener(GuiConfigHandler.TabButton tabButton) { 25 | this.tabButton = tabButton; 26 | } 27 | 28 | @Override 29 | public void actionPerformedWithButton(ButtonBase button, int mouseButton) { 30 | GuiConfig.TAB = tabButton.getTabSupplier(); 31 | GuiBase.openGui(new GuiConfig()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/gui/buttons/NamedSimpleButton.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.gui.buttons; 9 | 10 | import fi.dy.masa.malilib.gui.button.ButtonGeneric; 11 | import fi.dy.masa.malilib.util.StringUtils; 12 | 13 | public class NamedSimpleButton extends ButtonGeneric { 14 | 15 | public NamedSimpleButton(int x, int y, String text) { 16 | this(x, y, text, true); 17 | } 18 | 19 | public NamedSimpleButton(int x, int y, String text, boolean alineLeft) { 20 | super(x, y, 5, 20, text); 21 | setWidth(StringUtils.getStringWidth(text) + 10); 22 | if (!alineLeft) { 23 | setX(this.x - this.width); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/hotkeys/InputHandler.java: -------------------------------------------------------------------------------- 1 | package io.github.darkkronicle.advancedchatcore.hotkeys; 2 | 3 | import fi.dy.masa.malilib.config.options.ConfigHotkey; 4 | import fi.dy.masa.malilib.event.InputEventHandler; 5 | import fi.dy.masa.malilib.hotkeys.*; 6 | import lombok.Getter; 7 | 8 | import java.util.ArrayList; 9 | import java.util.HashMap; 10 | import java.util.List; 11 | import java.util.Map; 12 | 13 | public class InputHandler implements IKeybindProvider, IKeyboardInputHandler, IMouseInputHandler { 14 | 15 | private final static InputHandler INSTANCE = new InputHandler(); 16 | @Getter 17 | private final Map> hotkeys = new HashMap<>(); 18 | @Getter 19 | private final Map translation = new HashMap<>(); 20 | 21 | public static InputHandler getInstance() { 22 | return INSTANCE; 23 | } 24 | 25 | private InputHandler() {} 26 | 27 | public void clear(String modId) { 28 | hotkeys.remove(modId); 29 | } 30 | 31 | public void addDisplayName(String modId, String displayName) { 32 | translation.put(modId, displayName); 33 | } 34 | 35 | public void add(String modId, ConfigHotkey hotkey) { 36 | if (!hotkeys.containsKey(modId)) { 37 | hotkeys.put(modId, new ArrayList<>()); 38 | } 39 | hotkeys.get(modId).add(hotkey); 40 | } 41 | 42 | public void add(String modId, ConfigHotkey hotkey, IHotkeyCallback callback) { 43 | hotkey.getKeybind().setCallback(callback); 44 | add(modId, hotkey); 45 | } 46 | 47 | @Override 48 | public void addKeysToMap(IKeybindManager manager) { 49 | for (List hots : hotkeys.values()) { 50 | for (IHotkey hotkey : hots) { 51 | manager.addKeybindToMap(hotkey.getKeybind()); 52 | } 53 | } 54 | } 55 | 56 | @Override 57 | public void addHotkeys(IKeybindManager manager) { 58 | for (Map.Entry> hots : hotkeys.entrySet()) { 59 | manager.addHotkeysForCategory(hots.getKey(), "hotkeys", hots.getValue()); 60 | } 61 | } 62 | 63 | public void reload() { 64 | InputEventHandler.getKeybindManager().updateUsedKeys(); 65 | } 66 | 67 | public String getDisplayName(String key) { 68 | return translation.getOrDefault(key, key); 69 | } 70 | } -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/interfaces/AdvancedChatScreenSection.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.interfaces; 9 | 10 | import io.github.darkkronicle.advancedchatcore.chat.AdvancedChatScreen; 11 | import lombok.Getter; 12 | import net.minecraft.client.gui.Drawable; 13 | import net.minecraft.client.util.math.MatrixStack; 14 | 15 | /** 16 | * A class meant to extend onto the {@link AdvancedChatScreen} 17 | * 18 | *

This is used so that many modules can add onto the screen without problems occuring. 19 | */ 20 | public abstract class AdvancedChatScreenSection implements Drawable { 21 | 22 | /** The {@link AdvancedChatScreen} that is linked to this section */ 23 | @Getter private final AdvancedChatScreen screen; 24 | 25 | public AdvancedChatScreenSection(AdvancedChatScreen screen) { 26 | this.screen = screen; 27 | } 28 | 29 | /** Triggers when the gui is initiated */ 30 | public void initGui() {} 31 | 32 | /** 33 | * Triggered when the window is resized 34 | * 35 | * @param width Window width 36 | * @param height Window height 37 | */ 38 | public void resize(int width, int height) {} 39 | 40 | /** Triggered when the GUI is closed */ 41 | public void removed() {} 42 | 43 | /** 44 | * Triggered when the chatfield text is pudated 45 | * 46 | * @param chatText Updated value (?) 47 | * @param text The text of the chatfield 48 | */ 49 | public void onChatFieldUpdate(String chatText, String text) {} 50 | 51 | /** 52 | * Triggered when a key is pressed 53 | * 54 | * @param keyCode Keycode 55 | * @param scanCode Scancode 56 | * @param modifiers Modifiers 57 | * @return If it was handled and should stop. 58 | */ 59 | public boolean keyPressed(int keyCode, int scanCode, int modifiers) { 60 | return false; 61 | } 62 | 63 | /** 64 | * Triggered when the mouse is scrolled 65 | * 66 | * @param mouseX MouseX 67 | * @param mouseY MouseY 68 | * @param amount Scroll amount 69 | * @return If it was handled and should stop. 70 | */ 71 | public boolean mouseScrolled(double mouseX, double mouseY, double amount) { 72 | return false; 73 | } 74 | 75 | /** 76 | * Triggered when the mouse is clicked 77 | * 78 | * @param mouseX MouseX 79 | * @param mouseY MouseY 80 | * @param button Mouse button 81 | * @return If it was handled and should stop. 82 | */ 83 | public boolean mouseClicked(double mouseX, double mouseY, int button) { 84 | return false; 85 | } 86 | 87 | /** 88 | * Triggered when the mouse click is released 89 | * 90 | * @param mouseX MouseX 91 | * @param mouseY MouseY 92 | * @param mouseButton Mouse button 93 | * @return If it was handled and should stop. 94 | */ 95 | public boolean mouseReleased(double mouseX, double mouseY, int mouseButton) { 96 | return false; 97 | } 98 | 99 | /** 100 | * @param mouseX 101 | * @param mouseY 102 | * @param button 103 | * @param deltaX 104 | * @param deltaY 105 | * @return If it was handled and should stop. 106 | */ 107 | public boolean mouseDragged( 108 | double mouseX, double mouseY, int button, double deltaX, double deltaY) { 109 | return false; 110 | } 111 | 112 | /** 113 | * Called when the chat field gets set due to history (up arrows) 114 | * 115 | * @param hist History set from 116 | */ 117 | public void setChatFromHistory(String hist) {} 118 | 119 | /** 120 | * Called when the screen renders. 121 | * 122 | * @param matrixStack MatrixStack 123 | * @param mouseX MouseX 124 | * @param mouseY MouseY 125 | * @param partialTicks Partial tick from the last tick 126 | */ 127 | public void render(MatrixStack matrixStack, int mouseX, int mouseY, float partialTicks) {} 128 | } 129 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/interfaces/ConfigRegistryOption.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.interfaces; 9 | 10 | import com.google.gson.JsonElement; 11 | import com.google.gson.JsonObject; 12 | import fi.dy.masa.malilib.config.IConfigOptionListEntry; 13 | import fi.dy.masa.malilib.config.options.ConfigBoolean; 14 | import io.github.darkkronicle.advancedchatcore.config.SaveableConfig; 15 | import java.util.Map; 16 | import net.fabricmc.api.EnvType; 17 | import net.fabricmc.api.Environment; 18 | 19 | /** 20 | * A {@link RegistryOption} that can be saved and loaded from a JSON file. 21 | * 22 | * @param 23 | */ 24 | @Environment(EnvType.CLIENT) 25 | public interface ConfigRegistryOption 26 | extends RegistryOption, IConfigOptionListEntry, IJsonApplier { 27 | /** 28 | * Get's a configurable boolean for whether or not the option is active. 29 | * 30 | * @return Configurable boolean 31 | */ 32 | SaveableConfig getActive(); 33 | 34 | /** 35 | * Get's if the option is currently active. 36 | * 37 | * @return If the option is active 38 | */ 39 | @Override 40 | default boolean isActive() { 41 | return getActive().config.getBooleanValue(); 42 | } 43 | 44 | /** 45 | * Save's the config option and the object that it is wrapping. 46 | * 47 | *

By default it will only save if the option is active or not, but if the {@link TYPE} 48 | * implements {@link IJsonApplier} it will also save/load that object. 49 | * 50 | * @return Serialized object 51 | */ 52 | @Override 53 | default JsonObject save() { 54 | JsonObject obj = new JsonObject(); 55 | obj.add(getActive().key, getActive().config.getAsJsonElement()); 56 | JsonObject extra = null; 57 | if (getOption() instanceof IJsonApplier) { 58 | extra = ((IJsonApplier) getOption()).save(); 59 | } 60 | if (extra != null) { 61 | for (Map.Entry e : extra.entrySet()) { 62 | obj.add(e.getKey(), e.getValue()); 63 | } 64 | } 65 | return obj; 66 | } 67 | 68 | /** 69 | * Load's the config option and the object that it is wrapping. 70 | * 71 | *

By default it will only load if the option is active or not, but if the {@link TYPE} 72 | * implements {@link IJsonApplier} it will also save/load that object. 73 | */ 74 | @Override 75 | default void load(JsonElement element) { 76 | if (element == null || !element.isJsonObject()) { 77 | return; 78 | } 79 | JsonObject obj = element.getAsJsonObject(); 80 | getActive().config.setValueFromJsonElement(obj.get(getActive().key)); 81 | if (getOption() instanceof IJsonApplier) { 82 | ((IJsonApplier) getOption()).load(obj); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/interfaces/IChatMessageProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.interfaces; 9 | 10 | import io.github.darkkronicle.advancedchatcore.chat.ChatMessage; 11 | 12 | /** 13 | * A processor that will get updated whenever an event in {@link 14 | * io.github.darkkronicle.advancedchatcore.chat.ChatHistory} happens. This gets triggered for 15 | * specific {@link ChatMessage}. 16 | */ 17 | public interface IChatMessageProcessor { 18 | /** Types of chat message events that can be referenced */ 19 | enum UpdateType { 20 | /** A new message is sent. This still gets triggered even if the message is stacked. */ 21 | NEW, 22 | 23 | /** A message is added to the history. This does not get called on stack. */ 24 | ADDED, 25 | 26 | /** A previous message has been stacked. The stack number has changed. */ 27 | STACK, 28 | 29 | /** 30 | * A message is removed. This does not get called on clear, but only if a specific message 31 | * was called to remove. 32 | */ 33 | REMOVE, 34 | } 35 | 36 | /** 37 | * A method to handle a {@link ChatMessage} update. 38 | * 39 | * @param message Message that was updated 40 | * @param type Type of the update 41 | */ 42 | void onMessageUpdate(ChatMessage message, UpdateType type); 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/interfaces/IClosable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.interfaces; 9 | 10 | import fi.dy.masa.malilib.gui.button.ButtonBase; 11 | 12 | public interface IClosable { 13 | 14 | void close(ButtonBase button); 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/interfaces/IFinder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.interfaces; 9 | 10 | import io.github.darkkronicle.advancedchatcore.util.StringMatch; 11 | import net.minecraft.text.Text; 12 | 13 | import java.util.List; 14 | 15 | public interface IFinder { 16 | 17 | boolean isMatch(String input, String toMatch); 18 | 19 | default boolean isMatch(Text input, String toMatch) { 20 | return isMatch(input.getString(), toMatch); 21 | } 22 | 23 | List getMatches(String input, String toMatch); 24 | 25 | default List getMatches(Text input, String toMatch) { 26 | return getMatches(input.getString(), toMatch); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/interfaces/IJsonApplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.interfaces; 9 | 10 | import com.google.gson.JsonElement; 11 | import com.google.gson.JsonObject; 12 | 13 | /** An interface to serialize and deserialize classes into themselves. */ 14 | public interface IJsonApplier { 15 | /** 16 | * Serializes the object into a JsonObject. 17 | * 18 | * @return Constructed JsonObject 19 | */ 20 | JsonObject save(); 21 | 22 | /** 23 | * Takes a JsonElement and loads it into the class. 24 | * 25 | * @param element Element to load 26 | */ 27 | void load(JsonElement element); 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/interfaces/IJsonSave.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.interfaces; 9 | 10 | import com.google.gson.JsonObject; 11 | 12 | /** 13 | * Json serializer for other classes. 14 | * 15 | * @param Class that this class serializes. 16 | */ 17 | public interface IJsonSave { 18 | /** 19 | * Returns a new object from a JsonObject to deserialize from. 20 | * 21 | * @param obj Object containing serialized data 22 | * @return Constructed object 23 | */ 24 | T load(JsonObject obj); 25 | 26 | /** 27 | * Takes an object (T) and serializes it. 28 | * 29 | * @param t Object to serialize 30 | * @return Serialized {@link JsonObject} 31 | */ 32 | JsonObject save(T t); 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/interfaces/IMatchProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021-2022 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.interfaces; 9 | 10 | import io.github.darkkronicle.advancedchatcore.util.SearchResult; 11 | import net.minecraft.text.Text; 12 | import org.jetbrains.annotations.Nullable; 13 | 14 | /** 15 | * An interface to receive text and matches to process. 16 | * 17 | *

Similar to {@link IMessageProcessor} but it takes matches and can return a {@link Result} 18 | */ 19 | public interface IMatchProcessor extends IMessageProcessor { 20 | /** Different outcome's the processor can have */ 21 | enum Result { 22 | FAIL(false, true, false), 23 | PROCESSED(true, false, false), 24 | FORCE_FORWARD(true, true, true), 25 | FORCE_STOP(true, false, true); 26 | 27 | public final boolean success; 28 | public final boolean forward; 29 | public final boolean force; 30 | 31 | Result(boolean success, boolean forward, boolean force) { 32 | this.success = success; 33 | this.forward = forward; 34 | this.force = force; 35 | } 36 | 37 | public static Result getFromBool(boolean success) { 38 | if (!success) { 39 | return FAIL; 40 | } 41 | return PROCESSED; 42 | } 43 | } 44 | 45 | @Override 46 | default boolean process(Text text, Text unfiltered) { 47 | return processMatches(text, unfiltered, null).success; 48 | } 49 | 50 | /** 51 | * Process specific matches and return how the rest of the processors should be handled 52 | * 53 | * @param text Final text 54 | * @param unfiltered Unfiltered version of text. If not available null. 55 | * @param search {@link SearchResult} matches 56 | * @return The {@link Result} that the method performed 57 | */ 58 | Result processMatches( 59 | Text text, @Nullable Text unfiltered, @Nullable SearchResult search); 60 | 61 | /** 62 | * Whether or not this processor should only trigger when matches are present. If false {@link 63 | * SearchResult} can be null. 64 | * 65 | * @return If this processor should only trigger when matches are present 66 | */ 67 | default boolean matchesOnly() { 68 | return true; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/interfaces/IMessageFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021-2022 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.interfaces; 9 | 10 | import net.minecraft.text.Text; 11 | import java.util.Optional; 12 | 13 | /** An interface to modify text. */ 14 | public interface IMessageFilter { 15 | /** 16 | * Modifies text 17 | * 18 | * @param text Text to modify 19 | * @return Modified text. If empty, the text won't be changed. 20 | */ 21 | Optional filter(Text text); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/interfaces/IMessageProcessor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021-2022 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.interfaces; 9 | 10 | import net.minecraft.client.gui.hud.MessageIndicator; 11 | import net.minecraft.network.message.MessageSignatureData; 12 | import net.minecraft.text.Text; 13 | import java.util.Optional; 14 | import org.jetbrains.annotations.Nullable; 15 | 16 | /** An interface for taking text and processing it. */ 17 | public interface IMessageProcessor extends IMessageFilter { 18 | /** 19 | * Processes text without the unfiltered text. 20 | * 21 | *

Deprecated because it won't return anything. If unfiltered doesn't exist, insert null into 22 | * process. 23 | * 24 | * @param text Text to modify 25 | * @return Empty 26 | */ 27 | @Deprecated 28 | @Override 29 | default Optional filter(Text text) { 30 | process(text, null); 31 | return Optional.empty(); 32 | } 33 | 34 | /** 35 | * Consumes text. 36 | * 37 | * @param text Final text to process 38 | * @param unfiltered Original text (if available) 39 | * @return If the processing was a success 40 | */ 41 | boolean process(Text text, @Nullable Text unfiltered); 42 | 43 | default boolean process(Text text, @Nullable Text unfilterered, @Nullable MessageSignatureData signature, @Nullable MessageIndicator indicator) { 44 | return process(text, unfilterered); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/interfaces/IScreenSupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.interfaces; 9 | 10 | import java.util.function.Supplier; 11 | import net.minecraft.client.gui.screen.Screen; 12 | import org.jetbrains.annotations.Nullable; 13 | 14 | /** An interface to supply a screen. */ 15 | public interface IScreenSupplier { 16 | /** 17 | * Get's a supplier of a screen based off of a parent. 18 | * 19 | * @param parent Parent screen (nullable) 20 | * @return Supplier of a screen 21 | */ 22 | Supplier getScreen(@Nullable Screen parent); 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/interfaces/IStringFilter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.interfaces; 9 | 10 | import java.util.Optional; 11 | 12 | /** An interface to modify raw string */ 13 | public interface IStringFilter { 14 | 15 | Optional filter(String input); 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/interfaces/RegistryOption.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.interfaces; 9 | 10 | import io.github.darkkronicle.advancedchatcore.util.AbstractRegistry; 11 | import java.util.List; 12 | import java.util.function.Supplier; 13 | import net.minecraft.client.gui.screen.Screen; 14 | 15 | /** 16 | * An interface to get a RegistryOption that can be saved/configured in game. 17 | * 18 | * @param Object type to be wrapped 19 | */ 20 | public interface RegistryOption { 21 | /** 22 | * Get's the object that this option is wrapping 23 | * 24 | * @return Object that is wrapped 25 | */ 26 | TYPE getOption(); 27 | 28 | /** 29 | * Whether or not this option is currently active 30 | * 31 | * @return If it is active 32 | */ 33 | boolean isActive(); 34 | 35 | /** 36 | * Get's the string that will be saved inside of the JSON. 37 | * 38 | * @return Save string 39 | */ 40 | String getSaveString(); 41 | 42 | /** 43 | * Copies the registry option without a parent registry 44 | * 45 | * @return A copy of this object 46 | */ 47 | default RegistryOption copy() { 48 | return copy(null); 49 | } 50 | 51 | /** 52 | * If this value should be hidden in the menu 53 | * 54 | * @return If it should be hidden 55 | */ 56 | default boolean isHidden() { 57 | return false; 58 | } 59 | 60 | /** 61 | * Copies the registry option with a parent registry that it will be tied to. 62 | * 63 | *

Used for copying registries so that options can be modified easily. 64 | * 65 | * @param registry Registry that will be the parent 66 | * @return Copied object 67 | */ 68 | RegistryOption copy(AbstractRegistry registry); 69 | 70 | /** 71 | * Get's the configuration screen of this option. If this isn't null a button will be generated 72 | * if in a GUI. 73 | * 74 | * @param parent Parent screen 75 | * @return Supplier for the config screen. Null if it doesn't exist. 76 | */ 77 | default Supplier getScreen(Screen parent) { 78 | if (!(getOption() instanceof IScreenSupplier)) { 79 | return null; 80 | } 81 | return ((IScreenSupplier) getOption()).getScreen(parent); 82 | } 83 | 84 | /** 85 | * Hover lines to show when in the GUI and hovering. 86 | * 87 | * @return List of strings that contain the hover lines 88 | */ 89 | default List getHoverLines() { 90 | return null; 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/interfaces/Translatable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.interfaces; 9 | 10 | import fi.dy.masa.malilib.util.StringUtils; 11 | 12 | /** An interface for a translatable object */ 13 | public interface Translatable { 14 | /** 15 | * Translation key of the object 16 | * 17 | * @return Translation key 18 | */ 19 | String getTranslationKey(); 20 | 21 | /** 22 | * Translates the object 23 | * 24 | * @return Translated string 25 | */ 26 | default String translate() { 27 | return StringUtils.translate(getTranslationKey()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/konstruct/AdvancedChatKonstruct.java: -------------------------------------------------------------------------------- 1 | package io.github.darkkronicle.advancedchatcore.konstruct; 2 | 3 | import io.github.darkkronicle.Konstruct.functions.Function; 4 | import io.github.darkkronicle.Konstruct.functions.NamedFunction; 5 | import io.github.darkkronicle.Konstruct.functions.Variable; 6 | import io.github.darkkronicle.Konstruct.nodes.Node; 7 | import io.github.darkkronicle.Konstruct.parser.*; 8 | import io.github.darkkronicle.Konstruct.reader.builder.NodeBuilder; 9 | import io.github.darkkronicle.Konstruct.type.IntegerObject; 10 | import io.github.darkkronicle.Konstruct.type.StringObject; 11 | import io.github.darkkronicle.addons.*; 12 | import io.github.darkkronicle.advancedchatcore.AdvancedChatCore; 13 | import io.github.darkkronicle.advancedchatcore.util.Color; 14 | import io.github.darkkronicle.advancedchatcore.util.Colors; 15 | import io.github.darkkronicle.advancedchatcore.util.TextUtil; 16 | import lombok.Getter; 17 | import net.minecraft.util.Util; 18 | 19 | import java.util.List; 20 | 21 | public class AdvancedChatKonstruct { 22 | 23 | private static final AdvancedChatKonstruct INSTANCE = new AdvancedChatKonstruct(); 24 | 25 | public static AdvancedChatKonstruct getInstance() { 26 | return INSTANCE; 27 | } 28 | 29 | @Getter 30 | private NodeProcessor processor; 31 | 32 | private AdvancedChatKonstruct() { 33 | reset(); 34 | addFunction(new CalculatorFunction()); 35 | addFunction(new RandomFunction()); 36 | addFunction(new ReplaceFunction()); 37 | addFunction(new RoundFunction()); 38 | addFunction(new OwOFunction()); 39 | addFunction(new RomanNumeralFunction()); 40 | addFunction(new IsMatchFunction()); 41 | addFunction(new TimeFunction()); 42 | addVariable("server", () -> new StringObject(AdvancedChatCore.getServer())); 43 | addFunction("randomString", new Function() { 44 | @Override 45 | public Result parse(ParseContext context, List input) { 46 | return Result.success(AdvancedChatCore.getRandomString()); 47 | } 48 | 49 | @Override 50 | public IntRange getArgumentCount() { 51 | return IntRange.none(); 52 | } 53 | }); 54 | addFunction("getColor", new Function() { 55 | @Override 56 | public Result parse(ParseContext context, List input) { 57 | Result res = Function.parseArgument(context, input, 0); 58 | if (Function.shouldReturn(res)) return res; 59 | Color color = Colors.getInstance().getColorOrWhite(res.getContent().getString()); 60 | return Result.success(color.getString()); 61 | } 62 | 63 | @Override 64 | public IntRange getArgumentCount() { 65 | return IntRange.of(1); 66 | } 67 | }); 68 | addFunction("superscript", new Function() { 69 | @Override 70 | public Result parse(ParseContext context, List input) { 71 | int number; 72 | try { 73 | Result res = Function.parseArgument(context, input, 0); 74 | if (Function.shouldReturn(res)) return res; 75 | number = Integer.parseInt(res.getContent().getString().strip()); 76 | } catch (NumberFormatException e) { 77 | return Result.success("NaN"); 78 | } 79 | return Result.success(TextUtil.toSuperscript(number)); 80 | } 81 | 82 | @Override 83 | public IntRange getArgumentCount() { 84 | return IntRange.of(1); 85 | } 86 | }); 87 | addVariable("ms", () -> new IntegerObject((int) Util.getMeasuringTimeMs())); 88 | } 89 | 90 | public ParseResult parse(Node node) { 91 | return processor.parse(node); 92 | } 93 | 94 | public Node getNode(String string) { 95 | return new NodeBuilder(string).build(); 96 | } 97 | 98 | public NodeProcessor copy() { 99 | return processor.copy(); 100 | } 101 | 102 | /** Not really recommended to call... */ 103 | public void reset() { 104 | this.processor = new NodeProcessor(); 105 | } 106 | 107 | public void addVariable(String key, Variable variable) { 108 | processor.addVariable(key, variable); 109 | } 110 | 111 | public void addFunction(NamedFunction function) { 112 | processor.addFunction(function); 113 | } 114 | 115 | public void addFunction(String key, Function function) { 116 | processor.addFunction(key, function); 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/konstruct/StringMatchObject.java: -------------------------------------------------------------------------------- 1 | package io.github.darkkronicle.advancedchatcore.konstruct; 2 | 3 | import io.github.darkkronicle.Konstruct.functions.ObjectFunction; 4 | import io.github.darkkronicle.Konstruct.nodes.Node; 5 | import io.github.darkkronicle.Konstruct.parser.IntRange; 6 | import io.github.darkkronicle.Konstruct.parser.ParseContext; 7 | import io.github.darkkronicle.Konstruct.parser.Result; 8 | import io.github.darkkronicle.Konstruct.type.IntegerObject; 9 | import io.github.darkkronicle.Konstruct.type.KonstructObject; 10 | import io.github.darkkronicle.Konstruct.type.StringObject; 11 | import io.github.darkkronicle.advancedchatcore.util.StringMatch; 12 | 13 | import java.util.List; 14 | 15 | public class StringMatchObject extends KonstructObject { 16 | 17 | private final StringMatch result; 18 | 19 | private final static List> FUNCTIONS = List.of( 20 | new ObjectFunction<>() { 21 | @Override 22 | public Result parse(ParseContext context, StringMatchObject self, List input) { 23 | return Result.success(new IntegerObject(self.result.start)); 24 | } 25 | 26 | @Override 27 | public String getName() { 28 | return "getStart"; 29 | } 30 | 31 | @Override 32 | public IntRange getArgumentCount() { 33 | return IntRange.of(0); 34 | } 35 | }, 36 | new ObjectFunction<>() { 37 | @Override 38 | public Result parse(ParseContext context, StringMatchObject self, List input) { 39 | return Result.success(new IntegerObject(self.result.end)); 40 | } 41 | 42 | @Override 43 | public String getName() { 44 | return "getEnd"; 45 | } 46 | 47 | @Override 48 | public IntRange getArgumentCount() { 49 | return IntRange.of(0); 50 | } 51 | }, 52 | new ObjectFunction<>() { 53 | @Override 54 | public Result parse(ParseContext context, StringMatchObject self, List input) { 55 | return Result.success(new StringObject(self.result.match)); 56 | } 57 | 58 | @Override 59 | public String getName() { 60 | return "getMessage"; 61 | } 62 | 63 | @Override 64 | public IntRange getArgumentCount() { 65 | return IntRange.of(0); 66 | } 67 | } 68 | ); 69 | 70 | public StringMatchObject(StringMatch result) { 71 | super(FUNCTIONS); 72 | this.result = result; 73 | } 74 | 75 | @Override 76 | public String getString() { 77 | return result.toString(); 78 | } 79 | 80 | @Override 81 | public String getTypeName() { 82 | return "string_match"; 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/mixin/MixinChatHud.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.mixin; 9 | 10 | import io.github.darkkronicle.advancedchatcore.chat.AdvancedChatScreen; 11 | import io.github.darkkronicle.advancedchatcore.chat.MessageDispatcher; 12 | import io.github.darkkronicle.advancedchatcore.config.ConfigStorage; 13 | import net.minecraft.client.MinecraftClient; 14 | import net.minecraft.client.gui.hud.ChatHud; 15 | import net.minecraft.client.gui.hud.MessageIndicator; 16 | import net.minecraft.network.message.MessageSignatureData; 17 | import net.minecraft.text.Text; 18 | import org.jetbrains.annotations.Nullable; 19 | import org.spongepowered.asm.mixin.Final; 20 | import org.spongepowered.asm.mixin.Mixin; 21 | import org.spongepowered.asm.mixin.Shadow; 22 | import org.spongepowered.asm.mixin.injection.At; 23 | import org.spongepowered.asm.mixin.injection.Inject; 24 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 25 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 26 | 27 | @Mixin(value = ChatHud.class, priority = 1050) 28 | public class MixinChatHud { 29 | 30 | @Shadow @Final private MinecraftClient client; 31 | 32 | @Inject( 33 | method = "addMessage(Lnet/minecraft/text/Text;Lnet/minecraft/network/message/MessageSignatureData;Lnet/minecraft/client/gui/hud/MessageIndicator;)V", 34 | at = @At("HEAD"), 35 | cancellable = true) 36 | private void addMessage(Text message, @Nullable MessageSignatureData signature, @Nullable MessageIndicator indicator, CallbackInfo ci) { 37 | // Pass forward messages to dispatcher 38 | MessageDispatcher.getInstance().handleText(message, signature, indicator); 39 | ci.cancel(); 40 | } 41 | 42 | @Inject(method = "clear", at = @At("HEAD"), cancellable = true) 43 | private void clearMessages(boolean clearTextHistory, CallbackInfo ci) { 44 | if (!clearTextHistory) { 45 | // This only gets called if it is the keybind f3 + d 46 | return; 47 | } 48 | if (!ConfigStorage.General.CLEAR_ON_DISCONNECT.config.getBooleanValue()) { 49 | // Cancel clearing if it's turned off 50 | ci.cancel(); 51 | } 52 | } 53 | 54 | @Inject(method = "isChatFocused", at = @At("HEAD"), cancellable = true) 55 | private void isChatFocused(CallbackInfoReturnable ci) { 56 | // If the chat is focused 57 | ci.setReturnValue(AdvancedChatScreen.PERMANENT_FOCUS || client.currentScreen instanceof AdvancedChatScreen); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/mixin/MixinChatHudInvoker.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.mixin; 9 | 10 | import net.minecraft.client.gui.hud.ChatHud; 11 | import net.minecraft.client.gui.hud.MessageIndicator; 12 | import net.minecraft.network.message.MessageSignatureData; 13 | import net.minecraft.text.Text; 14 | import org.jetbrains.annotations.Nullable; 15 | import org.spongepowered.asm.mixin.Mixin; 16 | import org.spongepowered.asm.mixin.gen.Invoker; 17 | 18 | @Mixin(ChatHud.class) 19 | public interface MixinChatHudInvoker { 20 | @Invoker 21 | void invokeAddMessage(Text message, @Nullable MessageSignatureData signature, int ticks, @Nullable MessageIndicator indicator, boolean refresh); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/mixin/MixinChatScreen.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021-2022 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.mixin; 9 | 10 | import net.fabricmc.api.EnvType; 11 | import net.fabricmc.api.Environment; 12 | import net.minecraft.client.gui.screen.ChatScreen; 13 | import net.minecraft.client.gui.screen.narration.NarrationMessageBuilder; 14 | import org.spongepowered.asm.mixin.Mixin; 15 | import org.spongepowered.asm.mixin.injection.At; 16 | import org.spongepowered.asm.mixin.injection.Inject; 17 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 18 | 19 | @Environment(EnvType.CLIENT) 20 | @Mixin(ChatScreen.class) 21 | public class MixinChatScreen { 22 | 23 | @Inject(method = "addScreenNarrations", at = @At("HEAD"), cancellable = true) 24 | public void screenNarrations(NarrationMessageBuilder builder, CallbackInfo ci) { 25 | // Don't cause random narrations to happen/crashes 26 | ci.cancel(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/mixin/MixinClientPlayerEntity.java: -------------------------------------------------------------------------------- 1 | package io.github.darkkronicle.advancedchatcore.mixin; 2 | 3 | import io.github.darkkronicle.advancedchatcore.chat.AdvancedChatScreen; 4 | import net.minecraft.client.MinecraftClient; 5 | import net.minecraft.client.network.ClientPlayerEntity; 6 | import net.minecraft.entity.Entity; 7 | import net.minecraft.entity.EntityType; 8 | import net.minecraft.world.World; 9 | import org.spongepowered.asm.mixin.Final; 10 | import org.spongepowered.asm.mixin.Mixin; 11 | import org.spongepowered.asm.mixin.Shadow; 12 | import org.spongepowered.asm.mixin.injection.At; 13 | import org.spongepowered.asm.mixin.injection.Inject; 14 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 15 | 16 | @Mixin(ClientPlayerEntity.class) 17 | public abstract class MixinClientPlayerEntity extends Entity { 18 | 19 | @Shadow @Final protected MinecraftClient client; 20 | 21 | @Shadow public float nauseaIntensity; 22 | 23 | public MixinClientPlayerEntity(EntityType type, World world) { 24 | super(type, world); 25 | } 26 | 27 | @Inject( 28 | method="updateNausea", 29 | at = @At(value="INVOKE", target="Lnet/minecraft/client/MinecraftClient;setScreen(Lnet/minecraft/client/gui/screen/Screen;)V"), 30 | cancellable = true 31 | ) 32 | public void updateNauseaHook(CallbackInfo ci) { 33 | if (client.currentScreen instanceof AdvancedChatScreen) { 34 | ci.cancel(); 35 | nauseaIntensity += 0.0125f; 36 | if (this.nauseaIntensity >= 1.0f) { 37 | this.nauseaIntensity = 1.0f; 38 | } 39 | inNetherPortal = false; 40 | } 41 | } 42 | 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/mixin/MixinKeyboard.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.mixin; 9 | 10 | import io.github.darkkronicle.advancedchatcore.chat.ChatHistory; 11 | import net.fabricmc.api.EnvType; 12 | import net.fabricmc.api.Environment; 13 | import net.minecraft.client.Keyboard; 14 | import org.spongepowered.asm.mixin.Mixin; 15 | import org.spongepowered.asm.mixin.injection.At; 16 | import org.spongepowered.asm.mixin.injection.Inject; 17 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 18 | 19 | @Environment(EnvType.CLIENT) 20 | @Mixin(Keyboard.class) 21 | public class MixinKeyboard { 22 | 23 | @Inject( 24 | method = "processF3", 25 | at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/hud/ChatHud;clear(Z)V")) 26 | public void processF3Chat(int key, CallbackInfoReturnable ci) { 27 | // Make it so that history can still be cleared 28 | ChatHistory.getInstance().clearAll(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/mixin/MixinMessageIndicator.java: -------------------------------------------------------------------------------- 1 | package io.github.darkkronicle.advancedchatcore.mixin; 2 | 3 | import io.github.darkkronicle.advancedchatcore.config.ConfigStorage; 4 | import net.minecraft.client.gui.hud.MessageIndicator; 5 | import org.spongepowered.asm.mixin.Mixin; 6 | import org.spongepowered.asm.mixin.injection.At; 7 | import org.spongepowered.asm.mixin.injection.Inject; 8 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; 9 | 10 | @Mixin(MessageIndicator.class) 11 | public class MixinMessageIndicator { 12 | 13 | @Inject(method = "indicatorColor", at = @At("HEAD"), cancellable = true) 14 | private void getColor(CallbackInfoReturnable ci) { 15 | MessageIndicator indicator = ((MessageIndicator) (Object) this); 16 | String name = indicator.loggedName(); 17 | ci.setReturnValue(switch (name) { 18 | case "Modified" -> ConfigStorage.ChatScreen.MODIFIED.config.getColor().intValue; 19 | case "Filtered" -> ConfigStorage.ChatScreen.FILTERED.config.getColor().intValue; 20 | case "Not Secure" -> ConfigStorage.ChatScreen.NOT_SECURE.config.getColor().intValue; 21 | default -> // And "System" 22 | ConfigStorage.ChatScreen.SYSTEM.config.getColor().intValue; 23 | }); 24 | 25 | } 26 | 27 | @Inject(method = "icon", at = @At("HEAD"), cancellable = true) 28 | private void getIcon(CallbackInfoReturnable ci) { 29 | if (!ConfigStorage.ChatScreen.SHOW_CHAT_ICONS.config.getBooleanValue()) { 30 | ci.setReturnValue(null); 31 | } 32 | } 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/mixin/MixinMinecraftClient.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021-2022 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.mixin; 9 | 10 | import io.github.darkkronicle.advancedchatcore.chat.AdvancedChatScreen; 11 | import io.github.darkkronicle.advancedchatcore.chat.AdvancedSleepingChatScreen; 12 | import io.github.darkkronicle.advancedchatcore.chat.ChatHistory; 13 | import io.github.darkkronicle.advancedchatcore.config.ConfigStorage; 14 | import net.fabricmc.api.EnvType; 15 | import net.fabricmc.api.Environment; 16 | import net.minecraft.client.MinecraftClient; 17 | import net.minecraft.client.gui.screen.Screen; 18 | import org.jetbrains.annotations.Nullable; 19 | import org.spongepowered.asm.mixin.Mixin; 20 | import org.spongepowered.asm.mixin.injection.At; 21 | import org.spongepowered.asm.mixin.injection.Inject; 22 | import org.spongepowered.asm.mixin.injection.ModifyArg; 23 | import org.spongepowered.asm.mixin.injection.ModifyArgs; 24 | import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; 25 | import org.spongepowered.asm.mixin.injection.invoke.arg.Args; 26 | 27 | @Environment(EnvType.CLIENT) 28 | @Mixin(MinecraftClient.class) 29 | public class MixinMinecraftClient { 30 | 31 | @Inject(method = "disconnect(Lnet/minecraft/client/gui/screen/Screen;)V", at = @At("RETURN")) 32 | public void onDisconnect(Screen screen, CallbackInfo ci) { 33 | // Clear data on disconnect 34 | if (ConfigStorage.General.CLEAR_ON_DISCONNECT.config.getBooleanValue()) { 35 | ChatHistory.getInstance().clearAll(); 36 | } 37 | } 38 | 39 | @Inject(method = "openChatScreen(Ljava/lang/String;)V", 40 | at = @At(value = "HEAD"), cancellable = true) 41 | public void openChatScreen(String text, CallbackInfo ci) { 42 | MinecraftClient.getInstance().setScreen(new AdvancedChatScreen(text)); 43 | ci.cancel(); 44 | } 45 | 46 | @ModifyArg(method = "tick()V", 47 | at = @At(value = "INVOKE", 48 | target = "Lnet/minecraft/client/MinecraftClient;setScreen(Lnet/minecraft/client/gui/screen/Screen;)V", ordinal = 1)) 49 | public Screen openSleepingChatScreen(@Nullable Screen screen) { 50 | return new AdvancedSleepingChatScreen(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/mixin/MixinSleepingChatScreen.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021-2022 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.mixin; 9 | 10 | import io.github.darkkronicle.advancedchatcore.chat.AdvancedChatScreen; 11 | import net.fabricmc.api.EnvType; 12 | import net.fabricmc.api.Environment; 13 | import net.minecraft.client.gui.screen.ChatScreen; 14 | import net.minecraft.client.gui.screen.Screen; 15 | import net.minecraft.client.gui.screen.SleepingChatScreen; 16 | import org.jetbrains.annotations.Nullable; 17 | import org.spongepowered.asm.mixin.Mixin; 18 | import org.spongepowered.asm.mixin.injection.At; 19 | import org.spongepowered.asm.mixin.injection.ModifyArg; 20 | 21 | @Environment(EnvType.CLIENT) 22 | @Mixin(SleepingChatScreen.class) 23 | public class MixinSleepingChatScreen extends ChatScreen { 24 | 25 | public MixinSleepingChatScreen() { 26 | super(""); 27 | } 28 | 29 | @ModifyArg(method = "closeChatIfEmpty", 30 | at = @At(value = "INVOKE", 31 | target = "Lnet/minecraft/client/MinecraftClient;setScreen(Lnet/minecraft/client/gui/screen/Screen;)V", ordinal = 1)) 32 | public Screen openSleepingChatScreen(@Nullable Screen screen) { 33 | 34 | return new AdvancedChatScreen(this.chatField.getText()); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/util/AbstractRegistry.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.util; 9 | 10 | import io.github.darkkronicle.advancedchatcore.interfaces.RegistryOption; 11 | import java.util.ArrayList; 12 | import java.util.List; 13 | import java.util.function.Supplier; 14 | import lombok.Getter; 15 | import lombok.NonNull; 16 | 17 | /** 18 | * Create a registry with options that can be added from anywhere. 19 | * 20 | * @param Class to be wrapped 21 | * @param

https://easings.net/#easeInSine 29 | */ 30 | SINE(x -> 1 - Math.cos((x * Math.PI) / 2)), 31 | 32 | /** 33 | * Implements the quad easing function. 34 | * 35 | *

https://easings.net/#easeInQuad 36 | */ 37 | QUAD(x -> x * x), 38 | 39 | /** 40 | * Implements the quart easing function. 41 | * 42 | *

https://easings.net/#easeInQuart 43 | */ 44 | QUART(x -> x * x * x * x), 45 | 46 | /** 47 | * Implements the circ easing function. 48 | * 49 | *

https://easings.net/#easeInCirc 50 | */ 51 | CIRC(x -> 1 - Math.sqrt(1 - Math.pow(x, 2))); 52 | 53 | private final EasingMethod method; 54 | 55 | Method(EasingMethod method) { 56 | this.method = method; 57 | } 58 | 59 | @Override 60 | public double apply(double x) { 61 | if (x < 0) { 62 | return 0; 63 | } else if (x > 1) { 64 | return 1; 65 | } 66 | return method.apply(x); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/util/FindPair.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2022 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.util; 9 | 10 | import lombok.AllArgsConstructor; 11 | import lombok.Value; 12 | 13 | @Value 14 | @AllArgsConstructor 15 | public class FindPair { 16 | 17 | FindType type; 18 | String string; 19 | 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/util/FindType.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.util; 9 | 10 | import fi.dy.masa.malilib.config.IConfigOptionListEntry; 11 | import fi.dy.masa.malilib.util.StringUtils; 12 | import io.github.darkkronicle.advancedchatcore.finder.CustomFinder; 13 | import io.github.darkkronicle.advancedchatcore.finder.LiteralFinder; 14 | import io.github.darkkronicle.advancedchatcore.finder.RegexFinder; 15 | import io.github.darkkronicle.advancedchatcore.finder.UpperLowerFinder; 16 | import io.github.darkkronicle.advancedchatcore.interfaces.IFinder; 17 | import java.util.function.Supplier; 18 | 19 | /** Different methods of searching strings for matches. */ 20 | public enum FindType implements IConfigOptionListEntry { 21 | /** An exact match found in the input */ 22 | LITERAL("literal", LiteralFinder::new), 23 | 24 | /** A match found in the input that is case insensitive */ 25 | UPPERLOWER("upperlower", UpperLowerFinder::new), 26 | 27 | /** A regex match found in the input */ 28 | REGEX("regex", RegexFinder::new), 29 | 30 | /** 31 | * Use custom ones that mods can create. Defined in {@link 32 | * io.github.darkkronicle.advancedchatcore.finder.CustomFinder} 33 | */ 34 | CUSTOM("custom", CustomFinder::getInstance); 35 | 36 | /** Serialized name of the {@link FindType} */ 37 | public final String configString; 38 | 39 | private final Supplier finder; 40 | 41 | private static String translate(String key) { 42 | return StringUtils.translate("advancedchat.config.findtype." + key); 43 | } 44 | 45 | FindType(String configString, Supplier finder) { 46 | this.configString = configString; 47 | this.finder = finder; 48 | } 49 | 50 | /** Get's the finder associated with this */ 51 | public IFinder getFinder() { 52 | return finder.get(); 53 | } 54 | 55 | /** 56 | * Get's the serialized name of the object. 57 | * 58 | * @return The config string 59 | */ 60 | @Override 61 | public String getStringValue() { 62 | return configString; 63 | } 64 | 65 | /** 66 | * Get's the human readable form of the object. 67 | * 68 | * @return String that is for the display name. 69 | */ 70 | @Override 71 | public String getDisplayName() { 72 | return translate(configString); 73 | } 74 | 75 | /** 76 | * Get's the next {@link FindType} from the previous one. 77 | * 78 | * @param forward Should cycle forward 79 | * @return Next {@link FindType} 80 | */ 81 | @Override 82 | public FindType cycle(boolean forward) { 83 | int id = this.ordinal(); 84 | if (forward) { 85 | id++; 86 | } else { 87 | id--; 88 | } 89 | if (id >= values().length) { 90 | id = 0; 91 | } else if (id < 0) { 92 | id = values().length - 1; 93 | } 94 | return values()[id % values().length]; 95 | } 96 | 97 | /** 98 | * De-serializes a string to {@link FindType} 99 | * 100 | * @param value Serialized string 101 | * @return The found {@link FindType}, null if none 102 | */ 103 | @Override 104 | public FindType fromString(String value) { 105 | return fromFindType(value); 106 | } 107 | 108 | public static FindType fromFindType(String findtype) { 109 | for (FindType r : FindType.values()) { 110 | if (r.configString.equals(findtype)) { 111 | return r; 112 | } 113 | } 114 | return FindType.LITERAL; 115 | } 116 | } 117 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/util/LimitedInteger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.util; 9 | 10 | import lombok.Getter; 11 | import lombok.Setter; 12 | 13 | /** An object that will enforce limits on an integer value */ 14 | public class LimitedInteger { 15 | 16 | @Getter private Integer value; 17 | 18 | @Getter @Setter private Integer limit; 19 | 20 | public LimitedInteger(int limit) { 21 | this(limit, 0); 22 | } 23 | 24 | public LimitedInteger(int limit, int start) { 25 | this.limit = limit; 26 | this.value = start; 27 | } 28 | 29 | /** 30 | * Increment only if the value is less than the limit. 31 | * 32 | * @param increment Integer to increment by 33 | * @return If the increment was successful 34 | */ 35 | public boolean incrementIfLimited(int increment) { 36 | if (value >= limit) { 37 | return false; 38 | } 39 | value += increment; 40 | return true; 41 | } 42 | 43 | /** 44 | * Increment the value and then return if the value is over the limit 45 | * 46 | * @param increment Integer to increment by 47 | * @return If the incremented value is greater than the limit 48 | */ 49 | public boolean incrementAndCheck(int increment) { 50 | value += increment; 51 | return value >= limit; 52 | } 53 | 54 | /** 55 | * Increments the value if the value to increment by doesn't go over the limit. 56 | * 57 | * @param increment Integer to increment by 58 | * @return Boolean if it sucecessfully incremented. 59 | */ 60 | public boolean incrementIfPossible(int increment) { 61 | if ((value + increment) >= limit) { 62 | return false; 63 | } 64 | value += increment; 65 | return true; 66 | } 67 | 68 | /** 69 | * A method to see if it is possible to increment. This does not change any values. 70 | * 71 | * @param increment Value to increment 72 | * @return If it can increment 73 | */ 74 | public boolean isPossible(int increment) { 75 | return !(value + increment >= limit); 76 | } 77 | 78 | /** 79 | * Force set's the current value. Ignores limits. 80 | * 81 | * @param value Integer to set 82 | */ 83 | public void setValue(int value) { 84 | this.value = value; 85 | } 86 | } 87 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/util/RawText.java: -------------------------------------------------------------------------------- 1 | package io.github.darkkronicle.advancedchatcore.util; 2 | 3 | import net.minecraft.text.*; 4 | import net.minecraft.util.Language; 5 | 6 | import java.util.ArrayList; 7 | import java.util.List; 8 | 9 | public record RawText(String content, Style style) implements Text { 10 | 11 | @Override 12 | public Style getStyle() { 13 | return style; 14 | } 15 | 16 | @Override 17 | public TextContent getContent() { 18 | return PlainTextContent.of(content); 19 | } 20 | 21 | @Override 22 | public String getString() { 23 | return content; 24 | } 25 | 26 | @Override 27 | public List getSiblings() { 28 | return new ArrayList<>(); 29 | } 30 | 31 | @Override 32 | public OrderedText asOrderedText() { 33 | Language language = Language.getInstance(); 34 | return language.reorder(this); 35 | } 36 | 37 | public RawText withString(String string) { 38 | return RawText.of(string, style); 39 | } 40 | 41 | public static RawText of(String string) { 42 | return RawText.of(string, Style.EMPTY); 43 | } 44 | 45 | public static RawText of(String string, Style style) { 46 | return new RawText(string, style); 47 | } 48 | } -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/util/RowList.java: -------------------------------------------------------------------------------- 1 | package io.github.darkkronicle.advancedchatcore.util; 2 | 3 | import java.util.*; 4 | 5 | public class RowList { 6 | 7 | private final Map> list = new HashMap<>(); 8 | private final List order = new ArrayList<>(); 9 | 10 | public RowList() { 11 | 12 | } 13 | 14 | private List makeNewList() { 15 | return new ArrayList<>(); 16 | } 17 | 18 | public void createSection(String key, int y) { 19 | List newList = makeNewList(); 20 | order.add(y, key); 21 | list.put(key, newList); 22 | } 23 | 24 | public void add(String key, T value) { 25 | add(key, value, -1); 26 | } 27 | 28 | public void add(String key, T value, int index) { 29 | if (!list.containsKey(key)) { 30 | List newList = makeNewList(); 31 | order.add(key); 32 | newList.add(value); 33 | list.put(key, newList); 34 | return; 35 | } 36 | if (index < 0) { 37 | list.get(key).add(value); 38 | } else { 39 | list.get(key).add(index, value); 40 | } 41 | } 42 | 43 | public List get(String key) { 44 | return list.get(key); 45 | } 46 | 47 | public List get(int y) { 48 | String key; 49 | if (y >= order.size()) { 50 | key = order.get(order.size() - 1); 51 | } else { 52 | key = order.get(y); 53 | } 54 | return list.get(key); 55 | } 56 | 57 | public int rowSize() { 58 | return list.size(); 59 | } 60 | 61 | public void clear() { 62 | order.clear(); 63 | list.clear(); 64 | } 65 | } 66 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/util/SearchResult.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.util; 9 | 10 | import io.github.darkkronicle.advancedchatcore.finder.RegexFinder; 11 | import io.github.darkkronicle.advancedchatcore.interfaces.IFinder; 12 | import lombok.Getter; 13 | import net.fabricmc.api.EnvType; 14 | import net.fabricmc.api.Environment; 15 | import net.minecraft.text.Text; 16 | 17 | import java.util.ArrayList; 18 | import java.util.Collections; 19 | import java.util.List; 20 | import java.util.regex.Matcher; 21 | import java.util.regex.Pattern; 22 | 23 | /** An object that holds information about a search. */ 24 | @Environment(EnvType.CLIENT) 25 | public class SearchResult { 26 | 27 | /** All the {@link StringMatch} that were found in the input */ 28 | @Getter private final List matches; 29 | 30 | /** The finder used to find matches */ 31 | @Getter private final IFinder finder; 32 | 33 | /** The input string */ 34 | @Getter private final String input; 35 | 36 | /** The condition search */ 37 | @Getter private final String search; 38 | 39 | /** 40 | * Constructs a search result based off of found information. 41 | * 42 | * @param input Input to search 43 | * @param search Search value 44 | * @param finder {@link IFinder} used to search 45 | * @param matches {@link List} of {@link StringMatch} that were found 46 | */ 47 | public SearchResult(String input, String search, IFinder finder, List matches) { 48 | this.input = input; 49 | this.search = search; 50 | this.finder = finder; 51 | this.matches = new ArrayList<>(matches); 52 | Collections.sort(this.matches); 53 | } 54 | 55 | public int size() { 56 | return matches.size(); 57 | } 58 | 59 | /** 60 | * Get's a group from the result. This only works if it's a {@link RegexFinder}, otherwise it 61 | * returns the entire string. 62 | * 63 | * @param num Group number 64 | * @return StringMatch from group. It references the original string. 65 | */ 66 | public StringMatch getGroup(StringMatch match, int num) { 67 | if (!matches.contains(match)) { 68 | return null; 69 | } 70 | if (!(finder instanceof RegexFinder)) { 71 | return match; 72 | } 73 | try { 74 | RegexFinder regex = (RegexFinder) finder; 75 | Pattern p = regex.getPattern(input); 76 | if (p == null) { 77 | return null; 78 | } 79 | Matcher matcher = p.matcher(match.match); 80 | String group = matcher.group(num); 81 | int start = matcher.start(num); 82 | int end = matcher.start(num); 83 | return new StringMatch(group, start, end); 84 | } catch (Exception e) { 85 | return null; 86 | } 87 | } 88 | 89 | /** 90 | * Replaces the groups with a specified match 91 | * 92 | * @param string Contents to replace to 93 | * @param matchIndex If it will replace/return only the first group. -1 will return the full 94 | * string. 95 | * @return The replaced values in context. If onlyFirst it will only do the context of the first 96 | * group. 97 | */ 98 | public String getGroupReplacements(String string, int matchIndex) { 99 | if (matchIndex >= 0) { 100 | if (finder instanceof RegexFinder regex) { 101 | try { 102 | Pattern p = regex.getPattern(search); 103 | if (p != null) { 104 | return 105 | p 106 | .matcher(matches.get(matchIndex).match) 107 | .replaceAll(string); 108 | } 109 | } catch (Exception e) { 110 | // Didn't work 111 | } 112 | } 113 | return SearchUtils.replaceGroups(Collections.singletonList(matches.get(0)), string); 114 | } 115 | if (finder instanceof RegexFinder regex) { 116 | try { 117 | Pattern p = regex.getPattern(search); 118 | if (p != null) { 119 | return p.matcher(input).replaceAll(string); 120 | } 121 | } catch (Exception e) { 122 | // Did not work 123 | } 124 | } 125 | return SearchUtils.replaceGroups(matches, string); 126 | } 127 | 128 | /** 129 | * A method to construct a SearchResult based off of an input, condition, and {@link FindType} 130 | * 131 | * @param input Input string to match from 132 | * @param match Search string 133 | * @param type {@link FindType} way to search 134 | * @return SearchResult with compiled searches 135 | */ 136 | public static SearchResult searchOf(String input, String match, FindType type) { 137 | IFinder finder = type.getFinder(); 138 | List matches = finder.getMatches(input, match); 139 | return new SearchResult(input, match, finder, matches); 140 | } 141 | 142 | /** 143 | * A method to construct a SearchResult based off of an input, condition, and {@link FindType} 144 | * 145 | * @param input Input string to match from 146 | * @param match Search text 147 | * @param type {@link FindType} way to search 148 | * @return SearchResult with compiled searches 149 | */ 150 | public static SearchResult searchOf(Text input, String match, FindType type) { 151 | IFinder finder = type.getFinder(); 152 | List matches = finder.getMatches(input, match); 153 | return new SearchResult(input.getString(), match, finder, matches); 154 | } 155 | } 156 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/util/StringInsert.java: -------------------------------------------------------------------------------- 1 | package io.github.darkkronicle.advancedchatcore.util; 2 | 3 | import net.minecraft.text.MutableText; 4 | import net.minecraft.text.Text; 5 | 6 | /** 7 | * An interface to provide a way to get the text that should be replaced based off of the 8 | * current {@link Text} and the current {@link StringMatch} 9 | */ 10 | public interface StringInsert { 11 | /** 12 | * Return's the {@link MutableText} that should be inserted. 13 | * 14 | * @param current The current {@link Text} 15 | * @param match The current {@link StringMatch} 16 | * @return 17 | */ 18 | MutableText getText(Text current, StringMatch match); 19 | } -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/util/StringMatch.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.util; 9 | 10 | import lombok.AllArgsConstructor; 11 | import lombok.EqualsAndHashCode; 12 | import lombok.ToString; 13 | 14 | /** 15 | * A class to store data about a match. 16 | * 17 | *

This class is comparable based on where it starts. 18 | */ 19 | @EqualsAndHashCode 20 | @ToString 21 | @AllArgsConstructor 22 | public class StringMatch implements Comparable { 23 | 24 | /** The content that was matched */ 25 | public String match; 26 | 27 | /** The index of the start of the match */ 28 | public Integer start; 29 | 30 | /** The index of the end of the match */ 31 | public Integer end; 32 | 33 | @Override 34 | public int compareTo(StringMatch o) { 35 | return start.compareTo(o.start); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/util/SyncTaskQueue.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 DarkKronicle 3 | * 4 | * This Source Code Form is subject to the terms of the Mozilla Public 5 | * License, v. 2.0. If a copy of the MPL was not distributed with this 6 | * file, You can obtain one at https://mozilla.org/MPL/2.0/. 7 | */ 8 | package io.github.darkkronicle.advancedchatcore.util; 9 | 10 | import java.util.TreeSet; 11 | import lombok.AllArgsConstructor; 12 | import lombok.Value; 13 | import org.jetbrains.annotations.NotNull; 14 | 15 | // Referenced 16 | // https://github.com/vacla/Watson/blob/fabric_1.16.2/src/main/java/eu/minemania/watson/scheduler/SyncTaskQueue.java 17 | 18 | /** A queue to handle delayed tasks in ticks. */ 19 | public class SyncTaskQueue { 20 | 21 | private static final SyncTaskQueue INSTANCE = new SyncTaskQueue(); 22 | 23 | public static SyncTaskQueue getInstance() { 24 | return INSTANCE; 25 | } 26 | 27 | private int lastTick = 0; 28 | 29 | /** A task that contains a time to trigger and a {@link Runnable} for when it should happen. */ 30 | @Value 31 | @AllArgsConstructor 32 | public static class QueuedTask implements Comparable { 33 | 34 | /** 35 | * Tick number when it should be triggered. This isn't delay, this is based off of the 36 | * current tick value in {@link net.minecraft.client.gui.hud.InGameHud} 37 | */ 38 | int tick; 39 | 40 | /** {@link Runnable} to run when the task is called. */ 41 | Runnable task; 42 | 43 | @Override 44 | public int compareTo(@NotNull SyncTaskQueue.QueuedTask o) { 45 | // Compares when it should happen. Used to ensure that the first in the stack is what 46 | // needs to 47 | // happen. 48 | return Integer.compare(tick, o.tick); 49 | } 50 | } 51 | 52 | // Use TreeSet to automagically sort by when it needs to happen 53 | private final TreeSet queue = new TreeSet<>(); 54 | 55 | /** 56 | * Add's a new task to do after a certain amount of ticks 57 | * 58 | * @param after Delay in ticks 59 | * @param runnable What to run when it should be called 60 | */ 61 | public void add(int after, Runnable runnable) { 62 | queue.add(new QueuedTask(lastTick + after, runnable)); 63 | } 64 | 65 | /** 66 | * Updates the queue with the tick. This shouldn't be called outside of the core. 67 | * 68 | * @param tick Current time in ticks. 69 | */ 70 | public void update(int tick) { 71 | lastTick = tick; 72 | if (queue.size() == 0) { 73 | return; 74 | } 75 | QueuedTask task = queue.first(); 76 | while (task != null && task.tick <= lastTick) { 77 | task.task.run(); 78 | queue.pollFirst(); 79 | if (queue.size() == 0) { 80 | break; 81 | } 82 | task = queue.first(); 83 | } 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/io/github/darkkronicle/advancedchatcore/util/TextBuilder.java: -------------------------------------------------------------------------------- 1 | package io.github.darkkronicle.advancedchatcore.util; 2 | 3 | import net.minecraft.text.*; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | import java.util.Optional; 8 | import java.util.concurrent.atomic.AtomicReference; 9 | 10 | public class TextBuilder { 11 | 12 | private List siblings = new ArrayList<>(); 13 | 14 | public TextBuilder append(String string) { 15 | siblings.add(RawText.of(string)); 16 | return this; 17 | } 18 | 19 | public TextBuilder append(String string, Style style) { 20 | siblings.add(RawText.of(string, style)); 21 | return this; 22 | } 23 | 24 | public List getTexts() { 25 | return siblings; 26 | } 27 | 28 | public TextBuilder append(OrderedText text) { 29 | AtomicReference