Instancing (currently unused)
This commit is contained in:
@@ -1,5 +1,8 @@
|
|||||||
|
import Logging from "@proxnet/undead-logging";
|
||||||
import Profile from "../profiles.ts";
|
import Profile from "../profiles.ts";
|
||||||
|
|
||||||
|
const log = new Logging("Instances");
|
||||||
|
|
||||||
enum IntegratedRoomScene {
|
enum IntegratedRoomScene {
|
||||||
Calibration = "f5fbd9c9-e853-4036-9d48-5f68e861af04",
|
Calibration = "f5fbd9c9-e853-4036-9d48-5f68e861af04",
|
||||||
DormRoom = "76d98498-60a1-430c-ab76-b54a29b7a163",
|
DormRoom = "76d98498-60a1-430c-ab76-b54a29b7a163",
|
||||||
@@ -48,7 +51,7 @@ enum IntegratedRoomScene {
|
|||||||
DodgeballVR = "3d474b26-26f7-45e9-9a36-9b02847d5e6f",
|
DodgeballVR = "3d474b26-26f7-45e9-9a36-9b02847d5e6f",
|
||||||
}
|
}
|
||||||
|
|
||||||
interface RoomInstance {
|
export interface RoomInstance {
|
||||||
|
|
||||||
roomInstanceId: number,
|
roomInstanceId: number,
|
||||||
roomId: number,
|
roomId: number,
|
||||||
@@ -67,21 +70,98 @@ interface RoomInstance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const instancePlayers: Map<RoomInstance, Set<Profile>> = new Map();
|
const instancePlayers: Map<RoomInstance, Set<Profile>> = new Map();
|
||||||
|
/**
|
||||||
|
* `Map<roomId (number), RoomInstance>`
|
||||||
|
*/
|
||||||
const instanceMap: Map<number, Set<RoomInstance>> = new Map();
|
const instanceMap: Map<number, Set<RoomInstance>> = new Map();
|
||||||
|
|
||||||
class InstancesBase {
|
class InstancesBase {
|
||||||
|
|
||||||
async #ensureSubSet(roomId: number) {
|
getAllInstances() {
|
||||||
const subMap = instanceMap.get(roomId);
|
return new Set([...instanceMap.values()].flatMap(set => [...set]));
|
||||||
if (!subMap) instanceMap.set(roomId, new Set());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// get all instances
|
getAllRoomInstances(roomId: number) {
|
||||||
// get all instances for a room
|
let instances = instanceMap.get(roomId);
|
||||||
// do not put instance categorization here (instance searching, or "matchmaking"); put that in MatchmakingBase
|
if (!instances) {
|
||||||
|
instances = new Set();
|
||||||
|
instanceMap.set(roomId, instances);
|
||||||
|
}
|
||||||
|
return instances;
|
||||||
|
}
|
||||||
|
|
||||||
|
getInstancePlayers(instance: RoomInstance): Set<Profile> {
|
||||||
|
let players = instancePlayers.get(instance);
|
||||||
|
if (!players) {
|
||||||
|
players = new Set();
|
||||||
|
instancePlayers.set(instance, players);
|
||||||
|
}
|
||||||
|
return players;
|
||||||
|
}
|
||||||
|
|
||||||
|
clearEmptyInstances(instances: Set<RoomInstance>, roomId?: number) {
|
||||||
|
const beforeCount = instances.size;
|
||||||
|
for (const instance of instances) {
|
||||||
|
const profiles = this.getInstancePlayers(instance);
|
||||||
|
if (profiles.size === 0) {
|
||||||
|
log.i(`Instance ${instance.roomInstanceId} empty, deleting`);
|
||||||
|
instancePlayers.delete(instance);
|
||||||
|
this.getAllRoomInstances(instance.roomId).delete(instance);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const afterCount = instances.size;
|
||||||
|
log.d(`Cleared ${roomId !== undefined ? `room ${roomId}` : 'all'} empty instances.\n Instances before: ${beforeCount}\n Instances after: ${afterCount}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
clearAllEmptyInstances() {
|
||||||
|
this.clearEmptyInstances(this.getAllInstances());
|
||||||
|
}
|
||||||
|
|
||||||
|
clearAllRoomEmptyInstances(roomId: number) {
|
||||||
|
this.clearEmptyInstances(this.getAllRoomInstances(roomId), roomId);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateGlobalInstancesIsFull() {
|
||||||
|
for (const instance of this.getAllInstances()) {
|
||||||
|
instance.isFull = this.getInstancePlayers(instance).size >= instance.maxCapacity;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
updateSingleInstanceIsFull(instance: RoomInstance) {
|
||||||
|
const profiles = this.getInstancePlayers(instance);
|
||||||
|
if (profiles.size >= instance.maxCapacity) instance.isFull = true;
|
||||||
|
else instance.isFull = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
instanceCanFitPlayer(instance: RoomInstance) {
|
||||||
|
return this.getInstancePlayers(instance).size < instance.maxCapacity;
|
||||||
|
}
|
||||||
|
|
||||||
// add, remove, check for, get profile(s) in instances
|
// add, remove, check for, get profile(s) in instances
|
||||||
// synchronize profile.#instance with the profile's current instance (profile.setInstance(RoomInstance)?)
|
// synchronize profile.#instance with the profile's current instance (profile.setInstance(RoomInstance)?)
|
||||||
|
setPlayerInstance(player: Profile, instance: RoomInstance) {
|
||||||
|
const currentInstance = player.getInstance();
|
||||||
|
if (currentInstance === instance) return;
|
||||||
|
|
||||||
|
if (currentInstance) {
|
||||||
|
this.getInstancePlayers(currentInstance).delete(player);
|
||||||
|
this.updateSingleInstanceIsFull(currentInstance);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.instanceCanFitPlayer(instance)) {
|
||||||
|
this.getInstancePlayers(instance).add(player);
|
||||||
|
player.setInstance(instance);
|
||||||
|
this.updateSingleInstanceIsFull(instance);
|
||||||
|
} else log.w(`Instance ${instance.roomInstanceId} is full. Cannot add player ${player.getId()}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
playerIsInInstance(player: Profile, instance: RoomInstance) {
|
||||||
|
|
||||||
|
const profiles = this.getInstancePlayers(instance);
|
||||||
|
return profiles.has(player);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { Config } from "../config.ts";
|
|||||||
import { AuthType } from "./users.ts";
|
import { AuthType } from "./users.ts";
|
||||||
import * as JsonWebToken from "@gz/jwt";
|
import * as JsonWebToken from "@gz/jwt";
|
||||||
import { TokenBaseFormat } from "../apiutils.ts";
|
import { TokenBaseFormat } from "../apiutils.ts";
|
||||||
|
import { RoomInstance } from "./live/instances.ts";
|
||||||
|
|
||||||
const config = Config.getConfig();
|
const config = Config.getConfig();
|
||||||
|
|
||||||
@@ -180,15 +181,25 @@ class Profile {
|
|||||||
|
|
||||||
#id: number;
|
#id: number;
|
||||||
|
|
||||||
|
#instance: RoomInstance | null = null;
|
||||||
|
|
||||||
constructor(id: number) {
|
constructor(id: number) {
|
||||||
this.#id = id;
|
this.#id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setInstance(instance: RoomInstance) {
|
||||||
|
this.#instance = instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
getInstance() {
|
||||||
|
return this.#instance;
|
||||||
|
}
|
||||||
|
|
||||||
getId() {
|
getId() {
|
||||||
return this.#id;
|
return this.#id;
|
||||||
}
|
}
|
||||||
|
|
||||||
async getIsDev() {
|
async getIsOperator() {
|
||||||
return (await Redis.Database.sismember(Redis.buildKey(Redis.KeyGroups.Operators), this.#id.toString())) >= 1;
|
return (await Redis.Database.sismember(Redis.buildKey(Redis.KeyGroups.Operators), this.#id.toString())) >= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,7 +214,7 @@ class Profile {
|
|||||||
const payload: ProfileTokenFormat = {
|
const payload: ProfileTokenFormat = {
|
||||||
iss: config.web.publichost,
|
iss: config.web.publichost,
|
||||||
sub: this.#id,
|
sub: this.#id,
|
||||||
role: (await this.getIsDev()) ? 'developer' : 'user',
|
role: (await this.getIsOperator()) ? 'developer' : 'user',
|
||||||
exp: Math.round(Date.now() / 1000) + Math.round(config.auth.timeout * 60 * 60),
|
exp: Math.round(Date.now() / 1000) + Math.round(config.auth.timeout * 60 * 60),
|
||||||
typ: AuthType.Game
|
typ: AuthType.Game
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user