Skip to content

Releases: nicki41/UniversalAdmin

UniversalAdmin 0.1.0-alpha.5

Choose a tag to compare

@github-actions github-actions released this 26 Aug 17:58

Added

  • Every GitHub release is now automatically mirrored to the universaladmin
    Modrinth project as a new version (Kira-NT/mc-publish, the new
    MODRINTH_TOKEN repository secret). See
    docs/release/releasing.md.
  • The universaladmin Modrinth project page is now filled in: icon
    (assets/icon.png), title, summary, description, categories, license, and
    links - content lives in docs/release/modrinth.md.

Full Changelog: v0.1.0-alpha.4...v0.1.0-alpha.5

UniversalAdmin 0.1.0-alpha.4

Choose a tag to compare

@github-actions github-actions released this 26 Aug 17:03

UniversalAdmin 0.1.0-alpha.3

Choose a tag to compare

@github-actions github-actions released this 26 Aug 17:01

Changed

  • Releases are no longer flagged "Pre-release" on GitHub, -alpha/-beta/
    -rc versions included - the project's status is already communicated by
    the version string and the README, not GitHub's separate prerelease flag.
    See docs/release/releasing.md.
  • The telemetry endpoint is no longer a config value: telemetry.endpoint
    has been removed from config.yml and CoreSettings, and every heartbeat
    now goes to the official nicki41-telemetry instance, fixed in
    TelemetryBootstrap. telemetry.enabled remains the only switch. This
    also means an old config.yml with a leftover telemetry.endpoint value
    (e.g. an explicit empty string) no longer has any effect.

Fixed

  • auto-release.yml's version-bump commit/tag push had no recovery if
    main moved between checkout and push (hit for real when a backlog of
    delayed Actions runs raced each other) - now retries up to 5 times, each
    attempt recomputing from a fresh git fetch/reset --hard origin/main.

Full Changelog: v0.1.0-alpha.2...v0.1.0-alpha.3

UniversalAdmin 0.1.0-alpha.2

Choose a tag to compare

@github-actions github-actions released this 26 Aug 16:37

Added

  • Automatic update checks: dev.universaladmin.update polls the GitHub
    releases API on a jittered interval (default every 6 hours) and, when a
    newer version exists, notifies staff (universaladmin.update.notify) and
    logs a console warning. /admin update (universaladmin.update.apply)
    downloads the latest release's jar into Bukkit's own plugins/update/
    folder (verified against its published SHA-256 checksum) - applied at the
    next restart, never a live hot-swap. update.check-for-updates (default
    true) is the on/off switch; update.check-interval configures the
    background timer.
  • Empty-slot placeholders in the Players module's and Staff-Mode's
    inventory/ender-chest editors: a dyed-gray leather armor piece per slot
    (helmet/chestplate/leggings/boots), a grayed-out shield for offhand, and a
    visibly distinct hotbar row - EmptySlotPlaceholder, stripped back to
    null before ever writing to a real inventory.

Changed

  • TelemetryPayload's wire format gained a pluginId field (fixed:
    "universaladmin") and renamed universalAdminVersion to
    pluginVersion - the shape a shared, multi-plugin telemetry backend
    expects (see docs/user/telemetry.md). What's
    collected and the opt-out are unchanged.
  • telemetry.endpoint now defaults to https://telemetry.0nicki.de/v1/telemetry
    (the official nicki41-telemetry instance) instead of empty - a fresh
    install now reports anonymous usage statistics out of the box;
    telemetry.enabled: false (or clearing telemetry.endpoint) still turns
    it off entirely. See docs/user/telemetry.md.

Fixed

  • Closing a live inventory/ender-chest editor (Players module or the
    Staff-Mode Inspector tools) showed the "Done." confirmation twice - both
    halves of the split main-storage/equipment write notified independently;
    now only the first does.

Full Changelog: v0.1.0-alpha.1...v0.1.0-alpha.2

UniversalAdmin 0.1.0-alpha.1

Choose a tag to compare

@github-actions github-actions released this 26 Aug 00:20

