// ServiceService.js import { BaseService } from "./BaseService.js"; import { NetworkService } from "./NetworkService.js"; import { RenderService } from "./RenderService.js"; import { ReplicatorService } from "./ReplicatorService.js"; import { ScriptSchedulerService } from "./ScriptSchedulerService.js"; import { Players } from "./Players.js"; import { Workspace } from "./Workspace.js"; import { DataModel } from "../core/DataModel.js"; import * as THREE from "three"; export class ServiceService extends BaseService { constructor() { super("ServiceService"); this._services = new Map(); } register(name, ctor, ...args) { if (this._services.has(name)) return this._services.get(name); const instance = new ctor(...args); this._services.set(name, instance); return instance; } GetService(name) { return this._services.get(name); } GetDataModel() { return globalThis.game; } initAll(port) { // === Core DataModel === const dm = this.register("DataModel", DataModel); dm.SetParent(null); this.SetParent(dm); // Parent myself to the DataModel globalThis.game = dm; // === Workspace === const ws = this.register("Workspace", Workspace); ws.SetParent(dm); // === RenderService === const render = this.register("RenderService", RenderService, dm); render.isServer = true; render.start(); render.SetParent(dm); // === Networking === const net = this.register("NetworkService", NetworkService); net.listen(port); net.SetParent(dm); // === Players === const players = this.register("Players", Players, net); players.SetParent(dm); // === ReplicatorService === const replication = this.register("ReplicatorService", ReplicatorService, dm, net); // === ScriptSchedulerService === const scriptScheduler = this.register( "ScriptSchedulerService", ScriptSchedulerService, dm ); scriptScheduler.SetParent(dm); // Connect to RenderService for update loop render.Stepped.Connect((dt) => { scriptScheduler.step(dt); }); // Cross-link replication.Players = players; players.Replicator = replication; // === Example echo handler === net.registerHandler(0x01, 0x00, (payload, client) => { console.log("Echo:", new TextDecoder().decode(payload)); net.sendToClient(client, 0x01, 0x01, payload); }); // === Example test parts === //this._spawnDemoScene(ws); console.log("[ServiceService] Initialized all services."); } async _spawnDemoScene(ws) { const { LerpedBasePart } = await import("./LerpedBasePart.js"); const ground = new LerpedBasePart(); ground.Size = new THREE.Vector3(10, 1, 10); ground.Position.set(0, -0.5, 0); ground.setAnchored(true); ground.SetParent(ws); ground.updateSizes(); let angle = 0; setInterval(() => { angle += 0.01; ground.Orientation.set(0, angle, 0); ground.Position.set( 5 * Math.sin(angle * 2), -0.5, 5 * Math.cos(angle * 2) ); }, 16); const part = new LerpedBasePart(); part.Size = new THREE.Vector3(1, 1, 1); part.Position.set(10, 5, 0); part.setAnchored(false); part.SetParent(ws); part.updateSizes(); } }