UNPKG

reldens

Version:
128 lines (119 loc) 5.02 kB
/** * * Reldens - Prediction World Creator * */ const { CollisionsManager } = require('../../world/server/collisions-manager'); const { P2world } = require('../../world/server/p2world'); const { WorldPointsValidator } = require('../../world/world-points-validator'); const { WorldTimer } = require('../../world/world-timer'); const { Logger, sc } = require('@reldens/utils'); class PredictionWorldCreator { async createSceneWorld(scene) { if(!scene.experimentalClientPrediction){ return; } let validLayers = this.findValidLayers(scene); let mapJson = this.cloneMapJson(scene, validLayers); let worldData = { sceneName: scene.key, roomId: scene.params.roomId, roomMap: scene.params.roomMap, mapJson, config: scene.configManager, events: scene.eventsManager, allowSimultaneous: scene.configManager.get('client/general/controls/allowSimultaneousKeys', true), worldConfig: scene.gameManager.activeRoomEvents.roomData?.worldConfig || scene.worldConfig }; scene.worldPrediction = this.createWorldInstance(worldData); scene.worldPrediction.createLimits(); await scene.worldPrediction.createWorldContent({}); let currentPlayer = scene.gameManager.getCurrentPlayer(); if(!currentPlayer){ Logger.error('Current player not present for prediction.'); return; } let playerData = { id: currentPlayer.playerId, width: scene.configManager.get('client/players/physicalBody/width'), height: scene.configManager.get('client/players/physicalBody/height'), bodyState: currentPlayer.state // @TODO - BETA - Check speed is required here. }; let predictionBody = scene.worldPrediction.createPlayerBody(playerData); predictionBody.updateBodyState = this.updateBodyStateOverride(predictionBody, currentPlayer); currentPlayer.predictionBody = predictionBody; scene.worldPredictionTimer = new WorldTimer({ callbacks: [() => { if(!scene.worldPrediction){ Logger.error('Scene World not longer exists.', scene.roomWorld); return; } scene.worldPrediction.removeBodiesFromWorld(); }] }); scene.worldPredictionTimer.startWorldSteps(scene.worldPrediction); scene.collisionsManager = new CollisionsManager({roomWorld: scene.worldPrediction}); currentPlayer.pointsValidator = new WorldPointsValidator(mapJson.width, mapJson.height); } cloneMapJson(scene, validLayers) { return Object.assign( {}, (scene.cache?.tilemap?.entries?.entries[scene.tileset.name]?.data || {}), {layers: validLayers} ); } findValidLayers(scene) { let validLayers = []; for(let layer of scene.cache.tilemap.entries.entries[scene.tileset.name].data.layers){ if(-1 !== layer.name.indexOf('collision')){ validLayers.push(layer); } } return validLayers; } updateBodyStateOverride(predictionBody, currentPlayer) { return () => { if(!sc.hasOwn(predictionBody.bodyState, 'x') || !sc.hasOwn(predictionBody.bodyState, 'y')){ return; } if(!predictionBody.position[0] || !predictionBody.position[1]){ return; } // only update the body if it moves: if(predictionBody.isNotMoving()){ predictionBody.bodyState.mov = false; return; } // update position: if(predictionBody.bodyState.x !== predictionBody.position[0]){ predictionBody.bodyState.x = predictionBody.position[0]; } if(predictionBody.bodyState.y !== predictionBody.position[1]){ predictionBody.bodyState.y = predictionBody.position[1]; } // start or stop animation: let newStateMov = 0 !== Number(Number(predictionBody.velocity[0]).toFixed(2)) || 0 !== Number(predictionBody.velocity[1].toFixed(2)); if(predictionBody.bodyState.mov !== newStateMov){ predictionBody.bodyState.mov = newStateMov; } let state = { x: predictionBody.position[0], y: predictionBody.position[1], dir: predictionBody.bodyState.dir }; currentPlayer.updatePlayer(currentPlayer.playerId, {state}); }; } createWorldInstance(worldData) { return new P2world(worldData); } } module.exports.PredictionWorldCreator = PredictionWorldCreator;