[network] update

This commit is contained in:
2019-05-24 15:43:00 +03:00
parent 26ad5f47cd
commit 50a0cee044
19 changed files with 621 additions and 227 deletions

View File

@@ -6,6 +6,6 @@
remote_src: true remote_src: true
- name: "Gulp build" - name: "Gulp build"
command: "/usr/local/lib/npm/bin/gulp default" command: "/usr/local/lib/npm/bin/gulp default --host shmyga.ru"
args: args:
chdir: "{{ deploy_release_dir }}" chdir: "{{ deploy_release_dir }}"

View File

@@ -4,7 +4,7 @@ const Config = require('./config.json');
const packageInfo = require('./package.json'); const packageInfo = require('./package.json');
const {Sdk, Haxe, Project, FlashPlayer} = require('gulp-haxetool'); const {Sdk, Haxe, Project, FlashPlayer} = require('gulp-haxetool');
const dateformat = require('dateformat'); const dateformat = require('dateformat');
const argv = require('yargs').argv;
// ToDo: update default in gulp-haxetool // ToDo: update default in gulp-haxetool
FlashPlayer.VERSION = '32'; FlashPlayer.VERSION = '32';
@@ -49,11 +49,13 @@ const config = new Project.Config({
'src/common/resources' 'src/common/resources'
], ],
macros: [ macros: [
//'yield.parser.Parser.auto()', // ToDo: bug with extraParams.hxml in yield library
`CompilationOption.set('build','${dateformat(new Date(), 'yyyy-mm-dd HH:MM:ss')}')`, `CompilationOption.set('build','${dateformat(new Date(), 'yyyy-mm-dd HH:MM:ss')}')`,
] ]
}); });
const host = argv.host || 'localhost';
const port = argv.port || 5000;
/** /**
* client * client
*/ */
@@ -83,6 +85,10 @@ const client = new Project(
//'dev_layout', //'dev_layout',
//'bitmap_text', //'bitmap_text',
], ],
macros: [
`CompilationOption.set('host','${host}')`,
`CompilationOption.set('port',${port})`,
]
}), }),
module.exports.generate module.exports.generate
).bind(module, gulp); ).bind(module, gulp);

