Many changes. Commit before I break down.
- Authentication middleware uses Zod - PhotonRegionId in config - DB key changes and additions - WebSocket for SignalR mock - Presence additions * Needs modification for playerIds (do not store `Profile` in a set, this will cause sync issues) - Profile settings - Profile Device Class - Zod properly checks for issuer in token - Room scene type bug - Setting key import started - Instancing changes - PlayerReporting API route - Deduplicated auth/connect/token - match/player/login begin - WebSocket hands off connection to SignalR handler
This commit is contained in:
@@ -1,37 +1,13 @@
|
||||
import Logging from "@proxnet/undead-logging";
|
||||
import Profile from "../profiles.ts";
|
||||
import { IntegratedRoomScene, RoomDetails } from "../content/roomtypes.ts";
|
||||
import { RoomInstance, InstanceOptions } from "./types.ts";
|
||||
import { Config } from "../../config.ts";
|
||||
|
||||
const log = new Logging("Instances");
|
||||
|
||||
export interface RoomInstance {
|
||||
|
||||
roomInstanceId: number,
|
||||
roomId: number,
|
||||
subRoomId: number,
|
||||
location: IntegratedRoomScene,
|
||||
dataBlob?: string,
|
||||
eventId?: number,
|
||||
photonRegionId: "us",
|
||||
photonRoomId: string,
|
||||
name?: string,
|
||||
maxCapacity: number,
|
||||
isFull: boolean,
|
||||
isPrivate: boolean,
|
||||
isInProgress: boolean
|
||||
|
||||
}
|
||||
|
||||
interface InstanceOptions {
|
||||
|
||||
Room: RoomDetails,
|
||||
SceneIndex?: number,
|
||||
EventId?: number,
|
||||
Name?: string,
|
||||
Private?: boolean
|
||||
|
||||
}
|
||||
const config = Config.getConfig();
|
||||
|
||||
// `Profile` isn't synchronized. Fix this.
|
||||
const instancePlayers: Map<RoomInstance, Set<Profile>> = new Map();
|
||||
/**
|
||||
* `Map<roomId (number), RoomInstance>`
|
||||
@@ -101,10 +77,55 @@ class InstancesBase {
|
||||
return this.getInstancePlayers(instance).size < instance.maxCapacity;
|
||||
}
|
||||
|
||||
#generateUniqueInstanceId() {
|
||||
let newInstanceId = Math.round(Math.random() * Math.pow(2, 31))
|
||||
const allInstances = this.getAllInstances();
|
||||
while (Array.from(allInstances.values()).map(val => val.roomInstanceId).includes(newInstanceId)) newInstanceId = Math.round(Math.random() * Math.pow(2, 31));
|
||||
return newInstanceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an instance with options.
|
||||
*
|
||||
* If `options.FirstPlayer` is not specified, the created instance will not contain any players and may be removed.
|
||||
*
|
||||
* If one is, the player will be automatically added to the instance and their `profile.getInstance()` will be synchronized.
|
||||
*/
|
||||
createInstance(options: InstanceOptions) {
|
||||
// todo: use room data to create room instance
|
||||
|
||||
const scene = options.Room.Scenes[options.SceneIndex];
|
||||
const newId = this.#generateUniqueInstanceId();
|
||||
if (!scene) throw new Error("The specified scene did not exist.");
|
||||
|
||||
const newInstance: RoomInstance = {
|
||||
roomInstanceId: newId,
|
||||
roomId: options.Room.Room.RoomId,
|
||||
subRoomId: scene.RoomSceneId,
|
||||
location: scene.RoomSceneLocationId,
|
||||
dataBlob: scene.DataBlobName == "" ? undefined : scene.DataBlobName,
|
||||
eventId: options.EventId,
|
||||
photonRegionId: config.public.photonRegionId,
|
||||
photonRoomId: `20191120-GC${newId}`,
|
||||
name: scene.Name === "Home" ? `^${options.Room.Room.Name}` : `^${options.Room.Room.Name}.${scene.Name}`,
|
||||
maxCapacity: scene.MaxPlayers,
|
||||
isFull: false,
|
||||
isPrivate: typeof options.Private !== 'boolean' ? false : options.Private,
|
||||
isInProgress: false
|
||||
};
|
||||
|
||||
this.getAllRoomInstances(options.Room.Room.RoomId).add(newInstance);
|
||||
if (options.FirstPlayer) {
|
||||
this.setPlayerInstance(options.FirstPlayer, newInstance);
|
||||
this.getInstancePlayers(newInstance).add(options.FirstPlayer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Call only when the player is ready to be moved to an instance
|
||||
*
|
||||
* Synchronizes profile instance to `instance` and adds player to instance.
|
||||
*/
|
||||
setPlayerInstance(player: Profile, instance: RoomInstance) {
|
||||
const currentInstance = player.getInstance();
|
||||
if (currentInstance === instance) return;
|
||||
@@ -128,6 +149,19 @@ class InstancesBase {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Call only when the player is ready to be removed (or when not responding)
|
||||
*
|
||||
* Synchronizes profile instance to `null` and removes player from instance.
|
||||
*/
|
||||
removePlayerFromCurrentInstance(player: Profile) {
|
||||
const instance = player.getInstance();
|
||||
if (!instance) return;
|
||||
this.getInstancePlayers(instance).delete(player);
|
||||
player.setInstance(null);
|
||||
this.updateSingleInstanceIsFull(instance);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
const Instances = new InstancesBase();
|
||||
|
||||
Reference in New Issue
Block a user