Skip to content

Port mod to Fabric loader 0.19.3 Minecraft 26.2 - #32

Open
0r1k wants to merge 1 commit into
Sk1erLLC:masterfrom
0r1k:fabric-port
Open

Port mod to Fabric loader 0.19.3 Minecraft 26.2#32
0r1k wants to merge 1 commit into
Sk1erLLC:masterfrom
0r1k:fabric-port

Conversation

@0r1k

@0r1k 0r1k commented Jun 28, 2026

Copy link
Copy Markdown

Mod ported to latest minecraft version on this moment 26.2 with Fabric Loader.

Summary by CodeRabbit

  • New Features

    • Added Fabric-based support for launching and running the mod.
    • Added a client-side /autogg command with a refresh option.
    • Added automatic config handling with saved settings in a modern format.
  • Bug Fixes

    • Improved chat message handling and trigger detection.
    • Fixed secondary GG message behavior.
    • Added safer checks to avoid issues when connection or player data is unavailable.
  • Chores

    • Updated build tooling and project metadata for the new setup.

@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

AutoGG is migrated from a Forge/Essential multi-version mod to a single Fabric client mod targeting Minecraft 26.x (Java 25). The build system, settings, and Gradle wrapper are replaced; the config backend switches from Vigilant/TOML to Gson/JSON; the entrypoint, event handlers, command, detectors, and web utilities are rewritten to use Fabric and modern Java APIs.

Changes

Forge → Fabric Migration

Layer / File(s) Summary
Build system and Fabric descriptor
settings.gradle, gradle.properties, gradle/wrapper/gradle-wrapper.properties, build.gradle, src/main/resources/fabric.mod.json
Replaces Forge/Essential Gradle scripts (settings.gradle.kts, root.gradle.kts, build.gradle.kts) with Fabric Loom build files targeting Java 25, updates the Gradle wrapper to 9.5.1, and introduces fabric.mod.json as the mod descriptor.
AutoGGConfig: Gson/JSON singleton
src/main/java/club/sk1er/mods/autogg/config/AutoGGConfig.java
Removes the Vigilant/TOML config class; replaces it with a Gson-backed JSON singleton with static load()/save() lifecycle and clamped numeric getters.
AutoGG entrypoint and initialization
src/main/java/club/sk1er/mods/autogg/AutoGG.java
Converts the @Mod-annotated Forge class to a ClientModInitializer; onInitializeClient() loads config, registers handler/command, and submits trigger fetch and language check tasks. getTriggers() now returns a non-null default; volatile added to mutable shared fields.
AutoGGHandler: Fabric event wiring and GG logic
src/main/java/club/sk1er/mods/autogg/handlers/gg/AutoGGHandler.java
Replaces Forge @SubscribeEvent methods with a register() method wiring ClientPlayConnectionEvents (join/disconnect) and ClientReceiveMessageEvents (chat/game). handleIncoming cancels anti-trigger messages by returning false. invokeGG() fixes secondary message scheduling; sendChat() guards on mc.player and mc.getConnection().
AutoGGCommand: Fabric client command
src/main/java/club/sk1er/mods/autogg/command/AutoGGCommand.java
Replaces CommandBase with ClientCommandRegistrationCallback; registers autogg (info message) and autogg refresh (resubmits trigger fetch) subcommands using Component.literal system messages.
Detectors and utility updates
src/main/java/club/sk1er/mods/autogg/detectors/branding/ServerBrandingDetector.java, src/main/java/club/sk1er/mods/autogg/detectors/ip/ServerIPDetector.java, src/main/java/club/sk1er/mods/autogg/handlers/patterns/PatternHandler.java, src/main/java/club/sk1er/mods/autogg/handlers/web/WebHandler.java
Updates detectors to use Minecraft.getInstance() with null guards; PatternHandler switches to computeIfAbsent; WebHandler replaces Commons IO with URI.create().toURL() and readAllBytes().

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Poem

