Skip to content

Add per-server match-end trigger configuration - #12

Merged
CoasterFreakDE merged 2 commits into
mainfrom
feat/per-server-end-triggers
Nov 4, 2026
Merged

CoasterFreakDE merged 2 commits into
mainfrom
feat/per-server-end-triggers

Conversation

@CoasterFreakDE

@CoasterFreakDE CoasterFreakDE commented Nov 4, 2026 •

Copy link
Copy Markdown
Member

Summary

  • Extend existing persistent settings with independent per-hostname trigger overrides while retaining existing message JSON and legacy text imports.
  • Add Messages and End triggers tabs in Mod Menu with explicit customization/reset, inheritance previews, atomic saves, per-host unsaved drafts, and safeguards against saving edits under the wrong hostname.
  • Custom literal, case-sensitive snippets replace built-in detection. An absent override inherits, and an empty custom list disables detection.
  • Keep built-in servers, Mineplex state handling, burst suppression, and Hypixel duplicate protection unchanged when not overridden.
  • Preserve long saved lists without text-field truncation. Document exact escaping and Mineplex custom-rule behavior.
  • Add a read-only PR build/test workflow. No publishing or release changes.

Validation

  • 32 Kotlin/JUnit tests pass locally against real production source, including a headless Minecraft EditBox regression test for long-list editing.
  • Full local Gradle compilation is blocked during Fabric Loom setup by this environment's JVM socket restriction (SocketException: Operation not permitted), before application compilation.
  • The full Java 25 ./gradlew --no-daemon clean build passed on final head 3d4ab85 in CI, including all test classes.
  • In-game visual verification is not performed.

Server data

No guessed mcpvp.club or PvP Legacy end-message presets are included. Their real system/game chat snippets can be entered per server; unsupported servers remain inactive without configured snippets.

This PR remains a draft. No merge or release is requested.

@diffy-bot

diffy-bot Bot commented Nov 4, 2026

Copy link
Copy Markdown

TL;DR

Adds per-server configurable "end triggers" in addition to message lists, a full config editor UI rewrite, persistent trigger storage, built-in trigger exposure, detector behavior updates (including Mineplex state reset), many unit tests, and a GitHub Actions workflow to build/test with Java 25.


Summary of changes

New CI

  • .github/workflows/build.yml (new)
    • Adds a GitHub Actions workflow "Build and test".
    • Triggers: pull_request and push to main.
    • Runs on ubuntu-latest, sets up Java (Temurin) version 25, runs ./gradlew --no-daemon clean build.

README updates

  • README.md (modified)
    • Significant expansion of per-server settings documentation.
    • Describes Messages and new End triggers, escaping rules (\|, \\), inheritance, disabling detection, supported built-ins, storage location (autogg.json) and schema example (includes triggers map).
    • Clarifies behavior for unsupported servers and built-in servers list.
    • Notes suppression of repeated end messages and Hypixel duplicate protection.

New/Changed source files

New files

  • src/main/kotlin/cc/modlabs/autogg/AutoGgConfigEditor.kt

    • New class encapsulating unsaved editor state and logic for loading, toggling, saving messages and triggers.
    • Uses EventDetector to fetch built-in triggers for previewing.
    • Handles message/trigger parsing & validation via settings API.
    • Provides detectionDescription helper used by UI.
  • src/main/kotlin/cc/modlabs/autogg/MessageLists.kt

    • New helpers to format and parse messages and triggers:
      • formatMessages, formatTriggers
      • parseMessages, parseTriggers
      • Internal generic parseItems and escaping behavior
    • parseTriggers allows empty string -> empty list to explicitly disable detection; enforces non-empty entries.
  • src/test/kotlin/cc/modlabs/autogg/AutoGgEditorTest.kt (new)

    • Unit tests for editor loading/saving, inheritance, validation, and behavior around triggers/messages.
  • src/test/kotlin/cc/modlabs/autogg/EventDetectorTest.kt (new)

    • Tests for detector behavior with custom triggers, built-ins, Mineplex state machine, and integration with AutoGgGuard.
  • src/test/kotlin/cc/modlabs/autogg/TriggerSettingsTest.kt (new)

    • Tests persistence and validation of trigger overrides and interaction with messages and legacy formats.

