UNPKG

reldens

Version:
238 lines (223 loc) 9.54 kB
/** * * Reldens - RoomsManager * */ const { RoomGame } = require('./game'); const { RoomScene } = require('./scene'); const { RoomsConst } = require('../constants'); const { GameConst } = require('../../game/constants'); const { ErrorManager, Logger, sc } = require('@reldens/utils'); class RoomsManager { constructor(props) { this.events = sc.get(props, 'events', false); if(!this.events){ Logger.error('EventsManager undefined in RoomsManager.'); } this.dataServer = sc.get(props, 'dataServer', false); if(!this.dataServer){ Logger.error('DataServer undefined in RoomsManager.'); } this.loadedRooms = false; this.loadedRoomsById = false; this.loadedRoomsByName = false; this.defineExtraRooms = []; this.definedRooms = {}; this.creatingInstances = {}; this.createdInstances = {}; this.instanceIdByName = {}; this.availableRooms = {}; this.availableRoomsGuest = {}; } async defineRoomsInGameServer(gameServer, props) { await this.events.emit('reldens.roomsDefinition', this.defineExtraRooms); if(!this.defineExtraRooms.length){ Logger.info('None extra rooms to be defined.'); } // dispatch event to get the global message actions (that will be listened by every room): let globalMessageActions = {}; await this.events.emit('reldens.roomsMessageActionsGlobal', globalMessageActions); // lobby room: await this.defineRoom(gameServer, GameConst.ROOM_GAME, RoomGame, props, globalMessageActions); Logger.info('Loaded game room using stored configuration.'); let counter = await this.defineExtraRoomsInGameServer(gameServer, props, globalMessageActions); let rooms = await this.loadRooms(); // register room-scenes from storage: counter = await this.defineRoomsFromModels(rooms, props, gameServer, globalMessageActions, counter); Logger.info('Total rooms loaded: '+counter); await this.events.emit('reldens.defineRoomsInGameServerDone', this); return this.definedRooms; } async defineRoomsFromModels(rooms, props, gameServer, globalMessageActions, counter) { if(0 === rooms.length){ return counter; } for(let roomModel of rooms){ let roomClass = RoomScene; if(roomModel.roomClassPath){ let roomClassDefinition = props.config.get('server/customClasses/roomsClass/'+roomModel.roomClassPath); if(!roomClassDefinition){ Logger.error('Custom room class not found for room ID "'+roomModel.roomId+'".'); continue; } roomClass = roomClassDefinition; } await this.defineRoom(gameServer, roomModel.roomName, roomClass, props, globalMessageActions, roomModel); counter++; Logger.info('Loaded room: '+roomModel.roomName); } return counter; } async defineExtraRoomsInGameServer(gameServer, props, globalMessageActions) { if(0 === this.defineExtraRooms.length){ return 0; } let counter = 0; for(let roomData of this.defineExtraRooms){ await this.defineRoom(gameServer, roomData.roomName, roomData.room, props, globalMessageActions); counter++; Logger.info('Loaded extra room: '+roomData.roomName+(roomData.serverUrl ? '('+roomData.serverUrl+')' : '')); } return counter; } async defineRoom(gameServer, roomName, roomClass, props, globalMessageActions, roomModel = false) { let roomMessageActions = Object.assign({}, globalMessageActions); // run message actions event for each room: await this.events.emit('reldens.roomsMessageActionsByRoom', roomMessageActions, roomName); let roomProps = { loginManager: props.loginManager, config: props.config, messageActions: roomMessageActions, events: this.events, roomsManager: this, dataServer: this.dataServer, featuresManager: props.featuresManager }; if(roomModel){ roomProps.roomData = roomModel; } gameServer.define(roomName, roomClass, roomProps); this.definedRooms[roomName] = {roomClass, roomProps}; } async loadRooms() { // @TODO - BETA - This will change when hot-plug is introduced. if(this.loadedRooms){ return this.loadedRooms; } let roomsModels = await this.dataServer.getEntity('rooms').loadAllWithRelations([ 'rooms_change_points.next_room', 'rooms_return_points.from_room' ]); if(!roomsModels){ ErrorManager.error('None rooms found in the database. A room is required to run.'); } let rooms = []; let roomsById = {}; let roomsByName = {}; for(let room of roomsModels){ let temp = this.generateRoomModel(room); if(!temp){ Logger.error('Room model could not be generated.', room); continue; } rooms.push(temp); roomsById[room.id] = temp; roomsByName[room.name] = temp; } this.loadedRooms = rooms; this.loadedRoomsById = roomsById; this.loadedRoomsByName = roomsByName; return this.loadedRooms; } async loadRoomById(roomId) { return this.loadRoomBy('id', roomId); } async loadRoomByName(roomName) { return this.loadRoomBy('name', roomName); } async loadRoomBy(property, value) { try { let propertyLabel = property.charAt(0).toUpperCase()+property.slice(1); let managerProperty = 'loadedRoomsBy'+propertyLabel; if(this[managerProperty][value]){ return this[managerProperty][value]; } let room = await this.dataServer.getEntity('rooms').loadBy(property, value); if(!room){ Logger.critical('Load room by "'+property+'" with value "'+value+'", not found.'); return false; } let temp = this.generateRoomModel(room); if(!temp){ Logger.critical('Loading room by "'+property+'" with value "'+value+'", model could not be generated.'); return false; } this.loadedRooms.push(temp); this.loadedRoomsById[room.id] = temp; this.loadedRoomsByName[room.name] = temp; return temp; } catch (error) { Logger.critical('Load room by "'+property+'" with value "'+value+'" failed.', error); } return false; } generateRoomModel(room) { if(!sc.isObject(room) || 0 === Object.keys(room).length){ Logger.critical('Room not available.', room); return false; } let roomDataModel = { roomId: room.id, roomName: room.name, roomTitle: room.title, serverUrl: room.server_url, // @NOTE: the roomMap is the map file name without the extension (the extension is only used in the admin). roomMap: (room?.map_filename || '').toString().replace(/^.*[\\/]/, '').replace(/\.[^.]*$/, ''), sceneImages: room.scene_images.split(','), changePoints: [], returnPoints: [], roomClassPath: room.room_class_key, returnPointDefault: false, customData: sc.toJson(room.customData, {}) }; for(let changePoint of room.rooms_change_points){ let changePointData = {}; changePointData[RoomsConst.TILE_INDEX] = changePoint.tile_index; changePointData[RoomsConst.NEXT_SCENE] = changePoint.next_room.name; roomDataModel.changePoints.push(changePointData); } for(let returnPosition of room.rooms_return_points){ let fromRoom = returnPosition.from_room ? returnPosition.from_room.name : false; let position = { [RoomsConst.RETURN_POINT_KEYS.DIRECTION]: returnPosition.direction, [RoomsConst.RETURN_POINT_KEYS.X]: returnPosition.x, [RoomsConst.RETURN_POINT_KEYS.Y]: returnPosition.y, [RoomsConst.RETURN_POINT_KEYS.PREVIOUS]: fromRoom }; if(sc.hasOwn(returnPosition, 'is_default') && returnPosition.is_default){ position[RoomsConst.RETURN_POINT_KEYS.DEFAULT] = returnPosition.is_default; roomDataModel.returnPointDefault = position; } roomDataModel.returnPoints.push(position); } if(0 === roomDataModel.returnPoints.length){ Logger.warning('Return points found for room: '+roomDataModel.roomName+'. Room ID: '+roomDataModel.roomId); } if(!roomDataModel.returnPointDefault){ roomDataModel.returnPointDefault = roomDataModel.returnPoints[0]; } return roomDataModel; } } module.exports.RoomsManager = RoomsManager;