forked from zombieb/galvanic-corrosion-rewrite
duhhhhhhhh
This commit is contained in:
@@ -1,7 +1,121 @@
|
||||
import Logging from "@proxnet/undead-logging";
|
||||
import { ServerContentBase } from "../ContentBase.ts";
|
||||
import { Instance } from "../instances/Instance.ts";
|
||||
import { type RoomInstance } from "../instances/types.ts";
|
||||
import type Profile from "../profiles/profile.ts";
|
||||
import { RoomDataTypes } from "../rooms/internal/RoomDataTypes.ts";
|
||||
import { type RoomFactory } from "../rooms/internal/RoomFactory.ts";
|
||||
import { MatchmakingErrorCode } from "./types.ts";
|
||||
|
||||
const log = new Logging("Matchmaking");
|
||||
|
||||
export interface MatchmakingOptions {
|
||||
roomName: string,
|
||||
subRoomName?: string,
|
||||
private?: boolean,
|
||||
instanceId?: number,
|
||||
profile: Profile
|
||||
}
|
||||
|
||||
export interface InternalMatchmakingResponse {
|
||||
errorCode: MatchmakingErrorCode,
|
||||
roomInstance?: Instance
|
||||
}
|
||||
export interface MatchmakingResponse {
|
||||
errorCode: MatchmakingErrorCode,
|
||||
roomInstance?: RoomInstance
|
||||
}
|
||||
|
||||
export class ServerMatchmakingBase extends ServerContentBase {
|
||||
|
||||
|
||||
async matchmake(options: MatchmakingOptions): Promise<InternalMatchmakingResponse | null> {
|
||||
|
||||
function getInstanceName() {
|
||||
if (options.roomName === 'DormRoom')
|
||||
return `@${options.profile.getUsername()}'s Dorm`;
|
||||
else {
|
||||
if (options.subRoomName || options.subRoomName !== "Home") return `^${options.roomName}.${options.subRoomName}`;
|
||||
else return `^${options.roomName}`;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.instanceId) {
|
||||
|
||||
const instance = this.server.Instances.getInstance(options.instanceId);
|
||||
if (instance) {
|
||||
|
||||
if (instance.hasPlayer(options.profile)) return { errorCode: MatchmakingErrorCode.AlreadyInTargetInstance }
|
||||
else {
|
||||
if (instance.isFull) return { errorCode: MatchmakingErrorCode.InsufficientSpace }
|
||||
else if (instance.isPrivate) return { errorCode: MatchmakingErrorCode.RoomInstanceIsPrivate }
|
||||
|
||||
options.profile.updateInstance(instance);
|
||||
await this.server.Instances.clearEmptyInstances();
|
||||
|
||||
return { errorCode: MatchmakingErrorCode.Success, roomInstance: instance };
|
||||
}
|
||||
|
||||
} else return { errorCode: MatchmakingErrorCode.NoSuchGame };
|
||||
|
||||
} else {
|
||||
|
||||
let targetRoom: RoomFactory | null = null;
|
||||
if (options.roomName == 'DormRoom') targetRoom = await this.server.Rooms.getPlayerDorm(options.profile);
|
||||
else targetRoom = await this.server.Rooms.getByName(options.roomName);
|
||||
|
||||
if (!targetRoom) return { errorCode: MatchmakingErrorCode.NoSuchRoom };
|
||||
if (targetRoom.Accessibility == RoomDataTypes.RoomAccessibility.Private && targetRoom.CreatorPlayerId !== options.profile.getId())
|
||||
return { errorCode: MatchmakingErrorCode.RoomIsPrivate };
|
||||
if (targetRoom.State !== RoomDataTypes.RoomState.Active) return { errorCode: MatchmakingErrorCode.RoomIsNotActive };
|
||||
|
||||
await this.server.Instances.clearEmptyInstances();
|
||||
|
||||
let allInstances = this.server.Instances.getAllInstances();
|
||||
const subroom = (await targetRoom.getAllSubrooms()).values().find(factory => factory.Name == options.subRoomName);
|
||||
|
||||
// if a subroom was specified, filter instances that
|
||||
if (subroom) allInstances = new Set(allInstances.values().filter(inst => inst.subRoomId == subroom.RoomSceneId));
|
||||
|
||||
// filter out instances that are in progress and do not support joininprogress
|
||||
allInstances = new Set(allInstances.values().filter(inst => !(inst.isInProgress && !inst.supportsJoinInProgress)));
|
||||
|
||||
// sort instances
|
||||
allInstances = new Set(allInstances.values().toArray().sort((a, b) => a.size + b.size));
|
||||
|
||||
const foundInstance = allInstances.values().toArray()[0];
|
||||
if (!foundInstance) {
|
||||
|
||||
const matchmakeableSubrooms = (await targetRoom.getAllSubrooms()).values().filter(scene => scene.CanMatchmakeInto).toArray();
|
||||
const index = Math.floor(Math.random() * matchmakeableSubrooms.length);
|
||||
|
||||
log.d(`Scene ${matchmakeableSubrooms[index].RoomSceneId} was chosen for matchmaking into new instance of room ${targetRoom.getRoomId()}`);
|
||||
const newInst = this.server.Instances.createInstance({
|
||||
room: targetRoom,
|
||||
subroom: matchmakeableSubrooms[index],
|
||||
private: options.private,
|
||||
name: getInstanceName()
|
||||
});
|
||||
|
||||
options.profile.updateInstance(newInst);
|
||||
this.server.Instances.clearEmptyInstances();
|
||||
|
||||
return { errorCode: MatchmakingErrorCode.Success, roomInstance: newInst };
|
||||
|
||||
} else {
|
||||
|
||||
const currentInst = options.profile.getInstance();
|
||||
if (currentInst?.instanceId === foundInstance.instanceId)
|
||||
return { errorCode: MatchmakingErrorCode.AlreadyInBestInstance };
|
||||
|
||||
options.profile.updateInstance(foundInstance);
|
||||
this.server.Instances.clearEmptyInstances();
|
||||
|
||||
return { errorCode: MatchmakingErrorCode.Success, roomInstance: foundInstance };
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
enum MatchmakingErrorCode {
|
||||
export enum MatchmakingErrorCode {
|
||||
Success,
|
||||
NoSuchGame,
|
||||
PlayerNotOnline,
|
||||
|
||||
Reference in New Issue
Block a user