Modified files

  • src/main/kotlin/cc/modlabs/autogg/AutoGgModMenu.kt

    • Large UI refactor for the Mod Menu settings screen:
      • Introduces editor instance (AutoGgConfigEditor).
      • Switchable tabs: Messages and End triggers.
      • New controls: Load, Customize/Reset mode button, Save, Done.
      • Centralized field values for both messages and triggers; refreshFields() to update UI state.
      • Status messages updated and managed via attempt wrapper that sets UI status on exceptions.
      • Uses new format/parse functions and editor state instead of direct settings access.
  • src/main/kotlin/cc/modlabs/autogg/AutoGgSettings.kt

    • Extended schema and behavior:
      • Adds triggerOverrides: Map<String, List<String>>.
      • Loads triggers from JSON if present; validates triggers after loading.
      • Exposes new methods:
        • messagesFor(address): now uses matchingOverride helper.
        • triggersFor(address): returns nullable List (null when no override).
        • saveServerConfig(server, messages?, triggers?): new API to set per-server messages/triggers atomically; null removes override, empty trigger list disables detection for that host.
      • write(...) now writes triggers field into JSON.
      • validateTriggers(...) added (1–1024 chars, no control/formatting characters).
      • matchingOverride(address, values) and normalizeServer(server) are moved out of class and implemented as internal functions.
      • Preserves legacy behavior (legacy file autogg-message.txt) and compatibility for message-only JSON.
      • Ensures malformed loads block overwrites.
  • src/main/kotlin/cc/modlabs/autogg/Autogg.kt

    • Event scanning call updated to pass server and custom triggers:
      • Calls detector.scanForEvent(message, server, settings.triggersFor(client.serverAddress))
    • On disconnect, now calls detector.reset() instead of manipulating a static Mineplex flag.
  • src/main/kotlin/cc/modlabs/autogg/chat/EventDetector.kt

    • New behavior:
      • Supports scanForEvent(message, server, customTriggers?). If customTriggers != null, custom matching uses literal contains() checks and replaces built-in detection.
      • Exposes builtInTriggers(server) to list built-in trigger snippets for previews.
      • Mineplex state kept private inside the detector; added reset() method.
    • Removed dependency on Autogg.INSTANCE for server lookup in scan method.

Tests / coverage

  • Many unit tests added that cover:
    • Editor behavior and persistence.
    • Trigger parsing, validation, and persistence semantics (null vs empty).
    • Detector behavior with built-in and custom triggers, including Mineplex state.
    • Storage consistency when updating messages without disturbing stored triggers.

Notable behavior / design decisions

  • Triggers are literal string snippets:
    • Matching is case-sensitive and spaces are significant.
    • Trigger entries: 1–1024 chars, no control or formatting characters.
    • An empty custom trigger list explicitly disables detection for that hostname.
    • Null for triggers means "no override" and inherits built-in or parent-domain rules.
  • Messages remain 1–256 chars, no commands/control characters.
  • In-editor preview of built-in triggers is provided without saving them as overrides.
  • Atomic server config save method (saveServerConfig) ensures both fields are validated and written together; invalid input prevents partial writes.
  • EventDetector now supports custom trigger overrides to replace built-ins and to be consulted by Autogg when scanning messages.

Suggestions (issues to consider)

  • CI: The workflow uses Java 25 (non-LTS). Confirm this is intentional for build/test matrix or switch to an LTS version if broader compatibility is desired.
  • EventDetector file in the diff ends with "No newline at end of file" — consider adding a newline.
  • The new UI code relies on localized status strings; consider centralizing messages for localization or consistent phrasing.
  • Tests refer to com.google.gson.JsonParser (added import in one test); ensure gson version in build.gradle supports that API (JsonParser moved in newer Gson versions) to avoid test failures.
  • Review and confirm normalization/validation rules for hostnames meet expected UX for administrators (current regex is strict: lowercase a-z0-9 labels only, with hyphens allowed but no underscores or uppercase).
  • Consider documenting migration notes for users with existing autogg.json files that lack triggers — the code handles it, but mention in CHANGELOG or release notes.

You can generate a new summary by commenting @diffy-bot.

@diffy-bot

diffy-bot Bot commented Nov 4, 2026

Copy link
Copy Markdown

Summary of changes

Overview

This set of changes adds per-server "end triggers" (literal snippets that indicate a game end), refactors the config/editor UI and parsing code, extends settings storage to include trigger overrides, updates event detection to respect custom trigger lists, and adds a substantial suite of tests. The README and mod menu UI are updated to document and support the new behavior. A GitHub Actions workflow is added to build & test.

TL;DR: per-server trigger overrides + editor & settings refactor + EventDetector now accepts custom trigger lists and exposes built-in triggers + many new tests.


