[common] update for network

This commit is contained in:
2019-05-28 17:03:04 +03:00
parent ba13111a8e
commit 1d95de02e1
21 changed files with 130 additions and 20 deletions

View File

@@ -1,8 +1,11 @@
package ru.m.tankz.network; package ru.m.tankz.network;
import ru.m.tankz.game.IGame;
import haxe.Unserializer;
import haxework.signal.Signal; import haxework.signal.Signal;
import ru.m.connect.IConnection; import ru.m.connect.IConnection;
import ru.m.tankz.control.Control; 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.GameProto;
import ru.m.tankz.proto.core.UserProto; import ru.m.tankz.proto.core.UserProto;
import ru.m.tankz.proto.game.GameChangeProto; import ru.m.tankz.proto.game.GameChangeProto;
@@ -41,6 +44,7 @@ class NetworkManager {
@:provide private var connection:ClientConnection; @:provide private var connection:ClientConnection;
@:provide private var storage:MultiplayerStorage; @:provide private var storage:MultiplayerStorage;
@:provide private var _game:IGame;
public function new() { public function new() {
stateSignal = new Signal(); stateSignal = new Signal();
@@ -148,6 +152,11 @@ class NetworkManager {
} else if (packet.hasStartGame()) { } else if (packet.hasStartGame()) {
game = packet.startGame.game; game = packet.startGame.game;
gameSignal.emit(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);
} }
} }
} }

View File

@@ -224,6 +224,9 @@ class Render extends SpriteView implements IRender {
item.destroy(); item.destroy();
case _: case _:
} }
#if cpp
flash.Lib.current.stage.invalidate();
#end
} }
private function playAnimate(point:Point, animate:OnceAnimate):Promise<Dynamic> { private function playAnimate(point:Point, animate:OnceAnimate):Promise<Dynamic> {

View File

@@ -47,7 +47,8 @@ import ru.m.tankz.proto.core.UserProto;
public function onHide():Void { public function onHide():Void {
network.gameSignal.disconnect(onGame); network.gameSignal.disconnect(onGame);
network.stateSignal.disconnect(onState); network.stateSignal.disconnect(onState);
network.leaveGame(); // ToDo:
//network.leaveGame();
} }
private function onGame(game:GameProto):Void { private function onGame(game:GameProto):Void {

View File

@@ -20,7 +20,7 @@ class Timer {
try { try {
run(); run();
} catch (error:Dynamic) { } catch (error:Dynamic) {
trace(error); trace(haxework.log.BaseLogger.LoggerUtil.printError(error));
} }
} }
}); });

View File

@@ -5,7 +5,6 @@ import haxe.io.BytesBuffer;
import haxe.io.BytesInput; import haxe.io.BytesInput;
import protohx.Message; import protohx.Message;
class PacketQueue<P:Message> { class PacketQueue<P:Message> {
public var packetClass(default, null):Class<P>; public var packetClass(default, null):Class<P>;
@@ -73,4 +72,7 @@ class PacketQueue<P:Message> {
} }
} }
public function clean():Void {
bytesBuff = null;
}
} }

View File

@@ -80,7 +80,9 @@ class FlashConnection<O:Message, I:Message> extends BaseConnection<O, I> {
var bytes = Bytes.ofData(data); var bytes = Bytes.ofData(data);
pushData(bytes); pushData(bytes);
} catch (error:Dynamic) { } catch (error:Dynamic) {
handler.emit(ConnectionEvent.ERROR(error)); L.w("Connection", "onSocketData ", error);
queue.clean();
//handler.emit(ConnectionEvent.ERROR(error));
} }
} }

View File

@@ -1,6 +1,6 @@
package ru.m.tankz.bot; package ru.m.tankz.bot;
import haxe.Timer; import ru.m.Timer;
import ru.m.geom.Direction; import ru.m.geom.Direction;
import ru.m.tankz.control.Control; import ru.m.tankz.control.Control;
import ru.m.tankz.core.Tank; import ru.m.tankz.core.Tank;

View File

@@ -1,6 +1,6 @@
package ru.m.tankz.bot; package ru.m.tankz.bot;
import haxe.Timer; import ru.m.Timer;
import ru.m.tankz.core.Eagle; import ru.m.tankz.core.Eagle;
import ru.m.tankz.core.EntityType; import ru.m.tankz.core.EntityType;
import ru.m.tankz.core.Tank; import ru.m.tankz.core.Tank;

