feat(vip): VIP tiers + first-login pack + recurring tier gifts (#233, #234) - #98
Merged
Merged
Conversation
feat(vip): VIP tiers + first-login pack + recurring tier gifts (#233, #234)
Adds a spawn-driven VipPerks feature covering two board items:
#233 — first-time-login pack: the first time a player ever spawns, a
configured VIP-gift template is delivered straight into their inventory
(items dropped at feet, linked commands run). Once-ever, guarded by the
new first_login_grants table.
#234 — recurring tier gifts: players carry an admin-assigned VIP tier
(new player_metadata.vip_tier, admin-editable tier names in settings).
On spawn, each tier-gift rule for that tier is materialized once as a
repeatable vip_gifts row; the existing /vip claim flow then drives the
daily/weekly cadence. No tier ("pleb") = nothing.
Spawn-driven rather than timer-driven: a player must be online to claim or
receive items anyway, so doing the work on connect stays idempotent across
reconnects without a background sweep.
Backend:
- migration 012: player_metadata.vip_tier + first_login_grants
- VipPerksFeature + VipPerksSettings (persisted JSON, VoteRewards pattern)
- FirstLoginGrantRepository; VipGiftRepository.HasGiftByNameAndPeriod;
PlayerMetadataRepository.SetTier/GetPlayerIdsByTier (SetTier writes only
vip_tier so it never clobbers name colour / tag / notes)
- VipPerksController (settings + tiers); PlayerMetadataController tier route
Frontend:
- VIP tier dropdown in PlayerEditDialog
- VIP Perks settings tab (tiers, first-login pack, tier-gift rules)
- api/types/i18n (en translated; other locales English placeholders)
Tests: PlayerMetadata (tier set/clear, no-clobber both ways, by-tier query),
FirstLoginGrant (once-ever), VipGift (has-by-name-and-period). 10 new, green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
test(vip): frontend vitest coverage for VIP perks (#233, #234) codecov/patch flagged the frontend changes (coverage is frontend-only via vitest). Adds: - api/vipperks.test.ts — full coverage of the new API module - players.test.ts — setPlayerTier (encoded id, null-clear) - PlayerEditDialog.test.ts — tier load on open + save wires setPlayerTier - SettingsViewVipPerks.test.ts — renders the VIP Perks panel and exercises fetch / add+remove tier / add+remove tier-gift / save handlers +20 tests (89 total green). SettingsView.vue 0% -> 47.6%; the new VIP perks panel + handlers are the covered portion. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> @
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Board items #233 and #234. Single PR over a shared "VIP tier" foundation, as discussed.
What this adds
A new spawn-driven
VipPerksFeature(auto-discovered via theIFeaturescan), plus an admin-assigned VIP tier on player records.#233 — first-time-login pack
The first time a player ever spawns, a configured VIP-gift template is delivered straight into their inventory (items dropped at their feet via
LivePlayerManager.GiveItemToPlayer, linked commands run with{entityId}/{playerId}/{playerName}substitution). One-shot, guarded by the newfirst_login_grantstable (INSERT OR IGNOREon a PK = once-ever). No/vipstep — per the "auto-deliver on spawn" decision.#234 — recurring daily/weekly VIP gifts
Players carry a tier in the new
player_metadata.vip_tiercolumn; tier names are admin-editable in settings (no enum, no migration to add "VIP++"). On a (re)connect spawn, each tier-gift rule for that player's tier is materialized once as a repeatablevip_giftsrow — then the existingGetPendingForPlayer+/vipclaim flow drives the daily/weekly cadence. Players with no tier ("pleb") get nothing.Why spawn-driven, not a scheduled sweep: a player must be online to claim a gift or receive items anyway, so doing the work on connect is idempotent across reconnects and avoids a background timer entirely.
Changes
Backend
012_vip_tiers.sql:player_metadata.vip_tier+first_login_grantsVipPerksFeature+VipPerksSettings(persisted JSON, VoteRewards pattern)FirstLoginGrantRepository;VipGiftRepository.HasGiftByNameAndPeriod;PlayerMetadataRepository.SetTier/GetPlayerIdsByTier—SetTierwrites onlyvip_tierso it never clobbers a player's name colour / tag / notes (andUpsertleaves the tier alone)VipPerksController(settings + tier list); tier route onPlayerMetadataControllerFrontend
entranslated; other 7 locales get English placeholders (admin-only panel,fallbackLocaleisen)Tests
10 new repository tests, all green: tier set/clear + no-clobber both directions + by-tier query, first-login once-ever idempotency, has-gift-by-name-and-period.
Notes / follow-ups
enlocale strings are English placeholders pending translation.ModEventBusTestsfail locally with aLogLibraryBadImageFormatException(Unity reference assembly can't execute in the test host) — unrelated to this change; untouched here.🤖 Generated with Claude Code