forked from zombieb/galvanic-corrosion-rewrite
wer
This commit is contained in:
14
src/main.ts
14
src/main.ts
@@ -12,6 +12,7 @@ import { PushNotificationId } from "./server/socket/signalr/types.ts";
|
||||
import { genericResponse } from "./util/api.ts";
|
||||
import { getNetConfig } from "./net.ts";
|
||||
import { TokenFormat, TokenType } from "./server/platforms/types.ts";
|
||||
import { Context } from "node:vm";
|
||||
|
||||
LoggingConfiguration.resetTimeFormat = TimeFormat.Unix;
|
||||
LoggingConfiguration.resetLogTiming = LogTiming.Microtask;
|
||||
@@ -48,7 +49,7 @@ await routeImporter(AppRoot.app, 'src/', [
|
||||
]);
|
||||
|
||||
// deno-lint-ignore require-await
|
||||
AppRoot.app.use('*', async c => {
|
||||
AppRoot.app.use('*', async (c: Context) => {
|
||||
return c.json(genericResponse(false, "Resource Not Found"), 404);
|
||||
});
|
||||
|
||||
@@ -60,7 +61,11 @@ const onListen = async () => {
|
||||
await Deno.mkdir('persist');
|
||||
|
||||
await Promise.all(Object.values(Server).map(base => ((base as ServerContentBase).kvInit ? (base as ServerContentBase).kvInit() : undefined)));
|
||||
Server.emit('server.start', undefined);
|
||||
if (typeof Server == 'undefined') {
|
||||
log.e(`SERVER LOCKUP: Server is undefined!`);
|
||||
return;
|
||||
}
|
||||
Server.emit('server.start', { server: Server });
|
||||
}
|
||||
|
||||
const netConfig = getNetConfig();
|
||||
@@ -92,7 +97,7 @@ const server = Deno.serve({
|
||||
const splitHeader = authHeader.split(' ')[1];
|
||||
if (!splitHeader) return unauthRes;
|
||||
|
||||
const secret = Deno.env.get('secret');
|
||||
const secret = Deno.env.get('SECRET');
|
||||
if (!secret) {
|
||||
log.w(`No secret set!`);
|
||||
return unauthRes;
|
||||
@@ -140,6 +145,7 @@ const server = Deno.serve({
|
||||
formatHeader(req.headers, 'Content-Type'),
|
||||
formatHeader(req.headers, 'Connection'),
|
||||
formatHeader(req.headers, 'User-Agent'),
|
||||
formatHeader(req.headers, 'Accept-Encoding')
|
||||
]);
|
||||
if (!logBlacklist.includes(url.pathname)) {
|
||||
if (res.status === 404) log.e(netlog);
|
||||
@@ -163,7 +169,7 @@ Deno.addSignalListener('SIGINT', () => {
|
||||
for (const socket of consoleSockets) socket.destroy();
|
||||
for (const socket of gameSockets) socket.sendNotification(PushNotificationId.ModerationQuitGame);
|
||||
|
||||
Server.emit('server.destroy', undefined);
|
||||
Server.emit('server.destroy', { server: Server });
|
||||
});
|
||||
|
||||
Server.Commands.addRootCommand(new Command({
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
export function getNetConfig() {
|
||||
return {
|
||||
host: "10.0.1.39",
|
||||
host: "127.0.0.1",
|
||||
port: 13370,
|
||||
publicHost: "10.0.1.39:13370",
|
||||
publicHost: "127.0.0.1:13370",
|
||||
securePublicHost: false
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,7 @@
|
||||
import { createHonoRoute } from "../../../util/import.ts";
|
||||
|
||||
export const route = createHonoRoute("/messages");
|
||||
|
||||
route.app.get('/v2/get', c => {
|
||||
return c.json([]);
|
||||
});
|
||||
@@ -1,7 +1,17 @@
|
||||
import z from "zod";
|
||||
import { createHonoRoute } from "../../../util/import.ts";
|
||||
import { authenticate } from "../../../util/api.ts";
|
||||
import { typedZValidator } from "../../../util/validators.ts";
|
||||
|
||||
export const route = createHonoRoute("/players");
|
||||
|
||||
route.app.get('/v2/progression/bulk', c => {
|
||||
return c.json([]); // todo: progression
|
||||
});
|
||||
|
||||
const getProgParamSchema = z.object({
|
||||
id: z.coerce.number()
|
||||
});
|
||||
route.app.get('/v1/progression/:id', authenticate, typedZValidator('param', getProgParamSchema), async c => {
|
||||
return c.json(await c.get('profile').Reputation.export());
|
||||
});
|
||||
@@ -1,8 +1,7 @@
|
||||
import z from "zod";
|
||||
import { authenticate, genericResponse } from "../../../util/api.ts";
|
||||
import { createHonoRoute } from "../../../util/import.ts";
|
||||
import { transformStringToEnum, typedZValidator } from "../../../util/validators.ts";
|
||||
import { ProfileSetting } from "../../../server/profiles/content/Settings.ts";
|
||||
import { typedZValidator } from "../../../util/validators.ts";
|
||||
import { HonoEnv } from "../../../util/types.ts";
|
||||
import { Context } from "@hono/hono";
|
||||
|
||||
@@ -19,7 +18,7 @@ route.app.get('/v2/', getSettingsMiddleware);
|
||||
route.app.get('/v2', getSettingsMiddleware);
|
||||
|
||||
const settingsSetSchema = z.object({
|
||||
Key: z.string().transform(transformStringToEnum<ProfileSetting>(ProfileSetting, true)),
|
||||
Key: z.string(),
|
||||
Value: z.string()
|
||||
});
|
||||
route.app.post('/v2/set', typedZValidator('json', settingsSetSchema), async c => {
|
||||
|
||||
@@ -9,8 +9,12 @@ export class ServerContentBase {
|
||||
this.server = server;
|
||||
this.kv = new KV(id, kv);
|
||||
|
||||
server.on('server.start', this.start);
|
||||
server.on('server.destroy', this.destroy);
|
||||
server.on('server.start', _ev => {
|
||||
this.start();
|
||||
});
|
||||
server.on('server.destroy', _ev => {
|
||||
this.destroy();
|
||||
});
|
||||
}
|
||||
|
||||
async kvInit() {
|
||||
|
||||
@@ -2,6 +2,14 @@ import { CloudRegionCode } from "../../util/photon.ts";
|
||||
import type Profile from "../profiles/profile.ts";
|
||||
import { RoomInstance, RoomLocation } from "./base.ts";
|
||||
|
||||
export interface InstanceCreationOptions {
|
||||
roomId: number,
|
||||
subRoomId: number,
|
||||
name: string,
|
||||
maxCapacity: number,
|
||||
private?: boolean
|
||||
}
|
||||
|
||||
export class Instance {
|
||||
|
||||
#createdAt = new Date();
|
||||
@@ -9,40 +17,42 @@ export class Instance {
|
||||
#players: Set<Profile> = new Set();
|
||||
|
||||
#instanceId: number;
|
||||
//#roomId: number;
|
||||
//#subRoomId: number;
|
||||
#roomId: number;
|
||||
#subRoomId: number;
|
||||
#location: RoomLocation;
|
||||
//#name: string;
|
||||
//#maxCapacity: number;
|
||||
#name: string;
|
||||
#maxCapacity: number;
|
||||
#isFull: boolean = false;
|
||||
//#isPrivate: boolean;
|
||||
#isPrivate: boolean;
|
||||
#isInProgress: boolean = false;
|
||||
#photonRegionId: string = CloudRegionCode.us;
|
||||
//#photonRoomId: string;
|
||||
#photonRoomId: string;
|
||||
#dataBlob?: string;
|
||||
#eventId?: string
|
||||
#eventId?: number
|
||||
|
||||
constructor(options: {
|
||||
id: number,
|
||||
location: RoomLocation,
|
||||
}
|
||||
) {
|
||||
this.#instanceId = options.id;
|
||||
this.#location = options.location;
|
||||
constructor(id: number, location: RoomLocation, options: InstanceCreationOptions) {
|
||||
this.#instanceId = id;
|
||||
this.#location = location;
|
||||
|
||||
this.#roomId = options.roomId;
|
||||
this.#subRoomId = options.subRoomId;
|
||||
this.#isPrivate = typeof options.private == 'boolean' ? options.private : false;
|
||||
this.#name = options.name;
|
||||
this.#maxCapacity = options.maxCapacity;
|
||||
this.#photonRoomId = `GCR-${this.#instanceId}`;
|
||||
}
|
||||
|
||||
getPlayers() {
|
||||
return this.#players.values().toArray();
|
||||
}
|
||||
playerIsHere(profile: Profile) {
|
||||
return this.getPlayers().find(prof => prof.same(profile)) ? true : false;
|
||||
return Boolean(this.getPlayers().find(prof => prof.same(profile)));
|
||||
}
|
||||
removePlayer(profile: Profile) {
|
||||
this.#players.delete(profile);
|
||||
}
|
||||
addPlayer(profile: Profile) {
|
||||
this.#players.add(profile);
|
||||
|
||||
}
|
||||
|
||||
getCreatedAt() {
|
||||
@@ -50,10 +60,22 @@ export class Instance {
|
||||
}
|
||||
|
||||
export() {
|
||||
/*const inst: RoomInstance = {
|
||||
const inst: RoomInstance = {
|
||||
roomInstanceId: this.#instanceId,
|
||||
|
||||
}*/
|
||||
roomId: this.#roomId,
|
||||
subRoomId: this.#subRoomId,
|
||||
location: this.#location,
|
||||
name: this.#name,
|
||||
maxCapacity: this.#maxCapacity,
|
||||
isFull: this.#isFull,
|
||||
isPrivate: this.#isPrivate,
|
||||
isInProgress: this.#isInProgress,
|
||||
photonRegionId: this.#photonRegionId,
|
||||
photonRoomId: this.#photonRoomId,
|
||||
dataBlob: this.#dataBlob,
|
||||
eventId: this.#eventId
|
||||
};
|
||||
return inst;
|
||||
}
|
||||
|
||||
}
|
||||
5
src/server/profiles/content/Progression.ts
Normal file
5
src/server/profiles/content/Progression.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import ProfileContentManager from "./base.ts";
|
||||
|
||||
export class ProfileProgressionManager extends ProfileContentManager {
|
||||
|
||||
} // do this soon:tm:
|
||||
@@ -1,5 +1,33 @@
|
||||
import ProfileContentManager from "./base.ts";
|
||||
|
||||
interface ProfileReputation {
|
||||
AccountId: number,
|
||||
Noteriety: number,
|
||||
CheerGeneral: number,
|
||||
CheerHelpful: number,
|
||||
CheerGreatHost: number,
|
||||
CheerSportsman: number,
|
||||
CheerCreative: number,
|
||||
CheerCredit: number,
|
||||
SubscriberCount: number,
|
||||
SubscribedCount: number,
|
||||
}
|
||||
|
||||
export class ProfileReputationManager extends ProfileContentManager {
|
||||
|
||||
async export(): Promise<ProfileReputation> {
|
||||
return {
|
||||
AccountId: this.profile.getId(),
|
||||
Noteriety: 0.0,
|
||||
CheerGeneral: 0.0,
|
||||
CheerHelpful: 0.0,
|
||||
CheerGreatHost: 0.0,
|
||||
CheerSportsman: 0.0,
|
||||
CheerCreative: 0.0,
|
||||
CheerCredit: 0.0,
|
||||
SubscribedCount: 0,
|
||||
SubscriberCount: 0
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -34,7 +34,7 @@ export class ProfileSettingsManager extends ProfileContentManager {
|
||||
await this.kv.getKv().set(this.#key, settings);
|
||||
}
|
||||
|
||||
async setSetting(Key: ProfileSetting, Value: string) {
|
||||
async setSetting(Key: string, Value: string) {
|
||||
const settings = await this.getAllSettings();
|
||||
const s = settings.find(setting => setting.Key === Key);
|
||||
if (!s) settings.push({ Key, Value });
|
||||
|
||||
@@ -93,7 +93,7 @@ class ProfileManagerBase extends ServerContentBase {
|
||||
exec: async (id: number) => {
|
||||
const prof = await this.get(id);
|
||||
if (!prof) return prof;
|
||||
else return await prof.export();
|
||||
else return prof.export();
|
||||
},
|
||||
zod: z.tuple([
|
||||
z.string().transform(Number)
|
||||
|
||||
26
src/server/rooms/base.ts
Normal file
26
src/server/rooms/base.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { ServerContentBase } from "../ContentBase.ts";
|
||||
|
||||
export class ServerRoomsBase extends ServerContentBase {
|
||||
|
||||
#roomsKey = "rooms";
|
||||
#roomNamesKey = "room_names"
|
||||
|
||||
getKv() {
|
||||
return this.kv;
|
||||
}
|
||||
|
||||
async getIdFromName(name: string) {
|
||||
const id = await this.kv.getKv().get<number>([this.#roomsKey, name]);
|
||||
if (id.value == null) return null;
|
||||
return id.value;
|
||||
}
|
||||
|
||||
async getFromName(name: string) {
|
||||
|
||||
}
|
||||
|
||||
async get(id: number) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
178
src/server/rooms/internal/DataTypes.ts
Normal file
178
src/server/rooms/internal/DataTypes.ts
Normal file
@@ -0,0 +1,178 @@
|
||||
import { RoomLocation } from "../../instances/base.ts";
|
||||
import { RoomFactory } from "./RoomFactory.ts";
|
||||
import { SubroomFactory } from "./SubroomFactory.ts";
|
||||
|
||||
export enum WriteMode {
|
||||
Overwrite = "overwrite",
|
||||
WriteIfFree = "if_free"
|
||||
}
|
||||
|
||||
export enum FactoryMode {
|
||||
Fetch = 'fetch',
|
||||
Write = 'write'
|
||||
}
|
||||
|
||||
export type HardwareSupport = "screens" | "walk_vr" | "teleport_vr" | "low_vr" | "mobile";
|
||||
export const HardwareSupportStrings = ["screens", "walk_vr", "teleport_vr", "low_vr", "mobile"];
|
||||
|
||||
export enum RoomState {
|
||||
Active,
|
||||
PendingJunior = 11,
|
||||
Moderation_PendingReview = 100,
|
||||
Moderation_Closed,
|
||||
MarkedForDelete = 1000
|
||||
}
|
||||
|
||||
export enum RoomAccessibility {
|
||||
Private,
|
||||
Public,
|
||||
Unlisted
|
||||
}
|
||||
|
||||
export interface BuiltinScene {
|
||||
Name: string,
|
||||
RoomSceneLocationId: RoomLocation,
|
||||
IsSandbox: boolean,
|
||||
CanMatchmakeInto: boolean,
|
||||
SupportsJoinInProgress: boolean,
|
||||
UseLevelBasedMatchmaking: boolean,
|
||||
UseAgeBasedMatchmaking: boolean,
|
||||
UseRecRoyaleMatchmaking: boolean,
|
||||
MaxPlayers: number
|
||||
}
|
||||
|
||||
export interface BuiltinRoom {
|
||||
Name: string,
|
||||
Description: string,
|
||||
Accessibility: RoomAccessibility,
|
||||
SupportsLevelVoting: boolean,
|
||||
CloningAllowed: boolean,
|
||||
SupportsScreens: boolean,
|
||||
SupportsWalkVR: boolean,
|
||||
SupportsTeleportVR: boolean,
|
||||
Scenes: BuiltinScene[]
|
||||
}
|
||||
|
||||
export interface RoomScene {
|
||||
RoomSceneId: number,
|
||||
RoomId: number,
|
||||
RoomSceneLocationId: string,
|
||||
Name: string,
|
||||
IsSandbox: boolean,
|
||||
DataBlobName: string,
|
||||
MaxPlayers: number,
|
||||
CanMatchmakeInto?: boolean,
|
||||
DataModifiedAt: string
|
||||
}
|
||||
|
||||
export interface Room {
|
||||
RoomId: number,
|
||||
Name: string,
|
||||
Description: string,
|
||||
CreatorPlayerId: number,
|
||||
ImageName: string,
|
||||
State: RoomState,
|
||||
Accessibility: RoomAccessibility,
|
||||
SupportsLevelVoting: boolean,
|
||||
IsAGRoom: boolean,
|
||||
IsDormRoom?: boolean,
|
||||
CloningAllowed: boolean,
|
||||
SupportsScreens: boolean,
|
||||
SupportsWalkVR: boolean,
|
||||
SupportsTeleportVR: boolean,
|
||||
AllowsJuniors: boolean,
|
||||
RoomWarningMask: number,
|
||||
CustomRoomWarning: string,
|
||||
DisableMicAutoMute?: boolean | null
|
||||
}
|
||||
|
||||
export enum RoomWarningMask {
|
||||
None,
|
||||
Scary,
|
||||
Mature = 2,
|
||||
FlashingLights = 4,
|
||||
IntenseMotion = 8,
|
||||
Violence = 16,
|
||||
Custom = 32
|
||||
}
|
||||
|
||||
export enum TagType {
|
||||
General,
|
||||
Auto,
|
||||
AGOnly,
|
||||
Banned
|
||||
}
|
||||
|
||||
export interface TagDTO {
|
||||
Tag: string,
|
||||
Type: TagType
|
||||
}
|
||||
|
||||
export interface RoomDetails {
|
||||
Room: Room,
|
||||
Scenes: RoomScene[],
|
||||
CoOwners: number[],
|
||||
InvitedCoOwners: number[],
|
||||
Moderators?: number[],
|
||||
InvitedModerators?: number[],
|
||||
Hosts: number[],
|
||||
InvitedHosts: number[],
|
||||
CheerCount: number,
|
||||
FavoriteCount: number,
|
||||
VisitCount: number,
|
||||
Tags: TagDTO[]
|
||||
}
|
||||
|
||||
export enum CreateModifyRoomStatus {
|
||||
Success,
|
||||
Unknown,
|
||||
PermissionDenied,
|
||||
RoomNotActive,
|
||||
RoomDoesNotExist,
|
||||
RoomHasNoDataBlob,
|
||||
DuplicateName = 10,
|
||||
ReservedName,
|
||||
InappropriateName,
|
||||
InappropriateDescription,
|
||||
TooManyRooms = 20,
|
||||
InvalidMaxPlayers = 30,
|
||||
DataHistoryDoesNotExist = 40,
|
||||
DataHistoryAlreadyActive,
|
||||
InvalidTags = 50,
|
||||
NoStartingRoomScene = 55,
|
||||
RoomUnderModerationReview = 100,
|
||||
PlayerHasRoomUnderModerationReview,
|
||||
AccessibilityUnderModerationLock,
|
||||
JuniorStatusFail = 200,
|
||||
InappropriateCustomWarning = 300,
|
||||
PartialBanSuccessBanPower = 400,
|
||||
TargetHasBanPower,
|
||||
PlayerIsRoomBanned = 410
|
||||
}
|
||||
|
||||
export interface DatabaseRoom {
|
||||
Visits: number,
|
||||
Hardware: Set<HardwareSupport>,
|
||||
Subrooms: number[],
|
||||
Tags: Set<string>,
|
||||
CoOwners: Set<number>,
|
||||
InvitedCoOwners: Set<number>,
|
||||
Hosts: Set<number>,
|
||||
InvitedHosts: Set<number>,
|
||||
Favorites: Set<number>,
|
||||
Cheers: Set<number>
|
||||
}
|
||||
|
||||
export interface DatabaseSubroom {
|
||||
|
||||
}
|
||||
|
||||
export interface RoomUpdatedEvent {
|
||||
room: RoomFactory
|
||||
}
|
||||
|
||||
export interface SubroomUpdatedEvent {
|
||||
subroom: SubroomFactory
|
||||
}
|
||||
|
||||
export * as RoomDataTypes from "./DataTypes.ts";
|
||||
53
src/server/rooms/internal/RoomFactory.ts
Normal file
53
src/server/rooms/internal/RoomFactory.ts
Normal file
@@ -0,0 +1,53 @@
|
||||
import type KV from "../../persistence/kv.ts";
|
||||
import { type ServerBase } from "../../server.ts";
|
||||
import { DatabaseRoom, RoomDataTypes } from "./DataTypes.ts";
|
||||
|
||||
export interface RoomFactoryOptions {
|
||||
id?: number,
|
||||
name?: string,
|
||||
}
|
||||
|
||||
export class RoomFactory {
|
||||
|
||||
#server: ServerBase;
|
||||
#kv: KV;
|
||||
|
||||
#roomId: number | undefined;
|
||||
#name: string | undefined;
|
||||
#description: string | undefined;
|
||||
#creatorPlayerId: number | undefined;
|
||||
#imageName: string | undefined;
|
||||
#state: RoomDataTypes.RoomScene | undefined;
|
||||
#accessibility: RoomDataTypes.RoomAccessibility | undefined;
|
||||
#supportsLevelVoting: boolean | undefined;
|
||||
#isAGRoom: boolean | undefined;
|
||||
#isDormRoom: boolean | undefined;
|
||||
#cloningAllowed: boolean | undefined;
|
||||
#supportsScreens: boolean | undefined;
|
||||
#supportsWalkVR: boolean | undefined;
|
||||
#supportsTeleportVR: boolean | undefined;
|
||||
#allowsJuniors: boolean | undefined;
|
||||
#roomWarningMask: number | undefined;
|
||||
#customRoomWarning: string | undefined;
|
||||
#disableMicAutoMute: boolean | undefined;
|
||||
|
||||
#dbMeta: DatabaseRoom | null = null;
|
||||
|
||||
#visits: number | undefined;
|
||||
#hardware
|
||||
|
||||
constructor(server: ServerBase, kv: KV) {
|
||||
|
||||
this.#server = server;
|
||||
this.#kv = kv;
|
||||
|
||||
}
|
||||
|
||||
async init(options: RoomFactoryOptions) {
|
||||
if (typeof options.id == 'undefined' && typeof options.name == 'undefined')
|
||||
throw new Error("Must specify a room ID or a room name");
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ServerUpdateEvent } from "../serverevents.ts";
|
||||
import { AvatarContentBase } from "./avatars/base.ts";
|
||||
import { EventManager } from "./baseevent.ts";
|
||||
import { CommandsBase } from "./commands/commands.ts";
|
||||
@@ -9,13 +10,17 @@ import { type PresenceUpdateEvent } from "./presence/events/PresenceUpdateEvent.
|
||||
import { type ProfileUpdateEvent } from "./profiles/events/ProfileUpdate.ts";
|
||||
import { type RoleUpdateEvent } from "./profiles/events/RoleUpdate.ts";
|
||||
import ProfileManagerBase from "./profiles/manager.ts";
|
||||
import { ServerRoomsBase } from "./rooms/base.ts";
|
||||
import { RoomUpdatedEvent, SubroomUpdatedEvent } from "./rooms/internal/DataTypes.ts";
|
||||
|
||||
interface ServerEvents {
|
||||
'profile.roleupdate': RoleUpdateEvent,
|
||||
'profile.update': ProfileUpdateEvent,
|
||||
'presence.update': PresenceUpdateEvent,
|
||||
'server.start': undefined,
|
||||
'server.destroy': undefined,
|
||||
'server.start': ServerUpdateEvent,
|
||||
'server.destroy': ServerUpdateEvent,
|
||||
'room.updated': RoomUpdatedEvent,
|
||||
'room.subroom.updated': SubroomUpdatedEvent
|
||||
}
|
||||
|
||||
class ServerBase extends EventManager<ServerEvents> {
|
||||
@@ -26,6 +31,7 @@ class ServerBase extends EventManager<ServerEvents> {
|
||||
Avatars = new AvatarContentBase(this, 'avatars');
|
||||
Instances = new InstanceManager(this, 'instances');
|
||||
Content = new ServerContentManager(this, "content");
|
||||
Rooms = new ServerRoomsBase(this, 'rooms', true);
|
||||
}
|
||||
|
||||
const Server = new ServerBase();
|
||||
|
||||
5
src/serverevents.ts
Normal file
5
src/serverevents.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { ServerBase } from "./server/server.ts";
|
||||
|
||||
export interface ServerUpdateEvent {
|
||||
server: ServerBase
|
||||
}
|
||||
Reference in New Issue
Block a user