blockly3d/src/state/world.ts

152 lines
4.2 KiB
TypeScript

import { makeAutoObservable } from "mobx";
import { WorldFactory } from "../model/worldFactory";
import type { ObjectType, RunningGameState, Scene, World } from "../types";
import { CharacterState } from "./character";
import type { Pos3 } from "../types/3d";
import { clone } from "../utils";
import type { VoxelType } from "../types/voxel";
import { state } from "./root";
import { DEFAULT_VOXEL_TYPES } from "../model/defaultVoxelTypes";
export class WorldState {
public data: World = WorldFactory.create();
public character = new CharacterState(this);
constructor() {
makeAutoObservable(this);
}
public reset() {
state.worldEditor.resetSelectedObject();
this.data = WorldFactory.create();
}
public loadMock() {
const objTypeId = 'test1';
const voxelTypeId = 'glass';
const objectId1 = 'object1';
const objectId2 = 'object2';
this.data = {
objectTypes: {
[objTypeId]: {
id: objTypeId,
name: 'Test Object',
voxels: [
{
typeId: voxelTypeId,
position: [0, 0, 0],
},
],
},
},
voxelTypes: DEFAULT_VOXEL_TYPES,
editorCamera: {
position: [0, 2, 10],
look: [0, 0, 0],
},
initialScene: {
character: {
position: [0, 0, 0],
look: [0, 0, 0],
},
objects: {
[objectId1]: {
id: objectId1,
typeId: objTypeId,
position: [0, 0, 0],
rotation: [0, 0, 0],
scale: [1, 1, 1],
},
[objectId2]: {
id: objectId2,
typeId: objTypeId,
position: [1, 0, 0],
rotation: [0, 0, 0],
scale: [1, 1, 1],
},
},
},
gameRules: {
gravity: true,
},
state: {
playing: false,
},
};
state.worldEditor.resetSelectedObject();
this.save();
}
public load() {
this.data = WorldFactory.load() ?? WorldFactory.create();
state.worldEditor.resetSelectedObject();
}
public save(): void {
WorldFactory.save(this.data);
}
public get isPlaying(): boolean {
return this.data.state.playing;
}
public get currentScene(): Scene {
return this.isPlaying
? (this.data.state as RunningGameState).scene
: this.data.initialScene;
}
public get currentCamera(): Pos3 {
return this.isPlaying
? (this.data.state as RunningGameState).scene.character
: this.data.editorCamera;
}
public tick(_delta: number) {
if (!this.isPlaying)
return;
//TODO
}
public play(): void {
if (this.isPlaying) {
const state = clone(this.data.state) as RunningGameState;
state.paused = false;
this.data.state = state;
}
else {
this.data.state = {
playing: true,
paused: false,
time: 0,
scene: clone(this.data.initialScene),
}
}
state.worldEditor.resetSelectedObject();
}
public pause(): void {
if (!this.isPlaying)
return;
const state = clone(this.data.state) as RunningGameState;
state.paused = true;
this.data.state = state;
}
public stop(): void {
if (!this.isPlaying)
return;
this.data.state = { playing: false };
}
public getObjectTypeById(id: string): ObjectType | undefined {
return this.data.objectTypes[id];
}
public getVoxelTypeById(id: string): VoxelType | undefined {
return this.data.voxelTypes[id];
}
}