Tags
Creators
Details
All versions
1.1.1
Release
LSD 1.1.12 months ago 9
Compatibility
Minecraft: Java Edition
26.2
Platform
Paper
Changes
[1.1.1]
Security
- Validate official HTTPS Discord webhook URLs and prevent webhook IDs, tokens, full URLs, response bodies, and unsanitized exception details from appearing in plugin error logs.
Fixed
- Replace the pending/running flag race with a synchronized request queue so accepted synchronization requests cannot become permanently stranded.
- Add finite HTTP connection and request timeouts.
- Cap Discord rate-limit delays and schedule retries without sleeping the synchronization worker.
- Parse Discord responses with Gson and accept only a valid top-level message ID.
- Persist every newly created message ID atomically before continuing to the next page.
- Recreate a tracked Discord message when Discord confirms that it was deleted, then immediately persist the replacement ID.
- Retry HTTP 429 responses, temporary network failures, timeouts, and Discord server errors with bounded exponential backoff and jitter.
- Prevent ambiguous create requests from being retried when Discord may have accepted the message but its response was lost. A durable safety block now requires explicit administrator recovery before another create is attempted.
- Preserve a successfully returned message ID even if plugin shutdown begins while its create request is in flight.
- Treat a successful create response without a valid message ID as ambiguous and pause further creation.
- Retain known message IDs in memory and pause creation if runtime-state persistence fails.
- Disable synchronization when an existing
message-state.jsoncannot be read instead of falling back to stale legacy state. - Preserve the valid single-message legacy ID when the configured legacy ID list contains only blank or invalid entries.
- Treat HTTP 5xx responses to message creation as ambiguous outcomes so the create request is never retried automatically.
- Disable synchronization when legacy message IDs cannot be migrated into durable runtime state.
- Persist a write-ahead creation intent before every Discord POST, preventing message creation when runtime state is unwritable.
- Clear the write-ahead intent before retrying a create request that Discord definitively rejected, including HTTP 429 responses.
- Reject manual create recovery while a Discord create request is still in flight.
- Keep non-create persistence safety blocks recoverable by distinguishing them from active create intents.
- Treat only Discord's explicit unknown-message response as a successful deletion; propagate other HTTP 404 errors.
- Require atomic runtime-state replacement instead of risking a missing or truncated safety record on unsupported filesystems.
- Force state-directory metadata to stable storage after atomic replacement before allowing Discord synchronization to continue.
Changed
- Move managed Discord message IDs from user configuration into atomic
message-state.jsonruntime state. Existingmessage-idsand legacymessage-idvalues migrate automatically. - Remove the obsolete
com.example.lastseendiscordimplementation so the plugin ships one authoritative code path. - Pin the Paper API dependency to
26.2.build.120-stableand set the project version to1.1.1.
Added
- Add deterministic regression tests for synchronization queuing, JSON parsing, webhook validation and URL construction, retry bounds, atomic message-state persistence, interrupted page creation, and deleted-message recovery.
- Add GitHub Actions validation for pushes and pull requests.
- Add a release workflow that verifies the release tag, runs the tests, and attaches one versioned plugin JAR plus its SHA-256 checksum.
- Add a server-owner README covering installation, configuration, commands, upgrades, behavior, troubleshooting, and source builds.
- Add
/lsd recover-create confirmfor safely resuming creation after an administrator resolves an ambiguous Discord response.
Projects on Modrinth are automatically available through a Maven repository for use with JVM build tools such as Gradle. To learn more about the Modrinth Maven API, click here.
Note: When available, you should use the creator's maven repo instead as it will have transitive dependency information that the Modrinth Maven API does not. You may also end up with duplicate dependencies if you use a mix of Modrinth and non-Modrinth Maven repositories for your dependencies, because the group identifier will be different when served through the Modrinth Maven API.
Maven coordinates:
Version ID:
build.gradle:
repositories {
exclusiveContent {
forRepository {
maven {
name = "Modrinth"
url = "https://api.modrinth.com/maven"
}
}
// forRepositories(fg.repository) // Uncomment when using ForgeGradle
filter {
includeGroup "maven.modrinth"
}
}
}
// Standard Gradle dependency
dependencies {
implementation "maven.modrinth:Nuf4Ur89:47waBHvC"
}
// Legacy Loom dependency
dependencies {
modImplementation "maven.modrinth:Nuf4Ur89:47waBHvC"
}

