From 4a2f8387c09fd43fe5b0c1a0e4420bb266ee3f4b Mon Sep 17 00:00:00 2001 From: nak Date: Thu, 19 Mar 2026 03:17:54 +0000 Subject: [PATCH] Fix poker table spawn and deletion --- scripts/poker-admin-tablet.js | 93 ++++++++++++++++++++++++++++------- tablet/poker-admin.html | 14 ++++-- 2 files changed, 86 insertions(+), 21 deletions(-) diff --git a/scripts/poker-admin-tablet.js b/scripts/poker-admin-tablet.js index adbf5cd..62438b9 100644 --- a/scripts/poker-admin-tablet.js +++ b/scripts/poker-admin-tablet.js @@ -17,61 +17,81 @@ var webEventHandler = function(data) { try { var msg = JSON.parse(data); + if (msg.type === "ready") { - var username = AccountServices.username || ""; tablet.emitScriptEvent(JSON.stringify({ type: "init", - username: username, + username: AccountServices.username || "", position: MyAvatar.position, rotation: MyAvatar.orientation, })); + } else if (msg.type === "getPosition") { - // Tablet can request a fresh position snapshot any time tablet.emitScriptEvent(JSON.stringify({ type: "position", position: MyAvatar.position, rotation: MyAvatar.orientation, })); + } else if (msg.type === "spawnSeats") { - // HTML side has confirmed table created, now spawn seat pads in world - spawnSeatPads(msg.tableEntityID, msg.pokerID, msg.seatCount, - msg.position, msg.rotation); + spawnTable(msg.pokerID, msg.seatCount, msg.position, msg.rotation); + + } else if (msg.type === "deleteTable") { + deleteTableEntities(msg.pokerID); } + } catch(e) { print("[pokerAdmin] web event error: " + e); } }; - function spawnSeatPads(tableEntityID, pokerID, seatCount, position, rotation) { + function spawnTable(pokerID, seatCount, avatarPosition, avatarRotation) { var constants = Script.require(Script.resolvePath("poker_constants.js")); var layout = constants.POKER_SEATS[seatCount]; if (!layout) { print("[pokerAdmin] no layout for seatCount=" + seatCount); + tablet.emitScriptEvent(JSON.stringify({ + type: "spawnError", + error: "No seat layout for seatCount=" + seatCount, + })); return; } - // Spawn the table model entity first + // Place table in front of avatar at floor level + // Use only the yaw component of avatar rotation so table sits flat + var yaw = Quat.safeEulerAngles(avatarRotation).y; + var tableRot = Quat.fromPitchYawRollDegrees(0, yaw, 0); + + // 2.5m in front of avatar, snapped to floor (y: -0.45 relative to avatar) + var forward = Vec3.multiplyQbyV(tableRot, { x: 0, y: 0, z: -2.5 }); + var tablePos = { + x: avatarPosition.x + forward.x, + y: avatarPosition.y - 0.45, + z: avatarPosition.z + forward.z, + }; + + // Spawn table model — natural dimensions, not squished var tableID = Entities.addEntity({ type: "Model", name: "poker_table_" + pokerID, modelURL: constants.POKER_TABLE_MODEL_URL, - position: position, - rotation: rotation, - dimensions: { x: 3.0, y: 1.0, z: 3.0 }, + position: tablePos, + rotation: tableRot, + naturalDimensions: true, userData: JSON.stringify({ pokerID: pokerID, seatCount: seatCount, }), grabbable: false, + locked: true, }); - print("[pokerAdmin] spawned table entity " + tableID); + print("[pokerAdmin] spawned table entity " + tableID + " for " + pokerID); - // Spawn a seat pad for each seat + // Spawn seat pads as children of the table entity + // Offsets are in table-local space so no world transform needed for (var i = 0; i < seatCount; i++) { var seat = layout[i]; - var worldOffset = Vec3.multiplyQbyV(rotation, seat.offset); - var seatPos = Vec3.sum(position, worldOffset); var seatRot = Quat.fromPitchYawRollDegrees(0, seat.yaw, 0); Entities.addEntity({ @@ -80,8 +100,9 @@ imageURL: constants.POKER_SEAT_PAD.imageURL, dimensions: constants.POKER_SEAT_PAD.dimensions, alpha: constants.POKER_SEAT_PAD.alpha, - position: seatPos, - rotation: seatRot, + parentID: tableID, + localPosition: seat.offset, + localRotation: seatRot, script: "https://wizards.cyou/scripts/poker_sit.js", userData: JSON.stringify({ tableID: tableID, @@ -91,9 +112,10 @@ triggerable: true, grabbable: false, ignorePickIntersection: false, + locked: true, }); - print("[pokerAdmin] spawned seat " + i + " for table " + pokerID); + print("[pokerAdmin] spawned seat " + i + " parented to " + tableID); } tablet.emitScriptEvent(JSON.stringify({ @@ -102,6 +124,41 @@ })); } + function deleteTableEntities(pokerID) { + // Find table entity by name + var results = Entities.findEntitiesByName( + "poker_table_" + pokerID, MyAvatar.position, 100, false + ); + + if (results.length === 0) { + print("[pokerAdmin] no entities found for table " + pokerID); + tablet.emitScriptEvent(JSON.stringify({ + type: "deleteEntitiesComplete", + pokerID: pokerID, + found: false, + })); + return; + } + + results.forEach(function(tableEntityID) { + // Find and delete all children (seat pads) + var children = Entities.getChildrenIDs(tableEntityID); + children.forEach(function(childID) { + Entities.deleteEntity(childID); + print("[pokerAdmin] deleted seat entity " + childID); + }); + // Delete the table itself + Entities.deleteEntity(tableEntityID); + print("[pokerAdmin] deleted table entity " + tableEntityID); + }); + + tablet.emitScriptEvent(JSON.stringify({ + type: "deleteEntitiesComplete", + pokerID: pokerID, + found: true, + })); + } + button.clicked.connect(function() { tablet.gotoWebScreen(APP_URL); tablet.webEventReceived.connect(webEventHandler); diff --git a/tablet/poker-admin.html b/tablet/poker-admin.html index bf84c2c..36d8e24 100644 --- a/tablet/poker-admin.html +++ b/tablet/poker-admin.html @@ -487,10 +487,11 @@ function renderTables(tables) { } function deleteTable(id) { - ensureSession(function(err) { if (err) { setStatus(err, "error"); return; } setStatus("Deleting " + id + "..."); + + // Delete server-side first fetch(POKER_BASE + "/admin/tables/" + id, { method: "DELETE", headers: { "Authorization": "Bearer " + state.token }, @@ -500,8 +501,11 @@ function deleteTable(id) { return r.json(); }) .then(function() { - setStatus("Table " + id + " deleted", "ok"); - loadTables(); + // Then clean up in-world entities + EventBridge.emitWebEvent(JSON.stringify({ + type: "deleteTable", + pokerID: id, + })); }) .catch(function(e) { setStatus(e.message, "error"); }); }); @@ -535,6 +539,10 @@ function init() { } else if (msg.type === "spawnComplete") { setStatus("Table and seats spawned!", "ok"); document.getElementById("btn-create").disabled = false; + } else if (msg.type === "deleteEntitiesComplete") { + var detail = msg.found ? "Table and entities deleted" : "Table deleted (no entities found)"; + setStatus(detail, "ok"); + loadTables(); } } catch(e) { print("poker-admin event error: " + e);