diff --git a/app/src/react/components/humus.jsx b/app/src/react/components/humus.jsx index 29e99bb..e6d64a1 100644 --- a/app/src/react/components/humus.jsx +++ b/app/src/react/components/humus.jsx @@ -24,7 +24,6 @@ import Login from 'components/login'; import Room from 'components/room'; import Stage from 'components/stage'; import RoomView from 'components/renderers/room-view'; -// import Stupid from 'components/renderers/stupid'; import Title from 'components/title'; import Ui from 'components/ui'; import Universe from 'components/universe'; @@ -40,7 +39,7 @@ const RoutedStage = () => { const location = useLocation(); const latus = useLatus(); return ( - + <__RouterContext.Provider value={{location}}> @@ -59,7 +58,6 @@ const RoutedStage = () => { const Humus = ({history}) => { const isNative = useIsNative(); - // const location = useLocation(); return (
@@ -69,7 +67,7 @@ const Humus = ({history}) => { {isLoggedIn ? : Login} - + {isNative ? </Route> : <Redirect to="/universe" />} </Switch> diff --git a/app/src/react/components/renderers/room-view.jsx b/app/src/react/components/renderers/room-view.jsx index ec03ea9..e5ef034 100644 --- a/app/src/react/components/renderers/room-view.jsx +++ b/app/src/react/components/renderers/room-view.jsx @@ -1,11 +1,10 @@ -import React, {useState} from 'react'; +import React, {useEffect, useMemo, useState} from 'react'; -import {Container} from '@avocado/graphics'; +import {Container, Renderer} from '@avocado/graphics'; import {resource} from '@avocado/resource'; import {RoomView} from '@avocado/topdown'; -import {PixiComponent} from '@inlet/react-pixi'; +import {PixiComponent, useApp} from '@inlet/react-pixi'; import {useLatus} from '@latus/react/client'; -import {useSocketPacket} from '@latus/socket'; const container = new Container(); @@ -16,29 +15,43 @@ const Component = PixiComponent('RoomView', { container.removeAllChildren(); } if (newProps.room) { - container.addChild(new RoomView(newProps.room)); + container.addChild(new RoomView(newProps.room, newProps.renderer)); } }, }); export default () => { + const app = useApp(); + const renderer = useMemo(() => { + if (app.renderer) { + const renderer = new Renderer(); + renderer.renderer = app.renderer; + return renderer; + } + return undefined; + }, [app.renderer]); const latus = useLatus(); const [room, setRoom] = useState(); - const {config: {'%synchronizer': synchronizer}} = latus; - useSocketPacket((packet) => { - const {constructor: {s13nType}} = packet; - if ('create' === s13nType) { + const synchronizer = latus.get('%synchronizer'); + useEffect(() => { + if (!synchronizer) { + return undefined; + } + const onCreated = (type, created) => { const {fromResourceType: {Room}} = resource(latus); - const {type, id} = packet.data.synchronized; switch (type) { // Track room. case Room.resourceId: { - setRoom(synchronizer.synchronized(type, id)); + setRoom(created); break; } default: } - } + }; + synchronizer.on('created', onCreated); + return () => { + synchronizer.off('created', onCreated); + }; }); - return <Component room={room} />; + return <Component renderer={renderer} room={room} />; }; diff --git a/packages/universe/src/client/index.js b/packages/universe/src/client/index.js index 82e61a2..9a5a332 100644 --- a/packages/universe/src/client/index.js +++ b/packages/universe/src/client/index.js @@ -1,14 +1,12 @@ import {ReceiverSynchronizer} from '@avocado/s13n'; import {gatherWithLatus} from '@latus/core'; -import {socket} from '@latus/socket'; export default { hooks: { '@latus/http/client/up': (latus) => { - const synchronizer = new ReceiverSynchronizer(); - // eslint-disable-next-line no-param-reassign - latus.config['%synchronizer'] = synchronizer; - socket(latus).on('packet', synchronizer.acceptPacket, synchronizer); + const synchronizer = new ReceiverSynchronizer(latus); + latus.set('%synchronizer', synchronizer); + latus.get('%socket').on('packet', synchronizer.acceptPacket, synchronizer); }, '@latus/socket/packets': gatherWithLatus( require.context('./packets', false, /\.js$/), diff --git a/packages/universe/src/resources/universe.js b/packages/universe/src/resources/universe.js index 45cdd1e..0e8e78f 100644 --- a/packages/universe/src/resources/universe.js +++ b/packages/universe/src/resources/universe.js @@ -22,19 +22,13 @@ export default (latus) => class Universe extends JsonResource { #tps; - constructor({rooms = {}, tps = 60} = {}) { - super(); - Object.entries(rooms).forEach(([uri, room]) => { - this.addRoom(uri, room); - }); - this.#tps = tps; - } - addPlayer({entity, socket, user}) { const room = this.room(entity.currentRoom); room.addEntityToLayer(entity, 0); entity.addSynchronized(room); - this.#players.push(new Player({entity, socket, user})); + const player = new Player({entity, socket, user}); + this.#players.push(player); + return player; } addRoom(uri, room) { @@ -68,14 +62,23 @@ export default (latus) => class Universe extends JsonResource { return extended; } + load({rooms = {}, tps = 60} = {}) { + Object.entries(rooms).forEach(([uri, room]) => { + this.addRoom(uri, room); + }); + this.#tps = tps; + } + playerForUser(userId) { return this.#players.find(({user}) => user.id === userId); } - inform() { + async inform() { + const promises = []; for (let i = 0; i < this.#players.length; ++i) { - this.#players[i].inform(); + promises.push(this.#players[i].inform()); } + await Promise.all(promises); for (let i = 0; i < this.#roomsFlat.length; i++) { this.#roomsFlat[i].cleanPackets(); } @@ -88,6 +91,17 @@ export default (latus) => class Universe extends JsonResource { return super.load(json); } + removePlayer(player) { + const {entity} = player; + const room = this.room(entity.currentRoom); + entity.removeSynchronized(room); + room.removeEntityFromLayer(entity, 0); + const index = this.#players.indexOf(player); + if (-1 !== index) { + this.#players.splice(player, 1); + } + } + room(uri) { return this.#rooms[uri]; } @@ -95,8 +109,14 @@ export default (latus) => class Universe extends JsonResource { start() { if (!this.#informLoopHandle) { this.#informLoopHandle = setInterval( - () => { - this.inform(); + async () => { + try { + await this.inform(); + } + catch (error) { + // eslint-disable-next-line no-console + console.error('Informing error:', error); + } }, 1000 / 60, ); diff --git a/packages/universe/src/server/packets/join.js b/packages/universe/src/server/packets/join.js index df9ce06..cdff994 100644 --- a/packages/universe/src/server/packets/join.js +++ b/packages/universe/src/server/packets/join.js @@ -21,7 +21,7 @@ export default (latus) => class ServerJoin extends Join() { '%universe': universe, }, } = latus; - const player = universe.playerForUser(user ? user.id : 0); + let player = universe.playerForUser(user ? user.id : 0); if (player) { return player.entity.instanceUuid; } @@ -29,11 +29,14 @@ export default (latus) => class ServerJoin extends Join() { const entity = await Entity.load( {extends: join(dirname(universe.uri), 'players', user ? user.name : 'cha0s', 'index.entity.json')}, ); - universe.addPlayer({ + player = universe.addPlayer({ entity, socket, user, }); + socket.on('disconnect', () => { + universe.removePlayer(player); + }); return entity.instanceUuid; }