🐰 Hop, hop, away from Forge we go,
No more Vigilant, no more old woe.
Fabric loom weaves a brand new thread,
With Gson config and Java 25 ahead.
The GG fires fast, the triggers stay true—
A mod reborn, shiny and new! ✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 3.45% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: porting the mod to Fabric for Loader 0.19.3 and Minecraft 26.2.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@gradle.properties`:
- Line 8: The Loom dependency is currently set to a mutable snapshot, so update
loom_version in gradle.properties from the SNAPSHOT value to a specific released
version. Use the existing loom_version property as the single place to pin the
plugin to an immutable release so builds remain reproducible.

In `@src/main/java/club/sk1er/mods/autogg/AutoGG.java`:
- Around line 50-51: The JOIN detection path in AutoGG is treating an unloaded
trigger set as if it were empty, so update AutoGG.getTriggers()/the JOIN handler
to preserve a distinct “not loaded” state instead of returning an empty schema.
After RetrieveTriggersTask completes and populates triggers, explicitly run or
re-run the server detection flow so players who joined before async loading
finishes are still detected without needing to reconnect.

In `@src/main/java/club/sk1er/mods/autogg/config/AutoGGConfig.java`:
- Around line 41-44: The config load in AutoGGConfig’s startup path only catches
IOException, so malformed autogg.json can still throw from GSON.fromJson and
stop initialization. Update the load logic around the Reader/GSON.fromJson call
to also handle JsonParseException (or a broader Gson parse exception), then keep
the default AutoGGConfig instance and proceed to save a fresh config fallback.
Make sure the fix is applied in the same AutoGGConfig load method so hand-edited
invalid JSON never escapes the initialization flow.

In
`@src/main/java/club/sk1er/mods/autogg/detectors/branding/ServerBrandingDetector.java`:
- Around line 11-16: Update ServerBrandingDetector.detect so it no longer
returns early when mc.player is null; the method only depends on
Minecraft.getInstance().getConnection().serverBrand() and should still evaluate
the brand during ClientPlayConnectionEvents.JOIN. Keep the connection null
check, fetch the brand from ClientCommonPacketListenerImpl as before, and let
the pattern match run whenever the connection exists so server can be set even
if the player is temporarily unavailable.

In `@src/main/java/club/sk1er/mods/autogg/detectors/ip/ServerIPDetector.java`:
- Around line 11-15: Remove the unnecessary mc.player guard from
ServerIPDetector.detect(), since the method only needs
Minecraft.getInstance().getCurrentServer() to match the server IP. Keep the
existing ServerData null check and
PatternHandler.INSTANCE.getOrRegisterPattern(data).matcher(serverData.ip).matches()
logic, so detection can still populate the server value during JOIN even when
mc.player is not yet available.

In `@src/main/java/club/sk1er/mods/autogg/handlers/gg/AutoGGHandler.java`:
- Around line 61-107: Snapshot the server state once in
AutoGGHandler.handleIncoming and use that same local Server reference for the
entire message flow instead of re-reading the server field after crossing into
POOL.submit. Capture a local currentServer from server after the initial null
check, iterate currentServer.getTriggers() in both the immediate and async
trigger scans, and pass that snapshot into invokeGG and any delayed send path so
a disconnect or rejoin cannot cause an NPE or mix triggers with the wrong
server.

In `@src/main/java/club/sk1er/mods/autogg/handlers/patterns/PatternHandler.java`:
- Around line 13-14: The cache used by getOrRegisterPattern() is accessed from
both the message callback and the POOL.submit background path, so the plain
patternCache HashMap is not safe under concurrent access. Update patternCache in
PatternHandler to a thread-safe implementation such as ConcurrentHashMap, or
guard all accesses with synchronization, while keeping the existing
computeIfAbsent flow and Pattern::compile registration logic intact.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0ff63529-cf95-4f59-a7ff-750cc3c8452e

📥 Commits

Reviewing files that changed from the base of the PR and between 83c3c2c and d3c0c26.

⛔ Files ignored due to path filters (1)
  • deploy.jar is excluded by !**/*.jar
📒 Files selected for processing (17)
  • build.gradle
  • build.gradle.kts
  • gradle.properties
  • gradle/wrapper/gradle-wrapper.properties
  • root.gradle.kts
  • settings.gradle
  • settings.gradle.kts
  • src/main/java/club/sk1er/mods/autogg/AutoGG.java
  • src/main/java/club/sk1er/mods/autogg/command/AutoGGCommand.java
  • src/main/java/club/sk1er/mods/autogg/config/AutoGGConfig.java
  • src/main/java/club/sk1er/mods/autogg/detectors/branding/ServerBrandingDetector.java
  • src/main/java/club/sk1er/mods/autogg/detectors/ip/ServerIPDetector.java
  • src/main/java/club/sk1er/mods/autogg/handlers/gg/AutoGGHandler.java
  • src/main/java/club/sk1er/mods/autogg/handlers/patterns/PatternHandler.java
  • src/main/java/club/sk1er/mods/autogg/handlers/web/WebHandler.java
  • src/main/resources/fabric.mod.json
  • src/main/resources/mcmod.info
💤 Files with no reviewable changes (4)
  • root.gradle.kts
  • build.gradle.kts
  • src/main/resources/mcmod.info
  • settings.gradle.kts

Comment thread gradle.properties
# Fabric — check https://fabricmc.net/develop for updates
minecraft_version=26.2
loader_version=0.19.3
loom_version=1.17-SNAPSHOT

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Repo files of interest:\n'
git ls-files 'gradle.properties' 'build.gradle' 'build.gradle.kts' 'settings.gradle' 'settings.gradle.kts' | sed 's#^`#-` #'

