feat(vagrant): v0.16.0 stone-age tech chain (knap/twist/haft → stone_axe); fix crafting manifest.lib to 0.3.0

This commit is contained in:
calic
2026-07-28 11:38:23 +00:00
parent 8994b24567
commit ff9d50937d
3 changed files with 122 additions and 5 deletions

View File

@@ -8,11 +8,19 @@ callback, foot-body-orientation ("tactical twist"), scale-deformation walk
cycle, and inheritance-decoupled foot sprites. End-to-end inventory pickup/drop cycle, and inheritance-decoupled foot sprites. End-to-end inventory pickup/drop
demo: pick up a rock into a backpack container, drop it back into the world. demo: pick up a rock into a backpack container, drop it back into the world.
**Version:** 0.15.0 **Version:** 0.16.0
**Module-ID:** vagrant-skeleton **Module-ID:** vagrant-skeleton
**Requires:** lib-core.input >=0.4.0, lib-core.camera >=0.3.0, lib-core.render >=0.2.0, lib-core.maps >=0.1.2, lib-core.puppet >=0.4.4, lib-core.interaction >=0.1.0, lib-core.composition >=0.3.0, lib-core.actor >=0.1.0, lib-core.inventory-list >=0.1.0, lib-core.panel >=0.2.0, lib-core.inventory-list-display >=0.1.0, lib-core.notify >=0.1.0, lib-core.notify-display >=0.1.0, lib-core.world-overlay >=0.1.0, lib-core.crafting >=0.3.0, lib-core.crafting-display >=0.2.0, lib-asset.prototype-subterrain >=0.2.0, lib-asset.prototype-tc-basics >=0.1.0 **Requires:** lib-core.input >=0.4.0, lib-core.camera >=0.3.0, lib-core.render >=0.2.0, lib-core.maps >=0.1.2, lib-core.puppet >=0.4.4, lib-core.interaction >=0.1.0, lib-core.composition >=0.3.0, lib-core.actor >=0.1.0, lib-core.inventory-list >=0.1.0, lib-core.panel >=0.2.0, lib-core.inventory-list-display >=0.1.0, lib-core.notify >=0.1.0, lib-core.notify-display >=0.1.0, lib-core.world-overlay >=0.1.0, lib-core.crafting >=0.3.0, lib-core.crafting-display >=0.2.0, lib-asset.prototype-subterrain >=0.2.0, lib-asset.prototype-tc-basics >=0.1.0
**Tags:** test-chamber, puppet, walking-sim, interaction **Tags:** test-chamber, puppet, walking-sim, interaction
> **v0.16.0:** Stone-Age tech chain — a self-bootstrapping crafting graph on
> the v0.3 API. `knap_sharp_stone` (rock → sharp_stone, bare-handed) yields a
> cutting tool that feeds BOTH `saw_planks` (as the non-consumed tool) AND
> `craft_stone_axe`. `twist_cordage` (3× plant_fiber → cordage) + the axe haft
> (`sharp_stone + stick + cordage → stone_axe`, carries `affordance.chopping`).
> Three plant fibers spawn in the world. Validated headless end-to-end incl. the
> knap→saw and knap→haft connections.
>
> **v0.15.0:** First consumer of `lib-core.crafting` v0.3.0 (ADR-0055). New > **v0.15.0:** First consumer of `lib-core.crafting` v0.3.0 (ADR-0055). New
> stone-age slice: a **Log** (heavy wood item) + a **Sharp Stone** (cutting > stone-age slice: a **Log** (heavy wood item) + a **Sharp Stone** (cutting
> tool) spawn in the world, and the `saw_planks` recipe matches its input by > tool) spawn in the world, and the `saw_planks` recipe matches its input by

115
init.lua
View File