New files

  • .github/workflows/build.yml — CI: builds/tests with Java 25 via actions/setup-java and ./gradlew clean build.
  • src/main/kotlin/cc/modlabs/autogg/AutoGgConfigEditor.kt — Editor state object for unsaved drafts, message/trigger inheritance & save logic.
  • src/main/kotlin/cc/modlabs/autogg/ConfigValueField.kt — Helper to configure EditBox for long config values (sets max length to Int.MAX_VALUE).
  • src/main/kotlin/cc/modlabs/autogg/MessageLists.kt — Message/trigger formatting and parsing utilities (escape/parse helpers).
  • src/test/kotlin/cc/modlabs/autogg/AutoGgEditorTest.kt — Tests for editor behavior.
  • src/test/kotlin/cc/modlabs/autogg/ConfigValueFieldTest.kt — Test ensuring long trigger lists are not truncated by editor field.
  • src/test/kotlin/cc/modlabs/autogg/EventDetectorTest.kt — Tests for EventDetector behavior with custom/built-in triggers and Mineplex state machine.
  • src/test/kotlin/cc/modlabs/autogg/TriggerSettingsTest.kt — Tests for trigger persistence, validation, legacy import, and corruption handling.

Modified files (key points)

  • README.md
    • Expanded configuration documentation:
      • Added sections for per-server settings, messages vs end triggers, matching/inheritance behavior, storage format, examples (autogg.json), and notes about built-in servers and suppression behavior.
      • Specified limits/constraints: messages 1–256 chars, triggers 1–1024 chars, escaping rules, and that triggers are plain text (no regex).
  • src/main/kotlin/cc/modlabs/autogg/AutoGgModMenu.kt
    • Reworked UI:
      • Introduces tabs for "Messages" and "End triggers".
      • Integrates AutoGgConfigEditor and uses a single configurable EditBox "values".
      • Adds Load/Save/Customize/Reset behaviors and richer status messages.
      • Validation/error handling moved to a central attempt wrapper.
      • Visual indicators for active tab and mode.
  • src/main/kotlin/cc/modlabs/autogg/AutoGgSettings.kt
    • Added triggerOverrides: Map<String, List> and supporting loading/writing "triggers" field in JSON.
    • Added saveServerConfig(server: String, messages: List?, triggers: List?) — allows setting/removing per-server messages and triggers independently. Null = remove override; empty trigger list = explicit disable of detection.
    • Existing save/saveServer/saveDefaults adjusted to use the new write(...) signature.
    • Added validateTriggers(...) with limits and allowed characters.
    • Extracted matchingOverride(address, values) and normalizeServer(server) as internal functions.
    • JSON write now includes "triggers".
    • Legacy import behavior retained for older message-only schema.
  • src/main/kotlin/cc/modlabs/autogg/Autogg.kt
    • Event detection subscription updated:
      • Calls detector.scanForEvent(message, server, settings.triggersFor(client.serverAddress))
      • Uses guard.chooseMessage(server, messages) (passes server variable)
      • On disconnect: detector.reset() called (replaces prior mineplexStart global reset)
  • src/main/kotlin/cc/modlabs/autogg/chat/EventDetector.kt
    • API changes:
      • scanForEvent(message) -> scanForEvent(message, server: ServerConfig?, customTriggers: List? = null)
        • If customTriggers != null: check custom list (literal contains), case-sensitive; empty list disables detection.
        • Otherwise, fall back to built-in server rules.
      • added builtInTriggers(server: ServerConfig?) to expose built-in trigger snippets for preview.
      • replaced companion-level mineplexStart var with private instance var and added reset() method.
      • Removed dependency on Autogg singleton.
  • Misc refactors:
    • Message parsing and escaping moved to MessageLists.kt (replaces prior in-file parsing).
    • Editor logic (drafts, inheritance, previewing built-ins, toggling modes) extracted into AutoGgConfigEditor.

Behavior changes / user-visible

  • New feature: per-server "End triggers" (literal snippets used to detect game end). They are independent from per-server message overrides and can be inherited or explicitly disabled.
  • Editing flow in Mod Menu changed: Load hostname -> edit Messages or End triggers tabs -> Save. Default messages still editable via blank hostname.
  • Built-in detection for supported servers remains unchanged unless a custom trigger override is set.
  • When custom triggers are present: they replace built-ins entirely; an empty custom trigger list explicitly disables detection for that server.
  • Event detection:
    • If custom trigger list provided, detection uses literal contains checks against that list.
    • Built-in triggers can be previewed in the editor via detector.builtInTriggers(...).
    • Mineplex state machine still supported; its internal state is now per-detector instance and reset on disconnect.
  • Storage:
    • autogg.json now contains an optional "triggers" object alongside "default" and "servers".
    • Old single-file message-only schema and legacy autogg-message.txt are still supported.

