diff --git a/build/server.js b/build/server.js index 1ee668f..4d1a2f7 100755 --- a/build/server.js +++ b/build/server.js @@ -20,6 +20,7 @@ const build = () => function build() { 'orm', 'haxework:git', 'haxe-crypto', + 'yield', ], cp: [ 'src/common/haxe', diff --git a/src/client/haxe/ru/m/tankz/Init.hx b/src/client/haxe/ru/m/tankz/Init.hx index 830fa7a..cade9b2 100644 --- a/src/client/haxe/ru/m/tankz/Init.hx +++ b/src/client/haxe/ru/m/tankz/Init.hx @@ -3,8 +3,12 @@ package ru.m.tankz; import haxework.provider.Provider; import haxework.resources.IResources; import haxework.resources.Resources; +import ru.m.tankz.bundle.ConfigBundle; +import ru.m.tankz.bundle.IConfigBundle; import ru.m.tankz.bundle.ILevelBundle; import ru.m.tankz.bundle.LevelBundle; +import ru.m.tankz.control.ClientControlFactory; +import ru.m.tankz.control.IControlFactory; import ru.m.tankz.game.ClassicGame; import ru.m.tankz.game.DotaGame; import ru.m.tankz.game.Game; @@ -19,11 +23,12 @@ class Init { public static function init():Void { Provider.setFactory(IResources, Resources); Provider.setFactory(ILevelBundle, LevelBundle); - Provider.setFactory(ILevelBundle, LevelBundle); + Provider.setFactory(IConfigBundle, ConfigBundle); Provider.setFactory(SaveStorage, SaveStorage); Provider.setFactory(UserStorage, UserStorage); Provider.setFactory(SoundManager, SoundManager); Provider.setFactory(NetworkManager, NetworkManager); + Provider.setFactory(IControlFactory, ClientControlFactory); Provider.setFactory(Game, ClassicGame, ClassicGame.TYPE); Provider.setFactory(Game, DotaGame, DotaGame.TYPE); } diff --git a/src/client/haxe/ru/m/tankz/control/ClientControlFactory.hx b/src/client/haxe/ru/m/tankz/control/ClientControlFactory.hx new file mode 100644 index 0000000..58eba24 --- /dev/null +++ b/src/client/haxe/ru/m/tankz/control/ClientControlFactory.hx @@ -0,0 +1,23 @@ +package ru.m.tankz.control; + +import ru.m.tankz.game.Player; +import ru.m.tankz.bot.BotControl; + + +class ClientControlFactory implements IControlFactory { + + private var humanControlIndex:Int; + + public function new() { + humanControlIndex = 0; + } + + public function build(player:Player):Control { + return switch (player.config.control) { + case Control.HUMAN: new HumanControl(player.id, humanControlIndex++); + case Control.BOT: new BotControl(player.id); + case Control.NONE: null; + case _: throw 'Unsupported control type: "${player.config.control}"'; + } + } +} diff --git a/src/client/haxe/ru/m/draw/Color.hx b/src/common/haxe/ru/m/draw/Color.hx similarity index 100% rename from src/client/haxe/ru/m/draw/Color.hx rename to src/common/haxe/ru/m/draw/Color.hx diff --git a/src/common/haxe/ru/m/tankz/control/IControlFactory.hx b/src/common/haxe/ru/m/tankz/control/IControlFactory.hx new file mode 100644 index 0000000..74e978b --- /dev/null +++ b/src/common/haxe/ru/m/tankz/control/IControlFactory.hx @@ -0,0 +1,8 @@ +package ru.m.tankz.control; + +import ru.m.tankz.game.Player; + + +interface IControlFactory { + public function build(player:Player):Control; +} diff --git a/src/common/haxe/ru/m/tankz/control/NoneControlFactory.hx b/src/common/haxe/ru/m/tankz/control/NoneControlFactory.hx new file mode 100644 index 0000000..620154e --- /dev/null +++ b/src/common/haxe/ru/m/tankz/control/NoneControlFactory.hx @@ -0,0 +1,11 @@ +package ru.m.tankz.control; + +import ru.m.tankz.game.Player; + + +class NoneControlFactory implements IControlFactory { + + public function build(player:Player):Control { + return null; + } +} diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx index 2578adb..aed43f7 100644 --- a/src/common/haxe/ru/m/tankz/game/Game.hx +++ b/src/common/haxe/ru/m/tankz/game/Game.hx @@ -1,5 +1,6 @@ package ru.m.tankz.game; +import ru.m.tankz.control.IControlFactory; import ru.m.tankz.game.GameSave.PlayerSave; import haxe.ds.Option; import haxe.Timer; @@ -8,12 +9,10 @@ import promhx.Deferred; import promhx.Stream; import ru.m.geom.Direction; import ru.m.geom.Point; -import ru.m.tankz.bot.BotControl; import ru.m.tankz.bundle.IConfigBundle; import ru.m.tankz.bundle.ILevelBundle; import ru.m.tankz.config.Config; import ru.m.tankz.control.Control; -import ru.m.tankz.control.HumanControl; import ru.m.tankz.core.Bonus; import ru.m.tankz.core.Eagle; import ru.m.tankz.core.Entity; @@ -88,19 +87,14 @@ class Game implements EngineListener { points = level.points != null ? level.points : config.points; engine.map.setData(level.data); teams = new Map(); - var humanControlIndex = 0; + var controlFactory:IControlFactory = Provider.build(IControlFactory); for (teamConfig in preset.teams) { var teamPoints = points.filter(function(p:SpawnPoint) return p.team == teamConfig.id); var team:Team = new Team(teamConfig, teamPoints, save); teams[team.id] = team; for (player in team.players.iterator()) { if (player.config.control != null) { - var control = switch (player.config.control) { - case Control.HUMAN: new HumanControl(player.id, humanControlIndex++); - case Control.BOT: new BotControl(player.id); - case Control.NONE: null; - case _: throw 'Unsupported control type: "${player.config.control}"'; - } + var control = controlFactory.build(player); L.d(TAG, 'control(${player.id} - ${control})'); if (control != null) { player.control = control; diff --git a/src/server/haxe/ru/m/tankz/server/game/GameManager.hx b/src/server/haxe/ru/m/tankz/server/game/GameManager.hx index 7fbefaf..dc9e29c 100644 --- a/src/server/haxe/ru/m/tankz/server/game/GameManager.hx +++ b/src/server/haxe/ru/m/tankz/server/game/GameManager.hx @@ -1,11 +1,20 @@ package ru.m.tankz.server.game; +import ru.m.tankz.game.GameSave; +import ru.m.tankz.proto.pack.StartGameResponse; +import ru.m.tankz.game.ClassicGame; +import ru.m.tankz.proto.pack.LeaveGameResponse; +import ru.m.tankz.proto.pack.JoinGameResponse; +import ru.m.tankz.proto.pack.ListGameResponse; +import ru.m.tankz.proto.pack.CreateGameResponse; +import ru.m.tankz.proto.pack.Response; +import ru.m.tankz.game.Game as RunGame; import ru.m.tankz.proto.core.GameState; import ru.m.tankz.proto.core.Game; +import ru.m.tankz.proto.core.User; import ru.m.tankz.server.session.Thread; -import ru.m.tankz.engine.Engine; import ru.m.tankz.server.session.Session; -import protohx.Message; + /** * @@ -44,13 +53,12 @@ class GameManager { public static var byGameId:Map = new Map(); public static var byPersonId:Map = new Map(); - public static var subscribers:Map = new Map(); + public static var subscribers:Map = new Map(); private static var idCounter:Int = 0; public var game(default, null):Game; - - public var engine(default, null):Engine; + public var runGame(default, null):RunGame; private var timer:NekoTimer; @@ -64,7 +72,7 @@ class GameManager { game.addPlayers(creator); byGameId.set(game.id, this); byPersonId.set(creator.uuid, this); - broadcast(new CreateGameResponse().setGame(game)); + broadcast(new Response().setCreateGame(new CreateGameResponse().setGame(game))); broadcastGames(); } @@ -73,32 +81,32 @@ class GameManager { } public function broadcastGames() { - var packet = new GamesResponse().setGames(getReadyGames()); + var packet = new Response().setListGame(new ListGameResponse().setGames(getReadyGames())); for (personId in subscribers.keys()) { - var session = Session.sessions.get(personId); + var session:Session = Session.sessions.get(personId); session.send(packet); } } - public function broadcast(packet:Message) { + public function broadcast(packet:Response) { for (player in game.players) { - var session = Session.sessions.get(player.uuid); + var session:Session = Session.sessions.get(player.uuid); session.send(packet); } } - public function join(person:Person) { - game.addPersons(person); - byPersonId.set(person.id, this); - broadcast(new JoinGameResponse().setGame(game)); + public function join(user:User) { + game.addPlayers(user); + byPersonId.set(user.uuid, this); + broadcast(new Response().setJoinGame(new JoinGameResponse().setGame(game))); } - public function leave(person:Person) { - game.setPersons(game.persons.filter(function(p) return p.id != person.id)); - byPersonId.remove(person.id); - var packet = new LeaveGameResponse().setGame(game); - Session.sessions.get(person.id).send(packet); - if (game.persons.length == 0/* || person.id == game.creator.id*/) { + public function leave(user:User) { + game.setPlayers(game.players.filter(function(p) return p.uuid != user.uuid)); + byPersonId.remove(user.uuid); + var packet = new Response().setLeaveGame(new LeaveGameResponse().setGame(game)); + Session.sessions.get(user.uuid).send(packet); + if (game.players.length == 0/* || person.id == game.creator.id*/) { stop(); } else { broadcast(packet); @@ -107,67 +115,33 @@ class GameManager { public function start() { game.setState(GameState.STARTED); - engine = new Engine(); - engine.init(DEFAULT.CONFIG); - var changes = engine.initTanks(game.persons); + runGame = new ClassicGame(); + runGame.start(new GameSave({type: ClassicGame.TYPE, presetId: ClassicGame.PLAYER1})); timer = new NekoTimer(30); timer.run = update; - broadcast(new StartGameResponse().setGame(game)); - broadcast(new GameUpdateResponse().setChanges(changes)); + broadcast(new Response().setStartGame(new StartGameResponse().setGame(game))); } public function stop() { game.setState(GameState.ENDED); - game.setPersons([]); + game.setPlayers([]); byGameId.remove(game.id); - for (p in game.persons) byPersonId.remove(p.id); + for (p in game.players) byPersonId.remove(p.uuid); if (timer != null) { timer.stop(); timer = null; } - broadcast(new LeaveGameResponse().setGame(game)); + broadcast(new Response().setLeaveGame(new LeaveGameResponse().setGame(game))); broadcastGames(); } - public function action(person:Person, action:GameActionRequest) { - var tank = engine.tanks.get(person.id); - switch (action.type) { - case GameActionType.SHOT: - var bullet = tank.shot(); - if (bullet != null) { - engine.mobileEntities.set(bullet.id, bullet); - changes.push(new GameChange() - .setType(GameChangeType.APPEND) - .setObjectType(GameObjectType.BULLET) - .setPersonId(bullet.personId) - .setObjectId(bullet.id) - .setX(bullet.x) - .setY(bullet.y) - .setDirectionX(bullet.direction.x) - .setDirectionY(bullet.direction.y) - ); - } - case GameActionType.MOVE: - tank.move(Direction.from(action.directionX, action.directionY)); - changes.push(new GameChange() - .setType(GameChangeType.DIRECTION) - .setObjectType(GameObjectType.TANK) - .setPersonId(tank.personId) - .setObjectId(tank.id) - .setDirectionX(tank.direction.x) - .setDirectionY(tank.direction.y) - ); - case GameActionType.STOP: - tank.stop(); - } - } - private function update() { - var changes = engine.update(); + runGame.engine.update(); + /*var changes = engine.update(); changes = this.changes.concat(changes); this.changes = []; if (changes.length > 0) { broadcast(new GameUpdateResponse().setChanges(changes)); - } + }*/ } } diff --git a/src/server/haxe/ru/m/tankz/server/session/Session.hx b/src/server/haxe/ru/m/tankz/server/session/Session.hx index daf06f7..c5dc945 100755 --- a/src/server/haxe/ru/m/tankz/server/session/Session.hx +++ b/src/server/haxe/ru/m/tankz/server/session/Session.hx @@ -1,25 +1,28 @@ package ru.m.tankz.server.session; -import ru.m.tankz.proto.pack.LeaveGameRequest; -import ru.m.tankz.proto.pack.LeaveGameResponse; -import ru.m.tankz.proto.pack.LogoutResponse; -import ru.m.tankz.proto.pack.LogoutRequest; +import com.hurlant.crypto.extra.UUID; import haxe.io.Bytes; import ru.m.connect.IConnection; import ru.m.connect.neko.NekoConnection; import ru.m.connect.neko.NekoWebConnection; -import ru.m.tankz.proto.core.Game; import ru.m.tankz.proto.core.User; import ru.m.tankz.proto.pack.CreateGameRequest; import ru.m.tankz.proto.pack.CreateGameResponse; import ru.m.tankz.proto.pack.JoinGameRequest; import ru.m.tankz.proto.pack.JoinGameResponse; +import ru.m.tankz.proto.pack.LeaveGameRequest; +import ru.m.tankz.proto.pack.LeaveGameResponse; import ru.m.tankz.proto.pack.ListGameRequest; import ru.m.tankz.proto.pack.ListGameResponse; import ru.m.tankz.proto.pack.LoginRequest; import ru.m.tankz.proto.pack.LoginResponse; +import ru.m.tankz.proto.pack.LogoutRequest; +import ru.m.tankz.proto.pack.LogoutResponse; import ru.m.tankz.proto.pack.Request; import ru.m.tankz.proto.pack.Response; +import ru.m.tankz.proto.pack.StartGameRequest; +import ru.m.tankz.proto.pack.StartGameResponse; +import ru.m.tankz.server.game.GameManager; import sys.net.Socket; @@ -66,96 +69,59 @@ class Session { public function onRequest(request:Request):Void { if (request.hasLogin()) { - connection.send(new Response().setLogin(login(request.login))); + send(new Response().setLogin(login(request.login))); } else if (request.hasLogout()) { - connection.send(new Response().setLogout(logout(request.logout))); + send(new Response().setLogout(logout(request.logout))); } else if (request.hasListGame()) { - connection.send(new Response().setListGame(listGame(request.listGame))); + send(new Response().setListGame(listGame(request.listGame))); } else if (request.hasCreateGame()) { - connection.send(new Response().setCreateGame(createGame(request.createGame))); + send(new Response().setCreateGame(createGame(request.createGame))); } else if (request.hasJoinGame()) { - connection.send(new Response().setJoinGame(joinGame(request.joinGame))); + send(new Response().setJoinGame(joinGame(request.joinGame))); } else if (request.hasLeaveGame()) { - connection.send(new Response().setLeaveGame(leaveGame(request.leaveGame))); + send(new Response().setLeaveGame(leaveGame(request.leaveGame))); } } private function login(request:LoginRequest):LoginResponse { user = new User() - .setUuid(request.uuid != null ? request.uuid : 'xxx') + .setUuid(request.uuid != null ? request.uuid : UUID.generateRandom().toString()) .setName(request.name); sessions.set(user.uuid, this); + GameManager.subscribers.set(user.uuid, true); return new LoginResponse().setUser(user); } private function logout(request:LogoutRequest):LogoutResponse { + GameManager.subscribers.remove(user.uuid); user = null; return new LogoutResponse(); } private function listGame(request:ListGameRequest):ListGameResponse { - return new ListGameResponse().setGames([ - new Game().setId(1).setType('test').setPlayers([new User().setUuid('test').setName('test')]) - ]); + return new ListGameResponse().setGames(GameManager.getReadyGames()); } private function createGame(request:CreateGameRequest):CreateGameResponse { - return new CreateGameResponse().setGame( - new Game().setId(2).setType(request.type).setPlayers([user]) - ); + var gameManager:GameManager = new GameManager(user); + return new CreateGameResponse().setGame(gameManager.game); } private function joinGame(request:JoinGameRequest):JoinGameResponse { - return new JoinGameResponse().setGame( - new Game().setId(request.gameId).setType('test').setPlayers([ - new User().setUuid('test').setName('test'), - user - ]) - ); + var gameManager:GameManager = GameManager.byGameId.get(request.gameId); + gameManager.join(user); + return new JoinGameResponse().setGame(gameManager.game); } private function leaveGame(request:LeaveGameRequest):LeaveGameResponse { - return new LeaveGameResponse(); + var gameManager:GameManager = GameManager.byPersonId.get(user.uuid); + gameManager.leave(user); + return new LeaveGameResponse().setGame(gameManager.game); } - /*public function onPersonSelectRequest(packet:PersonSelectRequest):Void { - var db = new DbProvider(); - var person = db.getPerson(packet.personId); - if (person != null) { - this.person = person; - sessions.set(person.id, this); - connection.send(new PersonSelectResponse().setPerson(person)); - } else { - connection.send(new ErrorResponse().setCode(404).setMessage("Person not found")); - } + private function startGame(request:StartGameRequest):StartGameResponse { + var gameManager:GameManager = GameManager.byPersonId.get(user.uuid); + gameManager.start(); + return new StartGameResponse().setGame(gameManager.game); } - - public function onGamesSubscribeRequest(packet:GamesSubscribeRequest):Void { - GameManager.subscribers.set(person.id, true); - connection.send(new GamesResponse().setGames(GameManager.getReadyGames())); - } - - public function onGamesUnSubscribeRequest(packet:GamesUnSubscribeRequest):Void { - GameManager.subscribers.remove(person.id); - } - - public function onCreateGameRequest(packet:CreateGameRequest):Void { - new GameManager(person); - } - - public function onJoinGameRequest(packet:JoinGameRequest):Void { - GameManager.byGameId.get(packet.gameId).join(person); - } - - public function onLeaveGameRequest(packet:LeaveGameRequest):Void { - GameManager.byPersonId.get(person.id).leave(person); - } - - public function onStartGameRequest(packet:StartGameRequest):Void { - GameManager.byPersonId.get(person.id).start(); - } - - public function onGameActionRequest(packet:GameActionRequest):Void { - GameManager.byPersonId.get(person.id).action(person, packet); - }*/ } \ No newline at end of file