View File

@@ -1,6 +1,6 @@
package ru.m.tankz.bot; package ru.m.tankz.bot;
import haxe.Timer; import ru.m.Timer;
import ru.m.tankz.control.Control; import ru.m.tankz.control.Control;
import ru.m.tankz.core.Eagle; import ru.m.tankz.core.Eagle;
import ru.m.tankz.core.EntityType; import ru.m.tankz.core.EntityType;

View File

@@ -4,7 +4,6 @@ import ru.m.geom.Direction;
import ru.m.geom.Line; import ru.m.geom.Line;
import ru.m.geom.Point; import ru.m.geom.Point;
import ru.m.tankz.config.Config; import ru.m.tankz.config.Config;
import ru.m.tankz.core.Bullet;
import ru.m.tankz.core.Entity; import ru.m.tankz.core.Entity;
import ru.m.tankz.core.EntityType; import ru.m.tankz.core.EntityType;
import ru.m.tankz.core.MobileEntity; import ru.m.tankz.core.MobileEntity;
@@ -68,7 +67,7 @@ import ru.m.tankz.map.LevelMap;
} }
public function update():Void { public function update():Void {
var newTime:Float = Date.now().getTime(); var newTime:Float = Timer.stamp() * 1000;
var d:Float = newTime - time; var d:Float = newTime - time;
time = newTime; time = newTime;

View File

@@ -19,8 +19,8 @@ import ru.m.tankz.Type;
public var teams(default, null):Map<TeamId, Team>; public var teams(default, null):Map<TeamId, Team>;
public var config(default, null):Config; public var config(default, null):Config;
public var winner(default, null):Null<TeamId>; public var winner(default, null):Null<TeamId>;
public var state(default, null):GameState; public var state(default, null):GameState;
public var frame(default, null):Int;
@:provide var configBundle:IConfigBundle; @:provide var configBundle:IConfigBundle;
@@ -29,6 +29,7 @@ import ru.m.tankz.Type;
this.state = state; this.state = state;
this.teams = new Map(); this.teams = new Map();
this.config = configBundle.get(type); this.config = configBundle.get(type);
this.frame = 0;
connect(this); connect(this);
} }

View File