Tests

  • Large set of new unit tests covering:
    • Editor save/load behavior, drafts, inheritance, validation, and mode toggling.
    • Settings persistence, including trigger overrides, empty trigger disabling, and legacy import.
    • EventDetector behavior for custom triggers, built-ins, and Mineplex state machine interactions.
    • Ensures UI field configuration does not truncate large trigger entries.

Suggestions (issues found / potential concerns)

  • GitHub workflow uses Java 25 (java-version: '25'). Java 25 is very new and may not be available/desired in all CI environments; consider using a more common Java LTS (e.g., 17 or 21) unless Java 25 is required.
  • ConfigValueField sets EditBox.setMaxLength(Int.MAX_VALUE). While server/item-length validation is performed at save time, allowing arbitrarily large input in the GUI might cause client-side memory/UX issues. Consider capping the total input length (not just per-item), or explicitly guarding rendering paths that may assume bounded length.
  • EventDetector uses String.contains for custom triggers (literal, case-sensitive). This matches the README but may produce unexpected matches for large or overlapping triggers; documentation is clear but consider offering an option for whole-word matching or anchored matching if needed later.
  • The new API surface (AutoGgSettings.saveServerConfig, triggersFor, EventDetector.scanForEvent signature) is changed — if other modules/plugins depend on previous APIs, those will need to be updated.

You can generate a new summary by commenting @diffy-bot.

@CoasterFreakDE
CoasterFreakDE marked this pull request as ready for review November 4, 2026 12:19
@CoasterFreakDE
CoasterFreakDE merged commit feb50d0 into main Nov 4, 2026
3 checks passed
@diffy-bot

diffy-bot Bot commented Nov 4, 2026

Copy link
Copy Markdown

Summary of changes

TL;DR: Adds per-server trigger overrides and an editor UI refactor, moves message parsing into shared utilities, updates event detection to support custom triggers, adds many unit tests, and introduces a GitHub Actions build workflow.

New CI

  • .github/workflows/build.yml
    • Adds a GitHub Actions workflow "Build and test".
    • Runs on push to main and pull_request.
    • Uses ubuntu-latest, actions/checkout@v6 and actions/setup-java@v5 with Temurin Java 25.
    • Runs ./gradlew --no-daemon clean build.

README updates

  • README.md
    • Large expansion describing per-server settings, messages, and end triggers.
    • Describes inheritance, escaping rules, storage format, and examples.
    • Documents new triggers JSON map and config file layout.
    • Notes built-in servers and behavior (Hypixel duplicate suppression and Mineplex state machine).
    • Explains storage location and legacy-import behavior.

New/Updated Kotlin source files

  • src/main/kotlin/cc/modlabs/autogg/AutoGgConfigEditor.kt (new)

    • New editor model that tracks unsaved drafts per-hostname.
    • Keeps separate message and trigger editors, tracks whether each field is "custom" or inherited.
    • Provides load/save/toggle methods and detection description helpers.
    • Uses EventDetector to fetch built-in triggers.
    • Uses normalized keys for hostnames.
  • src/main/kotlin/cc/modlabs/autogg/AutoGgModMenu.kt (modified)

    • Reworked configuration screen UI:
      • Replaced separate message EditBox with a single "values" EditBox and tabs for "Messages" and "End triggers".
      • Introduced an AutoGgConfigEditor instance for state management.
      • Added Load / Save / Done buttons and a "Customize"/"Reset" flow for both messages and triggers.
      • Added attempt wrapper for unified error handling.
      • Uses configureConfigValueField to allow very long lists (setMaxLength(Int.MAX_VALUE)).
      • Updated UI text, status messages, and rendering layout.
      • Moved parsing/formatting logic out of the screen.
  • src/main/kotlin/cc/modlabs/autogg/AutoGgSettings.kt (modified)

    • Adds triggerOverrides: Map<String, List<String>>.
    • On load, reads optional "triggers" JSON object.
    • Validates triggers via new validateTriggers method.
    • Adds triggersFor(address: String?) : List<String>?.
    • Replaces messagesFor implementation with matchingOverride helper.
    • Adds public saveServerConfig(server: String, messages: List<String>?, triggers: List<String>?) to atomically update messages and triggers per-hostname:
      • null removes that override; empty list of triggers explicitly disables detection for that hostname.
    • Writes triggers into JSON alongside default and servers.
    • Introduces validateTriggers to check per-trigger length and disallowed characters.
    • Extracts and exposes helper functions:
      • matchingOverride(address, values)
      • normalizeServer(server)
    • Adjusts write/save flows to include triggers, and ensures load-failure prevents overwriting.
  • src/main/kotlin/cc/modlabs/autogg/Autogg.kt (modified)

    • Event detection now passes server and custom triggers to EventDetector.scanForEvent:
      • detector.scanForEvent(message.string, server, settings.triggersFor(client.serverAddress))
    • Uses detector.reset() on disconnect instead of manipulating static Mineplex state in Autogg.
  • src/main/kotlin/cc/modlabs/autogg/ConfigValueField.kt (new)

    • Small helper configureConfigValueField(field: EditBox) that sets max length to Int.MAX_VALUE (to avoid truncating long saved items).
  • src/main/kotlin/cc/modlabs/autogg/MessageLists.kt (new)

    • Centralizes message/trigger formatting and parsing:
      • formatMessages: joins items with " | " and escapes items.
      • formatTriggers: joins triggers with "|" and escapes items.
      • parseMessages / parseTriggers / parseItems with consistent escaping semantics and trimming behavior.
      • parseTriggers allows empty-list to mean "disabled" and enforces no empty items.
  • src/main/kotlin/cc/modlabs/autogg/chat/EventDetector.kt (modified)

    • Adds support for built-inTriggers(server) to expose built-in list.
    • scanForEvent now accepts (message: String, server: ServerConfig?, customTriggers: List?):
      • If customTriggers != null: match any literal snippet in list (case-sensitive, literal substring).
      • If customTriggers is emptyList(): detection disabled (returns null).
      • Otherwise, falls back to built-in server-based detection; Mineplex state machine remains but internal state is now private.
    • Replaces companion object global mineplexStart with a private instance var and adds reset() method.

