// // sitServer.js // // Created by Robin Wilson 1/17/2019 // // Copyright 2019 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // /* globals Entities Script */ (function () { var DEBUG = true; // Remotely callable // Resolves heartbeat called from sitClient function heartbeatResponse() { if (DEBUG) { console.log("sitServer.js: Heartbeat reply received!"); } // Called by remote client script // indicating avatar is still sitting in chair if (_this.heartbeatRequestTimeout) { Script.clearTimeout(_this.heartbeatRequestTimeout); _this.heartbeatRequestTimeout = false; } if (_this.nextHeartbeatTimeout) { Script.clearTimeout(_this.nextHeartbeatTimeout); _this.nextHeartbeatTimeout = false; } _this.nextHeartbeatTimeout = Script.setTimeout(sendHeartbeatRequest, HEARTBEAT_INTERVAL_TIME_MS); } function sendHeartbeatRequest() { _this.nextHeartbeatTimeout = false; if (_this.isOccupied) { if (DEBUG) { console.log("sitServer.js: heartbeat: `isOccupied` is set to `true`. Sending heartbeatRequest to sitting client..."); } Entities.callEntityClientMethod( _this.currentClientSessionID, _this.entityID, "heartbeatRequest" ); if (_this.heartbeatRequestTimeout) { Script.clearTimeout(_this.heartbeatRequestTimeout); _this.heartbeatRequestTimeout = false; } // If the heartbeatRequest call to the client script does not return heartbeatResponse // Will open the chair to other avatars to sit _this.heartbeatRequestTimeout = Script.setTimeout(function () { if (DEBUG) { console.log("sitServer.js: Heartbeat request timed out! Resetting seat occupied status..."); } _this.heartbeatRequestTimeout = false; // Seat is not occupied _this.isOccupied = false; _this.currentClientSessionID = false; // FIXME: This won't restore the sit overlay for other users. }, HEARTBEAT_TIMEOUT_MS); } else { if (DEBUG) { console.log("sitServer.js: We went to send a heartbeat, but the seat wasn't occupied. Aborting..."); } _this.currentClientSessionID = false; if (_this.nextHeartbeatTimeout) { Script.clearTimeout(_this.nextHeartbeatTimeout); _this.nextHeartbeatTimeout = false; } if (_this.heartbeatRequestTimeout) { Script.clearTimeout(_this.heartbeatRequestTimeout); _this.heartbeatRequestTimeout = false; } } } function requestSitData(id, args) { var requestingID = args[0]; if (DEBUG) { console.log("sitServer.js: Request for sit data received from :" + requestingID); } var replyData = { "isOccupied": _this.isOccupied } replyData = JSON.stringify(replyData); Entities.callEntityClientMethod( requestingID, _this.entityID, "requestSitDataReply", [replyData] ); } // Remotely callable // Called from client to check if chair is occupied // If seat is not occupied, server script calls the client method that begins the sit down process var HEARTBEAT_INTERVAL_TIME_MS = 10000; // ms var HEARTBEAT_TIMEOUT_MS = 2500; // ms function onMousePressOnEntity(id, param) { if (DEBUG) { console.log("sitServer.js: Entering onMousePressOnEntity().."); } if (!_this.isOccupied) { if (DEBUG) { console.log("sitServer.js: `isOccupied` is set to `false`"); } _this.currentClientSessionID = param[0]; _this.isOccupied = true; Entities.callEntityClientMethod( _this.currentClientSessionID, _this.entityID, "checkBeforeSitDown" ); if (_this.nextHeartbeatTimeout) { Script.clearTimeout(_this.nextHeartbeatTimeout); _this.nextHeartbeatTimeout = false; } sendHeartbeatRequest(); } } // Remotely callable // Called from client to open the chair to other avatars function onStandUp(id, params) { if (DEBUG) { console.log("sitServer.js: Entering `onStandUp()` for seat ID: " + id + "..."); } _this.isOccupied = false; _this.currentClientSessionID = false; if (_this.nextHeartbeatTimeout) { Script.clearTimeout(_this.nextHeartbeatTimeout); _this.nextHeartbeatTimeout = false; } if (_this.heartbeatRequestTimeout) { Script.clearTimeout(_this.heartbeatRequestTimeout); _this.heartbeatRequestTimeout = false; } if (DEBUG) { console.log("Calling 'createClickToSitOverlay' on entity " + id + " for all avatars..."); } if (_this.isOccupied === false) { for (var i = 0; i < params.length; i++) { Entities.callEntityClientMethod( params[i], _this.entityID, "createClickToSitOverlay" ); } } } // Remotely callable function removeThisSittableOverlayForEveryoneElse(id, params) { if (DEBUG) { console.log("sitServer.js: Calling `deleteAllClickToSitOverlays()` on entity " + id + " for all avatars..."); } for (var i = 0; i < params.length; i++) { Entities.callEntityClientMethod( params[i], _this.entityID, "deleteAllClickToSitOverlays" ); } } // Preload entity lifetime method function preload(id) { if (DEBUG) { console.log("ZRF HERE: sitServer.js preload()"); } _this.entityID = id; _this.isOccupied = false; } // Unload entity lifetime method function unload() { if (DEBUG) { console.log("ZRF HERE: sitServer.js unload()"); } _this.isOccupied = false; _this.currentClientSessionID = false; if (_this.nextHeartbeatTimeout) { Script.clearTimeout(_this.nextHeartbeatTimeout); _this.nextHeartbeatTimeout = false; } if (_this.heartbeatRequestTimeout) { Script.clearTimeout(_this.heartbeatRequestTimeout); _this.heartbeatRequestTimeout = false; } } // Constructor var _this = null; function SitServer() { _this = this; this.isOccupied = false; this.entityID = null; this.currentClientSessionID = null; this.nextHeartbeatTimeout = null; this.heartbeatRequestTimeout = null; } // Entity methods SitServer.prototype = { remotelyCallable: [ "requestSitData", "onMousePressOnEntity", "onStandUp", "heartbeatResponse", "removeThisSittableOverlayForEveryoneElse" ], preload: preload, requestSitData: requestSitData, heartbeatResponse: heartbeatResponse, onMousePressOnEntity: onMousePressOnEntity, onStandUp: onStandUp, removeThisSittableOverlayForEveryoneElse: removeThisSittableOverlayForEveryoneElse, unload: unload }; return new SitServer(); });