Port mod to Fabric loader 0.19.3 Minecraft 26.2 - #32
Conversation
📝 WalkthroughWalkthroughAutoGG 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. ChangesForge → Fabric Migration
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
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
⛔ Files ignored due to path filters (1)
deploy.jaris excluded by!**/*.jar
📒 Files selected for processing (17)
build.gradlebuild.gradle.ktsgradle.propertiesgradle/wrapper/gradle-wrapper.propertiesroot.gradle.ktssettings.gradlesettings.gradle.ktssrc/main/java/club/sk1er/mods/autogg/AutoGG.javasrc/main/java/club/sk1er/mods/autogg/command/AutoGGCommand.javasrc/main/java/club/sk1er/mods/autogg/config/AutoGGConfig.javasrc/main/java/club/sk1er/mods/autogg/detectors/branding/ServerBrandingDetector.javasrc/main/java/club/sk1er/mods/autogg/detectors/ip/ServerIPDetector.javasrc/main/java/club/sk1er/mods/autogg/handlers/gg/AutoGGHandler.javasrc/main/java/club/sk1er/mods/autogg/handlers/patterns/PatternHandler.javasrc/main/java/club/sk1er/mods/autogg/handlers/web/WebHandler.javasrc/main/resources/fabric.mod.jsonsrc/main/resources/mcmod.info
💤 Files with no reviewable changes (4)
- root.gradle.kts
- build.gradle.kts
- src/main/resources/mcmod.info
- settings.gradle.kts
| # Fabric — check https://fabricmc.net/develop for updates | ||
| minecraft_version=26.2 | ||
| loader_version=0.19.3 | ||
| loom_version=1.17-SNAPSHOT |
There was a problem hiding this comment.
🩺 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.propertiesRepository: 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)
PYRepository: 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:
- 1: https://maven.fabricmc.net/net/fabricmc/fabric-loom/1.17-SNAPSHOT/
- 2: https://maven.fabricmc.net/fabric-loom/fabric-loom.gradle.plugin/1.17-SNAPSHOT/
- 3: https://github.com/FabricMC/fabric-loom/blob/dev/1.17/build.gradle
- 4: https://gitlab.com/fabricmc/fabric-loom/-/tags
- 5: https://mvnrepository.com/artifact/net.fabricmc/fabric-loom/versions
- 6: https://maven.fabricmc.net/net/fabricmc/fabric-loom/1.17.0-alpha.17/
- 7: https://docs.fabricmc.net/develop/loom/
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.
| POOL.submit(new RetrieveTriggersTask()); | ||
| POOL.submit(this::checkUserLanguage); |
There was a problem hiding this comment.
🎯 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.
| try (Reader reader = Files.newBufferedReader(CONFIG_PATH)) { | ||
| AutoGGConfig loaded = GSON.fromJson(reader, AutoGGConfig.class); | ||
| if (loaded != null) instance = loaded; | ||
| } catch (IOException e) { |
There was a problem hiding this comment.
🩺 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.javaRepository: 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.
| 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.
| 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(); |
There was a problem hiding this comment.
🎯 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.javaRepository: 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/autoggRepository: 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.
| 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(); |
There was a problem hiding this comment.
🎯 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.javaRepository: 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.
| 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; |
There was a problem hiding this comment.
🩺 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.
| String processed = PlaceholderAPI.INSTANCE.process(pattern); | ||
| return patternCache.computeIfAbsent(processed, Pattern::compile); |
There was a problem hiding this comment.
🩺 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.javaRepository: 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.javaRepository: 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.
Mod ported to latest minecraft version on this moment 26.2 with Fabric Loader.
Summary by CodeRabbit
New Features
/autoggcommand with a refresh option.Bug Fixes
Chores