Rooms and matchmaking debugging

* Dorm is not properly cloned (fix this)
* Basic matchmaking implementation
* Goto route
* Goto DormRoom
This commit is contained in:
2025-04-02 14:10:01 -04:00
parent 27b3754330
commit bcee414004
6 changed files with 237 additions and 86 deletions

View File

@@ -15,11 +15,14 @@ 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 { it } from "node:test";
import { Redis } from "../../db.ts";
import { RootPath } from "./baseimages.ts";
import { BuiltinRoom, RoomState } from "./roomtypes.ts";
import { BuiltinRoom, RoomDetails, RoomState } from "./roomtypes.ts";
import { RoomFetch } from "./room.ts";
import { Profile } from "../profiles.ts";
import Logging from "@proxnet/undead-logging";
const log = new Logging("Rooms");
const rooms = JSON.parse(Deno.readTextFileSync(`${RootPath}/res/rooms.json`)) as BuiltinRoom[];
@@ -119,58 +122,166 @@ class RoomsBase {
return id;
}
async #setRoom(details: RoomDetails) {
const rootKey = Redis.buildKey(Redis.KeyGroups.Rooms.Root, details.Room.RoomId.toString());
const roomMetaRootKey = Redis.buildKey(rootKey, this.roomRootKeys.Meta);
await Promise.all([
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.RoomId, details.Room.RoomId),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.Name, details.Room.Name),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.Description, details.Room.Description),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.CreatorPlayerId, details.Room.CreatorPlayerId),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.ImageName, `DefaultProfileImage.png`),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.State, details.Room.State),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.Accessibility, details.Room.Accessibility),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.SupportsLevelVoting, `${details.Room.SupportsLevelVoting}`),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.IsAGRoom, `${details.Room.IsAGRoom}`),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.IsDormRoom, `${details.Room.IsDormRoom}`),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.CloningAllowed, `${details.Room.CloningAllowed}`),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.SupportsScreens, `${details.Room.SupportsScreens}`),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.SupportsWalkVR, `${details.Room.SupportsWalkVR}`),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.SupportsTeleportVR, `${details.Room.SupportsTeleportVR}`),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.AllowsJuniors, `${details.Room.AllowsJuniors}`),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.RoomWarningMask, details.Room.RoomWarningMask),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.CustomRoomWarning, details.Room.CustomRoomWarning),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.DisableMicAutoMute, `${details.Room.DisableMicAutoMute}`),
]);
for (const subroom of details.Scenes) {
const newSubId = await this.#getAvailableSubRoomId(details.Room.RoomId);
const subRootMetaKey = Redis.buildKey(
Redis.KeyGroups.Rooms.Root,
details.Room.RoomId.toString(),
this.roomRootKeys.Subrooms,
newSubId.toString(),
this.subroomRootKeys.Meta
);
await Promise.all([
Redis.Database.hset(subRootMetaKey, this.subroomMetaKeys.RoomSceneLocationId, subroom.RoomSceneLocationId),
Redis.Database.hset(subRootMetaKey, this.subroomMetaKeys.Name, subroom.RoomSceneLocationId),
Redis.Database.hset(subRootMetaKey, this.subroomMetaKeys.IsSandbox, `${subroom.IsSandbox}`),
Redis.Database.hset(subRootMetaKey, this.subroomMetaKeys.DataBlobName, subroom.DataBlobName),
Redis.Database.hset(subRootMetaKey, this.subroomMetaKeys.MaxPlayers, subroom.MaxPlayers),
Redis.Database.hset(subRootMetaKey, this.subroomMetaKeys.CanMatchmakeInto, `${subroom.CanMatchmakeInto}`),
Redis.Database.hset(subRootMetaKey, this.subroomMetaKeys.DataModifiedAt, new Date().toISOString()),
]);
await Redis.Database.sadd(Redis.buildKey(Redis.KeyGroups.Rooms.Root, details.Room.RoomId.toString(), this.roomRootKeys.Subrooms), newSubId);
}
}
async cloneRoom(roomid: number, newname: string, newowner: Profile, dorm?: boolean) {
const canBeClonedRaw = await Redis.Database.hget(Redis.buildKey(
Redis.KeyGroups.Rooms.Root,
roomid.toString(),
Rooms.roomRootKeys.Meta
), Rooms.roomMetaKeys.CloningAllowed);
if (!canBeClonedRaw) return null;
let canBeCloned = null;
try {
canBeCloned = JSON.parse(canBeClonedRaw) as boolean;
} catch {
return null;
}
if (!canBeCloned) return null;
const beforeRoom = await Rooms.get(roomid); // room must exist
if (!beforeRoom || !beforeRoom.Room.CloningAllowed) return null; // room must be cloneable
if (await Rooms.getByName(newname)) return null; // room name cannot be taken
const newId = await this.#getAvailableRoomId();
beforeRoom.Room.CreatorPlayerId = newowner.getId();
beforeRoom.Room.RoomId = newId;
for (const subroom of beforeRoom.Scenes) subroom.RoomId = newId;
if (dorm) {
beforeRoom.Room.IsAGRoom = true;
beforeRoom.Room.IsDormRoom = true;
}
await Redis.Database.set(Redis.buildKey(Redis.KeyGroups.Room_Names, newname), newId);
await Rooms.#setRoom(beforeRoom);
return beforeRoom;
}
async getProfileDormDefault(player: Profile) {
const unparsedId = await Redis.Database.hget(Redis.buildKey(
Redis.KeyGroups.Rooms.Root,
Redis.KeyGroups.Rooms.PlayerDorms
), player.getId().toString());
if (unparsedId) {
const parsedId = parseInt(unparsedId);
if (!isNaN(parsedId)) return await Rooms.get(parsedId);
}
const baseDorm = await Rooms.getByName("DormRoom");
log.d('got base dorm');
if (!baseDorm) return null;
log.d('base dorm is not null');
const newDorm = await this.cloneRoom(baseDorm.Room.RoomId, "DormRoom", player, true);
await Redis.Database.hset(Redis.buildKey(
Redis.KeyGroups.Rooms.Root,
Redis.KeyGroups.Rooms.PlayerDorms
), player.getId().toString(), baseDorm.Room.RoomId);
log.d('got new dorm');
if (!newDorm) return null;
log.d('new dorm is not null');
return newDorm;
}
async generateBuiltinRooms() {
if ((await Redis.Database.get(Redis.buildKey(Redis.KeyGroups.Rooms.Root, this.miscKeys.BuiltinGenerated))) !== null) return true;
for (const builtinRoom of rooms) {
const newId = await this.#getAvailableRoomId();
await Redis.Database.sadd(Redis.buildKey(Redis.KeyGroups.Rooms.Root, this.miscKeys.AGRooms), newId);
await Redis.Database.set(Redis.buildKey(Redis.KeyGroups.Room_Names, builtinRoom.Name), newId);
const rootKey = Redis.buildKey(Redis.KeyGroups.Rooms.Root, newId.toString());
const roomMetaRootKey = Redis.buildKey(rootKey, this.roomRootKeys.Meta);
await Promise.all([
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.RoomId, newId),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.Name, builtinRoom.Name),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.Description, builtinRoom.Description),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.CreatorPlayerId, `1`),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.ImageName, `${builtinRoom.Name}.png`),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.State, `${RoomState.Active}`),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.Accessibility, `${builtinRoom.Accessibility}`),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.SupportsLevelVoting, `${builtinRoom.SupportsLevelVoting}`),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.IsAGRoom, "true"),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.IsDormRoom, "false"),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.CloningAllowed, `${builtinRoom.CloningAllowed}`),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.SupportsScreens, `${builtinRoom.SupportsScreens}`),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.SupportsWalkVR, `${builtinRoom.SupportsWalkVR}`),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.SupportsTeleportVR, `${builtinRoom.SupportsTeleportVR}`),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.AllowsJuniors, "true"),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.RoomWarningMask, 0),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.CustomRoomWarning, ""),
Redis.Database.hset(roomMetaRootKey, this.roomMetaKeys.DisableMicAutoMute, "false"),
]);
for (const subroom of builtinRoom.Scenes) {
const newSubId = await this.#getAvailableSubRoomId(newId);
const subRootMetaKey = Redis.buildKey(
Redis.KeyGroups.Rooms.Root,
newId.toString(),
this.roomRootKeys.Subrooms,
newSubId.toString(),
this.subroomRootKeys.Meta
);
await Promise.all([
Redis.Database.hset(subRootMetaKey, this.subroomMetaKeys.RoomSceneLocationId, subroom.RoomSceneLocationId),
Redis.Database.hset(subRootMetaKey, this.subroomMetaKeys.Name, subroom.RoomSceneLocationId),
Redis.Database.hset(subRootMetaKey, this.subroomMetaKeys.IsSandbox, `${subroom.IsSandbox}`),
Redis.Database.hset(subRootMetaKey, this.subroomMetaKeys.DataBlobName, ""),
Redis.Database.hset(subRootMetaKey, this.subroomMetaKeys.MaxPlayers, subroom.MaxPlayers),
Redis.Database.hset(subRootMetaKey, this.subroomMetaKeys.CanMatchmakeInto, `${subroom.CanMatchmakeInto}`),
Redis.Database.hset(subRootMetaKey, this.subroomMetaKeys.DataModifiedAt, new Date().toISOString()),
]);
await Redis.Database.sadd(Redis.buildKey(Redis.KeyGroups.Rooms.Root, newId.toString(), this.roomRootKeys.Subrooms), newSubId);
const roomDets: RoomDetails = {
Room: {
Name: builtinRoom.Name,
RoomId: newId,
Description: builtinRoom.Description,
CreatorPlayerId: 1,
ImageName: `${builtinRoom.Name}.png`,
State: RoomState.Active,
Accessibility: builtinRoom.Accessibility,
SupportsLevelVoting: builtinRoom.SupportsLevelVoting,
IsAGRoom: true,
IsDormRoom: builtinRoom.Name == 'DormRoom',
CloningAllowed: builtinRoom.CloningAllowed,
SupportsScreens: builtinRoom.SupportsScreens,
SupportsWalkVR: builtinRoom.SupportsWalkVR,
SupportsTeleportVR: builtinRoom.SupportsTeleportVR,
AllowsJuniors: true,
RoomWarningMask: 0,
CustomRoomWarning: ""
},
Scenes: [],
CoOwners: [],
InvitedCoOwners: [],
Hosts: [],
InvitedHosts: [],
CheerCount: 0,
FavoriteCount: 0,
VisitCount: 0,
Tags: []
}
for (const subroom of builtinRoom.Scenes) {
const newSubroomId = await this.#getAvailableSubRoomId(newId);
roomDets.Scenes.push({
RoomSceneId: newSubroomId,
RoomId: newId,
RoomSceneLocationId: subroom.RoomSceneLocationId,
Name: subroom.Name,
IsSandbox: subroom.IsSandbox,
DataBlobName: "",
MaxPlayers: subroom.MaxPlayers,
CanMatchmakeInto: subroom.CanMatchmakeInto ? subroom.CanMatchmakeInto : true,
DataModifiedAt: new Date().toISOString()
});
}
await this.#setRoom(roomDets);
}
Redis.Database.set(Redis.buildKey(Redis.KeyGroups.Rooms.Root, this.miscKeys.BuiltinGenerated), "1");
return false;