diff --git a/src/client/haxe/ru/m/tankz/network/NetworkManager.hx b/src/client/haxe/ru/m/tankz/network/NetworkManager.hx index abba077..e8fdcc5 100644 --- a/src/client/haxe/ru/m/tankz/network/NetworkManager.hx +++ b/src/client/haxe/ru/m/tankz/network/NetworkManager.hx @@ -1,8 +1,11 @@ package ru.m.tankz.network; +import ru.m.tankz.game.IGame; +import haxe.Unserializer; import haxework.signal.Signal; import ru.m.connect.IConnection; import ru.m.tankz.control.Control; +import ru.m.tankz.game.GameEvent; import ru.m.tankz.proto.core.GameProto; import ru.m.tankz.proto.core.UserProto; import ru.m.tankz.proto.game.GameChangeProto; @@ -41,6 +44,7 @@ class NetworkManager { @:provide private var connection:ClientConnection; @:provide private var storage:MultiplayerStorage; + @:provide private var _game:IGame; public function new() { stateSignal = new Signal(); @@ -148,6 +152,11 @@ class NetworkManager { } else if (packet.hasStartGame()) { game = packet.startGame.game; gameSignal.emit(game); + } else if (packet.hasGameEvent()) { + var frame = packet.gameEvent.frame; + var eventStr = packet.gameEvent.event; + var event:GameEvent = Unserializer.run(eventStr); + _game.gameEventSignal.emit(event); } } } diff --git a/src/client/haxe/ru/m/tankz/render/Render.hx b/src/client/haxe/ru/m/tankz/render/Render.hx index 33be52a..fd5db66 100755 --- a/src/client/haxe/ru/m/tankz/render/Render.hx +++ b/src/client/haxe/ru/m/tankz/render/Render.hx @@ -224,6 +224,9 @@ class Render extends SpriteView implements IRender { item.destroy(); case _: } + #if cpp + flash.Lib.current.stage.invalidate(); + #end } private function playAnimate(point:Point, animate:OnceAnimate):Promise { diff --git a/src/client/haxe/ru/m/tankz/view/network/GameRoomFrame.hx b/src/client/haxe/ru/m/tankz/view/network/GameRoomFrame.hx index 9332be3..2b6c359 100644 --- a/src/client/haxe/ru/m/tankz/view/network/GameRoomFrame.hx +++ b/src/client/haxe/ru/m/tankz/view/network/GameRoomFrame.hx @@ -47,7 +47,8 @@ import ru.m.tankz.proto.core.UserProto; public function onHide():Void { network.gameSignal.disconnect(onGame); network.stateSignal.disconnect(onState); - network.leaveGame(); + // ToDo: + //network.leaveGame(); } private function onGame(game:GameProto):Void { diff --git a/src/common/haxe/ru/m/Timer.hx b/src/common/haxe/ru/m/Timer.hx index c1732ac..c14cf13 100644 --- a/src/common/haxe/ru/m/Timer.hx +++ b/src/common/haxe/ru/m/Timer.hx @@ -20,7 +20,7 @@ class Timer { try { run(); } catch (error:Dynamic) { - trace(error); + trace(haxework.log.BaseLogger.LoggerUtil.printError(error)); } } }); diff --git a/src/common/haxe/ru/m/connect/PacketQueue.hx b/src/common/haxe/ru/m/connect/PacketQueue.hx index 4c893e4..8e82eb9 100755 --- a/src/common/haxe/ru/m/connect/PacketQueue.hx +++ b/src/common/haxe/ru/m/connect/PacketQueue.hx @@ -5,7 +5,6 @@ import haxe.io.BytesBuffer; import haxe.io.BytesInput; import protohx.Message; - class PacketQueue { public var packetClass(default, null):Class