printf '\nRelevant property references:\n'
rg -n 'loom_version|fabric-loom|fabricmc|minecraft_version|loader_version|fabric_api_version' gradle.properties build.gradle build.gradle.kts settings.gradle settings.gradle.kts || true

printf '\nCurrent gradle.properties contents:\n'
cat -n gradle.properties

Repository: Sk1erLLC/AutoGG

Length of output: 1461


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import urllib.request, ssl
url = 'https://maven.fabricmc.net/net/fabricmc/fabric-loom/maven-metadata.xml'
try:
    with urllib.request.urlopen(url, timeout=20, context=ssl.create_default_context()) as r:
        data = r.read().decode('utf-8', 'replace')
    print(data[:4000])
except Exception as e:
    print('ERROR:', e)
PY

Repository: Sk1erLLC/AutoGG

Length of output: 294


🌐 Web query:

Fabric Loom 1.17-SNAPSHOT 1.17.9 maven metadata fabricmc.net

💡 Result:

The Fabric Loom 1.17-SNAPSHOT maven metadata is located at the official Fabric Maven repository [1]. You can access the directory listing directly at https://maven.fabricmc.net/net/fabricmc/fabric-loom/1.17-SNAPSHOT/ [1]. The maven-metadata.xml file for this snapshot version serves as the central descriptor for the 1.17-SNAPSHOT builds, tracking the latest versions and build timestamps [1]. Additionally, the corresponding plugin marker metadata is available at https://maven.fabricmc.net/fabric-loom/fabric-loom.gradle.plugin/1.17-SNAPSHOT/ [2]. As of June 2026, Fabric Loom utilizes a versioning scheme where snapshot versions (e.g., 1.17-SNAPSHOT) are generated to allow users to pull the latest development builds [3]. Official stable releases for Fabric Loom are also published as distinct versions (e.g., 1.17.0-alpha.17, 1.17.9, etc.) and can be found under the same maven group ID (net.fabricmc) [4][5][6]. For development projects, ensure your build configuration is set to include the Fabric Maven repository [7].

Citations:


Pin Loom to a released version

1.17-SNAPSHOT pulls mutable snapshot artifacts, so the same commit can resolve different plugin bits over time and make builds non-reproducible.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@gradle.properties` at line 8, The Loom dependency is currently set to a
mutable snapshot, so update loom_version in gradle.properties from the SNAPSHOT
value to a specific released version. Use the existing loom_version property as
the single place to pin the plugin to an immutable release so builds remain
reproducible.

Comment on lines +50 to +51
POOL.submit(new RetrieveTriggersTask());
POOL.submit(this::checkUserLanguage);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Don’t treat “triggers still loading” as an empty trigger set.

The JOIN handler runs detection once against AutoGG.INSTANCE.getTriggers().getServers(). Because trigger loading is async and getTriggers() returns an empty schema while unset, a player who joins before retrieval completes won’t be detected until reconnect/another detection path exists. Keep a distinct “not loaded” state and trigger server detection after RetrieveTriggersTask populates triggers.

Also applies to: 68-69

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/club/sk1er/mods/autogg/AutoGG.java` around lines 50 - 51, The
JOIN detection path in AutoGG is treating an unloaded trigger set as if it were
empty, so update AutoGG.getTriggers()/the JOIN handler to preserve a distinct
“not loaded” state instead of returning an empty schema. After
RetrieveTriggersTask completes and populates triggers, explicitly run or re-run
the server detection flow so players who joined before async loading finishes
are still detected without needing to reconnect.