@@ -1,6 +1,5 @@
package ru.m.tankz.game; package ru.m.tankz.game;
import haxe.ds.Option;
import ru.m.geom.Line; import ru.m.geom.Line;
import ru.m.geom.Point; import ru.m.geom.Point;
import ru.m.tankz.control.Control; import ru.m.tankz.control.Control;
@@ -34,6 +33,7 @@ class GameRunner extends Game implements EngineListener {
} }
private function update():Void { private function update():Void {
frame++;
engine.update(); engine.update();
} }
@@ -331,7 +331,10 @@ class GameRunner extends Game implements EngineListener {
gameEventSignal.emit(GameEvent.STOP(TANK(tankId))); gameEventSignal.emit(GameEvent.STOP(TANK(tankId)));
engine.stop(tankId); engine.stop(tankId);
case GameEvent.SPAWN(TANK(_, _, playerId, _)): case GameEvent.SPAWN(TANK(_, _, playerId, _)):
getPlayer(playerId).control.start(); var control = getPlayer(playerId).control;
if (control != null) {
control.start();
}
case GameEvent.SPAWN(BULLET(_, _, playerId, _)): case GameEvent.SPAWN(BULLET(_, _, playerId, _)):
getPlayer(playerId).bullets++; getPlayer(playerId).bullets++;
case GameEvent.DESTROY(EAGLE(id, shot)): case GameEvent.DESTROY(EAGLE(id, shot)):
@@ -346,7 +349,9 @@ class GameRunner extends Game implements EngineListener {
var tank:Tank = engine.getEntity(id); var tank:Tank = engine.getEntity(id);
var team = getTeam(tank.playerId.team); var team = getTeam(tank.playerId.team);
var player = getPlayer(tank.playerId); var player = getPlayer(tank.playerId);
player.control.stop(); if (player.control != null) {
player.control.stop();
}
player.tankId = 0; //ToDo: ? player.tankId = 0; //ToDo: ?
team.onDestroy(player.id); team.onDestroy(player.id);
if (player.state.life > 0) { if (player.state.life > 0) {

View File

@@ -10,6 +10,7 @@ interface IGame extends GameListener {
public var config(default, null):Config; public var config(default, null):Config;
public var winner(default, null):Null<TeamId>; public var winner(default, null):Null<TeamId>;
public var state(default, null):GameState; public var state(default, null):GameState;
public var frame(default, null):Int;
public var gameEventSignal(default, null):Signal<GameEvent>; public var gameEventSignal(default, null):Signal<GameEvent>;

View File

@@ -19,6 +19,7 @@ class Team {
public function new(config:TeamConfig, points:Array<SpawnPoint>, state:TeamState = null) { public function new(config:TeamConfig, points:Array<SpawnPoint>, state:TeamState = null) {
this.id = config.id; this.id = config.id;
this.config = config; this.config = config;
this.active = 0;
this.players = new Map(); this.players = new Map();
for (playerConfig in config.players) { for (playerConfig in config.players) {
var playerState = state == null ? null : state.players[playerConfig.index]; var playerState = state == null ? null : state.players[playerConfig.index];

View File

@@ -6,7 +6,6 @@ import ru.m.tankz.game.record.GameRecord;
class GamePlayer extends Game { class GamePlayer extends Game {
private var frame:Int;
private var record:GameRecord; private var record:GameRecord;
private var data:Array<EventItem>; private var data:Array<EventItem>;

View File

@@ -68,6 +68,17 @@ message StartGameResponse {
ru.m.tankz.proto.core.GameProto game = 1; 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 // Request
message Request { message Request {
oneof content { oneof content {
@@ -78,6 +89,7 @@ message Request {
JoinGameRequest joinGame = 5; JoinGameRequest joinGame = 5;
LeaveGameRequest leaveGame = 6; LeaveGameRequest leaveGame = 6;
StartGameRequest startGame = 7; StartGameRequest startGame = 7;
GameEventRequest gameEvent = 8;
} }
} }
@@ -91,6 +103,7 @@ message Response {
JoinGameResponse joinGame = 5; JoinGameResponse joinGame = 5;
LeaveGameResponse leaveGame = 6; LeaveGameResponse leaveGame = 6;
StartGameResponse startGame = 7; StartGameResponse startGame = 7;
GameEventResponse gameEvent = 8;
ErrorResponse error = 999; ErrorResponse error = 999;
} }

View File

@@ -7,9 +7,9 @@ import neko.net.ThreadServer;
import ru.m.tankz.bundle.IConfigBundle; import ru.m.tankz.bundle.IConfigBundle;
import ru.m.tankz.bundle.ILevelBundle; import ru.m.tankz.bundle.ILevelBundle;
import ru.m.tankz.control.IControlFactory; 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.ServerConfigBundle;
import ru.m.tankz.server.bundle.ServerLevelBundle; 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.GameManager;
import ru.m.tankz.server.game.IGameManager; import ru.m.tankz.server.game.IGameManager;
import ru.m.tankz.server.session.GameSession; import ru.m.tankz.server.session.GameSession;
@@ -50,7 +50,7 @@ class Server extends ThreadServer<GameSession, Bytes> {
L.i(TAG, 'Build: ${CompilationOption.get("build")}'); L.i(TAG, 'Build: ${CompilationOption.get("build")}');
Provider.setFactory(IConfigBundle, ServerConfigBundle); Provider.setFactory(IConfigBundle, ServerConfigBundle);
Provider.setFactory(ILevelBundle, ServerLevelBundle); Provider.setFactory(ILevelBundle, ServerLevelBundle);
Provider.setFactory(IControlFactory, NoneControlFactory); Provider.setFactory(IControlFactory, ServerControlFactory);
gameManager = new GameManager(); gameManager = new GameManager();
var host:String = Sys.args().length > 0 ? Sys.args()[0] : "0.0.0.0"; 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; var port:Int = Sys.args().length > 1 ? Std.parseInt(Sys.args()[1]) : 5000;

View File

@@ -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;
}
}
}

View File

@@ -1,10 +1,39 @@
package ru.m.tankz.server.game; 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.GameProto;
import ru.m.tankz.proto.core.GameStateProto; import ru.m.tankz.proto.core.GameStateProto;
import ru.m.tankz.proto.core.UserProto; import ru.m.tankz.proto.core.UserProto;
import ru.m.tankz.server.game.IGameManager; 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 { @:dispatcher(GameManagerListener) class GameManager implements IGameManager {
public var games(default, null):Array<ServerGame>; public var games(default, null):Array<ServerGame>;
public var gamesById(default, null):Map<Int, ServerGame>; public var gamesById(default, null):Map<Int, ServerGame>;
@@ -70,9 +99,15 @@ import ru.m.tankz.server.game.IGameManager;
public function start(gameId:Int):Void { public function start(gameId:Int):Void {
if (gamesById.exists(gameId)) { if (gamesById.exists(gameId)) {
var game = gamesById[gameId]; var game:ServerGame = gamesById[gameId];
game.proto.setState(GameStateProto.STARTED); game.proto.setState(GameStateProto.STARTED);
changeSignal.emit(game, START); changeSignal.emit(game, START);
game.connect(new _GameListener(game, this));
game.start();
} }
} }
public function dispatchEvent(game:ServerGame, event:GameEvent):Void {
eventSignal.emit(game, event);
}
} }

View File

@@ -1,5 +1,6 @@
package ru.m.tankz.server.game; package ru.m.tankz.server.game;
import ru.m.tankz.game.GameEvent;
import haxework.signal.Signal; import haxework.signal.Signal;
import ru.m.tankz.proto.core.UserProto; import ru.m.tankz.proto.core.UserProto;
@@ -13,6 +14,7 @@ interface GameManagerListener {
public function onCreate(game:ServerGame):Void; public function onCreate(game:ServerGame):Void;
public function onChange(game:ServerGame, change:GameChange):Void; public function onChange(game:ServerGame, change:GameChange):Void;
public function onDelete(game:ServerGame):Void; public function onDelete(game:ServerGame):Void;
public function onEvent(game:ServerGame, event:GameEvent):Void;
} }
interface IGameManager { interface IGameManager {
@@ -23,6 +25,9 @@ interface IGameManager {
private var createSignal(default, null):Signal<ServerGame>; private var createSignal(default, null):Signal<ServerGame>;
private var changeSignal(default, null):Signal2<ServerGame, GameChange>; private var changeSignal(default, null):Signal2<ServerGame, GameChange>;
private var deleteSignal(default, null):Signal<ServerGame>; private var deleteSignal(default, null):Signal<ServerGame>;
private var eventSignal(default, null):Signal2<ServerGame, GameEvent>;
public function dispatchEvent(game:ServerGame, event:GameEvent):Void;
public function connect(listener:GameManagerListener):Void; public function connect(listener:GameManagerListener):Void;
public function disconnect(listener:GameManagerListener):Void; public function disconnect(listener:GameManagerListener):Void;

View File

@@ -1,5 +1,8 @@
package ru.m.tankz.server.session; 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.extra.UUID;
import com.hurlant.crypto.prng.Random; import com.hurlant.crypto.prng.Random;
import haxework.log.BaseLogger.LoggerUtil; import haxework.log.BaseLogger.LoggerUtil;
@@ -47,7 +50,7 @@ class GameSession extends ProtoSession<Response, Request> implements GameManager
} }
override public function send(packet:Response):Void { override public function send(packet:Response):Void {
L.d(TAG, '$tag send: ${packet}'); #if proto_debug L.d(TAG, '$tag send: ${packet}'); #end
try { try {
super.send(packet); super.send(packet);
} catch (error:Dynamic) { } catch (error:Dynamic) {
@@ -65,7 +68,7 @@ class GameSession extends ProtoSession<Response, Request> implements GameManager
} }
override private function onRequest(request:Request):Void { override private function onRequest(request:Request):Void {
L.d(TAG, '$tag onRequest: ${request}'); #if proto_debug L.d(TAG, '$tag onRequest: ${request}'); #end
try { try {
if (!request.hasLogin() && user == null) { if (!request.hasLogin() && user == null) {
throw "Not Authorized"; throw "Not Authorized";
@@ -148,4 +151,10 @@ class GameSession extends ProtoSession<Response, Request> implements GameManager
send(new Response().setLeaveGame(new LeaveGameResponse().setGame(game.proto).setUser(user))); 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))));
}
}
} }