diff --git a/app.py b/app.py index 3fb0120..73d61e4 100644 --- a/app.py +++ b/app.py @@ -326,6 +326,8 @@ class Handler(BaseHTTPRequestHandler): if path == "/api/order": return game.post_order(world, player, body.get("kind"), str(item), qty, body.get("provide"), body.get("reward"), now) + if path == "/api/order/provide": + return game.provide_reagent(world, player, body.get("id"), str(item)) if path == "/api/order/cancel": return game.cancel_order(world, player, body.get("id"), now) if path == "/api/order/work": diff --git a/game.py b/game.py index 5a2ddad..3b6d093 100644 --- a/game.py +++ b/game.py @@ -2125,6 +2125,22 @@ def post_order(world: dict, player: dict, kind: str, item: str, qty, provide, re return None +def provide_reagent(world: dict, player: dict, order_id, item: str) -> str | None: + """Put a reagent into your own order after posting it, enough for what's still to be made.""" + order = order_by_id(world, order_id) + if not order or order["by"] != player["id"] or order["status"] != "open" or order["kind"] != "craft": + return "No such order" + action = ACTION_BY_ID[order["action"]] + if item not in action["inputs"] or item in order["provided"]: + return "Already provided" if item in order["provided"] else "That isn't in the recipe" + need = action["inputs"][item] * _batches(action, order["item"], order["qty"] - order["delivered"]) + if player["bank"].get(item, 0) < need: + return f"{ITEMS[item]['name']}: {player['bank'].get(item, 0)} / {need}" + bank_take(player, item, need) + order["provided"][item] = need + return None + + def _refund(world: dict, order: dict, now: float) -> None: owner = world["players"].get(order["by"]) if not owner: diff --git a/static/app.js b/static/app.js index dabf582..b96874b 100644 --- a/static/app.js +++ b/static/app.js @@ -90,7 +90,7 @@ async function refresh() { function accept(state) { version ??= state.version; - if (state.version !== version && !document.querySelector("[data-keep]:focus") && $("#modal").hidden) { + if (state.version !== version && !document.querySelector("[data-keep]:focus") && $("#modal").hidden && !draft) { location.reload(); // a new build was deployed return; } @@ -1197,8 +1197,12 @@ function orderSlots(o) { ${fmt(per * all)}✓`; } const need = per * (o.status === "open" ? left : all), have = S.me.bank[id] || 0; - return `
${item(id).icon} - ${o.by === S.uid ? `×${fmt(need)}` : `${fmt(have)} / ${fmt(need)}`}
`; + // On your own open order, an empty slot can still be filled from your bank. + const fill = o.by === S.uid && o.status === "open"; + return `
${fill + ? `` + : `${item(id).icon}`} + ${o.status !== "open" ? `×${fmt(need)}` : `${fmt(have)} / ${fmt(need)}`}
`; }).join(""); } @@ -1614,6 +1618,7 @@ document.addEventListener("click", (e) => { if (d.orderDrop) return act("/api/order/drop", { id: Number(d.orderDrop) }); if (d.orderDeliver) return act("/api/order/deliver", { id: Number(d.orderDeliver) }); if (d.orderCancel) return act("/api/order/cancel", { id: Number(d.orderCancel) }); + if (d.orderFill) return act("/api/order/provide", { id: Number(d.orderFill), item: d.item }); if (d.doll) { dollPick = dollPick === d.doll ? null : d.doll; return render(); diff --git a/tests/test_game.py b/tests/test_game.py index 367d8d9..5dd9d0a 100644 --- a/tests/test_game.py +++ b/tests/test_game.py @@ -1580,3 +1580,16 @@ class WorkOrderTest(unittest.TestCase): game.expire_orders(self.world, T0 + 4 * game.DAY) self.assertEqual(self.mike["gold"], 200) self.assertEqual(self.mike["bank"]["iron_bar"], 3) + + def test_requester_can_fill_a_slot_after_posting(self): + self.mike["gold"] = 200 + self.mike["bank"] = {"iron_bar": 3, "clay_core": 3} + game.post_order(self.world, self.mike, "craft", "iron_warhammer", 1, [], 140, T0) + order = self.world["orders"][0] + self.assertIsNone(game.provide_reagent(self.world, self.mike, order["id"], "iron_bar")) + self.assertEqual(order["provided"], {"iron_bar": 3}) + self.fred["bank"] = {"oak_plank": 1, "clay_core": 3} + self.assertIsNone(game.work_order(self.world, self.fred, order["id"], T0)) + game.process_player(self.world, self.fred, T0 + 600, random.Random(1)) + self.assertEqual(self.mike["bank"].get("iron_warhammer"), 1) + self.assertEqual(self.fred["bank"], {}) # used his own plank and cores, never needed bars