feat: universe time

This commit is contained in:
cha0s 2022-05-03 04:44:31 -05:00
parent 9de78bb35e
commit 883d231e26
5 changed files with 107 additions and 0 deletions

View File

@ -32,6 +32,7 @@
],
"dependencies": {
"@avocado/resource": "^3.0.0",
"@avocado/s13n": "^3.0.0",
"@avocado/timing": "^3.0.0",
"@avocado/traits": "^3.0.0",
"@flecks/core": "^1.4.1",

View File

@ -6,6 +6,7 @@ export * from './state';
export default {
[Hooks]: {
'@avocado/resource.resources': Flecks.provide(require.context('./resources', false, /\.js$/)),
'@avocado/traits.traits': Flecks.provide(require.context('./traits', false, /\.js$/)),
'@flecks/core.config': () => ({
resource: 'resource',

View File

@ -0,0 +1,10 @@
export default (flecks) => {
const {Packet} = flecks.fleck('@flecks/socket');
return class UniverseUpdateTime extends Packet {
static get data() {
return 'float32';
}
};
};

View File

@ -0,0 +1,70 @@
import {JsonResource} from '@avocado/resource';
import {Synchronized} from '@avocado/s13n';
import {Ticker} from '@avocado/timing';
import {compose, EventEmitter} from '@flecks/core';
const UPDATE_INTERVAL = 0.25;
export default (flecks) => {
const decorate = compose(
EventEmitter,
Synchronized(flecks),
);
return class Universe extends decorate(JsonResource) {
isUpdating = false;
online = [];
time = 0;
updater = new Ticker(UPDATE_INTERVAL);
constructor() {
super();
this.updater.on('tick', this.update, this);
}
acceptPacket(packet) {
if ('UniverseUpdateTime' === packet.constructor.type) {
this.time = packet.data;
}
}
async load(json) {
await super.load(json);
if (json.online) {
this.online = json.online;
}
if (json.time) {
this.time = json.time;
}
}
packetsFor() {
const packets = [];
if (this.isUpdating) {
packets.push(['UniverseUpdateTime', this.time]);
this.isUpdating = false;
}
return packets;
}
tick(elapsed) {
this.time += elapsed;
this.updater.tick(elapsed);
}
toJSON() {
return {
online: this.online,
time: this.time,
};
}
update() {
this.isUpdating = true;
}
};
};

View File

@ -61,6 +61,7 @@ export default class Universe {
entity.startInformingAbout(room);
}
};
entity.startInformingAbout(this.$$universe);
entity.on('currentRoomChanged', onCurrentRoomChanged);
player.once('removed', () => {
entity.off('currentRoomChanged', onCurrentRoomChanged);
@ -130,6 +131,7 @@ export default class Universe {
await mkdir(path);
}
const universe = new this(flecks, path);
await universe.loadOrCreateResource();
const {Room} = flecks.get('$avocado/resource.resources');
await Promise.all(
(await pglob('**/*.room.json', {cwd: path}))
@ -166,10 +168,32 @@ export default class Universe {
}
}
async loadOrCreateResource() {
const uri = join(this.$$root, 'index.universe.json');
try {
const stats = await stat(uri);
if (!stats.isFile()) {
throw new Error(`universe resource ${uri} is not a file`);
}
}
catch (error) {
if ('ENOENT' !== error.code) {
throw error;
}
debug("resource doesn't exist, creating...");
await writeFile(uri, '{}');
}
const {Universe} = this.$$flecks.get('$avocado/resource.resources');
const buffer = await readFile(uri);
const json = JSON.parse(buffer.toString());
this.$$universe = await Universe.load(json);
}
removePlayer(player) {
const {entity} = player;
const room = this.room(entity.currentRoom);
entity.stopInformingAbout(room);
entity.stopInformingAbout(this.$$universe);
room.removeEntity(entity);
const index = this.$$players.indexOf(player);
if (-1 !== index) {
@ -215,6 +239,7 @@ export default class Universe {
for (let i = 0; i < this.$$roomsFlat.length; i++) {
this.$$roomsFlat[i].tick(elapsed);
}
this.$$universe.tick(elapsed);
}
}