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:
2025-03-27 00:44:58 -04:00
parent 3538321487
commit c920dbe88a
23 changed files with 792 additions and 194 deletions

View File

@@ -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();