Список изменений
What's New
Added
- Permission-aware tab completion for
/stormtrooperx. The first argument completes to only the subcommands the sender may actually run; foroptout/optin, the second argument completes to online player names — but only for admins holdingstormtrooperx.optout.others. Tab-completion pools are pre-sorted and computed once at startup. /stormtrooperx helplists only the commands the sender has permission to run, so a regular player no longer sees admin-only subcommands they can't use.- Idempotent
optoutand newoptin.optoutno longer toggles — it always sets opted-out (reporting "already opted out" instead of silently flipping).optinis the symmetric counterpart.toggleis retained for the flip behavior. - Admin opt-out management.
/stormtrooperx optout|optin <player>lets admins manage opt-out state for any online player, gated by the newstormtrooperx.optout.otherspermission. The target receives a chat notification of the change. stormtrooperx.adminpermission, required for/stormtrooperx reloadand grantingstormtrooperx.optout.othersvia permission children. The previous setup had no clean "give one player everything" knob.- Join-time opt-out reminder. When an opted-out player's state finishes loading from the database, they get a one-shot chat message confirming the status.
- PlaceholderAPI soft dependency. When PlaceholderAPI is present,
%stormtrooperx_optout%resolves totrue/falsefor the requesting player. The expansion persists across/papi reload. PAPI is a soft dependency only — the plugin loads and runs identically without it.
Changed
- Projectile math extracted. The speed-preserving direction perturbation now lives in a package-private
ProjectileNerf.perturb(Vector, double, Supplier<Vector>)with an injectable random source, making the pure-math invariants directly unit-testable without event mocking. Runtime behavior is unchanged. stormtrooperx.usedefault flipped fromoptotrueso non-op players can actually reach/stormtrooperx optout(itselfdefault: true). The old default made the public opt-out command unreachable for the audience it was meant for.- Ignores cancelled
EntityShootBowEvent.onBowShootnow declares@EventHandler(ignoreCancelled = true)— if an upstream plugin cancels the shoot event, we no longer perturb the (cancelled) projectile's velocity. - HikariCP MySQL pool sets the Connector/J performance properties from the HikariCP wiki:
useServerPrepStmts,useLocalSessionState,rewriteBatchedStatements,cacheResultSetMetadata,cacheServerConfiguration,elideSetAutoCommits,maintainTimeStats=false. No config change needed. - Hot-path micro-optimizations in
onBowShoot:lengthSquared()for the zero-velocity guard, cached projectile andisH2references, pattern-matchinginstanceof.
Fixed
- Folia regional-thread safety on
/stormtrooperx reload.entityConfigsanddebugare nowvolatile, andloadConfigurationpublishes a freshly-builtEnumMapin a single reference write instead of mutating the live map. The old code could expose a partially populated map to a regionalEntityShootBowEventthread during a reload.
Security
- CWE-117 log injection — release tags. Closed log-injection vectors in
UpdateChecker. GitHub release tags pass avalidateReleaseTagbarrier (^v?\d+(\.\d+){0,3}(-++)?$) before reaching any logger or version compare; malformed tags are dropped at the source. - CWE-117 log injection — sink-side allowlist. A new
sanitizeForLoghelper reduces logged version strings at the sink to[A-Za-z0-9._+-]via a negated-character-classreplaceAll— the form CodeQL recognizes as a sanitizer (a[\r\n]denylist does not satisfyjava/log-injection). - JDBC parameter smuggling.
DatabaseManagernow validates the MySQLpropertiesmap against an explicit allowlist (SAFE_MYSQL_PROPERTY_KEYS) and URL-encodes values. Unsupported keys throwIllegalArgumentExceptionatinitialize(). This closes a parameter-smuggling vector that could otherwise enable high-risk Connector/J flags (allowLoadLocalInfile,autoDeserialize,queryInterceptors, …) with RCE / file-read history. - Defense-in-depth Connector/J defaults. Even with the allowlist,
dataSourcePropertiesforcesallowLoadLocalInfile=false,allowUrlInLocalInfile=false,autoDeserialize=false, andallowPublicKeyRetrieval=falseat the HikariCP layer. - Chat-injection echo. Player names echoed by the offline branch of
/stormtrooperx optout|optin <player>are run through a newsanitizeNameForEcho(strips control chars and§, caps at 16 chars), closing a low-severity chat-injection vector on offline-mode servers. - AssertJ pinned to 3.27.7 (test-scope), clear of CVE-2026-24400 (GHSA-rqfh-9r24-8c9r — XXE in the unused
isXmlEqualTo).
Build
- CycloneDX SBOM. Added
cyclonedx-maven-pluginon theverifyphase;release.ymluploadsbom.xml/bom.jsonalongside the JAR. release.ymlactions pinned to commit SHAs (with# vX.Y.Ztrailers) instead of mutable major tags — the release job holdsid-token/attestations: writescope. Dependabot keeps the pins current.
Tests
- AssertJ added. Migrated assertions to fluent
assertThat(...)style for richer failure messages. Mockito 5.x + JUnit Jupiter 6.x stack is unchanged. - Branch-coverage gate. Jacoco now enforces
BRANCH COVEREDRATIO >= 0.50per package alongside the existing 0.60 line-coverage rule. Current: 72% line / 75% branch. - CI runs
mvn clean verifyinstead ofpackage, so the Jacoco gate (bound toverify) is enforced in CI — not just locally. - Shared test infrastructure. New
support/test package:TestSupport(reflective field/method access) andInlinePluginScheduler(shared inline scheduler), replacing duplicated boilerplate across test classes. - YAML fixtures under
src/test/resources/fixtures/(config-v2.yml,config-v3.yml);ConfigMigrationTestexercises real-load → migrate → assert instead of synthetic YamlConfiguration objects. - New
ProjectileNerfTestfor the extracted pure function — speed preservation, zero-velocity guard, mutation semantics, accuracy clamping. Plus expandedUpdateCheckerTestcoveringvalidateReleaseTagaccept/reject sets.
Dependencies
- Bumped
me.clip:placeholderapifrom2.11.6to2.12.2(providedscope, soft dependency — not shaded into the JAR).
Documentation
OptOutManager#isOptedOut,StormtrooperXExpansion, and the README PlaceholderAPI section all document the online-only semantics of%stormtrooperx_optout%: offline players resolve tofalseregardless of persisted state.DatabaseManager.initializeH2Javadoc now warns against enablingAUTO_SERVER=TRUE/ H2 server mode without revisiting the hardcodedsa/empty credentials.
Upgrade Notes
If upgrading from 1.9.x:
- Behavior change —
/stormtrooperx optout. Previously toggled; now it always sets opted-out. Use/stormtrooperx togglefor the old flip behavior. If you bind macros or scripts to the command, this is a one-line update. - Permission default change —
stormtrooperx.use. Default flipped fromoptotrueso theoptoutsubcommand (alwaysdefault: true) is reachable for the intended audience. Servers using a permissions plugin that explicitly grantedstormtrooperx.useto non-ops are unaffected; servers relying on the old default should explicitly denystormtrooperx.useto revert. - New permissions to wire up (admins):
stormtrooperx.admin(grantsreloadandoptout.othersvia children) andstormtrooperx.optout.others(grants admin opt-out commands for other players). Both default toop. - PlaceholderAPI is optional. To use
%stormtrooperx_optout%, install PlaceholderAPI; no config change required. - Config: No schema change.
config-version: 3continues to apply, no migration runs on upgrade.
Server compatibility: Unchanged — Spigot, Paper, Purpur, and Folia 1.20.4+, on Minecraft 1.18 through 26.1.x, Java 17+.
JAR verification: Built and attested via GitHub Actions with Sigstore. Verify with gh attestation verify StormtrooperX-1.10.0.jar --repo GooberCraft/StormtrooperX (requires gh 2.43.0+).
Файлы
StormtrooperX-1.10.0.jar(7.35 MiB)
ОсновнойМетаданные
Канал релиза
Release
Номер версии
1.10.0
Загрузчики
BukkitPaperPurpurSpigot
Версии игры
1.18–26.1.2
Загрузок
17
Дата публикации
15.05.2026

