Rooms and matchmaking
* Added missing config (route) data * Fetch room class, database hash * Basic room querying * Built-in room generation during first runtime * Matchmaking response base and notes for myself, later today * Instance fixes * Challenge and quick play routes (unused for now) * Rooms route (untested) * Matchmaking goto route * Avatar route addition * Settings/set route
This commit is contained in:
132
src/data/content/room.ts
Normal file
132
src/data/content/room.ts
Normal file
@@ -0,0 +1,132 @@
|
||||
/* Galvanic Corrosion - Rec Room custom server for communities.
|
||||
<https://gitea.proxnet.dev/zombieb-galvanic-corrosion>
|
||||
Copyright (C) 2025 @zombieb (Discord / proxnet Gitea)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU Affero General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Affero General Public License
|
||||
along with this program. If not, see <https://www.gnu.org/licenses/>. */
|
||||
|
||||
import { Redis } from "../../db.ts";
|
||||
import Rooms from "./rooms.ts";
|
||||
import { IntegratedRoomScene, RoomAccessibility, RoomDetails, RoomState } from "./roomtypes.ts";
|
||||
|
||||
interface RoomFetchOptions {
|
||||
roomName?: string,
|
||||
roomId?: number
|
||||
}
|
||||
|
||||
export function parseBooleanDefault(obj: string, def: boolean | undefined = false) {
|
||||
try {
|
||||
return JSON.parse(obj) as boolean;
|
||||
} catch {
|
||||
return def;
|
||||
}
|
||||
}
|
||||
|
||||
export class RoomFetch {
|
||||
|
||||
roomId: number | null = null;
|
||||
roomName: string | null = null;
|
||||
|
||||
constructor(options: RoomFetchOptions) {
|
||||
|
||||
this.roomId = options.roomId ?? null;
|
||||
this.roomName = options.roomName ?? null;
|
||||
|
||||
}
|
||||
|
||||
async fetch() {
|
||||
|
||||
if (!this.roomId && this.roomName) {
|
||||
const givenId = await Rooms.getIdFromName(this.roomName);
|
||||
if (!givenId) return null;
|
||||
else this.roomId = givenId;
|
||||
} else if (!this.roomName && this.roomId) {
|
||||
const givenName = await Rooms.getNameFromId(this.roomId);
|
||||
if (!givenName) return null;
|
||||
else this.roomName = givenName;
|
||||
} else if (!this.roomId && !this.roomName) return null;
|
||||
|
||||
const roomRootKey = Redis.buildKey(
|
||||
Redis.KeyGroups.Rooms.Root,
|
||||
this.roomId!.toString(), // code above takes care of null possibility
|
||||
);
|
||||
const roomMetaKey = Redis.buildKey(
|
||||
roomRootKey,
|
||||
Rooms.roomRootKeys.Meta
|
||||
);
|
||||
|
||||
const [ hash, cheerCount, favoriteCount, visitCount ] = await Promise.all([
|
||||
Redis.Database.hgetall(roomMetaKey),
|
||||
Redis.Database.get(Redis.buildKey(roomRootKey, Rooms.roomRootKeys.CheerCount)),
|
||||
Redis.Database.get(Redis.buildKey(roomRootKey, Rooms.roomRootKeys.FavoriteCount)),
|
||||
Redis.Database.get(Redis.buildKey(roomRootKey, Rooms.roomRootKeys.VisitCount)),
|
||||
]);
|
||||
|
||||
const room: RoomDetails = {
|
||||
Room: {
|
||||
RoomId: hash[Rooms.roomMetaKeys.RoomId] ? parseInt(hash[Rooms.roomMetaKeys.RoomId]) : 0,
|
||||
Name: hash[Rooms.roomMetaKeys.Name] ?? "DATABASEERROR",
|
||||
Description: hash[Rooms.roomMetaKeys.Description] ?? "DATABASEERROR",
|
||||
CreatorPlayerId: hash[Rooms.roomMetaKeys.CreatorPlayerId] ? parseInt(hash[Rooms.roomMetaKeys.CreatorPlayerId]) : 1,
|
||||
ImageName: hash[Rooms.roomMetaKeys.ImageName] ?? "DefaultProfileImage.png",
|
||||
State: hash[Rooms.roomMetaKeys.State] ? parseInt(hash[Rooms.roomMetaKeys.State]) : RoomState.Active,
|
||||
Accessibility: hash[Rooms.roomMetaKeys.Accessibility] ? parseInt(hash[Rooms.roomMetaKeys.Accessibility]) : RoomAccessibility.Unlisted,
|
||||
SupportsLevelVoting: hash[Rooms.roomMetaKeys.SupportsLevelVoting] ? parseBooleanDefault(hash[Rooms.roomMetaKeys.SupportsLevelVoting], true) : true,
|
||||
IsAGRoom: hash[Rooms.roomMetaKeys.IsAGRoom] ? parseBooleanDefault(hash[Rooms.roomMetaKeys.IsAGRoom], false) : false,
|
||||
IsDormRoom: hash[Rooms.roomMetaKeys.IsDormRoom] ? parseBooleanDefault(hash[Rooms.roomMetaKeys.IsDormRoom], false) : false,
|
||||
CloningAllowed: hash[Rooms.roomMetaKeys.CloningAllowed] ? parseBooleanDefault(hash[Rooms.roomMetaKeys.CloningAllowed], false) : false,
|
||||
SupportsScreens: hash[Rooms.roomMetaKeys.SupportsScreens] ? parseBooleanDefault(hash[Rooms.roomMetaKeys.SupportsScreens], true) : true,
|
||||
SupportsWalkVR: hash[Rooms.roomMetaKeys.SupportsWalkVR] ? parseBooleanDefault(hash[Rooms.roomMetaKeys.SupportsWalkVR], true) : true,
|
||||
SupportsTeleportVR: hash[Rooms.roomMetaKeys.SupportsTeleportVR] ? parseBooleanDefault(hash[Rooms.roomMetaKeys.SupportsTeleportVR], true) : true,
|
||||
AllowsJuniors: hash[Rooms.roomMetaKeys.AllowsJuniors] ? parseBooleanDefault(hash[Rooms.roomMetaKeys.AllowsJuniors], true) : true,
|
||||
RoomWarningMask: hash[Rooms.roomMetaKeys.RoomWarningMask] ? parseInt(hash[Rooms.roomMetaKeys.RoomWarningMask]) : 0,
|
||||
CustomRoomWarning: hash[Rooms.roomMetaKeys.CustomRoomWarning] ?? "",
|
||||
DisableMicAutoMute: hash[Rooms.roomMetaKeys.DisableMicAutoMute] ? parseBooleanDefault(hash[Rooms.roomMetaKeys.DisableMicAutoMute], false) : undefined,
|
||||
},
|
||||
Scenes: [], // temporary
|
||||
CoOwners: [], // temporary
|
||||
InvitedCoOwners: [], // temporary
|
||||
Hosts: [], // temporary
|
||||
InvitedHosts: [], // temporary
|
||||
CheerCount: cheerCount ? parseInt(cheerCount) : 0,
|
||||
FavoriteCount: favoriteCount ? parseInt(favoriteCount) : 0,
|
||||
VisitCount: visitCount ? parseInt(visitCount) : 0,
|
||||
Tags: [] // temporary
|
||||
}
|
||||
const subrooms = await Rooms.getSubroomIdsFromRoom(this.roomId!);
|
||||
for (const subroom of subrooms) {
|
||||
const subroomMetaKey = Redis.buildKey(
|
||||
Redis.KeyGroups.Rooms.Root,
|
||||
this.roomId!.toString(),
|
||||
Rooms.roomRootKeys.Subrooms,
|
||||
subroom.toString(),
|
||||
Rooms.subroomRootKeys.Meta
|
||||
);
|
||||
const subroomDetails = await Redis.Database.hgetall(subroomMetaKey);
|
||||
room.Scenes.push({
|
||||
RoomSceneId: parseInt(subroom),
|
||||
RoomId: this.roomId ?? 0,
|
||||
RoomSceneLocationId: subroomDetails[Rooms.subroomMetaKeys.RoomSceneLocationId] ?? IntegratedRoomScene.MakerRoom,
|
||||
Name: subroomDetails[Rooms.subroomMetaKeys.Name] ?? "DATABASE ERROR",
|
||||
IsSandbox: subroomDetails[Rooms.subroomMetaKeys.IsSandbox] ? parseBooleanDefault(subroomDetails[Rooms.subroomMetaKeys.IsSandbox], false) : false,
|
||||
CanMatchmakeInto: subroomDetails[Rooms.subroomMetaKeys.IsSandbox] ? parseBooleanDefault(subroomDetails[Rooms.subroomMetaKeys.IsSandbox], true) : undefined,
|
||||
DataBlobName: subroomDetails[Rooms.subroomMetaKeys.DataBlobName] ?? "",
|
||||
MaxPlayers: subroomDetails[Rooms.subroomMetaKeys.MaxPlayers] ? parseInt(subroomDetails[Rooms.subroomMetaKeys.MaxPlayers]) : 1,
|
||||
DataModifiedAt: subroomDetails[Rooms.subroomMetaKeys.DataModifiedAt] ?? new Date().toISOString()
|
||||
});
|
||||
}
|
||||
|
||||
return room;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user