overte-www/scripts/poker-admin-tablet.js

188 lines
6.5 KiB
JavaScript
Raw Normal View History

2026-03-19 02:01:23 +00:00
(function() {
2026-03-19 02:31:12 +00:00
var ADMIN_USER = "nak";
if (AccountServices.username !== ADMIN_USER) {
return;
}
var APP_NAME = "POKER";
2026-03-19 02:01:23 +00:00
var APP_URL = "https://wizards.cyou/tablet/poker-admin.html";
var APP_ICON = "https://wizards.cyou/tablet/poker-admin-icon.svg";
var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system");
var button = tablet.addButton({
text: APP_NAME,
icon: APP_ICON
});
var webEventHandler = function(data) {
try {
var msg = JSON.parse(data);
2026-03-19 03:17:54 +00:00
2026-03-19 02:01:23 +00:00
if (msg.type === "ready") {
tablet.emitScriptEvent(JSON.stringify({
type: "init",
2026-03-19 03:17:54 +00:00
username: AccountServices.username || "",
2026-03-19 02:01:23 +00:00
position: MyAvatar.position,
rotation: MyAvatar.orientation,
}));
2026-03-19 03:17:54 +00:00
2026-03-19 02:01:23 +00:00
} else if (msg.type === "getPosition") {
tablet.emitScriptEvent(JSON.stringify({
type: "position",
position: MyAvatar.position,
rotation: MyAvatar.orientation,
}));
2026-03-19 03:17:54 +00:00
2026-03-19 02:01:23 +00:00
} else if (msg.type === "spawnSeats") {
2026-03-19 03:17:54 +00:00
spawnTable(msg.pokerID, msg.seatCount, msg.position, msg.rotation);
} else if (msg.type === "deleteTable") {
deleteTableEntities(msg.pokerID);
2026-03-19 02:01:23 +00:00
}
2026-03-19 03:17:54 +00:00
2026-03-19 02:01:23 +00:00
} catch(e) {
print("[pokerAdmin] web event error: " + e);
}
};
2026-03-19 03:17:54 +00:00
function spawnTable(pokerID, seatCount, avatarPosition, avatarRotation) {
2026-03-19 02:01:23 +00:00
var constants = Script.require(Script.resolvePath("poker_constants.js"));
var layout = constants.POKER_SEATS[seatCount];
if (!layout) {
print("[pokerAdmin] no layout for seatCount=" + seatCount);
2026-03-19 03:17:54 +00:00
tablet.emitScriptEvent(JSON.stringify({
type: "spawnError",
error: "No seat layout for seatCount=" + seatCount,
}));
2026-03-19 02:01:23 +00:00
return;
}
2026-03-19 03:17:54 +00:00
// 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;
2026-03-20 08:02:39 +00:00
var tableRot = Quat.fromPitchYawRollDegrees(0, yaw, 0);
2026-03-19 03:17:54 +00:00
2026-03-19 04:30:12 +00:00
// 2.5m in front of avatar, snapped to floor
2026-03-19 03:17:54 +00:00
var forward = Vec3.multiplyQbyV(tableRot, { x: 0, y: 0, z: -2.5 });
var tablePos = {
x: avatarPosition.x + forward.x,
2026-03-19 04:30:12 +00:00
y: -0.45,
2026-03-19 03:17:54 +00:00
z: avatarPosition.z + forward.z,
};
// Spawn table model — natural dimensions, not squished
2026-03-19 02:01:23 +00:00
var tableID = Entities.addEntity({
type: "Model",
name: "poker_table_" + pokerID,
modelURL: constants.POKER_TABLE_MODEL_URL,
2026-03-19 03:17:54 +00:00
position: tablePos,
rotation: tableRot,
naturalDimensions: true,
2026-03-19 03:39:16 +00:00
registrationPoint: { x: 0.5, y: 0, z: 0.5 },
2026-03-19 02:01:23 +00:00
userData: JSON.stringify({
pokerID: pokerID,
seatCount: seatCount,
}),
grabbable: false,
2026-03-19 05:05:37 +00:00
locked: false,
2026-03-19 02:01:23 +00:00
});
2026-03-20 08:02:39 +00:00
// Timeout to set locked true after displaying mesh in world
2026-03-19 05:05:37 +00:00
Script.setTimeout(function() {
Entities.editEntity(tableID, { locked: true });
}, 2000);
2026-03-19 03:17:54 +00:00
print("[pokerAdmin] spawned table entity " + tableID + " for " + pokerID);
2026-03-19 02:01:23 +00:00
2026-03-19 03:17:54 +00:00
// Spawn seat pads as children of the table entity
// Offsets are in table-local space so no world transform needed
2026-03-19 02:01:23 +00:00
for (var i = 0; i < seatCount; i++) {
var seat = layout[i];
2026-03-19 05:28:12 +00:00
var seatRot = Quat.fromPitchYawRollDegrees(-90, seat.yaw, 0);
var seatOffset = {
x: seat.offset.x,
y: seat.offset.y - 0.13,
z: seat.offset.z
};
2026-03-19 02:01:23 +00:00
Entities.addEntity({
type: "Image",
name: "poker_seat_" + pokerID + "_" + i,
imageURL: constants.POKER_SEAT_PAD.imageURL,
dimensions: constants.POKER_SEAT_PAD.dimensions,
alpha: constants.POKER_SEAT_PAD.alpha,
2026-03-19 03:17:54 +00:00
parentID: tableID,
2026-03-19 05:28:12 +00:00
localPosition: seatOffset,
2026-03-19 03:17:54 +00:00
localRotation: seatRot,
2026-03-19 02:01:23 +00:00
script: "https://wizards.cyou/scripts/poker_sit.js",
userData: JSON.stringify({
tableID: tableID,
pokerID: pokerID,
seatIndex: i,
}),
2026-03-20 08:02:39 +00:00
grab: {
triggerable: true,
grabbable: false
},
//grabbable: false,
2026-03-19 02:01:23 +00:00
ignorePickIntersection: false,
2026-03-19 03:17:54 +00:00
locked: true,
2026-03-19 02:01:23 +00:00
});
2026-03-19 03:17:54 +00:00
print("[pokerAdmin] spawned seat " + i + " parented to " + tableID);
2026-03-19 02:01:23 +00:00
}
tablet.emitScriptEvent(JSON.stringify({
type: "spawnComplete",
tableEntityID: tableID,
}));
}
2026-03-19 03:17:54 +00:00
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.editEntity(childID, { locked: false });
2026-03-19 03:17:54 +00:00
Entities.deleteEntity(childID);
print("[pokerAdmin] deleted seat entity " + childID);
});
// Delete the table itself
Entities.editEntity(tableEntityID, { locked: false });
2026-03-19 03:17:54 +00:00
Entities.deleteEntity(tableEntityID);
print("[pokerAdmin] deleted table entity " + tableEntityID);
});
tablet.emitScriptEvent(JSON.stringify({
type: "deleteEntitiesComplete",
pokerID: pokerID,
found: true,
}));
}
2026-03-19 02:01:23 +00:00
button.clicked.connect(function() {
tablet.gotoWebScreen(APP_URL);
tablet.webEventReceived.connect(webEventHandler);
});
Script.scriptEnding.connect(function() {
tablet.removeButton(button);
tablet.webEventReceived.disconnect(webEventHandler);
});
})();