636
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,8 @@
"gulp": "^4.0.0", "gulp": "^4.0.0",
"gulp-add": "0.0.2", "gulp-add": "0.0.2",
"gulp-clean": "^0.4.0", "gulp-clean": "^0.4.0",
"gulp-haxetool": "^0.0.19" "gulp-haxetool": "^0.0.19",
"yargs": "^13.2.4"
}, },
"haxeDependencies": { "haxeDependencies": {
"haxework": "git@bitbucket.org:shmyga/haxework.git", "haxework": "git@bitbucket.org:shmyga/haxework.git",

View File

@@ -20,11 +20,6 @@ import ru.m.tankz.storage.GameStorage;
import ru.m.tankz.storage.MultiplayerStorage; import ru.m.tankz.storage.MultiplayerStorage;
import ru.m.tankz.storage.RecordStorage; import ru.m.tankz.storage.RecordStorage;
import ru.m.tankz.storage.SettingsStorage; import ru.m.tankz.storage.SettingsStorage;
#if flash
import flash.Lib;
#elseif html5
import js.Browser;
#end
class Init { class Init {
@@ -41,19 +36,16 @@ class Init {
@:provide static var popupManager:PopupManager; @:provide static var popupManager:PopupManager;
@:provide static var connection:IConnection<Request, Response>; @:provide static var connection:IConnection<Request, Response>;
private static function getHost():String { private static function buildConnection():IConnection<Request, Response> {
var host:String = CompilationOption.get("host");
var port:Int = CompilationOption.get("port");
L.d("Init", 'connect to $host:$port');
#if flash #if flash
var url = Lib.current.loaderInfo.url; return new ru.m.connect.flash.FlashConnection<Request, Response>(host, port, Response);
var r:EReg = ~/(app|https?):\/\/?([-_\w\d\.]+)(:\d+)?\/?/;
if (r.match(url) && !(r.matched(1) == "app")) {
return r.matched(2);
} else {
return "localhost";
}
#elseif html5 #elseif html5
return Browser.location.hostname; return new ru.m.connect.js.JsConnection<Request, Response>(host, port + (ru.m.connect.js.JsConnection.isSecured() ? 1 : 0), Response);
#else #else
return "localhost"; return new ru.m.connect.desktop.DesktopConnection<Request, Response>(host, port, Response);
#end #end
} }
@@ -72,15 +64,7 @@ class Init {
popupManager.showAnimateFactory = function(v) return new UnFadeAnimate(v, 100); popupManager.showAnimateFactory = function(v) return new UnFadeAnimate(v, 100);
popupManager.closeAnimateFactory = function(v) return new FadeAnimate(v, 100); popupManager.closeAnimateFactory = function(v) return new FadeAnimate(v, 100);
var host:String = getHost(); connection = buildConnection();
L.d('Init', 'host: ${host}');
#if flash
connection = new ru.m.connect.flash.FlashConnection<Request, Response>(host, 5000, Response);
#elseif html5
connection = new ru.m.connect.js.JsConnection<Request, Response>(host, 5000, Response);
#else
connection = new ru.m.connect.desktop.DesktopConnection<Request, Response>(host, 5000, Response);
#end
networkManager = new NetworkManager(); networkManager = new NetworkManager();
} }
} }

View File

@@ -133,18 +133,21 @@ class NetworkManager {
listGameSignal.emit(packet.listGame.games); listGameSignal.emit(packet.listGame.games);
} else if (packet.hasCreateGame()) { } else if (packet.hasCreateGame()) {
game = packet.createGame.game; game = packet.createGame.game;
gameSignal.emit(packet.createGame.game); gameSignal.emit(game);
} else if (packet.hasJoinGame()) { } else if (packet.hasJoinGame()) {
game = packet.createGame.game; game = packet.joinGame.game;
gameSignal.emit(packet.joinGame.game); gameSignal.emit(game);
} else if (packet.hasLeaveGame()) { } else if (packet.hasLeaveGame()) {
if (packet.leaveGame.user.uuid == user.uuid) { if (packet.leaveGame.user.uuid == user.uuid) {
game = null;
gameSignal.emit(null); gameSignal.emit(null);
} else { } else {
gameSignal.emit(packet.leaveGame.game); game = packet.leaveGame.game;
gameSignal.emit(game);
} }
} else if (packet.hasStartGame()) { } else if (packet.hasStartGame()) {
gameSignal.emit(packet.startGame.game); game = packet.startGame.game;
gameSignal.emit(game);
} }
} }
} }

View File

