feat: v0.12.0 Workbench-Integration

Workbench-Entity bei (350, 380) als Crafting-Context-Erweiterung.
Right-Click oeffnet Workbench-Crafting-Panel + Workbench-Inventory.
Crafting nutzt Multi-Source-Locale {backpack, workbench} mit sink
= workbench; Take-Action verschiebt vom Workbench-Inventory zum
Backpack. C-Key Backpack-Crafting bleibt unveraendert via Bw-
Compat-Shim in crafting v0.2.0.

Deps: crafting 0.1.0 -> 0.2.0, crafting-display 0.1.0 -> 0.2.0.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Axel Meyer
2026-06-14 20:04:04 +02:00
parent f16c8954d9
commit 644bfe98fd
3 changed files with 314 additions and 13 deletions

View File

@@ -8,9 +8,9 @@ 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.11.0 **Version:** 0.12.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.1.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.1.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.1.0, lib-core.crafting-display >=0.1.0, lib-asset.prototype-subterrain >=0.1.0 **Requires:** lib-core.input >=0.4.0, lib-core.camera >=0.3.0, lib-core.render >=0.1.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.1.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.2.0, lib-core.crafting-display >=0.2.0, lib-asset.prototype-subterrain >=0.1.0
**Tags:** test-chamber, puppet, walking-sim, interaction **Tags:** test-chamber, puppet, walking-sim, interaction
## Topology ## Topology
@@ -26,19 +26,21 @@ demo: pick up a rock into a backpack container, drop it back into the world.
- **E** — interact: if within range of the rock or stick, picks it up into the backpack - **E** — interact: if within range of the rock or stick, picks it up into the backpack
- **Q** — quick-drop (LIFO): places the most-recently-added backpack item at player position (+30px right) - **Q** — quick-drop (LIFO): places the most-recently-added backpack item at player position (+30px right)
- **Tab** — toggle inventory panel (Backpack contents) - **Tab** — toggle inventory panel (Backpack contents)
- **C** — toggle Crafting panel (lists known recipes; availability dimmed by inventory) - **C** — toggle Backpack-Crafting panel (lists known recipes; availability dimmed by inventory)
- **Right-Click on item row** (inventory panel): context menu with **Drop** / **Inspect** - **Right-Click on Workbench** (within range) — opens Workbench-Crafting + Workbench-Inventory panels (Phase D v0.2)
- **Right-Click on item row** (inventory panel): context menu with **Drop** / **Inspect** (Backpack) or **Take** / **Inspect** (Workbench)
- **Right-Click on recipe row** (crafting panel): context menu with **Craft** / **Inspect** - **Right-Click on recipe row** (crafting panel): context menu with **Craft** / **Inspect**
- **L** — toggle game-log (chronological list of all events) - **L** — toggle game-log (chronological list of all events)
- **Right-Click on item row → Inspect** — opens a modal Item Details panel (instead of console-only output) - **Right-Click on item row → Inspect** — opens a modal Item Details panel (instead of console-only output)
- **Pickup (E)** — shows "+1 <name>" floating above the player + toast at top-right + log entry - **Pickup (E)** — shows "+1 <name>" floating above the player + toast at top-right + log entry
- **Drop (right-click on item → Drop, or Q for LIFO quick-drop)** — toast at top-right + log entry - **Drop (right-click on item → Drop, or Q for LIFO quick-drop)** — toast at top-right + log entry
- **Craft (right-click on recipe → Craft)** — consumes inputs from backpack, adds output, posts a success/failure toast - **Craft (right-click on recipe → Craft)** — consumes inputs from current locale, adds output, posts a success/failure toast
- **ESC** — return to launcher - **Take (right-click on Workbench-item → Take)** — moves item from Workbench → Backpack + toast
- **ESC** — close any open panel; if no panel is open, return to launcher
## Demo Walkthrough ## Demo Walkthrough
The world contains four notable entities at startup: The world contains five notable entities at startup:
1. **Player** — spawns at (320, 240), controlled via WASD + mouse. 1. **Player** — spawns at (320, 240), controlled via WASD + mouse.
2. **Backpack** — a visible sprite at (350, 400). Acts as a container (kind="list"). 2. **Backpack** — a visible sprite at (350, 400). Acts as a container (kind="list").
@@ -48,6 +50,9 @@ The world contains four notable entities at startup:
4. **Stick** — a placeholder pickup-item at (190, 400), 160px to the left of the backpack. 4. **Stick** — a placeholder pickup-item at (190, 400), 160px to the left of the backpack.
Re-uses the `slot_04_straight` blob_rect_stone tile for its visual (Phase C-Q10 Re-uses the `slot_04_straight` blob_rect_stone tile for its visual (Phase C-Q10
pragmatic resolution — echtes Stick-Sprite folgt mit dem ersten atlas-baker-decals-Slice). pragmatic resolution — echtes Stick-Sprite folgt mit dem ersten atlas-baker-decals-Slice).
5. **Workbench** — a crafting bench at (350, 380), just above the backpack. Container
(kind="list"); placeholder visual re-uses the `slot_07_tee_full` blob_rect_stone tile.
Right-Click within range opens Workbench-Crafting + Workbench-Inventory panels.
**Pickup flow:** **Pickup flow:**
- Walk toward the rock (it sits to the left of the backpack). - Walk toward the rock (it sits to the left of the backpack).
@@ -67,6 +72,21 @@ The world contains four notable entities at startup:
**Multiple pickups:** Each E → Q → E cycle moves the same rock in and out. **Multiple pickups:** Each E → Q → E cycle moves the same rock in and out.
Only one rock is spawned per session. Only one rock is spawned per session.
**Workbench flow (Phase D v0.2):**
- Pick up rock + stick into the backpack (E on each).
- Walk to the Workbench (just above the Backpack at (350, 380)) and
right-click within 40px range.
- Two panels open simultaneously (Workbench-Crafting + Workbench-Inventory).
Because `lib-core.panel` v0.1 is single-active, only one panel is visible
at a time — closing it (X) reveals the other.
- Right-click on a recipe row (e.g. **Stone Pick**) → context menu with
**Craft** + **Inspect**. Click **Craft** → crafted item lands in
**Workbench-Inventory** (NOT Backpack).
- Open Workbench-Inventory, right-click on the crafted item → **Take** moves
it to the Backpack; a "Took <item>" toast appears.
- Crafting inputs are aggregated from `{backpack, workbench}` (drain order:
backpack first, then workbench).
## Demonstrates ## Demonstrates
- lib-core.puppet v0.4.3 integration: - lib-core.puppet v0.4.3 integration:
@@ -121,6 +141,37 @@ Only one rock is spawned per session.
## CHANGELOG ## CHANGELOG
### v0.12.0 — Workbench
- **New: Workbench entity** in the world at (350, 380) — `composition.define_template`
with `container = {kind="list"}`, tagged `renderable`, `container`, `workbench`,
`interactable`. Placeholder visual re-uses the `slot_07_tee_full`
blob_rect_stone tile (visually distinct from rock/stick/rock_pick/rock_pile).
- **New: Right-Click on Workbench** opens two panels:
- **Workbench Crafting** — recipes are still listed by `lib-core.crafting`,
but availability + craft-action use a **multi-source locale**
`{sources={backpack, workbench}, sink=workbench}` (crafting v0.2.0 API).
Inputs are drained greedy in source-array order (backpack first, then
workbench). Output lands in the Workbench, not the Backpack.
- **Workbench Inventory** — workbench contents with **Take** + **Inspect**
actions on right-click. Take moves the item to the Backpack and fires
a `transfer` event-toast.
- **Still works**: C-key Backpack-Crafting (basic recipes still craftable
with Backpack-only via the bw-compat shim in crafting v0.2.0). The
Phase-C C-key callsite passes `state.backpack` as a bare entity-handle;
crafting v0.2.0's resolve_locale wraps that as `{sources={backpack},
sink=backpack}` transparently.
- **Caveat (panel-lib v0.1 single-active)**: `lib-core.panel` v0.1.1
enforces one active widget. Opening both Workbench panels means only
the second (`workbench_inv`) is visible until the player closes it (X);
closing it reveals `workbench_crafting`. Proper side-by-side stacking
is a future panel-lib slice.
- **Deps**: crafting 0.1.0 → 0.2.0, crafting-display 0.1.0 → 0.2.0.
- **Notify events-Channel**: filter um `"transfer"` erweitert, damit
Take-Action-Toasts im events-channel landen.
- **Input binding**: `"use"` bound to `mouse_right` (mirrors the lib-core.input
v0.3.0 unified key+mouse binding).
### v0.11.0 — crafting integration ### v0.11.0 — crafting integration
- **New: stick pickup-item** neben rock am Boden (Position 190,400 — 160px links - **New: stick pickup-item** neben rock am Boden (Position 190,400 — 160px links

256
init.lua
View File

@@ -1,4 +1,4 @@
-- sporel-module-vagrant-skeleton v0.11.0 -- sporel-module-vagrant-skeleton v0.12.0
-- Sprite-mode test-chamber: 13-bone humanoid puppet + sprite-tilemap + -- Sprite-mode test-chamber: 13-bone humanoid puppet + sprite-tilemap +
-- hardcoded furniture. Subterrain-style puppet control model: -- hardcoded furniture. Subterrain-style puppet control model:
-- multi-look-target (aim/soft), slerp body rotation, hip-static legs, -- multi-look-target (aim/soft), slerp body rotation, hip-static legs,
@@ -49,6 +49,17 @@
-- Right-click a recipe row → Craft + Inspect actions; Craft consumes -- Right-click a recipe row → Craft + Inspect actions; Craft consumes
-- inputs from the backpack and adds the output; Inspect routes -- inputs from the backpack and adds the output; Inspect routes
-- recipe details to a notify-display detail-channel. -- recipe details to a notify-display detail-channel.
--
-- v0.12.0: Workbench-Entity added at (350, 380). Right-Click on the
-- workbench opens a Workbench-Crafting panel + Workbench-Inventory
-- panel. The crafting panel uses a multi-source locale {backpack,
-- workbench} via crafting v0.2.0's locale-factory API; output lands
-- in the workbench. Take-action in workbench-inv moves an item back
-- to the backpack. C-key Backpack-Crafting remains via the bw-compat
-- shim in crafting v0.2.0 (Form-1 bare entity-handle stays valid).
-- Panel-lib v0.1 is single-active so opening both panels lets
-- workbench_inv win; user can close it (X) to reveal workbench_crafting
-- below — Gate-2 walkthrough documents the flow.
local input = require("lib-core.input") local input = require("lib-core.input")
local camera = require("lib-core.camera") local camera = require("lib-core.camera")
@@ -196,7 +207,10 @@ local state = {
backpack = nil, -- composition-entity, created in M.init after atlas load backpack = nil, -- composition-entity, created in M.init after atlas load
rock = nil, -- composition-entity (item), created in M.init after blob_rect_stone load rock = nil, -- composition-entity (item), created in M.init after blob_rect_stone load
stick = nil, -- composition-entity (item), placeholder for crafting demo stick = nil, -- composition-entity (item), placeholder for crafting demo
crafting_widget = nil, -- crafting-display widget handle workbench = nil, -- composition-entity (container), Phase D Workbench
crafting_widget = nil, -- crafting-display widget handle (Backpack)
workbench_crafting_widget = nil, -- crafting-display widget handle (Workbench-context)
workbench_inv_widget = nil, -- inventory-list-display widget handle (Workbench-Inv)
-- Subterrain-style controller state: -- Subterrain-style controller state:
walk_anim_current = nil, -- "walk_fwd_lower" / "walk_back_lower" / etc. (nil = idle_lower) walk_anim_current = nil, -- "walk_fwd_lower" / "walk_back_lower" / etc. (nil = idle_lower)
lower_control_rot_deg = 0, lower_control_rot_deg = 0,
@@ -276,6 +290,59 @@ local function register_pickup(item)
end) end)
end end
-- register_interaction_use(entity)
-- Phase D Workbench: registers a right-click ("use") interaction-trigger at
-- the entity's current world position. When the player fires "use" within
-- INTERACTION_RANGE, the callback opens both the Workbench-Crafting and
-- Workbench-Inventory panels.
--
-- lib-core.interaction v0.1.0 is XY-based (not entity-bound); the trigger
-- snapshots the position at registration time. Workbench is static in v0.12
-- so a single registration suffices. Action-name "use" is bound to
-- mouse_right in M.init's input.bind block.
--
-- Note on dual-panel-open: lib-core.panel v0.1.1 enforces a single active
-- widget. Calling panel.open twice means the second call wins
-- (workbench_inv shows on top; workbench_crafting is hidden until the
-- player closes the inv panel via X). This matches the spec §4.4 note that
-- "v0.2 default ist whatever panel-lib default" — proper side-by-side
-- layout is a panel-lib v0.2 task, out of scope for D.2.
local function register_interaction_use(entity)
local x = entity:get_property("position.x")
local y = entity:get_property("position.y")
interaction.register(x, y, INTERACTION_RANGE, "use", function()
panel.open("workbench_crafting")
panel.open("workbench_inv")
if CI_FRAME_PERF then engine.print("vagrant: event=workbench_use") end
end)
end
-- discover_sources(workbench) → array of container entities
-- Phase D v0.2 source-discovery policy: Player-Backpack is always a source
-- (independent of workbench position; player carries it everywhere), and
-- the workbench itself is always a source. Forward-compat stub below
-- documents the intended adjacent-container scan (deferred to a future
-- slice with multi-container demos).
local function discover_sources(workbench)
local sources = { state.backpack, workbench }
-- Forward-compat stub for adjacent-container scan (deferred):
-- for _, ent in ipairs(composition.list_by_tag("container")) do
-- if ent ~= workbench and ent ~= state.backpack then
-- local wx = workbench:get_property("position.x")
-- local wy = workbench:get_property("position.y")
-- local ex = ent:get_property("position.x")
-- local ey = ent:get_property("position.y")
-- if ex and ey and wx and wy then
-- local dx, dy = math.abs(ex - wx), math.abs(ey - wy)
-- if math.max(dx, dy) <= 1 then -- Chebyshev radius 1
-- sources[#sources + 1] = ent
-- end
-- end
-- end
-- end
return sources
end
-- Signed angle between two 2D vectors (in degrees, range [-180, 180]). -- Signed angle between two 2D vectors (in degrees, range [-180, 180]).
-- Sporel uses Y-down screen-coords. Substrate's math assumes Y-up; the cross -- Sporel uses Y-down screen-coords. Substrate's math assumes Y-up; the cross
-- component is flipped so "positive num = move-direction is CCW from body-fwd -- component is flipped so "positive num = move-direction is CCW from body-fwd
@@ -511,6 +578,34 @@ function M.init(ctx)
tags = {"renderable", "item"}, tags = {"renderable", "item"},
} }
-- Workbench-Template (Phase D v0.2). Container-kind=list so it can
-- accept items via inventory.add (crafting output landing spot).
-- Placeholder visual re-uses the blob_rect_stone atlas with
-- slot_07_tee_full — visually distinct from the slots already taken
-- (00=rock, 04=stick, 05=rock_pick, 13=rock_pile). slot_07 is a
-- filled T-junction shape — dense + asymmetric, reads as a sturdy
-- piece of furniture against the rest of the in-world items. A
-- proper sprite would come from atlas-baker-decals in a future slice.
local workbench_uv = stone_uvs["slot_07_tee_full"]
composition.define_template{
id = "workbench",
properties = {
stack_mode = "individual",
name = "Workbench",
description = "A crafting bench.",
weight = 50,
volume = 100,
["composition.wood"] = 0.7,
["composition.stone"] = 0.3,
sprite_atlas = stone_atlas_png,
sprite_uv = {x = workbench_uv.x, y = workbench_uv.y,
w = workbench_uv.w, h = workbench_uv.h},
position = {x = 0, y = 0},
},
container = { kind = "list" },
tags = { "renderable", "container", "workbench", "interactable" },
}
-- Spawn Rock-Entity 80px to the left of the backpack so it sits in a -- Spawn Rock-Entity 80px to the left of the backpack so it sits in a
-- distinct position: visible to the player on first load, not overlapping -- distinct position: visible to the player on first load, not overlapping
-- the backpack, reachable by walking left from spawn. -- the backpack, reachable by walking left from spawn.
@@ -546,6 +641,18 @@ function M.init(ctx)
register_pickup(state.stick) register_pickup(state.stick)
if CI_FRAME_PERF then engine.print("vagrant: stick_spawned") end if CI_FRAME_PERF then engine.print("vagrant: stick_spawned") end
-- Workbench spawn (Phase D v0.2). Placed at (350, 380) — 20px above
-- the backpack (at 350, 400) so they are visually distinct but still
-- on the visible-on-spawn area. register_interaction_use registers a
-- right-click ("use") proximity-trigger at the workbench position.
state.workbench = composition.create{
template = "workbench",
properties = {
position = {x = 350, y = 380},
},
}
if CI_FRAME_PERF then engine.print("vagrant: workbench_spawned") end
-- ====== Crafting Recipes ====== -- ====== Crafting Recipes ======
crafting.define_recipe{ crafting.define_recipe{
id = "rock_pick", id = "rock_pick",
@@ -692,12 +799,154 @@ function M.init(ctx)
panel.register("crafting", state.crafting_widget) panel.register("crafting", state.crafting_widget)
panel.bind_default_trigger("c", "crafting") panel.bind_default_trigger("c", "crafting")
-- ====== Workbench Crafting Widget (Phase D v0.2) ======
-- Locale-Factory returns Form-2 locale {sources, sink}: sources come
-- from discover_sources (player-backpack + workbench), sink is the
-- workbench. Crafting v0.2.0 greedy-drains sources in array-order
-- (backpack first, then workbench) before adding the output to sink.
state.workbench_crafting_widget = crafting_display.create(
function()
return {
sources = discover_sources(state.workbench),
sink = state.workbench,
}
end,
{
title = "Workbench Crafting",
widget_id = "workbench_crafting",
pause_on_open = false,
ctx_factory = function()
return { actor = state.actor, at_workbench = true }
end,
})
-- Craft action: invokes crafting.craft on the resolved locale (multi-
-- source), posts a success or warning toast. ctx_inner.locale carries
-- the per-frame-resolved Form-2 locale; we forward it verbatim.
crafting_display.register_action(state.workbench_crafting_widget,
"Craft", function(recipe_id, ctx_inner)
local r = crafting.craft(recipe_id, ctx_inner.locale,
{ actor = state.actor, at_workbench = true })
if r.ok then
local recipe = crafting.get_recipe(recipe_id)
notify.post{
tags = {"craft", "event"},
text = "Crafted " .. (recipe.name or recipe_id),
severity = "info",
}
if CI_FRAME_PERF then
engine.print("vagrant: event=craft_ok recipe=" .. recipe_id
.. " at_workbench=1")
end
else
local msg
if r.error == "missing_inputs" then
msg = "Missing inputs"
else
msg = "Cannot craft: " .. tostring(r.error)
end
notify.warn({"craft", "event"}, msg)
if CI_FRAME_PERF then
engine.print("vagrant: event=craft_fail recipe=" .. recipe_id
.. " error=" .. tostring(r.error)
.. " at_workbench=1")
end
end
ctx_inner.close_menu()
end)
-- Inspect action: routes recipe details to the notify detail-channel
-- (same pattern as backpack-crafting Inspect).
crafting_display.register_action(state.workbench_crafting_widget,
"Inspect", function(recipe_id, ctx_inner)
local recipe = crafting.get_recipe(recipe_id)
local lines = {
recipe.name or recipe.id,
"",
recipe.description or "",
"",
"Inputs:",
}
for _, inp in ipairs(recipe.inputs) do
lines[#lines + 1] = " " .. inp.template
.. " \xc3\x97 " .. inp.count
end
lines[#lines + 1] = ""
lines[#lines + 1] = "Output: " .. recipe.output.template
.. " \xc3\x97 " .. recipe.output.count
notify.post{
tags = {"inspect", "detail"},
text = table.concat(lines, "\n"),
severity = "info",
}
ctx_inner.close_menu()
end)
panel.register("workbench_crafting", state.workbench_crafting_widget)
-- KEIN bind_default_trigger: trigger is the workbench right-click via
-- register_interaction_use(state.workbench) below.
-- ====== Workbench Inventory Widget (Phase D v0.2) ======
state.workbench_inv_widget = inv_display.create(state.workbench, {
title = "Workbench Inventory",
widget_id = "workbench_inv",
pause_on_open = false,
})
-- Take action: moves an item from workbench → backpack via
-- inventory.remove + inventory.add. Posts a transfer-event toast.
inv_display.register_action(state.workbench_inv_widget, "Take",
function(item, c)
inventory.remove(state.workbench, item)
inventory.add(state.backpack, item)
notify.post{
tags = {"transfer", "event"},
text = "Took " .. (item:get_property("name")
or composition.template_of(item) or "item"),
severity = "info",
}
c.close_menu()
if CI_FRAME_PERF then engine.print("vagrant: event=take") end
if c.refresh then c.refresh() end
end)
-- Inspect action: mirrors the backpack-inv Inspect so that workbench
-- contents have the same detail-modal payload (name + description +
-- weight + volume + composition.* materials).
inv_display.register_action(state.workbench_inv_widget, "Inspect",
function(item, c)
local props = item:get_properties()
local comp = {}
for k, v in pairs(props) do
local mat = k:match("^composition%.(.+)$")
if mat and mat ~= "reg_id" then comp[mat] = v end
end
notify.post{
tags = {"inspect"},
text = item:get_property("name") or "(unnamed)",
data = {
description = item:get_property("description"),
weight = item:get_property("weight"),
volume = item:get_property("volume"),
composition = comp,
},
}
c.close_menu()
end)
panel.register("workbench_inv", state.workbench_inv_widget)
-- Right-click trigger registered AFTER both workbench widgets are
-- panel.register'd; the callback panel.open()s them by id, so they
-- must already be in the panel registry.
register_interaction_use(state.workbench)
-- ====== Notification System Setup ====== -- ====== Notification System Setup ======
-- Channels (created BEFORE display attach + widget register) -- Channels (created BEFORE display attach + widget register)
notify.create_channel{ id = "inspect", filter = {"inspect"}, notify.create_channel{ id = "inspect", filter = {"inspect"},
display_mode = "detail" } display_mode = "detail" }
notify.create_channel{ id = "events", filter = {"pickup", "drop", "craft"}, notify.create_channel{ id = "events", filter = {"pickup", "drop", "craft", "transfer"},
display_mode = "toast" } display_mode = "toast" }
notify.create_channel{ id = "log", filter = {}, -- catch-all notify.create_channel{ id = "log", filter = {}, -- catch-all
display_mode = "log" } display_mode = "log" }
@@ -726,6 +975,7 @@ function M.init(ctx)
input.bind("walk_down", { "s" }) input.bind("walk_down", { "s" })
input.bind("sprint", { "shift" }) -- held while walking → 2x speed input.bind("sprint", { "shift" }) -- held while walking → 2x speed
input.bind("interact", { "e" }) -- fires nearest proximity-trigger input.bind("interact", { "e" }) -- fires nearest proximity-trigger
input.bind("use", { "mouse_right" }) -- Phase D right-click "use" trigger (workbench)
input.bind("drop", { "q" }) -- drop most-recent item from backpack input.bind("drop", { "q" }) -- drop most-recent item from backpack
input.bind("quit_to_launcher", { "escape" }) input.bind("quit_to_launcher", { "escape" })

View File

@@ -1,6 +1,6 @@
{ {
"id": "vagrant-skeleton", "id": "vagrant-skeleton",
"version": "0.11.0", "version": "0.12.0",
"kind": "module", "kind": "module",
"api": "^0.1", "api": "^0.1",
"ci_frames": 60, "ci_frames": 60,
@@ -26,8 +26,8 @@
{"id": "lib-core.puppet", "version": "0.5.0"}, {"id": "lib-core.puppet", "version": "0.5.0"},
{"id": "lib-core.interaction", "version": "0.1.0"}, {"id": "lib-core.interaction", "version": "0.1.0"},
{"id": "lib-core.inventory-list", "version": "0.1.0"}, {"id": "lib-core.inventory-list", "version": "0.1.0"},
{"id": "lib-core.crafting", "version": "0.1.0"}, {"id": "lib-core.crafting", "version": "0.2.0"},
{"id": "lib-core.crafting-display", "version": "0.1.0"}, {"id": "lib-core.crafting-display", "version": "0.2.0"},
{"id": "lib-asset.prototype-subterrain", "version": "0.2.0"}, {"id": "lib-asset.prototype-subterrain", "version": "0.2.0"},
{"id": "lib-asset.prototype-blob-geom", "version": "0.1.0"} {"id": "lib-asset.prototype-blob-geom", "version": "0.1.0"}
] ]