@@ -251,6 +251,23 @@ composition.define_template{
tags = {"renderable", "item"}, tags = {"renderable", "item"},
} }
-- `plant_fiber` is a light gatherable; three twist into cordage (binding).
composition.define_template{
id = "plant_fiber",
properties = {
stack_mode = "individual",
name = "Plant Fiber",
description = "A strand of tough plant fiber. Twist several into cordage.",
weight = 0.05,
volume = 0.0002,
["composition.fiber"] = 1.0,
sprite_atlas = "",
sprite_uv = {x = 0, y = 0, w = 1, h = 1},
position = {x = 0, y = 0},
},
tags = {"renderable", "item"},
}
-- NOTE: Crafted-output templates (rock_pick, rock_pile) are defined inside -- NOTE: Crafted-output templates (rock_pick, rock_pile) are defined inside
-- M.init rather than at top-level, because their sprite_atlas defaults need -- M.init rather than at top-level, because their sprite_atlas defaults need
-- the resolved blob_rect_stone PNG path. Crafting calls composition.create -- the resolved blob_rect_stone PNG path. Crafting calls composition.create
@@ -718,6 +735,48 @@ function M.init(ctx)
tags = {"renderable", "item"}, tags = {"renderable", "item"},
} }
-- cordage: crafted from 3 plant_fiber; a binding material for hafting.
local cordage_uv = tc_sprites.sack1
composition.define_template{
id = "cordage",
properties = {
stack_mode = "individual",
name = "Cordage",
description = "A length of twisted plant-fiber cord.",
weight = 0.1,
volume = 0.0003,
["composition.fiber"] = 1.0,
sprite_atlas = tc_atlas_png,
sprite_uv = {x = cordage_uv.x, y = cordage_uv.y, w = cordage_uv.w, h = cordage_uv.h},
sprite_scale = tc_scale,
position = {x = 0, y = 0},
},
tags = {"renderable", "item"},
}
-- stone_axe: hafted tool (sharp_stone head + stick haft + cordage binding).
-- Carries affordance.chopping for future wood-felling recipes.
local axe_uv = tc_sprites.spade
composition.define_template{
id = "stone_axe",
properties = {
stack_mode = "individual",
name = "Stone Axe",
description = "A hafted stone axe. Chops wood.",
weight = 1.8,
volume = 0.0012,
["composition.stone"] = 0.6,
["composition.wood"] = 0.3,
["composition.fiber"] = 0.1,
["affordance.chopping"] = true,
sprite_atlas = tc_atlas_png,
sprite_uv = {x = axe_uv.x, y = axe_uv.y, w = axe_uv.w, h = axe_uv.h},
sprite_scale = tc_scale,
position = {x = 0, y = 0},
},
tags = {"renderable", "item"},
}
-- Workbench-Template (Phase D v0.2). Container-kind=list so it can -- Workbench-Template (Phase D v0.2). Container-kind=list so it can
-- accept items via inventory.add (crafting output landing spot). -- accept items via inventory.add (crafting output landing spot).
-- Placeholder visual re-uses the blob_rect_stone atlas with -- Placeholder visual re-uses the blob_rect_stone atlas with
@@ -813,6 +872,23 @@ function M.init(ctx)
}, },
} }
register_pickup(state.sharp_stone) register_pickup(state.sharp_stone)
-- Three plant fibers (twist into cordage → haft a stone axe).
state.fibers = {}
local fiber_uv = tc_sprites.sack1
for i = 1, 3 do
local f = composition.create{
template = "plant_fiber",
properties = {
sprite_atlas = tc_atlas_png,
sprite_uv = {x = fiber_uv.x, y = fiber_uv.y, w = fiber_uv.w, h = fiber_uv.h},
sprite_scale = tc_scale * 0.6,
position = {x = LOG_X - 60, y = LOG_Y - 100 + (i - 1) * 28},
},
}
register_pickup(f)
state.fibers[i] = f
end
if CI_FRAME_PERF then engine.print("vagrant: stoneage_spawned") end if CI_FRAME_PERF then engine.print("vagrant: stoneage_spawned") end
-- Workbench spawn (Phase D v0.2). Placed at (350, 380) — 20px above -- Workbench spawn (Phase D v0.2). Placed at (350, 380) — 20px above
@@ -866,6 +942,36 @@ function M.init(ctx)
name = "Saw Planks", name = "Saw Planks",
description = "Saw a wooden log into four planks (needs a cutting edge).", description = "Saw a wooden log into four planks (needs a cutting edge).",
} }
-- ── Stone-Age tech chain (crafting v0.3) ──────────────────────────────
-- Self-bootstrapping graph: knap a rock into a sharp_stone (bare hands),
-- which is then the cutting TOOL for saw_planks AND the head for a
-- stone_axe. Twist plant fibers into cordage, then haft axe = head + stick
-- + cordage. Tier-0 steps need no tool (the bootstrap entry points).
crafting.define_recipe{
id = "knap_sharp_stone",
inputs = { {template = "rock", count = 1} },
outputs = { {template = "sharp_stone", count = 1} },
name = "Knap Sharp Stone",
description = "Strike a rock to flake off a sharp-edged stone.",
}
crafting.define_recipe{
id = "twist_cordage",
inputs = { {template = "plant_fiber", count = 3} },
outputs = { {template = "cordage", count = 1} },
name = "Twist Cordage",
description = "Twist three plant fibers into a length of cordage.",
}
crafting.define_recipe{
id = "craft_stone_axe",
inputs = {
{template = "sharp_stone", count = 1}, -- head (consumed)
{template = "stick", count = 1}, -- haft
{template = "cordage", count = 1}, -- binding
},
outputs = { {template = "stone_axe", count = 1} },
name = "Haft Stone Axe",
description = "Bind a sharp stone to a stick with cordage.",
}
-- v0.14.0: per-recipe icon resolver for the Crafting + Workbench-Crafting -- v0.14.0: per-recipe icon resolver for the Crafting + Workbench-Crafting
-- widgets. Maps recipe.output.template → {atlas, uv} for the icon -- widgets. Maps recipe.output.template → {atlas, uv} for the icon
@@ -874,9 +980,12 @@ function M.init(ctx)
-- domain-free), so the module-side that DEFINES the templates is the -- domain-free), so the module-side that DEFINES the templates is the
-- canonical place to know each output's sprite. -- canonical place to know each output's sprite.
local craft_icons = { local craft_icons = {
rock_pick = { atlas = tc_atlas_png, uv = tc_sprites.spade }, rock_pick = { atlas = tc_atlas_png, uv = tc_sprites.spade },
rock_pile = { atlas = stone_atlas_png, uv = stone_uvs.slot_13_solid }, rock_pile = { atlas = stone_atlas_png, uv = stone_uvs.slot_13_solid },
plank = { atlas = tc_atlas_png, uv = tc_sprites.bench1 }, plank = { atlas = tc_atlas_png, uv = tc_sprites.bench1 },
sharp_stone = { atlas = stone_atlas_png, uv = stone_uvs.slot_13_solid },
cordage = { atlas = tc_atlas_png, uv = tc_sprites.sack1 },
stone_axe = { atlas = tc_atlas_png, uv = tc_sprites.spade },
} }
local function craft_icon_for(recipe) local function craft_icon_for(recipe)
if recipe and recipe.output and recipe.output.template then if recipe and recipe.output and recipe.output.template then

View File

@@ -1,6 +1,6 @@
{ {
"id": "vagrant-skeleton", "id": "vagrant-skeleton",
"version": "0.15.0", "version": "0.16.0",
"kind": "module", "kind": "module",
"api": "^0.1", "api": "^0.1",
"ci_frames": 60, "ci_frames": 60,