Added

  • Anonymous usage statistics (dev.universaladmin.telemetry):
    InstallationIdentity/InstallationIdentityStore (128 bits from
    SecureRandom, derived from nothing, persisted in
    installation-id.yml), TelemetryPayload (exactly six fields),
    TelemetryClient with HttpTelemetryClient (JDK HTTP client, short
    timeouts, no redirects, response discarded) and NoOpTelemetryClient,
    TelemetryService (enabled check on every heartbeat, player counts read
    on the main thread, the request runs in the background, failures are
    swallowed and only warned once per run), TelemetryScheduler (a
    delayed start, an interval with jitter, its own daemon thread), and
    TelemetryBootstrap (wiring with three outcomes: off / no endpoint /
    active). New settings telemetry.enabled (switchable live),
    telemetry.endpoint (empty by default - nothing is sent by
    default), and telemetry.interval. Full documentation including
    everything that's never collected:
    docs/user/telemetry.md.

  • Tests for telemetry with zero real network requests: id
    generation/persistence, "disabled means zero requests", a payload
    without player identities, serialization, an endpoint failure with no
    side effect, jitter bounds, scheduler cleanup.

  • LICENSE (Apache-2.0, unmodified official license text) and a
    licensing decision with rationale in
    docs/release/licensing.md.

  • docs/development/architecture-rules.md - the binding architecture,
    package, threading, settings, module, security, dependency, and test
    rules as regular developer documentation.

  • docs/release/releasing.md - a reproducible release process
    (version → CHANGELOG → build → commit → tag → push).

  • .github/workflows/release.yml - a v* tag automatically produces a
    GitHub release: a tag-vs-project-version check, a build including
    tests, the shaded jar plus a SHA-256 file as assets, prerelease
    detection for -alpha/-beta/-rc. contents: write, no additional
    secrets. Also callable directly (workflow_call, with a tag input) by
    auto-release.yml below, not only by its own tag-push trigger.

  • .github/workflows/auto-release.yml - releases automatically after any
    push to main that changes more than docs/CI metadata: bumps the
    -alpha.N counter in build.gradle.kts, moves the CHANGELOG.md
    [Unreleased] section into a dated one, commits, tags, and calls
    release.yml. Skips a beta/rc/stable version bump (a bigger decision
    than this workflow makes on its own) and its own release commits (no
    loop). See docs/release/releasing.md.

  • A printVersion Gradle task as the single source of the project
    version for CI (the tag check, artifact naming).

  • Issue forms (bug_report.yml, feature_request.yml) and
    ISSUE_TEMPLATE/config.yml pointing at private vulnerability reporting
    instead of public security issues.

  • Project architecture defined and documented (see ARCHITECTURE.md,
    docs/architecture/, ADRs under docs/architecture/decisions/).

  • Gradle setup (Java 25 toolchain, Shadow plugin, SQLite/MySQL drivers,
    JUnit 5).

  • Plugin bootstrap (UniversalAdminPlugin) with manual dependency wiring.

  • Core abstractions: Module, Action/ActionResult, GuiPage,
    Repository/Migration, PermissionRegistry, ServiceRegistry,
    AuditService, MessageService, NotificationService, TaskScheduler.

  • Eight module skeletons: Players, Moderation, Server, Worlds, Whitelist,
    Performance, Audit Log, Settings. Players as the complete reference
    implementation (repository → service → action, including a migration).

  • Test infrastructure with example tests (registry, permission
    validation, a service with an in-memory fake, migrations against a
    real SQLite database).

  • Core bootstrap lifecycle (onLoad/onEnable/onDisable) with a clear
    separation between critical core components (config, scheduler,
    storage/migrations, shared registries - failures abort the whole
    plugin start) and individual modules (failures are isolated, see
    ModuleManager).

  • Internal module lifecycle system: ModuleDescriptor (metadata
    including dependencies, settings/permission namespace, an optional GUI
    icon placeholder), ModuleState
    (DISCOVERED/LOADED/ENABLED/DISABLED/FAILED), ModuleRegistry
    (state tracking), ModuleManager (dependency ordering, failure
    isolation), ModuleResources (automatic release of
    listeners/tasks/registry entries on disable). See
    docs/architecture/modules.md.

  • PluginStatus/ComponentStatus - a live snapshot of version, uptime,
    active/failed modules, coarse database/web status.

  • /admin command (aliases /ua, /uadmin) as a status placeholder,
    rendering PluginStatus.

  • unregister(...) on ActionRegistry/GuiRegistry/PermissionRegistry
    for module-disable cleanup.

  • Tests for the module lifecycle system (ModuleManagerTest):
    registration, a duplicate module id, lifecycle ordering, failure
    isolation, disable cleanup, dependency ordering, cycle detection, a
    missing dependency.

  • Typed settings system (dev.universaladmin.settings):
    SettingKey<T>/SettingType<T>/SettingValidator<T>/SettingDefinition<T>/
    SettingValue<T>/SettingRegistry/SettingsService, with built-in
    types for string/boolean/int/long/double/Duration/enum/string list,
    validators for min/max/regex/multiple-of, and namespacing between core
    settings and future module/extension settings. See
    docs/development/settings.md and ADR 0007.

  • CoreSettings - registers the complete config.yml tree (general,
    database, gui, audit, modules, performance, maintenance,
    web); modules.* now actually controls whether a built-in module
    gets registered at all.

  • config.yml versioning: config-version, ConfigMigration/
    ConfigMigrationRunner (dev.universaladmin.config) - an existing
    user config gets migrated on future schema changes instead of
    overwritten.

  • A safe /admin reload (ReloadConfigAction, permission
    universaladmin.reload) - only ever reloads UniversalAdmin's own
    config.yml, never Bukkit's global /reload. Restart-required
    settings are reported as "pending restart" on change instead of
    applied live.

  • Multi-language message system: lang/en_US.yml (default/fallback) and
    lang/de_DE.yml, YamlLocaleMessageService with a fallback chain
    (active locale → en_US → a visible [missing: ...] marker with a
    one-time debug log), ComponentMessages as a MiniMessage renderer for
    in-game output, kept separate from plain string resolution (for web
    reuse).

  • Tests for the settings/localization system: defaults, invalid values
    (parse/validation errors → fallback instead of a crash), enum parsing,
    duration parsing, duplicate setting keys, locale fallback, parameter
    interpolation.

  • DatabaseHealth (DISCONNECTED/CONNECTING/READY/FAILED),
    tracked by StorageService and mapped onto the existing
    ComponentStatus in UniversalAdmin#status() - see
    docs/architecture/storage.md#health.

  • SQLite pragmas in DataSourceFactory (journal_mode=WAL,
    synchronous=NORMAL, foreign_keys=on, busy_timeout=5000).

  • Transactions (dev.universaladmin.storage) - a helper for repository
    methods that need to run multiple statements atomically (commit/
    rollback) over one connection.

  • StorageException - a generic unchecked wrapper for SQLException in
    the storage foundation itself (StorageService, Transactions).

  • docs/user/database.md - user documentation for SQLite vs.
    MySQL/MariaDB (when which, creating a MySQL user, behavior on startup
    failure, backups).

  • Tests: StorageServiceTest (SQLite init, health states, failure on an
    invalid path), TransactionsTest (commit, rollback on error),
    JdbcPlayerProfileRepositoryTest (the repository foundation end to
    end against a real SQLite database), database-type parsing in
    SettingTypesTest, an explicit "no duplicate migration run" assertion
    in MigrationRunnerTest.

  • A reusable in-game GUI framework (dev.universaladmin.gui):
    AbstractGuiPage/AbstractListGuiPage (navigation, permission-driven
    visibility, pagination, async loading with loading/empty/error state),
    GuiSession/GuiSessionManager (per-player state with no held
    Player references, cleanup on disconnect/a real inventory close),
    GuiListener as the single, centrally registered click/drag handler,
    GuiLayout/Pagination as pure, tested slot/pagination logic,
    IconProvider/MaterialIconProvider as the central material
    resolution, ConfirmationDialog (danger level NORMAL/WARNING/
    DANGEROUS), SelectionDialog, GuiTextInput (a free-text/search flow
    via the Paper dialog API instead of packet hacks/anvil/sign) - see
    docs/development/gui-framework.md.

  • MainMenuPage: the /admin main menu with one button per built-in
    module, filtered by actual ModuleState.ENABLED and permission;
    PlaceholderGuiPage as the "not built yet" target page per module. A
    new permission universaladmin.menu.open.

  • ModuleDescriptor.icon() set for all eight built-in modules
    (previously null everywhere, see GuiIcon).

  • Tests for the GUI framework: PaginationTest, GuiLayoutTest,
    GuiSessionTest, GuiSessionManagerTest, GuiButtonVisibilityTest,
    GuiClickContextTest (the navigation stack), GuiListenerTest
    (click cancel/dispatch, close/quit cleanup).

  • GuiView#onChange - a live-sync hook GuiListener runs one tick after a
    click/drag it let through, on top of the existing onClose. Used by the
    Players module's inventory/ender chest editors and the new Staff-Mode
    Ender Chest Inspector tool so an edit mirrors onto the real target
    immediately instead of only when the viewer closes the GUI.

  • Staff-Mode Ender Chest Inspector tool (EnderChestInspectorPage),
    alongside a now-live (not read-only) Inventory Inspect...

Read more