Comment on lines +41 to +44
try (Reader reader = Files.newBufferedReader(CONFIG_PATH)) {
AutoGGConfig loaded = GSON.fromJson(reader, AutoGGConfig.class);
if (loaded != null) instance = loaded;
} catch (IOException e) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify config load handles both IO and Gson parse failures.
rg -n -C3 'fromJson\(reader,\s*AutoGGConfig\.class\)|catch\s*\(' src/main/java/club/sk1er/mods/autogg/config/AutoGGConfig.java

Repository: Sk1erLLC/AutoGG

Length of output: 882


Handle malformed JSON during config load.

GSON.fromJson(...) can throw unchecked Gson parse exceptions, so a malformed hand-edited autogg.json can escape this IOException catch and abort client initialization. Catch JsonParseException as well and fall back to defaults before saving.

Proposed fix
 import com.google.gson.Gson;
 import com.google.gson.GsonBuilder;
+import com.google.gson.JsonParseException;
@@
-            } catch (IOException e) {
+            } catch (IOException | JsonParseException e) {
                 AutoGG.LOGGER.error("Failed to load AutoGG config", e);
             }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
try (Reader reader = Files.newBufferedReader(CONFIG_PATH)) {
AutoGGConfig loaded = GSON.fromJson(reader, AutoGGConfig.class);
if (loaded != null) instance = loaded;
} catch (IOException e) {
try (Reader reader = Files.newBufferedReader(CONFIG_PATH)) {
AutoGGConfig loaded = GSON.fromJson(reader, AutoGGConfig.class);
if (loaded != null) instance = loaded;
} catch (IOException | JsonParseException e) {
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/club/sk1er/mods/autogg/config/AutoGGConfig.java` around lines
41 - 44, The config load in AutoGGConfig’s startup path only catches
IOException, so malformed autogg.json can still throw from GSON.fromJson and
stop initialization. Update the load logic around the Reader/GSON.fromJson call
to also handle JsonParseException (or a broader Gson parse exception), then keep
the default AutoGGConfig instance and proceed to save a fresh config fallback.
Make sure the fix is applied in the same AutoGGConfig load method so hand-edited
invalid JSON never escapes the initialization flow.

Comment on lines +11 to +16
Minecraft mc = Minecraft.getInstance();
if (mc.player == null || mc.getConnection() == null) return false;
ClientCommonPacketListenerImpl connection = (ClientCommonPacketListenerImpl) mc.getConnection();
String brand = connection.serverBrand();
if (brand == null) return false;
return PatternHandler.INSTANCE.getOrRegisterPattern(data).matcher(brand).matches();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n -C2 'ClientPlayConnectionEvents\.JOIN|mc\.player == null|serverBrand\(' \
  src/main/java/club/sk1er/mods/autogg/handlers/gg/AutoGGHandler.java \
  src/main/java/club/sk1er/mods/autogg/detectors/branding/ServerBrandingDetector.java

Repository: Sk1erLLC/AutoGG

Length of output: 1768


🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Map the relevant files first
ast-grep outline src/main/java/club/sk1er/mods/autogg/handlers/gg/AutoGGHandler.java --view expanded
ast-grep outline src/main/java/club/sk1er/mods/autogg/detectors/branding/ServerBrandingDetector.java --view expanded

# Read the surrounding code with line numbers
echo '--- AutoGGHandler.java ---'
sed -n '1,200p' src/main/java/club/sk1er/mods/autogg/handlers/gg/AutoGGHandler.java | cat -n
echo '--- ServerBrandingDetector.java ---'
sed -n '1,120p' src/main/java/club/sk1er/mods/autogg/detectors/branding/ServerBrandingDetector.java | cat -n

# Find other detector registrations / invocations
rg -n -C2 'detect\(|getOrRegisterPattern|serverBrand\(|ClientPlayConnectionEvents\.JOIN|server =' src/main/java/club/sk1er/mods/autogg

Repository: Sk1erLLC/AutoGG

Length of output: 17900


Drop the mc.player gate here. detect() only uses mc.getConnection().serverBrand(), and it runs once on ClientPlayConnectionEvents.JOIN, so a temporary null player can leave server unset for the rest of the session.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@src/main/java/club/sk1er/mods/autogg/detectors/branding/ServerBrandingDetector.java`
around lines 11 - 16, Update ServerBrandingDetector.detect so it no longer
returns early when mc.player is null; the method only depends on
Minecraft.getInstance().getConnection().serverBrand() and should still evaluate
the brand during ClientPlayConnectionEvents.JOIN. Keep the connection null
check, fetch the brand from ClientCommonPacketListenerImpl as before, and let
the pattern match run whenever the connection exists so server can be set even
if the player is temporarily unavailable.

Comment on lines +11 to +15
Minecraft mc = Minecraft.getInstance();
if (mc.player == null) return false;
ServerData serverData = mc.getCurrentServer();
if (serverData == null) return false;
return PatternHandler.INSTANCE.getOrRegisterPattern(data).matcher(serverData.ip).matches();

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n -C2 'ClientPlayConnectionEvents\.JOIN|mc\.player == null|getCurrentServer\(' \
  src/main/java/club/sk1er/mods/autogg/handlers/gg/AutoGGHandler.java \
  src/main/java/club/sk1er/mods/autogg/detectors/ip/ServerIPDetector.java

Repository: Sk1erLLC/AutoGG

Length of output: 1493


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== AutoGGHandler ==\n'
sed -n '1,220p' src/main/java/club/sk1er/mods/autogg/handlers/gg/AutoGGHandler.java

printf '\n== ServerIPDetector ==\n'
sed -n '1,120p' src/main/java/club/sk1er/mods/autogg/detectors/ip/ServerIPDetector.java

printf '\n== detector/search references ==\n'
rg -n 'new ServerIPDetector|ServerIPDetector|server =|detect\(' src/main/java/club/sk1er/mods/autogg -g '!**/build/**'

Repository: Sk1erLLC/AutoGG

Length of output: 7860


Remove the mc.player gate from IP detection. detect() only needs getCurrentServer(), and this early false can leave server unset because the detector only runs on JOIN, so the connection never gets matched.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/club/sk1er/mods/autogg/detectors/ip/ServerIPDetector.java`
around lines 11 - 15, Remove the unnecessary mc.player guard from
ServerIPDetector.detect(), since the method only needs
Minecraft.getInstance().getCurrentServer() to match the server IP. Keep the
existing ServerData null check and
PatternHandler.INSTANCE.getOrRegisterPattern(data).matcher(serverData.ip).matches()
logic, so detection can still populate the server value during JOIN even when
mc.player is not yet available.

Comment on lines +61 to +107
private boolean handleIncoming(String rawMessage) {
if (!AutoGGConfig.get().isModEnabled() || server == null) return true;

if (AutoGG.INSTANCE.getAutoGGConfig().isModEnabled() && server != null) {
String stripped = ChatFormatting.stripFormatting(rawMessage);

for (Trigger trigger : server.getTriggers()) {
switch (trigger.getType()) {
case ANTI_GG:
if (AutoGGConfig.get().isAntiGGEnabled() &&
PatternHandler.INSTANCE.getOrRegisterPattern(trigger.getPattern()).matcher(stripped).matches()) {
return false;
}
break;
case ANTI_KARMA:
if (AutoGGConfig.get().isAntiKarmaEnabled() &&
PatternHandler.INSTANCE.getOrRegisterPattern(trigger.getPattern()).matcher(stripped).matches()) {
return false;
}
break;
default:
break;
}
}

POOL.submit(() -> {
for (Trigger trigger : server.getTriggers()) {
switch (trigger.getType()) {
case ANTI_GG:
if (AutoGG.INSTANCE.getAutoGGConfig().isAntiGGEnabled()) {
if (PatternHandler.INSTANCE.getOrRegisterPattern(trigger.getPattern()).matcher(stripped).matches()) {
event.setCanceled(true);
return;
}
case NORMAL:
if (PatternHandler.INSTANCE.getOrRegisterPattern(trigger.getPattern()).matcher(stripped).matches()) {
invokeGG();
return;
}
break;
case ANTI_KARMA:
if (AutoGG.INSTANCE.getAutoGGConfig().isAntiKarmaEnabled()) {
if (PatternHandler.INSTANCE.getOrRegisterPattern(trigger.getPattern()).matcher(stripped).matches()) {
event.setCanceled(true);
return;
}
case CASUAL:
if (AutoGGConfig.get().isCasualAutoGGEnabled() &&
PatternHandler.INSTANCE.getOrRegisterPattern(trigger.getPattern()).matcher(stripped).matches()) {
invokeGG();
return;
}
break;
default:
break;
}
}
});

POOL.submit(() -> {
// Casual GG feature
for (Trigger trigger : server.getTriggers()) {
switch (trigger.getType()) {
case NORMAL:
if (PatternHandler.INSTANCE.getOrRegisterPattern(trigger.getPattern()).matcher(stripped).matches()) {
invokeGG();
return;
}
break;

case CASUAL:
if (AutoGG.INSTANCE.getAutoGGConfig().isCasualAutoGGEnabled()) {
if (PatternHandler.INSTANCE.getOrRegisterPattern(trigger.getPattern()).matcher(stripped).matches()) {
invokeGG();
return;
}
}
break;
}
}
});
}
return true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Snapshot server once for the whole message path.

Line 62 checks server, but Lines 66, 86, and 115 read it again after control has crossed thread boundaries. A disconnect/rejoin in between can turn Line 86 into an NPE or make a trigger from one server send a GG with another server's prefix/connection. Capture a local Server currentServer = server;, iterate that snapshot, and pass it through to invokeGG(...)/the delayed send path instead of re-reading the field.

Also applies to: 110-126

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/club/sk1er/mods/autogg/handlers/gg/AutoGGHandler.java` around
lines 61 - 107, Snapshot the server state once in AutoGGHandler.handleIncoming
and use that same local Server reference for the entire message flow instead of
re-reading the server field after crossing into POOL.submit. Capture a local
currentServer from server after the initial null check, iterate
currentServer.getTriggers() in both the immediate and async trigger scans, and
pass that snapshot into invokeGG and any delayed send path so a disconnect or
rejoin cannot cause an NPE or mix triggers with the wrong server.

Comment on lines +13 to +14
String processed = PlaceholderAPI.INSTANCE.process(pattern);
return patternCache.computeIfAbsent(processed, Pattern::compile);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
rg -n -C2 'POOL\.(submit|schedule)|getOrRegisterPattern\(' \
  src/main/java/club/sk1er/mods/autogg/handlers/gg/AutoGGHandler.java \
  src/main/java/club/sk1er/mods/autogg/handlers/patterns/PatternHandler.java

Repository: Sk1erLLC/AutoGG

Length of output: 5547


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf '\n== PatternHandler ==\n'
cat -n src/main/java/club/sk1er/mods/autogg/handlers/patterns/PatternHandler.java

printf '\n== AutoGGHandler ==\n'
cat -n src/main/java/club/sk1er/mods/autogg/handlers/gg/AutoGGHandler.java

Repository: Sk1erLLC/AutoGG

Length of output: 7334


Make patternCache thread-safe. getOrRegisterPattern() is called from both the message callback and the background POOL.submit path, but patternCache is still a plain HashMap. computeIfAbsent doesn’t make that access safe; switch to ConcurrentHashMap or synchronize the cache.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main/java/club/sk1er/mods/autogg/handlers/patterns/PatternHandler.java`
around lines 13 - 14, The cache used by getOrRegisterPattern() is accessed from
both the message callback and the POOL.submit background path, so the plain
patternCache HashMap is not safe under concurrent access. Update patternCache in
PatternHandler to a thread-safe implementation such as ConcurrentHashMap, or
guard all accesses with synchronization, while keeping the existing
computeIfAbsent flow and Pattern::compile registration logic intact.

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