+ }
+ case "pollclientsandgamers": {
+ // From Hall
+ let sockIds = {};
+ Object.keys(clients["/"]).forEach(k => {
+ sockIds[k] = {};
+ Object.keys(clients[page][k]).forEach(x => {
+ // Avoid polling my tmpId: no information to get
+ if (k != sid || x != tmpId) {
+ sockIds[k][x] = {
+ page: "/",
+ focus: clients[page][k][x].focus
+ };
+ }
+ });
+ });
+ // NOTE: a "gamer" could also just be an observer
+ Object.keys(clients).forEach(p => {
+ if (p.indexOf("/game/") >= 0) {
+ Object.keys(clients[p]).forEach(k => {
+ if (!sockIds[k]) sockIds[k] = {};
+ Object.keys(clients[p][k]).forEach(x => {
+ if (k != sid || x != tmpId) {
+ sockIds[k][x] = {
+ page: p,
+ focus: clients[p][k][x].focus
+ };
+ }
+ });
+ });
+ }
+ });
+ send(socket, { code: "pollclientsandgamers", sockIds: sockIds });
+ break;
+ }
+
+ // Asking something: from is fully identified,
+ // but the requested resource can be from any tmpId (except current!)
+ case "askidentity":
+ case "asklastate":
+ case "askchallenges":
+ case "askgame": {
+ const pg = obj.page || page; //required for askidentity and askgame
+ if (!!clients[pg] && !!clients[pg][obj.target]) {
+ let tmpIds = Object.keys(clients[pg][obj.target]);
+ if (obj.target == sid) {
+ // Targetting myself
+ const idx_myTmpid = tmpIds.findIndex(x => x == tmpId);
+ if (idx_myTmpid >= 0) tmpIds.splice(idx_myTmpid, 1);
+ }
+ if (tmpIds.length > 0) {
+ const ttmpId = tmpIds[Math.floor(Math.random() * tmpIds.length)];
+ send(
+ clients[pg][obj.target][ttmpId].socket,
+ { code: obj.code, from: [sid,tmpId,page] }
+ );
+ }
+ }