Select a Part or Model in Studio, answer "what is this object?", fill a form —
it becomes a gatherable node, a mob or a quest giver. Closes the gap between
authoring a def and setting up a world object, which until now meant knowing to
tag a part and hand-typing PascalCase attributes in the property panel.
Engine — components can declare an attribute SCHEMA:
- src/components/Schema.luau (new): AttributeSpec/Display/ComponentSchema types,
normalize/defaults/get/list, and the schemas for Gatherable, Mob, QuestGiver.
Dependency-free ON PURPOSE: the plugin requires it live at edit time, and the
component modules themselves can't be required there (Harvesting asserts
IsServer; Remotes creates instances in ReplicatedStorage).
- Components.define now accepts EITHER the legacy `attr = default` map or a
schema array, normalizing both to one ordered spec list; bind() reads the
derived default map, so binding is byte-identical. Legacy maps are sorted, as
`pairs` order is arbitrary and would make a UI jitter. New getSchema/
listSchemas. The three shipped components pull name/tag/display/attributes
from the schema; their onSetup bodies are untouched (defaults verified
identical, all 23 attributes).
Plugin — the Build page:
- Field.luau (new): coerce/format/equalsDefault, lifted from ConfigAdmin (which
now delegates), shared by every schema-driven editor.
- FieldRow.luau (new): the shared [○/●] label … control + help row, including a
⌄ picker that cycles authored ids for fields declaring `ref`.
- BuildAdmin.luau (new): live schema read with three distinct empty states,
selection/eligibility/identify, deltas-only attribute writes, applyType
(tag + clear any other component) and clear.
- BuildAdminUi.luau (new): chooser cards, grouped form, multi-select apply,
stale-bind-marker warning, SelectionChanged-driven refresh.
- init.server.luau: record()-wrapped buildActions + the page.
Docs: docs/admin-plugin.md Build section + a 60-second walkthrough,
docs/extending.md schema guide, a CONTRIBUTING rule that new creator components
declare one, CHANGELOG.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
A new server-authoritative, dupe-proof trade system. Walk up to another player,
trigger the "Trade" prompt; they Accept/Decline; both stage loose backpack
stacks (drag from the inventory grid, with −/+ qty steppers) and must Confirm
before anything moves.
Anti-dupe by construction: staging is by-reference (items never leave the owner
until commit), and the commit is one synchronous, no-yield critical section —
re-validate holds → pre-flight both receivers have room (new Inventory.canAccept)
→ remove both → grant with addUpTo → refund any residue. Item count is conserved
on every branch (verified: 200k-iteration conservation + fit-oracle fuzz).
Auto-cancels on death / leave / out-of-range (MaxDistance) / request timeout; a
staging change resets both confirms. New Trade server system + TradeUi client
window, the "Trading" Config section (tunable in SurvivorCore Studio), hooks
trade:started / trade:completed, and a trades_total progression counter. v1 is
backpack stacks only (worn gear reserved behind AllowEquippedItems).
- src/systems/Trade.luau, src/client/TradeUi.luau, src/shared/TradingConfig.luau (new)
- src/systems/Inventory.luau: exported canAccept (weight+slot fit oracle)
- src/shared/EngineConfig.luau: Trading section; src/init.luau boot wiring
- docs/trading.md, README, CHANGELOG (Unreleased), Hooks catalogue, extending.md
- demo/server/TradeTestStation.server.luau: /tradetest 2-player conservation harness
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Hunting & butchering (#13): mob defs gain flat carcass fields (carcassItem/Hp/
Tool/YieldMin/Max/Seconds); a slain mob leaves a butcherable CARCASS that is a
tagged Gatherable — the whole harvesting pipeline (tool gate, per-hit yields,
HP bar, gather:* hooks, progression counters) is reused as the butcher flow.
Carcass looks come from SurvivorCoreContent.Carcasses.<mobType>; reactions key
on "<mobType>_carcass"; fields editable in the admin Mobs editor. Gatherable
gains generic PromptText/PromptObject attributes.
Death loot bags (#19, TCE port): dying drops inventory AND worn equipment
(config-toggleable) into an anchored ground-clamped bag — IntValue contents,
instant-loot prompt for anyone, floating countdown, owner-only beacon, death
toast, LifetimeSeconds despawn. Pickup is loss-proof: equipment restores to
empty slots first (satchel re-grows capacity before stacks), the rest grants
up-to-fit and the remainder stays bagged. New player:died lifecycle → deaths
counters via Progression; lootbag:dropped/collected hooks; TCE respawn camera
fix. New Inventory APIs: getEquipment, clearAll (capacity-safe order), addUpTo,
restoreEquip.
Fixed: ToolEquip forces CanBeDropped=false on cloned creator templates.
Demo: stone_knife + raw_meat (risky raw: Hunger -25, Poison +8), boar carcass,
multi-objective hunt_boar quest, hunter/butcher/hard_way achievements. Docs:
mobs.md butchering section + loot-bags.md; CHANGELOG; site card copy.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Quests (#10): a Quests registry + server runtime — objectives (gather/craft/
kill/use × count, blank target = any) and rewards, autoStart + requires chains
(completing a prerequisite auto-starts dependents), optional turn-in at a
tagged QuestGiver (component + prompt). Rewards are never lost: a full
inventory parks the quest as ready and the grant retries on inventory change.
Quests menu tab (L) with per-objective progress bars; QuestLog JSON attribute
replicates state; quest:started/progress/completed/blocked via Hooks + bus.
Achievements: an always-on runtime for the existing registry, ported
architecturally from TCE. A shared Progression layer translates bus events
into auto-derived counters (gathers_reed, crafts_total, kills_husk, …) so a
def is just { key, name, counter, threshold } — flat in code and no-code.
Unlock-once + toast + Achievements tab (J) with progress bars.
Toasts: themed top-right notification queue (Notify remote + Toasts.show).
No-code: admin plugin gains Quests (single-objective + "+ Quest giver" drop)
and Achievements (counter/threshold) editors; the engine loads both from
SurvivorCoreContent. Demo: a 3-quest chain + 4 achievements + a giver post.
Fixed: registerPanel now ADOPTS a template-scaffolded tab (hides the
placeholder, builds into the authored frame) instead of silently no-opping —
this replaces the Quests/Achievements "coming soon" placeholders.
EventBridge parity: gather:*, craft:* and item:use now also cross the bus.
Changed: rojo 7.6.1 → 7.7.0 (rokit pin; CI follows; gate verified).
Docs: quests.md + achievements.md (new), content-authoring/admin-plugin/
extending/README updated, CHANGELOG Unreleased, site feature card.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Server-authoritative slots+weight inventory, a 9-slot hotbar (keys 1-9),
equipment slots, and a restyleable tabbed menu (functional Inventory +
Character Sheet; Codex/Achievements/Quests scaffolded), built the engine's
way: authored ScreenGui templates + attribute-discovering binders, with a
zero-setup fallback.
- Drag-and-drop is driven by a per-frame cursor poll (immune to the grid
ScrollingFrame that swallows InputChanged) with GUI-inset-corrected drop
hit-testing so releases land on the actual slot.
- Menu key defaults to Tab; the engine frees it by disabling the CoreGui
player roster (ReclaimCoreKeys) and moves the chat to bottom-left so it
clears the top-left HUD (Chat config). Toggle ignores focused TextBoxes.
- Consumables apply onConsume via the stat-effects layer + fire item:use;
gather yields flow into the inventory; pickups auto-pin to the hotbar.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add docs/survival-stats.md (the stat model, no-code SurvivalStatsConfig tuning, the
SurvivorStatBar/Stat contract, the Rojo one-way-sync caveat) and cross-link it.
CHANGELOG Unreleased entry. CI + CONTRIBUTING now run stylua/luau-lsp over assets/
so the HUD loader is checked.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
CONTRIBUTING mirrors FediHome's structure for the Roblox stack: prerequisites
(Studio + Rojo plugin 7.6.1, rokit, wally), local dev, code style (no hardcoded
asset IDs, content via register()/components, content-free core), the dev/main
branching model, PR flow, changelog rule, and label conventions. Seed
CHANGELOG.md (Keep a Changelog) with Unreleased + a 0.1.0 foundation entry. Add
getting-started (Rojo+Wally and drop-in .rbxm) and extending (register() API,
components, Hooks) guides; cross-link from architecture.md.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>