From 3eee4db51bfaba54305d326759d99060a6de8ade Mon Sep 17 00:00:00 2001 From: shmyga Date: Wed, 12 Aug 2015 16:00:41 +0300 Subject: [PATCH] update --- .../ClientTankz.hx => engine/ClientEngine.hx} | 4 +- src/client/haxe/ru/m/tankz/render/IRender.hx | 4 +- src/client/haxe/ru/m/tankz/render/Render.hx | 4 +- .../haxe/ru/m/tankz/view/frames/GameFrame.hx | 22 +- .../tankz/{game/Tankz.hx => engine/Engine.hx} | 4 +- .../{game/ITankz.hx => engine/IEngine.hx} | 4 +- src/common/proto/base.proto | 8 + .../haxe/ru/m/tankz/server/game/Game.hx | 12 -- .../ru/m/tankz/server/game/GameManager.hx | 170 +++++++++++++++ .../haxe/ru/m/tankz/server/session/Session.hx | 196 ++---------------- 10 files changed, 211 insertions(+), 217 deletions(-) rename src/client/haxe/ru/m/tankz/{game/ClientTankz.hx => engine/ClientEngine.hx} (92%) rename src/common/haxe/ru/m/tankz/{game/Tankz.hx => engine/Engine.hx} (98%) rename src/common/haxe/ru/m/tankz/{game/ITankz.hx => engine/IEngine.hx} (89%) delete mode 100644 src/server/haxe/ru/m/tankz/server/game/Game.hx create mode 100644 src/server/haxe/ru/m/tankz/server/game/GameManager.hx diff --git a/src/client/haxe/ru/m/tankz/game/ClientTankz.hx b/src/client/haxe/ru/m/tankz/engine/ClientEngine.hx similarity index 92% rename from src/client/haxe/ru/m/tankz/game/ClientTankz.hx rename to src/client/haxe/ru/m/tankz/engine/ClientEngine.hx index 2d36ff7..acde717 100644 --- a/src/client/haxe/ru/m/tankz/game/ClientTankz.hx +++ b/src/client/haxe/ru/m/tankz/engine/ClientEngine.hx @@ -1,4 +1,4 @@ -package ru.m.tankz.game; +package ru.m.tankz.engine; import ru.m.tankz.core.Direction; import ru.m.tankz.core.Tank.TankAction; @@ -6,7 +6,7 @@ import flash.ui.Keyboard; import ru.m.tankz.core.PlayerTank; import ru.m.tankz.core.ITank; -class ClientTankz extends Tankz { +class ClientEngine extends Engine { public var personId(default, default):Int; diff --git a/src/client/haxe/ru/m/tankz/render/IRender.hx b/src/client/haxe/ru/m/tankz/render/IRender.hx index 7dd366f..6ddc8da 100755 --- a/src/client/haxe/ru/m/tankz/render/IRender.hx +++ b/src/client/haxe/ru/m/tankz/render/IRender.hx @@ -1,8 +1,8 @@ package ru.m.tankz.render; import haxework.gui.IView; -import ru.m.tankz.game.ITankz; +import ru.m.tankz.engine.IEngine; interface IRender extends IView { - public function draw(game:ITankz):Void; + public function draw(game:IEngine):Void; } diff --git a/src/client/haxe/ru/m/tankz/render/Render.hx b/src/client/haxe/ru/m/tankz/render/Render.hx index d0c1b42..6a6fb8c 100755 --- a/src/client/haxe/ru/m/tankz/render/Render.hx +++ b/src/client/haxe/ru/m/tankz/render/Render.hx @@ -3,7 +3,7 @@ package ru.m.tankz.render; import flash.display.Sprite; import flash.display.Graphics; import haxework.gui.SpriteView; -import ru.m.tankz.game.ITankz; +import ru.m.tankz.engine.IEngine; class Render extends SpriteView implements IRender { @@ -18,7 +18,7 @@ class Render extends SpriteView implements IRender { contentAsSprite.addChild(tankLayer); } - public function draw(game:ITankz):Void { + public function draw(game:IEngine):Void { var mapWidth = game.map.gridWidth * game.map.cellWidth; var mapHeight = game.map.gridHeight * game.map.cellHeight; diff --git a/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx b/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx index 01ed32e..2a813a5 100755 --- a/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/frames/GameFrame.hx @@ -4,7 +4,7 @@ import ru.m.tankz.core.MobileEntity; import ru.m.tankz.core.Direction; import ru.m.tankz.proto.GameObjectType; import ru.m.tankz.proto.GameChangeType; -import ru.m.tankz.game.ClientTankz; +import ru.m.tankz.engine.ClientEngine; import protohx.Message; import ru.m.tankz.proto.GameUpdateResponse; import ru.m.core.connect.IConnection; @@ -22,27 +22,27 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand public static inline var ID = "game"; - private var game:ClientTankz; + private var engine:ClientEngine; public function init():Void { - game = new ClientTankz(); + engine = new ClientEngine(); } public function onShow():Void { var person = Provider.get(GameData).person; var persons = Provider.get(GameData).game.persons; name.text = person.name; - game.personId = person.id; - game.init(persons, DEFAULT.CONFIG); + engine.personId = person.id; + engine.init(persons, DEFAULT.CONFIG); content.addEventListener(Event.ENTER_FRAME, updateGame); Provider.get(IConnection).packetHandler.addListener(this); - render.draw(game); + render.draw(engine); } public function onHide():Void { Provider.get(IConnection).packetHandler.removeListener(this); content.removeEventListener(Event.ENTER_FRAME, updateGame); - game.clear(); + engine.clear(); } private function updateGame(_):Void { @@ -56,7 +56,7 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand case GameChangeType.DIRECTION: switch (change.objectType) { case GameObjectType.TANK: - for (tank in game.tanks) { + for (tank in engine.tanks) { if (tank.id == change.objectId) { tank.direction = new Direction(change.directionX, change.directionY); break; @@ -66,7 +66,7 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand case GameChangeType.MOVED: switch (change.objectType) { case GameObjectType.TANK: - for (tank in game.tanks) { + for (tank in engine.tanks) { if (tank.id == change.objectId) { tank.x = change.x; tank.y = change.y; @@ -77,7 +77,7 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand case GameChangeType.APPEND: switch (change.objectType) { case GameObjectType.BULLET: - for (tank in game.tanks) { + for (tank in engine.tanks) { if (tank.id == change.parentObjectId) { tank.bullets.push(new MobileEntity(0, change.x, change.y, 0, new Direction(change.directionX, change.directionY))); break; @@ -86,7 +86,7 @@ class GameFrame extends VGroupView implements ViewBuilder implements IPacketHand } } } - render.draw(game); + render.draw(engine); } public function onPacket(packet:Message):Void {} diff --git a/src/common/haxe/ru/m/tankz/game/Tankz.hx b/src/common/haxe/ru/m/tankz/engine/Engine.hx similarity index 98% rename from src/common/haxe/ru/m/tankz/game/Tankz.hx rename to src/common/haxe/ru/m/tankz/engine/Engine.hx index 9b8a26a..80f930e 100755 --- a/src/common/haxe/ru/m/tankz/game/Tankz.hx +++ b/src/common/haxe/ru/m/tankz/engine/Engine.hx @@ -1,4 +1,4 @@ -package ru.m.tankz.game; +package ru.m.tankz.engine; import ru.m.tankz.proto.Person; import ru.m.tankz.core.Direction; @@ -10,7 +10,7 @@ import ru.m.tankz.map.TankzMap; import ru.m.tankz.core.ITank; import ru.m.tankz.map.ITankzMap; -class Tankz implements ITankz { +class Engine implements IEngine { public var config(default, default):TankzConfig; public var map(default, null):ITankzMap; diff --git a/src/common/haxe/ru/m/tankz/game/ITankz.hx b/src/common/haxe/ru/m/tankz/engine/IEngine.hx similarity index 89% rename from src/common/haxe/ru/m/tankz/game/ITankz.hx rename to src/common/haxe/ru/m/tankz/engine/IEngine.hx index eb32b2a..c9e4faf 100755 --- a/src/common/haxe/ru/m/tankz/game/ITankz.hx +++ b/src/common/haxe/ru/m/tankz/engine/IEngine.hx @@ -1,11 +1,11 @@ -package ru.m.tankz.game; +package ru.m.tankz.engine; import ru.m.tankz.proto.Person; import ru.m.tankz.config.TankzConfig; import ru.m.tankz.core.ITank; import ru.m.tankz.map.ITankzMap; -interface ITankz { +interface IEngine { public var config(default, default):TankzConfig; public var map(default, null):ITankzMap; public var tanks(default, null):Array; diff --git a/src/common/proto/base.proto b/src/common/proto/base.proto index 2819634..f0b1b32 100755 --- a/src/common/proto/base.proto +++ b/src/common/proto/base.proto @@ -71,6 +71,14 @@ message JoinGameResponse { required Game game = 1; } +message LeaveGameRequest { + required int32 game_id = 1; +} + +message LeaveGameResponse { + required Game game = 1; +} + message StartGameRequest { } diff --git a/src/server/haxe/ru/m/tankz/server/game/Game.hx b/src/server/haxe/ru/m/tankz/server/game/Game.hx deleted file mode 100644 index c014624..0000000 --- a/src/server/haxe/ru/m/tankz/server/game/Game.hx +++ /dev/null @@ -1,12 +0,0 @@ -package ru.m.tankz.server.game; - -import ru.m.tankz.game.ITankz; - -class Game { - - private var tankz:ITankz; - - public function new() { - - } -} diff --git a/src/server/haxe/ru/m/tankz/server/game/GameManager.hx b/src/server/haxe/ru/m/tankz/server/game/GameManager.hx new file mode 100644 index 0000000..c4d6d1b --- /dev/null +++ b/src/server/haxe/ru/m/tankz/server/game/GameManager.hx @@ -0,0 +1,170 @@ +package ru.m.tankz.server.game; + +import ru.m.tankz.proto.ExitGameResponse; +import ru.m.tankz.proto.GameObjectType; +import ru.m.tankz.proto.GameChangeType; +import ru.m.tankz.proto.GameUpdateResponse; +import ru.m.tankz.proto.GameChange; +import ru.m.tankz.proto.StartGameResponse; +import ru.m.tankz.core.Direction; +import ru.m.tankz.server.session.Thread; +import ru.m.tankz.config.TankzConfig.DEFAULT; +import ru.m.tankz.engine.Engine; +import ru.m.tankz.proto.CreateGameResponse; +import ru.m.tankz.proto.LeaveGameResponse; +import ru.m.tankz.proto.JoinGameResponse; +import ru.m.tankz.server.session.Session; +import protohx.Message; +import ru.m.tankz.proto.Person; +import ru.m.tankz.proto.GameState; +import ru.m.tankz.proto.Game; +import ru.m.tankz.engine.IEngine; + +/** + * + **/ +class NekoTimer { + + private var sleep:Float; + private var stopped:Bool; + + public function new(time_ms:Int) { + this.sleep = time_ms / 1000.0; + this.stopped = false; + Thread.create(function() { + while (!stopped) { + Sys.sleep(sleep); + try { + run(); + } catch (error:Dynamic) { + trace(error); + } + } + }); + } + + public dynamic function run() {} + + public function stop() { + stopped = true; + } +} + +/** + * + **/ +typedef ObjectState = { + var x:Float; + var y:Float; + var d:Direction; +} + +/** + * + **/ +class GameManager { + + public static var byGameId:Map = new Map(); + public static var byPersonId:Map = new Map(); + + private static var idCounter:Int = 0; + + public var game(default, null):Game; + + public var engine(default, null):IEngine; + + private var timer:NekoTimer; + + public function new(person:Person) { + game = new Game() + .setId(idCounter++) + .setState(GameState.READY) + .setCreator(person); + game.addPersons(person); + byGameId.set(game.id, this); + byPersonId.set(person.id, this); + broadcast(new CreateGameResponse().setGame(game)); + } + + public function broadcast(packet:Message) { + for (person in game.persons) { + var session = Session.sessions.get(person.id); + session.send(packet); + } + } + + public function join(person:Person) { + game.addPersons(person); + byPersonId.set(person.id, this); + broadcast(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); + if (game.persons.length == 0 || person.id == game.creator.id) { + stop(); + } else { + broadcast(new LeaveGameResponse().setGame(game)); + } + } + + public function start() { + game.setState(GameState.STARTED); + engine = new Engine(); + engine.init(game.persons, DEFAULT.CONFIG); + timer = new NekoTimer(30); + timer.run = update; + broadcast(new StartGameResponse().setGame(game)); + } + + public function stop() { + game.setState(GameState.ENDED); + byGameId.remove(game.id); + for (p in game.persons) byPersonId.remove(p.id); + if (timer != null) { + timer.stop(); + timer = null; + } + broadcast(new ExitGameResponse()); + } + + private function update() { + var states = new Map(); + for (tank in engine.tanks) { + states.set(tank.id, { + x: tank.x, + y: tank.y, + d: tank.direction + }); + } + engine.update(); + var changes = new Array(); + for (tank in engine.tanks) { + if (states.exists(tank.id)) { + var state = states.get(tank.id); + if (state.d != tank.direction) { + changes.push(new GameChange() + .setType(GameChangeType.DIRECTION) + .setObjectType(GameObjectType.TANK) + .setObjectId(tank.id) + .setDirectionX(tank.direction.x) + .setDirectionY(tank.direction.y) + ); + } + if (state.x != tank.x || state.y != tank.y) { + changes.push(new GameChange() + .setType(GameChangeType.MOVED) + .setObjectType(GameObjectType.TANK) + .setObjectId(tank.id) + .setX(tank.x) + .setY(tank.y) + ); + } + } + } + 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 0d169f5..fe46117 100755 --- a/src/server/haxe/ru/m/tankz/server/session/Session.hx +++ b/src/server/haxe/ru/m/tankz/server/session/Session.hx @@ -1,5 +1,6 @@ package ru.m.tankz.server.session; +import ru.m.tankz.server.game.GameManager; import ru.m.tankz.proto.GameObjectType; import ru.m.tankz.proto.GameChangeType; import ru.m.tankz.proto.GameChange; @@ -7,8 +8,8 @@ import ru.m.tankz.config.TankzConfig.DEFAULT; import ru.m.tankz.proto.GameUpdateResponse; import haxe.Timer; import ru.m.tankz.core.Direction; -import ru.m.tankz.game.Tankz; -import ru.m.tankz.game.ITankz; +import ru.m.tankz.engine.Engine; +import ru.m.tankz.engine.IEngine; import ru.m.tankz.proto.GameActionType; import ru.m.tankz.proto.GameActionRequest; import ru.m.tankz.proto.ExitGameResponse; @@ -38,180 +39,9 @@ import protohx.Message; import ru.m.core.connect.IConnection; import sys.net.Socket; -class NekoTimer { - - private var sleep:Float; - private var stopped:Bool; - - public function new(time_ms:Int) { - this.sleep = time_ms / 1000.0; - this.stopped = false; - Thread.create(function() { - while (!stopped) { - Sys.sleep(sleep); - try { - run(); - } catch (error:Dynamic) { - trace(error); - } - } - }); - } - - public dynamic function run() {} - - public function stop() { - stopped = true; - } -} - - -typedef ObjectState = { - var x:Float; - var y:Float; - var d:Direction; -} - -class GameCenter { - - private var game_id:Int = 0; - private var games:Map; - private var created:Map; - private var persons:Map; - - public var running:Map; - private var timers:Map; - - public function new() { - games = new Map(); - created = new Map(); - persons = new Map(); - running = new Map(); - timers = new Map(); - } - - public function getReadyGames():Array { - return Lambda.array(games).filter(function(g) return g.state == GameState.READY); - } - - public function getCreatedGame(peronsId:Int):Game { - return games.get(created.get(peronsId)); - } - - public function getPersonGameId(personId:Int):Int { - return persons.get(personId); - } - - public function createGame(person:Person):Game { - var game:Game = new Game() - .setId(game_id++) - .setState(GameState.READY) - .setCreator(person); - games.set(game.id, game); - created.set(person.id, game.id); - join(person, game.id); - return game; - } - - public function join(person:Person, gameId:Int):Game { - exit(person.id); - var game:Game = games.get(gameId); - game.addPersons(person); - persons.set(person.id, gameId); - return game; - } - - public function exit(personId:Int):Void { - if (persons.exists(personId)) { - var game:Game = games.get(persons.get(personId)); - for (person in game.persons) if (person.id == personId) { - game.persons.remove(person); - if (game.persons.length == 0) { - games.remove(game.id); - if (timers.exists(game.id)) { - timers.get(game.id).stop(); - timers.remove(game.id); - } - } - break; - } - persons.remove(personId); - } - } - - public function start(gameId:Int):Void { - if (games.exists(gameId)) { - var game:Game = games.get(gameId); - game.setState(GameState.STARTED); - var tankz = new Tankz(); - tankz.init(game.persons, DEFAULT.CONFIG); - running.set(gameId, tankz); - var timer = new NekoTimer(30); - timer.run = buildUpdater(gameId, tankz); - timers.set(gameId, timer); - broadcast(gameId, new StartGameResponse().setGame(game)); - } - } - - private function buildUpdater(gameId:Int, tankz:ITankz):Void->Void { - return function() { - var states = new Map(); - for (tank in tankz.tanks) { - states.set(tank.id, { - x: tank.x, - y: tank.y, - d: tank.direction - }); - } - tankz.update(); - var changes = new Array(); - for (tank in tankz.tanks) { - if (states.exists(tank.id)) { - var state = states.get(tank.id); - if (state.d != tank.direction) { - trace("DDD"); - changes.push(new GameChange() - .setType(GameChangeType.DIRECTION) - .setObjectType(GameObjectType.TANK) - .setObjectId(tank.id) - .setDirectionX(tank.direction.x) - .setDirectionY(tank.direction.y) - ); - } - if (state.x != tank.x || state.y != tank.y) { - changes.push(new GameChange() - .setType(GameChangeType.MOVED) - .setObjectType(GameObjectType.TANK) - .setObjectId(tank.id) - .setX(tank.x) - .setY(tank.y) - ); - } - } - } - if (changes.length > 0) { - broadcast(gameId, new GameUpdateResponse().setChanges(changes)); - } - } - } - - public function broadcast(gameId:Int, packet:Message):Void { - var game = games.get(gameId); - if (game != null) { - for (person in game.persons) { - var session = Session.sessions.get(person.id); - if (session != null) { - session.send(packet); - } - } - } - } -} - class Session implements IConnectionHandler implements IPacketHandler { - private static var games:GameCenter = new GameCenter(); public static var sessions:Map = new Map(); public var account(default, null):Account; @@ -254,7 +84,8 @@ class Session implements IConnectionHandler implements IPacketHandler { public function onDisconnected():Void { if (person != null) { - games.exit(person.id); + var game = GameManager.byPersonId.get(person.id); + if (game != null) game.leave(person); } } @@ -292,31 +123,28 @@ class Session implements IConnectionHandler implements IPacketHandler { } public function onGamesRequest(packet:GamesRequest):Void { - connection.send(new GamesResponse().setGames(games.getReadyGames())); + var games = Lambda.array(Lambda.map(GameManager.byGameId, function(gm) return gm.game)); + connection.send(new GamesResponse().setGames(games)); } public function onCreateGameRequest(packet:CreateGameRequest):Void { - var game:Game = games.createGame(person); - connection.send(new CreateGameResponse().setGame(game)); + new GameManager(person); } public function onJoinGameRequest(packet:JoinGameRequest):Void { - var game:Game = games.join(person, packet.gameId); - connection.send(new JoinGameResponse().setGame(game)); + GameManager.byGameId.get(packet.gameId).join(person); } public function onStartGameRequest(packet:StartGameRequest):Void { - var game:Game = games.getCreatedGame(person.id); - games.start(game.id); + GameManager.byPersonId.get(person.id).start(); } public function onExitGameRequest(packet:ExitGameRequest):Void { - games.exit(person.id); - connection.send(new ExitGameResponse()); + GameManager.byPersonId.get(person.id).leave(person); } public function onGameActionRequest(packet:GameActionRequest):Void { - var game:ITankz = games.running.get(games.getPersonGameId(person.id)); + var game:IEngine = GameManager.byPersonId.get(person.id).engine; for (tank in game.tanks) { if (tank.id == person.id) { switch (packet.type) {