; @@ -73,4 +72,7 @@ class PacketQueue { } } -} \ No newline at end of file + public function clean():Void { + bytesBuff = null; + } +} diff --git a/src/common/haxe/ru/m/connect/flash/FlashConnection.hx b/src/common/haxe/ru/m/connect/flash/FlashConnection.hx index 7d33d33..5d7437f 100755 --- a/src/common/haxe/ru/m/connect/flash/FlashConnection.hx +++ b/src/common/haxe/ru/m/connect/flash/FlashConnection.hx @@ -80,7 +80,9 @@ class FlashConnection extends BaseConnection { var bytes = Bytes.ofData(data); pushData(bytes); } catch (error:Dynamic) { - handler.emit(ConnectionEvent.ERROR(error)); + L.w("Connection", "onSocketData ", error); + queue.clean(); + //handler.emit(ConnectionEvent.ERROR(error)); } } diff --git a/src/common/haxe/ru/m/tankz/bot/BotControl.hx b/src/common/haxe/ru/m/tankz/bot/BotControl.hx index 3b7970d..29874e5 100644 --- a/src/common/haxe/ru/m/tankz/bot/BotControl.hx +++ b/src/common/haxe/ru/m/tankz/bot/BotControl.hx @@ -1,6 +1,6 @@ package ru.m.tankz.bot; -import haxe.Timer; +import ru.m.Timer; import ru.m.geom.Direction; import ru.m.tankz.control.Control; import ru.m.tankz.core.Tank; diff --git a/src/common/haxe/ru/m/tankz/bot/HardBotControl.hx b/src/common/haxe/ru/m/tankz/bot/HardBotControl.hx index e50357c..4866649 100644 --- a/src/common/haxe/ru/m/tankz/bot/HardBotControl.hx +++ b/src/common/haxe/ru/m/tankz/bot/HardBotControl.hx @@ -1,6 +1,6 @@ package ru.m.tankz.bot; -import haxe.Timer; +import ru.m.Timer; import ru.m.tankz.core.Eagle; import ru.m.tankz.core.EntityType; import ru.m.tankz.core.Tank; diff --git a/src/common/haxe/ru/m/tankz/bot/StupidBotControl.hx b/src/common/haxe/ru/m/tankz/bot/StupidBotControl.hx index 909e4a4..f89539a 100644 --- a/src/common/haxe/ru/m/tankz/bot/StupidBotControl.hx +++ b/src/common/haxe/ru/m/tankz/bot/StupidBotControl.hx @@ -1,6 +1,6 @@ package ru.m.tankz.bot; -import haxe.Timer; +import ru.m.Timer; import ru.m.tankz.control.Control; import ru.m.tankz.core.Eagle; import ru.m.tankz.core.EntityType; diff --git a/src/common/haxe/ru/m/tankz/engine/Engine.hx b/src/common/haxe/ru/m/tankz/engine/Engine.hx index 4fef152..30eca56 100755 --- a/src/common/haxe/ru/m/tankz/engine/Engine.hx +++ b/src/common/haxe/ru/m/tankz/engine/Engine.hx @@ -4,7 +4,6 @@ import ru.m.geom.Direction; import ru.m.geom.Line; import ru.m.geom.Point; import ru.m.tankz.config.Config; -import ru.m.tankz.core.Bullet; import ru.m.tankz.core.Entity; import ru.m.tankz.core.EntityType; import ru.m.tankz.core.MobileEntity; @@ -68,7 +67,7 @@ import ru.m.tankz.map.LevelMap; } public function update():Void { - var newTime:Float = Date.now().getTime(); + var newTime:Float = Timer.stamp() * 1000; var d:Float = newTime - time; time = newTime; diff --git a/src/common/haxe/ru/m/tankz/game/Game.hx b/src/common/haxe/ru/m/tankz/game/Game.hx index 2905eee..62ae536 100644 --- a/src/common/haxe/ru/m/tankz/game/Game.hx +++ b/src/common/haxe/ru/m/tankz/game/Game.hx @@ -19,8 +19,8 @@ import ru.m.tankz.Type; public var teams(default, null):Map; public var config(default, null):Config; public var winner(default, null):Null; - public var state(default, null):GameState; + public var frame(default, null):Int; @:provide var configBundle:IConfigBundle; @@ -29,6 +29,7 @@ import ru.m.tankz.Type; this.state = state; this.teams = new Map(); this.config = configBundle.get(type); + this.frame = 0; connect(this); } diff --git a/src/common/haxe/ru/m/tankz/game/GameRunner.hx b/src/common/haxe/ru/m/tankz/game/GameRunner.hx index bc26bc1..15668c9 100644 --- a/src/common/haxe/ru/m/tankz/game/GameRunner.hx +++ b/src/common/haxe/ru/m/tankz/game/GameRunner.hx @@ -1,6 +1,5 @@ package ru.m.tankz.game; -import haxe.ds.Option; import ru.m.geom.Line; import ru.m.geom.Point; import ru.m.tankz.control.Control; @@ -34,6 +33,7 @@ class GameRunner extends Game implements EngineListener { } private function update():Void { + frame++; engine.update(); } @@ -331,7 +331,10 @@ class GameRunner extends Game implements EngineListener { gameEventSignal.emit(GameEvent.STOP(TANK(tankId))); engine.stop(tankId); case GameEvent.SPAWN(TANK(_, _, playerId, _)): - getPlayer(playerId).control.start(); + var control = getPlayer(playerId).control; + if (control != null) { + control.start(); + } case GameEvent.SPAWN(BULLET(_, _, playerId, _)): getPlayer(playerId).bullets++; case GameEvent.DESTROY(EAGLE(id, shot)): @@ -346,7 +349,9 @@ class GameRunner extends Game implements EngineListener { var tank:Tank = engine.getEntity(id); var team = getTeam(tank.playerId.team); var player = getPlayer(tank.playerId); - player.control.stop(); + if (player.control != null) { + player.control.stop(); + } player.tankId = 0; //ToDo: ? team.onDestroy(player.id); if (player.state.life > 0) { diff --git a/src/common/haxe/ru/m/tankz/game/IGame.hx b/src/common/haxe/ru/m/tankz/game/IGame.hx index b4dd7df..514455c 100644 --- a/src/common/haxe/ru/m/tankz/game/IGame.hx +++ b/src/common/haxe/ru/m/tankz/game/IGame.hx @@ -10,6 +10,7 @@ interface IGame extends GameListener { public var config(default, null):Config; public var winner(default, null):Null; public var state(default, null):GameState; + public var frame(default, null):Int; public var gameEventSignal(default, null):Signal; diff --git a/src/common/haxe/ru/m/tankz/game/Team.hx b/src/common/haxe/ru/m/tankz/game/Team.hx index e0b06b6..5f514a6 100644 --- a/src/common/haxe/ru/m/tankz/game/Team.hx +++ b/src/common/haxe/ru/m/tankz/game/Team.hx @@ -19,6 +19,7 @@ class Team { public function new(config:TeamConfig, points:Array, state:TeamState = null) { this.id = config.id; this.config = config; + this.active = 0; this.players = new Map(); for (playerConfig in config.players) { var playerState = state == null ? null : state.players[playerConfig.index]; diff --git a/src/common/haxe/ru/m/tankz/game/record/GamePlayer.hx b/src/common/haxe/ru/m/tankz/game/record/GamePlayer.hx index f914e0a..da9f88d 100644 --- a/src/common/haxe/ru/m/tankz/game/record/GamePlayer.hx +++ b/src/common/haxe/ru/m/tankz/game/record/GamePlayer.hx @@ -6,7 +6,6 @@ import ru.m.tankz.game.record.GameRecord; class GamePlayer extends Game { - private var frame:Int; private var record:GameRecord; private var data:Array; diff --git a/src/common/proto/pack.proto b/src/common/proto/pack.proto index 66ecb25..f3232e0 100644 --- a/src/common/proto/pack.proto +++ b/src/common/proto/pack.proto @@ -68,6 +68,17 @@ message StartGameResponse { ru.m.tankz.proto.core.GameProto game = 1; } +// Game +message GameEventRequest { + int32 frame = 1; + string event = 2; +} + +message GameEventResponse { + int32 frame = 1; + string event = 2; +} + // Request message Request { oneof content { @@ -78,6 +89,7 @@ message Request { JoinGameRequest joinGame = 5; LeaveGameRequest leaveGame = 6; StartGameRequest startGame = 7; + GameEventRequest gameEvent = 8; } } @@ -91,6 +103,7 @@ message Response { JoinGameResponse joinGame = 5; LeaveGameResponse leaveGame = 6; StartGameResponse startGame = 7; + GameEventResponse gameEvent = 8; ErrorResponse error = 999; } diff --git a/src/server/haxe/ru/m/tankz/server/Server.hx b/src/server/haxe/ru/m/tankz/server/Server.hx index 28f67d0..77c4a42 100755 --- a/src/server/haxe/ru/m/tankz/server/Server.hx +++ b/src/server/haxe/ru/m/tankz/server/Server.hx @@ -7,9 +7,9 @@ import neko.net.ThreadServer; import ru.m.tankz.bundle.IConfigBundle; import ru.m.tankz.bundle.ILevelBundle; import ru.m.tankz.control.IControlFactory; -import ru.m.tankz.control.NoneControlFactory; import ru.m.tankz.server.bundle.ServerConfigBundle; import ru.m.tankz.server.bundle.ServerLevelBundle; +import ru.m.tankz.server.control.ServerControlFactory; import ru.m.tankz.server.game.GameManager; import ru.m.tankz.server.game.IGameManager; import ru.m.tankz.server.session.GameSession; @@ -50,7 +50,7 @@ class Server extends ThreadServer { L.i(TAG, 'Build: ${CompilationOption.get("build")}'); Provider.setFactory(IConfigBundle, ServerConfigBundle); Provider.setFactory(ILevelBundle, ServerLevelBundle); - Provider.setFactory(IControlFactory, NoneControlFactory); + Provider.setFactory(IControlFactory, ServerControlFactory); gameManager = new GameManager(); var host:String = Sys.args().length > 0 ? Sys.args()[0] : "0.0.0.0"; var port:Int = Sys.args().length > 1 ? Std.parseInt(Sys.args()[1]) : 5000; diff --git a/src/server/haxe/ru/m/tankz/server/control/ServerControlFactory.hx b/src/server/haxe/ru/m/tankz/server/control/ServerControlFactory.hx new file mode 100644 index 0000000..16f95c0 --- /dev/null +++ b/src/server/haxe/ru/m/tankz/server/control/ServerControlFactory.hx @@ -0,0 +1,25 @@ +package ru.m.tankz.server.control; + +import ru.m.tankz.bot.HardBotControl; +import ru.m.tankz.bot.StupidBotControl; +import ru.m.tankz.control.Control; +import ru.m.tankz.control.Controller; +import ru.m.tankz.control.IControlFactory; +import ru.m.tankz.Type.PlayerId; + +class ServerControlFactory implements IControlFactory { + + public function new() {} + + public function build(id:PlayerId, controller:Controller):Control { + return switch controller { + case HUMAN(index): new HardBotControl(id); // ToDo: + case BOT(type): switch type { + case StupidBotControl.BOT_TYPE: new StupidBotControl(id); + case HardBotControl.BOT_TYPE: new HardBotControl(id); + case _: null; + } + case NONE: null; + } + } +} 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 7cd5060..ab2dcd3 100644 --- a/src/server/haxe/ru/m/tankz/server/game/GameManager.hx +++ b/src/server/haxe/ru/m/tankz/server/game/GameManager.hx @@ -1,10 +1,39 @@ package ru.m.tankz.server.game; +import ru.m.tankz.game.GameEvent; +import ru.m.tankz.game.IGame.GameListener; +import ru.m.tankz.game.IGame; import ru.m.tankz.proto.core.GameProto; import ru.m.tankz.proto.core.GameStateProto; import ru.m.tankz.proto.core.UserProto; import ru.m.tankz.server.game.IGameManager; +class _GameListener implements GameListener { + private var game:ServerGame; + private var dispatcher:IGameManager; + + public function new(game:ServerGame, dispatcher:IGameManager) { + this.game = game; + this.dispatcher = dispatcher; + } + + public function onGameEvent(event:GameEvent):Void { + dispatcher.dispatchEvent(game, event); + switch event { + case COMPLETE(_, _): + dispose(); + dispatcher.delete(game.proto.id); + case _: + } + } + + public function dispose():Void { + game.disconnect(this); + game = null; + dispatcher = null; + } +} + @:dispatcher(GameManagerListener) class GameManager implements IGameManager { public var games(default, null):Array; public var gamesById(default, null):Map; @@ -70,9 +99,15 @@ import ru.m.tankz.server.game.IGameManager; public function start(gameId:Int):Void { if (gamesById.exists(gameId)) { - var game = gamesById[gameId]; + var game:ServerGame = gamesById[gameId]; game.proto.setState(GameStateProto.STARTED); changeSignal.emit(game, START); + game.connect(new _GameListener(game, this)); + game.start(); } } + + public function dispatchEvent(game:ServerGame, event:GameEvent):Void { + eventSignal.emit(game, event); + } } diff --git a/src/server/haxe/ru/m/tankz/server/game/IGameManager.hx b/src/server/haxe/ru/m/tankz/server/game/IGameManager.hx index cf18c92..b03d62c 100644 --- a/src/server/haxe/ru/m/tankz/server/game/IGameManager.hx +++ b/src/server/haxe/ru/m/tankz/server/game/IGameManager.hx @@ -1,5 +1,6 @@ package ru.m.tankz.server.game; +import ru.m.tankz.game.GameEvent; import haxework.signal.Signal; import ru.m.tankz.proto.core.UserProto; @@ -13,6 +14,7 @@ interface GameManagerListener { public function onCreate(game:ServerGame):Void; public function onChange(game:ServerGame, change:GameChange):Void; public function onDelete(game:ServerGame):Void; + public function onEvent(game:ServerGame, event:GameEvent):Void; } interface IGameManager { @@ -23,6 +25,9 @@ interface IGameManager { private var createSignal(default, null):Signal; private var changeSignal(default, null):Signal2; private var deleteSignal(default, null):Signal; + private var eventSignal(default, null):Signal2; + + public function dispatchEvent(game:ServerGame, event:GameEvent):Void; public function connect(listener:GameManagerListener):Void; public function disconnect(listener:GameManagerListener):Void; diff --git a/src/server/haxe/ru/m/tankz/server/session/GameSession.hx b/src/server/haxe/ru/m/tankz/server/session/GameSession.hx index 56f7fcc..25d61cd 100644 --- a/src/server/haxe/ru/m/tankz/server/session/GameSession.hx +++ b/src/server/haxe/ru/m/tankz/server/session/GameSession.hx @@ -1,5 +1,8 @@ package ru.m.tankz.server.session; +import haxe.Serializer; +import ru.m.tankz.proto.pack.GameEventResponse; +import ru.m.tankz.game.GameEvent; import com.hurlant.crypto.extra.UUID; import com.hurlant.crypto.prng.Random; import haxework.log.BaseLogger.LoggerUtil; @@ -47,7 +50,7 @@ class GameSession extends ProtoSession implements GameManager } override public function send(packet:Response):Void { - L.d(TAG, '$tag send: ${packet}'); + #if proto_debug L.d(TAG, '$tag send: ${packet}'); #end try { super.send(packet); } catch (error:Dynamic) { @@ -65,7 +68,7 @@ class GameSession extends ProtoSession implements GameManager } override private function onRequest(request:Request):Void { - L.d(TAG, '$tag onRequest: ${request}'); + #if proto_debug L.d(TAG, '$tag onRequest: ${request}'); #end try { if (!request.hasLogin() && user == null) { throw "Not Authorized"; @@ -148,4 +151,10 @@ class GameSession extends ProtoSession implements GameManager send(new Response().setLeaveGame(new LeaveGameResponse().setGame(game.proto).setUser(user))); } } + + public function onEvent(game:ServerGame, event:GameEvent):Void { + if (gameId == game.proto.id) { + send(new Response().setGameEvent(new GameEventResponse().setFrame(game.frame).setEvent(Serializer.run(event)))); + } + } }