Tests added

Multiple new unit test files to cover editor, settings, detector and UI behavior:

  • src/test/kotlin/cc/modlabs/autogg/AutoGgEditorTest.kt (new)
    • Tests editor save/load, inheritance, draft preservation, validation and behavior around toggling custom/inherited options.
  • src/test/kotlin/cc/modlabs/autogg/AutoGgTest.kt (modified)
    • Adds a test ensuring saved message changes preserve stored trigger configuration.
  • src/test/kotlin/cc/modlabs/autogg/ConfigValueFieldTest.kt (new)
    • Tests that the UI field does not truncate long triggers and that saves preserve long values.
  • src/test/kotlin/cc/modlabs/autogg/EventDetectorTest.kt (new)
    • Tests custom triggers, built-in triggers, Mineplex state machine, and guard interaction.
  • src/test/kotlin/cc/modlabs/autogg/TriggerSettingsTest.kt (new)
    • Tests trigger persistence, empty-trigger semantics (disable detection), validation, legacy import interactions, and no partial writes on invalid save.

Behavior changes / notable design

  • Per-server "triggers" are introduced and persisted separately from message lists; they can be:
    • Absent (inherit built-ins),
    • A non-empty list (custom literal trigger snippets),
    • An empty list (explicitly disable detection for that hostname and its subdomains unless a more specific override exists).
  • The EventDetector now accepts custom triggers and will use them in preference to built-in detection.
  • UI now exposes both Messages and End triggers, with clear guidance and escape rules.
  • Editor holds unsaved drafts per hostname to let the user switch hostnames without losing unsaved changes.

Suggestions / Issues found

  • GitHub Actions: workflow uses actions/setup-java@v5 with java-version: '25'.
    • Java 25 is a non-LTS release and may not be available on all runners or supported by all toolchains; consider using a stable LTS (e.g., 17, 21) or explicitly test availability in CI. If Java 25 is required, document the reason.
  • UI field max length: configureConfigValueField sets setMaxLength(Int.MAX_VALUE).
    • Allowing effectively unlimited input could cause memory/UI issues if users paste extremely large data. Consider setting a more conservative max length (based on trigger max 1024 chars * max items or a safe total) or validating/limiting at save time to avoid performance problems or denial-of-service via extremely long inputs.
  • Escaping/Parsing semantics:
    • parseTriggers disallows empty items, while formatTriggers may produce empty items only if the data was invalid; tests cover these. Ensure the UX explains how to clear detection (explicitly save an empty list) to avoid confusion.
  • JSON schema compatibility:
    • The settings file now includes triggers. The code handles older files and legacy autogg-message.txt import, but care is taken to treat malformed trigger data as a load failure that prevents overwriting. This is safe but can leave users unable to save until they fix corrupt files; provide a clearer user guidance or a repair command/documentation path if desired.

You can generate a new summary by commenting @diffy-bot.

@CoasterFreakDE
CoasterFreakDE deleted the feat/per-server-end-triggers branch November 4, 2026 12:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant