Skip to content

Changelog

The full per-fix history lives in the mod repo at mods/shops/CHANGELOG.md. Below is a curated highlights view organised by theme.

  • Vacant shell NPC lifecycle - vacant slots have a real persistent NPC, not just a database row. F-key opens rent / bid pages.
  • Auction auto-restart after rental ends - onEmptyAuction = RESTART now also kicks in after a normal rental window closes, not just empty bidding rounds.
  • Force-expire admin command - /kssa forceexpirerental <slotId> runs the full expiry path (mailbox refund + NPC swap + auto-rearm) without waiting for the scheduler.
  • Rental remaining time everywhere - chat on auction-win, NPC nameplate, editor settings panel, MyRentalsPage, BidPage all read from the slot’s authoritative rented_until.
  • Bid page polish - shows Rental Period: X day(s) if you win (from slot.maxDays); countdown disambiguates Auction not active vs Closing... vs live timer.
  • Wildcard sentinel - * and ks.shop.* no longer silently grant permanent listings, infinite shop limits, etc. The plugin probes for a never-defined node; if it matches, falls back to config defaults.
  • hasExplicit helper - call site distinguishes “explicit grant” from “wildcard match” for ks.shop.list.permanent, ks.shop.list.free, all ks.*.limit.N nodes.
  • Free-listing once-per-lifetime - listingFreeDaysOnCreate is a one-time freebie tracked in shop_player_flags; delete + recreate cannot reuse it.
  • Spawn delay on first-player-join - npc.spawnDelaySecondsOnJoin (default 3s) defers the per-world NPC spawn burst, giving the client cosmetic subsystem time to initialise so skins apply correctly.
  • Skin retry on PlayerDB hiccup - npc.skinRetryDelaySeconds (default 5s) retries a failed skin fetch once. Logs (attempt 2) when the retry succeeds.
  • Removed legacy 1.2-block lazy-spawn offset - shops no longer drift 1 block back-left after server restart. Both spawn paths now use the shop’s stored coords directly.
  • Closed shops keep NPC visible - [CLOSED] nameplate suffix instead of removing the entity. Owners still get the editor; visitors see the closed message.
  • Optional-arg migration - rental, transfer, delete, closeplayer, blacklist all use withOptionalArg so positional optional args don’t trigger Hytale’s expected:N, actual:M validation error.
  • Transfer subcommand handshake - /ksshop transfer X Y -> request to target -> /ksshop accepttransfer / declinetransfer flow. Sender no longer auto-confirms without target consent.
  • Name-or-id resolution - most player-side commands (delete, visit, rate, transfer, open, close, list) accept either UUID or case-insensitive shop name.
  • Browse grid preserves editor slot positions - item placed in editor slot 10 stays in browse slot 10 for buyers.
  • Directory cards show listing remaining time - 5 items - Listed 5d 0h on each card.
  • Directory listing in shop editor - Settings tab has a slider + live cost + BUY/EXTEND button for purchasing visibility without leaving the UI.
  • Sell success message - Sold 10x Stone for 50 Gold chat after successful sale (was missing before; only fail message existed).
  • ShopBrowse pagination fix - directory cards on page 2+ used to be empty due to double pagination; now correctly indexes into pre-sliced page list.
  • deployToServer configurable target - gradle.properties can set hytaleServerModsDir to deploy directly to the live server’s mods folder instead of a dev-tree mirror.
  • Default config schema rewrite - defaults/config.json sync’d 1:1 with ConfigData Java schema. Old fields removed, new fields included.
  • Economy retry detection - 4 retries during early boot (+2s, +5s, +10s, +20s) so slow-registering Vault providers (Ecotale registers after Shops loads) get picked up automatically.
  • shop_player_flags table - persistent per-player flags. Currently tracks free_listing_used. Independent from shop_shops so a delete + recreate can’t reset.
  • Source-of-truth columns - shop_rental_slots.rented_until is authoritative for rental expiry; shop_shops.rental_expires_at is a denormalised mirror. UI now reads from the slot for accuracy.

If you’re upgrading from a pre-rental-system version:

  1. The rental tables (shop_rental_slots, shop_rental_bids, shop_player_flags) are created idempotently on init - no manual migration needed.
  2. Your existing shops are unaffected by the rental code paths unless you create a rental slot.
  3. manifest.json no longer declares Ecotale:Ecotale as a dependency (we use retry-detection instead). If you load Ecotale + VaultUnlocked, the bridge attaches within 20s.
  4. The defaults/config.json template was rewritten - your live config.json is not overwritten. To pick up new fields, either delete it (regenerated on next start) or copy the missing blocks manually.

For the running per-fix history, see the GitHub repo CHANGELOG.