@@ -2,7 +2,7 @@ package ru.m.tankz.view.network;
import haxework.view.LabelView; import haxework.view.LabelView;
import haxework.view.HGroupView; import haxework.view.HGroupView;
import haxework.view.list.ListView.IListItemView; import haxework.view.list.ListView;
import ru.m.tankz.proto.core.GameProto; import ru.m.tankz.proto.core.GameProto;
@:template class GameItemView extends HGroupView implements IListItemView<GameProto> { @:template class GameItemView extends HGroupView implements IListItemView<GameProto> {
@@ -14,7 +14,7 @@ import ru.m.tankz.proto.core.GameProto;
private function set_data(value:GameProto):GameProto { private function set_data(value:GameProto):GameProto {
data = value; data = value;
label.text = '${value.id}. ${value.type} - ${value.level} (${value.creator.name})'; label.text = '[${value.creator.name}] ${value.type} ${value.level} (${value.players.length})';
return data; return data;
} }

View File

@@ -43,7 +43,9 @@ import ru.m.tankz.proto.core.GameProto;
} }
private function onGame(game:GameProto):Void { private function onGame(game:GameProto):Void {
switcher.change(GameRoomFrame.ID); if (game != null) {
switcher.change(GameRoomFrame.ID);
}
} }
private function selectGame(game:GameProto):Void { private function selectGame(game:GameProto):Void {

View File

@@ -1,22 +1,30 @@
package ru.m.tankz.view.network; package ru.m.tankz.view.network;
import haxework.view.frame.FrameSwitcher; import haxework.view.frame.FrameSwitcher;
import haxework.view.list.VListView;
import haxework.view.TextView; import haxework.view.TextView;
import haxework.view.VGroupView; import haxework.view.VGroupView;
import ru.m.tankz.network.NetworkManager; import ru.m.tankz.network.NetworkManager;
import ru.m.tankz.proto.core.GameProto; import ru.m.tankz.proto.core.GameProto;
import ru.m.tankz.proto.core.UserProto;
@:template class GameRoomFrame extends VGroupView { @:template class GameRoomFrame extends VGroupView {
public static inline var ID = "game_room"; public static inline var ID = "game_room";
@:view var info:TextView; @:view var info:TextView;
@:view var players:VListView<UserProto>;
@:provide var switcher:FrameSwitcher; @:provide var switcher:FrameSwitcher;
@:provide var network:NetworkManager; @:provide var network:NetworkManager;
private function refresh(game:GameProto):Void { private function refresh(game:GameProto):Void {
info.text = '${game.id}. ${game.type}'; if (game != null) {
info.text = '[${game.creator.name}] ${game.type} ${game.level} (${game.players.length})';
players.data = game.players;
} else {
Timer.delay(function() switcher.change(GameListFrame.ID), 1);
}
} }
public function onShow():Void { public function onShow():Void {

View File

@@ -10,11 +10,16 @@ views:
skinId: text.header skinId: text.header
text: Game Room text: Game Room
- id: info - id: info
$type: haxework.view.TextView $type: haxework.view.LabelView
geometry.size.width: 100%
skinId: text.box
- id: players
$type: haxework.view.list.VListView
geometry.size.stretch: true geometry.size.stretch: true
factory: $code:ru.m.tankz.view.network.PlayerItemView.factory
- $type: haxework.view.HGroupView - $type: haxework.view.HGroupView
skinId: panel skinId: panel
views: views:
- $type: haxework.view.ButtonView - $type: haxework.view.ButtonView
skinId: button.close skinId: button.close
+onPress: $code:switcher.change('start') +onPress: $code:network.leaveGame()

View File

@@ -0,0 +1,24 @@
package ru.m.tankz.view.network;
import haxework.view.HGroupView;
import haxework.view.LabelView;
import haxework.view.list.ListView;
import ru.m.tankz.proto.core.UserProto;
@:template class PlayerItemView extends HGroupView implements IListItemView<UserProto> {
public var item_index(default, default):Int;
public var data(default, set):UserProto;
@:view var label:LabelView;
private function set_data(value:UserProto):UserProto {
data = value;
label.text = '${value.name}';
return data;
}
public static function factory():PlayerItemView {
return new PlayerItemView();
}
}

View File

@@ -0,0 +1,8 @@
---
geometry.size.width: 100%
geometry.size.height: 48
views:
- id: label
$type: haxework.view.LabelView
geometry.size.stretch: true
skinId: text.box

View File

@@ -22,12 +22,12 @@ class JsConnection<O:Message, I:Message> extends BaseConnection<O, I> {
connected = false; connected = false;
} }
public static function isSecured():Bool {
return Browser.location.protocol == "https";
}
private function buildSocket(host:String, port:Int):WebSocket { private function buildSocket(host:String, port:Int):WebSocket {
var protocol = switch Browser.location.protocol { var protocol = isSecured() ? "wss:" : "ws:";
case 'http:': 'ws:';
case 'https:': 'wss:';
case _: 'ws:';
}
return new WebSocket('$protocol//$host:$port'); return new WebSocket('$protocol//$host:$port');
} }

View File

@@ -52,7 +52,7 @@ class Server extends ThreadServer<GameSession, Bytes> {
Provider.setFactory(ILevelBundle, ServerLevelBundle); Provider.setFactory(ILevelBundle, ServerLevelBundle);
Provider.setFactory(IControlFactory, NoneControlFactory); Provider.setFactory(IControlFactory, NoneControlFactory);
gameManager = new GameManager(); gameManager = new GameManager();
var host:String = Sys.args().length > 0 ? Sys.args()[0] : "localhost"; 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;
var wserver = new Server(); var wserver = new Server();
L.i(TAG, 'Start on ${host}:${port}'); L.i(TAG, 'Start on ${host}:${port}');

View File

@@ -1,8 +1,7 @@
package ru.m.tankz.server.game; package ru.m.tankz.server.game;
import ru.m.tankz.proto.core.GameStateProto;
import ru.m.tankz.game.GameState;
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.UserProto; import ru.m.tankz.proto.core.UserProto;
import ru.m.tankz.server.game.IGameManager; import ru.m.tankz.server.game.IGameManager;

View File

@@ -1,18 +1,18 @@
package ru.m.tankz.server.game; package ru.m.tankz.server.game;
import ru.m.tankz.game.Game; import ru.m.tankz.game.Game;
//import ru.m.tankz.game.GameRunner; import ru.m.tankz.game.GameRunner;
import ru.m.tankz.game.GameState; import ru.m.tankz.game.GameState;
import ru.m.tankz.proto.core.GameProto; import ru.m.tankz.proto.core.GameProto;
class ServerGame extends Game { class ServerGame extends Game {
//public var runner(default, null):GameRunner; public var runner(default, null):GameRunner;
public var proto(default, null):GameProto; public var proto(default, null):GameProto;
public function new(proto:GameProto) { public function new(proto:GameProto) {
super(new GameState(proto.type, 0, proto.level)); super(new GameState(proto.type, 0, proto.level));
this.proto = proto; this.proto = proto;
//runner = new GameRunner(this); runner = new GameRunner(this);
} }
} }

View File

@@ -26,8 +26,15 @@ class GameSession extends ProtoSession<Response, Request> implements GameManager
public var user(default, null):UserProto; public var user(default, null):UserProto;
public var gameId(default, null):Int; public var gameId(default, null):Int;
private var tag(get, never):String;
private function get_tag():String {
return '[${id}|${user == null ? '-' : user.name}|${gameId == -1 ? '-' : Std.string(gameId)}]';
}
public function new(socket:Socket) { public function new(socket:Socket) {
super(socket, Request); super(socket, Request);
gameId = -1;
} }
private function sendError(code:Int, message:String):Void { private function sendError(code:Int, message:String):Void {
@@ -40,12 +47,25 @@ 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, 'send: ${user == null ? '' : user.name} - ${packet}'); L.d(TAG, '$tag send: ${packet}');
super.send(packet); try {
super.send(packet);
} catch (error:Dynamic) {
L.e(TAG, '$tag send ', error);
}
}
private function logout():Void {
gameId = -1;
gameManager.disconnect(this);
if (user != null) {
gameManager.leave(user);
user = null;
}
} }
override private function onRequest(request:Request):Void { override private function onRequest(request:Request):Void {
L.d(TAG, 'onRequest: ${user == null ? '' : user.name} - ${request}'); L.d(TAG, '$tag onRequest: ${request}');
try { try {
if (!request.hasLogin() && user == null) { if (!request.hasLogin() && user == null) {
throw "Not Authorized"; throw "Not Authorized";
@@ -59,11 +79,7 @@ class GameSession extends ProtoSession<Response, Request> implements GameManager
send(new Response().setLogin(new LoginResponse().setUser(user))); send(new Response().setLogin(new LoginResponse().setUser(user)));
// logout // logout
} else if (request.hasLogout()) { } else if (request.hasLogout()) {
gameManager.disconnect(this); logout();
if (user != null) {
gameManager.leave(user);
user = null;
}
send(new Response().setLogout(new LogoutResponse())); send(new Response().setLogout(new LogoutResponse()));
// create // create
} else if (request.hasCreateGame()) { } else if (request.hasCreateGame()) {
@@ -85,23 +101,21 @@ class GameSession extends ProtoSession<Response, Request> implements GameManager
gameManager.start(gameId); gameManager.start(gameId);
} }
} catch (error:Dynamic) { } catch (error:Dynamic) {
L.e(TAG, "onRequest ", error); L.e(TAG, '$tag onRequest ', error);
sendError(500, LoggerUtil.printError(error)); sendError(500, LoggerUtil.printError(error));
} }
} }
override public function disconnect():Void { override public function disconnect():Void {
gameId = null; L.d(TAG, '$tag disconnect');
gameManager.disconnect(this); logout();
if (user != null) {
gameManager.leave(user);
user = null;
}
super.disconnect(); super.disconnect();
} }
public function onCreate(game:ServerGame):Void { public function onCreate(game:ServerGame):Void {
send(new Response().setListGame(listGame())); if (gameId == -1) {
send(new Response().setListGame(listGame()));
}
} }
public function onChange(game:ServerGame, change:GameChange):Void { public function onChange(game:ServerGame, change:GameChange):Void {
@@ -109,21 +123,29 @@ class GameSession extends ProtoSession<Response, Request> implements GameManager
switch change { switch change {
case JOIN(user): case JOIN(user):
if (user.uuid == this.user.uuid) { if (user.uuid == this.user.uuid) {
gameId = gameId = game.proto.id; gameId = game.proto.id;
} }
send(new Response().setJoinGame(new JoinGameResponse().setGame(game.proto).setUser(user))); send(new Response().setJoinGame(new JoinGameResponse().setGame(game.proto).setUser(user)));
case LEAVE(user): case LEAVE(user):
if (user.uuid == this.user.uuid) { if (user.uuid == this.user.uuid) {
gameId = null; gameId = -1;
} }
send(new Response().setLeaveGame(new LeaveGameResponse().setGame(game.proto).setUser(user))); send(new Response().setLeaveGame(new LeaveGameResponse().setGame(game.proto).setUser(user)));
case START: case START:
send(new Response().setStartGame(new StartGameResponse().setGame(game.proto))); send(new Response().setStartGame(new StartGameResponse().setGame(game.proto)));
} }
} else {
// ToDo: change game event
send(new Response().setListGame(listGame()));
} }
} }
public function onDelete(game:ServerGame):Void { public function onDelete(game:ServerGame):Void {
send(new Response().setListGame(listGame())); if (gameId == -1) {
send(new Response().setListGame(listGame()));
} else if (gameId == game.proto.id) {
gameId = -1;
send(new Response().setLeaveGame(new LeaveGameResponse().setGame(game.proto).setUser(user)));
}
} }
} }

View File

@@ -3,6 +3,7 @@ package ru.m.tankz.server.session;
import haxe.io.Bytes; import haxe.io.Bytes;
interface ISession { interface ISession {
public var id(default, null):Int;
public function pushData(bytes:Bytes):Void; public function pushData(bytes:Bytes):Void;
public function disconnect():Void; public function disconnect():Void;
} }

View File

@@ -19,11 +19,15 @@ class ProtoSession<O:Message, I:Message> implements ISession {
"</cross-domain-policy>" "</cross-domain-policy>"
].join("\n"); ].join("\n");
private static var idCounter:Int = 0;
public var id(default, null):Int;
public var connection(default, null):IConnection<O, I>; public var connection(default, null):IConnection<O, I>;
private var socket:Socket; private var socket:Socket;
private var request:Class<I>; private var request:Class<I>;
public function new(socket:Socket, request:Class<I>) { public function new(socket:Socket, request:Class<I>) {
this.id = ++idCounter;
this.socket = socket; this.socket = socket;
this.request = request; this.request = request;
} }
@@ -41,7 +45,6 @@ class ProtoSession<O:Message, I:Message> implements ISession {
} else { } else {
connection = new NekoConnection<O, I>(socket, request); connection = new NekoConnection<O, I>(socket, request);
} }
connection.handler.connect(onConnectionEvent);
connection.receiveHandler.connect(onRequest); connection.receiveHandler.connect(onRequest);
return connection; return connection;
} }
@@ -60,11 +63,7 @@ class ProtoSession<O:Message, I:Message> implements ISession {
} }
public function disconnect():Void { public function disconnect():Void {
connection.handler.emit(ConnectionEvent.DISCONNECTED); connection.disconnect();
}
private function onConnectionEvent(event:ConnectionEvent):Void {
L.d(TAG, 'onConnectionEvent: ${event}');
} }
private function onRequest(request:I):Void { private function onRequest(request:I):Void {