[common] add DesktopConnection
This commit is contained in:
9
.editorconfig
Normal file
9
.editorconfig
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# Editor configuration, see http://editorconfig.org
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
charset = utf-8
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
insert_final_newline = true
|
||||||
|
trim_trailing_whitespace = true
|
||||||
@@ -124,7 +124,7 @@ const server = new Project(
|
|||||||
config.branch({
|
config.branch({
|
||||||
name: 'server',
|
name: 'server',
|
||||||
sources: ['src/server/haxe'],
|
sources: ['src/server/haxe'],
|
||||||
main: 'ru.m.tankz.server.Server',
|
main: 'ru.m.tankz.server.TestServer',
|
||||||
})
|
})
|
||||||
).bind(module, gulp);
|
).bind(module, gulp);
|
||||||
|
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ class Init {
|
|||||||
#elseif html5
|
#elseif html5
|
||||||
connection = new ru.m.connect.js.JsConnection<Request, Response>(host, 5000, Response);
|
connection = new ru.m.connect.js.JsConnection<Request, Response>(host, 5000, Response);
|
||||||
#else
|
#else
|
||||||
connection = new ru.m.connect.fake.FakeConnection<Request, Response>(Response);
|
connection = new ru.m.connect.desktop.DesktopConnection<Request, Response>(host, 5000, Response);
|
||||||
#end
|
#end
|
||||||
networkManager = new NetworkManager();
|
networkManager = new NetworkManager();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -146,5 +146,7 @@ class Style {
|
|||||||
registerButton("close", "times-circle-solid.svg");
|
registerButton("close", "times-circle-solid.svg");
|
||||||
registerButton("next", "arrow-alt-circle-right-solid.svg");
|
registerButton("next", "arrow-alt-circle-right-solid.svg");
|
||||||
registerButton("start", "play-circle-solid.svg");
|
registerButton("start", "play-circle-solid.svg");
|
||||||
|
registerButton("login", "sign-in-solid.svg");
|
||||||
|
registerButton("logout", "sign-out-solid.svg");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,70 +1,80 @@
|
|||||||
package ru.m.tankz.network;
|
package ru.m.tankz.network;
|
||||||
|
|
||||||
import ru.m.tankz.storage.MultiplayerStorage;
|
|
||||||
import haxework.storage.IStorage;
|
|
||||||
import haxework.signal.Signal;
|
import haxework.signal.Signal;
|
||||||
import ru.m.tankz.proto.pack.GameRequest;
|
import ru.m.connect.IConnection;
|
||||||
import ru.m.tankz.proto.core.GameProto;
|
|
||||||
import ru.m.tankz.proto.pack.StartGameRequest;
|
|
||||||
import ru.m.tankz.proto.game.GameChangeProto;
|
|
||||||
import ru.m.tankz.proto.game.GameActionTypeProto;
|
|
||||||
import ru.m.tankz.proto.pack.GameUpdateRequest;
|
|
||||||
import ru.m.tankz.control.Control;
|
import ru.m.tankz.control.Control;
|
||||||
|
import ru.m.tankz.proto.core.GameInfoProto;
|
||||||
|
import ru.m.tankz.proto.game.GameActionTypeProto;
|
||||||
|
import ru.m.tankz.proto.game.GameChangeProto;
|
||||||
|
import ru.m.tankz.proto.pack.CreateGameRequest;
|
||||||
|
import ru.m.tankz.proto.pack.GameUpdateRequest;
|
||||||
import ru.m.tankz.proto.pack.JoinGameRequest;
|
import ru.m.tankz.proto.pack.JoinGameRequest;
|
||||||
import ru.m.tankz.proto.pack.LeaveGameRequest;
|
import ru.m.tankz.proto.pack.LeaveGameRequest;
|
||||||
import ru.m.tankz.proto.pack.CreateGameRequest;
|
|
||||||
import ru.m.connect.IConnection;
|
|
||||||
import ru.m.tankz.proto.core.GameInfoProto;
|
|
||||||
import ru.m.tankz.proto.pack.ListGameRequest;
|
import ru.m.tankz.proto.pack.ListGameRequest;
|
||||||
import ru.m.tankz.proto.pack.LoginRequest;
|
import ru.m.tankz.proto.pack.LoginRequest;
|
||||||
|
import ru.m.tankz.proto.pack.LogoutRequest;
|
||||||
import ru.m.tankz.proto.pack.Request;
|
import ru.m.tankz.proto.pack.Request;
|
||||||
import ru.m.tankz.proto.pack.Response;
|
import ru.m.tankz.proto.pack.Response;
|
||||||
|
import ru.m.tankz.proto.pack.StartGameRequest;
|
||||||
|
import ru.m.tankz.storage.MultiplayerStorage;
|
||||||
|
|
||||||
typedef ClientConnection = IConnection<Request, Response>;
|
typedef ClientConnection = IConnection<Request, Response>;
|
||||||
|
|
||||||
|
enum ConnectionState {
|
||||||
|
OFFLINE;
|
||||||
|
CONNECT;
|
||||||
|
CONNECTED;
|
||||||
|
LOGIN;
|
||||||
|
ONLINE(user:User);
|
||||||
|
ERROR(error:Dynamic);
|
||||||
|
}
|
||||||
|
|
||||||
class NetworkManager {
|
class NetworkManager {
|
||||||
|
|
||||||
public var state(default, null):String;
|
public var state(default, null):ConnectionState;
|
||||||
public var stateSignal:Signal<String>;
|
public var stateSignal:Signal<ConnectionState>;
|
||||||
public var listGameSignal:Signal<Array<GameInfoProto>>;
|
public var listGameSignal:Signal<Array<GameInfoProto>>;
|
||||||
public var gameSignal:Signal<GameInfoProto>;
|
public var gameSignal:Signal<GameInfoProto>;
|
||||||
public var gameUpdateSignal:Signal<Array<GameChangeProto>>;
|
public var gameUpdateSignal:Signal<Array<GameChangeProto>>;
|
||||||
public var user(default, null):User;
|
|
||||||
public var game(default, set):NetworkGame;
|
|
||||||
|
|
||||||
@:provide private var connection:ClientConnection;
|
@:provide private var connection:ClientConnection;
|
||||||
@:provide private var storage:MultiplayerStorage;
|
@:provide private var storage:MultiplayerStorage;
|
||||||
|
|
||||||
public function new() {
|
public function new() {
|
||||||
stateSignal = new Signal<String>();
|
stateSignal = new Signal();
|
||||||
listGameSignal = new Signal<Array<GameInfoProto>>();
|
listGameSignal = new Signal();
|
||||||
gameSignal = new Signal<GameInfoProto>();
|
gameSignal = new Signal();
|
||||||
gameUpdateSignal = new Signal<Array<GameChangeProto>>();
|
gameUpdateSignal = new Signal();
|
||||||
updateState('offline');
|
updateState(OFFLINE);
|
||||||
connection.handler.connect(onConnectionEvent);
|
connection.handler.connect(onConnectionEvent);
|
||||||
connection.receiveHandler.connect(onResponse);
|
connection.receiveHandler.connect(onResponse);
|
||||||
user = storage.user;
|
var user = storage.user;
|
||||||
if (user == null) {
|
if (user != null) {
|
||||||
user = {name: 'User', uuid: null};
|
login(user.name, user.uuid);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function updateState(value:String):Void {
|
private function updateState(value:ConnectionState):Void {
|
||||||
state = value;
|
state = value;
|
||||||
stateSignal.emit(value);
|
stateSignal.emit(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function login(name:String):Void {
|
public function login(name:String, uuid:String = null):Void {
|
||||||
user.name = name;
|
updateState(CONNECT);
|
||||||
updateState('connect...');
|
|
||||||
connection.connect().then(function(c:ClientConnection) {
|
connection.connect().then(function(c:ClientConnection) {
|
||||||
updateState('login...');
|
updateState(LOGIN);
|
||||||
c.send(new Request().setLogin(
|
c.send(new Request().setLogin(
|
||||||
new LoginRequest()
|
new LoginRequest()
|
||||||
.setUuid(user.uuid)
|
.setUuid(uuid)
|
||||||
.setName(user.name)
|
.setName(name)
|
||||||
));
|
));
|
||||||
}).catchError(function(_) {});
|
}).catchError(function(error) {
|
||||||
|
updateState(ERROR(error));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function logout():Void {
|
||||||
|
connection.send(new Request().setLogout(new LogoutRequest()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function listGame():Void {
|
public function listGame():Void {
|
||||||
@@ -108,30 +118,30 @@ class NetworkManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function onConnectionEvent(event:ConnectionEvent):Void {
|
private function onConnectionEvent(event:ConnectionEvent):Void {
|
||||||
updateState(switch (event) {
|
updateState(switch event {
|
||||||
case ConnectionEvent.CONNECTED:
|
case CONNECTED:
|
||||||
L.d('Network', '$event');
|
L.d('Network', '$event');
|
||||||
'connected';
|
CONNECTED;
|
||||||
case ConnectionEvent.DISCONNECTED:
|
case DISCONNECTED:
|
||||||
L.d('Network', '$event');
|
L.d('Network', '$event');
|
||||||
'offline';
|
OFFLINE;
|
||||||
case ConnectionEvent.ERROR(error):
|
case ERROR(error):
|
||||||
L.e('Network', '$error', error);
|
L.e('Network', '$error', error);
|
||||||
'error';
|
ERROR(error);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private function onResponse(packet:Response):Void {
|
private function onResponse(packet:Response):Void {
|
||||||
if (packet.hasLogin()) {
|
if (packet.hasLogin()) {
|
||||||
user = {
|
var user = {
|
||||||
uuid: packet.login.user.uuid,
|
uuid: packet.login.user.uuid,
|
||||||
name: packet.login.user.name,
|
name: packet.login.user.name,
|
||||||
};
|
};
|
||||||
storage.user = user;
|
storage.user = user;
|
||||||
updateState('online');
|
updateState(ONLINE(user));
|
||||||
} else if (packet.hasLogout()) {
|
} else if (packet.hasLogout()) {
|
||||||
user = null;
|
storage.user = null;
|
||||||
updateState('connected');
|
updateState(CONNECTED);
|
||||||
} else if (packet.hasListGame()) {
|
} else if (packet.hasListGame()) {
|
||||||
listGameSignal.emit(packet.listGame.games);
|
listGameSignal.emit(packet.listGame.games);
|
||||||
} else if (packet.hasCreateGame()) {
|
} else if (packet.hasCreateGame()) {
|
||||||
@@ -145,13 +155,7 @@ class NetworkManager {
|
|||||||
} else if (packet.hasUpdateGame()) {
|
} else if (packet.hasUpdateGame()) {
|
||||||
gameUpdateSignal.emit(packet.updateGame.changes);
|
gameUpdateSignal.emit(packet.updateGame.changes);
|
||||||
} else if (packet.hasGame()) {
|
} else if (packet.hasGame()) {
|
||||||
game.load(packet.game.game);
|
//game.load(packet.game.game);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function set_game(value:NetworkGame):NetworkGame {
|
|
||||||
this.game = value;
|
|
||||||
connection.send(new Request().setGame(new GameRequest()));
|
|
||||||
return this.game;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,25 +1,69 @@
|
|||||||
package ru.m.tankz.view;
|
package ru.m.tankz.view;
|
||||||
|
|
||||||
|
import haxework.view.ButtonView;
|
||||||
|
import haxework.view.LabelView;
|
||||||
import haxework.view.frame.FrameSwitcher;
|
import haxework.view.frame.FrameSwitcher;
|
||||||
import haxework.view.VGroupView;
|
import haxework.view.VGroupView;
|
||||||
import ru.m.tankz.game.GameState;
|
import ru.m.tankz.game.GameState;
|
||||||
|
import ru.m.tankz.network.NetworkManager;
|
||||||
import ru.m.tankz.Type.GameType;
|
import ru.m.tankz.Type.GameType;
|
||||||
import ru.m.tankz.view.popup.FontPopup;
|
import ru.m.tankz.view.popup.FontPopup;
|
||||||
|
import ru.m.tankz.view.popup.LoginPopup;
|
||||||
|
|
||||||
@:template class StartFrame extends VGroupView {
|
@:template class StartFrame extends VGroupView {
|
||||||
|
|
||||||
public static var ID(default, never):String = "start";
|
public static var ID(default, never):String = "start";
|
||||||
|
|
||||||
|
@:view var username:LabelView;
|
||||||
|
@:view("login") var loginButton:ButtonView;
|
||||||
|
@:view("logout") var logoutButton:ButtonView;
|
||||||
|
@:view("network") var networkButton:ButtonView;
|
||||||
|
|
||||||
@:provide var state:GameState;
|
@:provide var state:GameState;
|
||||||
@:provide var switcher:FrameSwitcher;
|
@:provide var switcher:FrameSwitcher;
|
||||||
|
@:provide var network:NetworkManager;
|
||||||
|
|
||||||
private var fontPopup:FontPopup;
|
private var fontPopup:FontPopup;
|
||||||
|
|
||||||
|
public function onShow():Void {
|
||||||
|
onConnectionState(network.state);
|
||||||
|
network.stateSignal.connect(onConnectionState);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onHide():Void {
|
||||||
|
network.stateSignal.disconnect(onConnectionState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function onConnectionState(state:ConnectionState):Void {
|
||||||
|
trace("state", state);
|
||||||
|
setUser(switch state {
|
||||||
|
case ONLINE(user): user;
|
||||||
|
case _: null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private function setUser(value:User):Void {
|
||||||
|
username.text = value == null ? "" : value.name;
|
||||||
|
loginButton.visible = value == null;
|
||||||
|
logoutButton.visible = value != null;
|
||||||
|
networkButton.disabled = value == null;
|
||||||
|
}
|
||||||
|
|
||||||
private function startGame(type:GameType):Void {
|
private function startGame(type:GameType):Void {
|
||||||
state = new GameState(type);
|
state = new GameState(type);
|
||||||
switcher.change(LevelFrame.ID);
|
switcher.change(LevelFrame.ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function login():Void {
|
||||||
|
LoginPopup.instance.show().then(function(user:User):Void {
|
||||||
|
L.d("Login", 'user: $user');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private function logout():Void {
|
||||||
|
network.logout();
|
||||||
|
}
|
||||||
|
|
||||||
private function choiceFont():Void {
|
private function choiceFont():Void {
|
||||||
if (fontPopup == null) {
|
if (fontPopup == null) {
|
||||||
fontPopup = new FontPopup();
|
fontPopup = new FontPopup();
|
||||||
|
|||||||
@@ -1,40 +1,63 @@
|
|||||||
---
|
---
|
||||||
views:
|
views:
|
||||||
- $type: haxework.view.VGroupView
|
- $type: haxework.view.VGroupView
|
||||||
skinId: container
|
skinId: container
|
||||||
layout.margin: 10
|
layout.margin: 10
|
||||||
views:
|
views:
|
||||||
- $type: haxework.view.LabelView
|
- $type: haxework.view.LabelView
|
||||||
text: Tank'z
|
text: Tank'z
|
||||||
skinId: font
|
skinId: font
|
||||||
fontSize: 100
|
fontSize: 100
|
||||||
geometry.margin.bottom: 30
|
geometry.margin.bottom: 30
|
||||||
- $type: haxework.view.ButtonView
|
- $type: haxework.view.ButtonView
|
||||||
skinId: button
|
skinId: button
|
||||||
+onPress: $code:startGame('classic')
|
+onPress: $code:startGame('classic')
|
||||||
text: Classic
|
text: Classic
|
||||||
- $type: haxework.view.ButtonView
|
- $type: haxework.view.ButtonView
|
||||||
skinId: button
|
skinId: button
|
||||||
+onPress: $code:startGame('dota')
|
+onPress: $code:startGame('dota')
|
||||||
text: DotA
|
text: DotA
|
||||||
- $type: haxework.view.ButtonView
|
- $type: haxework.view.ButtonView
|
||||||
skinId: button
|
skinId: button
|
||||||
+onPress: $code:startGame('death')
|
+onPress: $code:startGame('death')
|
||||||
text: DeathMatch
|
text: DeathMatch
|
||||||
- $type: haxework.view.ButtonView
|
- $type: haxework.view.ButtonView
|
||||||
skinId: button
|
skinId: button
|
||||||
+onPress: $code:switcher.change('record')
|
+onPress: $code:switcher.change('record')
|
||||||
text: Records
|
text: Records
|
||||||
- $type: haxework.view.HGroupView
|
- id: network
|
||||||
skinId: panel
|
$type: haxework.view.ButtonView
|
||||||
views:
|
skinId: button
|
||||||
- id: settings
|
# +onPress: $code:switcher.change('record')
|
||||||
$type: haxework.view.ButtonView
|
text: Network
|
||||||
skinId: button.settings
|
disabled: true
|
||||||
+onPress: $code:switcher.change('settings')
|
- $type: haxework.view.HGroupView
|
||||||
- $type: haxework.view.SpriteView
|
skinId: panel
|
||||||
geometry.size.width: 100%
|
views:
|
||||||
- $type: haxework.view.LabelView
|
- id: settings
|
||||||
geometry.padding: [20, 5]
|
$type: haxework.view.ButtonView
|
||||||
skinId: text.box
|
skinId: button.settings
|
||||||
text: $r:text:version
|
+onPress: $code:switcher.change('settings')
|
||||||
|
- $type: haxework.view.SpriteView
|
||||||
|
geometry.size.width: 100%
|
||||||
|
- id: username
|
||||||
|
$type: haxework.view.LabelView
|
||||||
|
skinId: text
|
||||||
|
geometry.margin.right: 10
|
||||||
|
- id: login
|
||||||
|
$type: haxework.view.ButtonView
|
||||||
|
skinId: button.login
|
||||||
|
+onPress: $code:login()
|
||||||
|
- id: logout
|
||||||
|
$type: haxework.view.ButtonView
|
||||||
|
skinId: button.logout
|
||||||
|
+onPress: $code:logout()
|
||||||
|
visible: false
|
||||||
|
- $type: haxework.view.LabelView
|
||||||
|
geometry.hAlign: right
|
||||||
|
geometry.vAlign: top
|
||||||
|
geometry.padding: [20, 5]
|
||||||
|
geometry.position: absolute
|
||||||
|
geometry.margin: [0, 20, 20, 0]
|
||||||
|
skinId: text.box
|
||||||
|
text: $r:text:version
|
||||||
|
|||||||
@@ -1,27 +1,27 @@
|
|||||||
---
|
---
|
||||||
view:
|
view:
|
||||||
$type: haxework.view.VGroupView
|
$type: haxework.view.VGroupView
|
||||||
geometry.size.width: 400
|
geometry.size.width: 400
|
||||||
geometry.size.height: 80%
|
geometry.size.height: 80%
|
||||||
geometry.padding: 10
|
geometry.padding: 10
|
||||||
geometry.hAlign: center
|
geometry.hAlign: center
|
||||||
geometry.vAlign: middle
|
geometry.vAlign: middle
|
||||||
skinId: dark
|
skinId: dark
|
||||||
views:
|
views:
|
||||||
- id: fonts
|
- id: fonts
|
||||||
$type: haxework.view.list.VListView
|
$type: haxework.view.list.VListView
|
||||||
geometry.size.stretch: true
|
geometry.size.stretch: true
|
||||||
factory: $this:fontViewFactory
|
factory: $this:fontViewFactory
|
||||||
+onItemSelect: $code:function(item) close(item.data)
|
+onItemSelect: $code:function(item) close(item.data)
|
||||||
scroll:
|
scroll:
|
||||||
$type: haxework.view.list.VScrollBarView
|
$type: haxework.view.list.VScrollBarView
|
||||||
skinId: scroll.vertical
|
skinId: scroll.vertical
|
||||||
- $type: haxework.view.HGroupView
|
- $type: haxework.view.HGroupView
|
||||||
geometry.size.width: 100%
|
geometry.size.width: 100%
|
||||||
geometry.margin.top: 10
|
geometry.margin.top: 10
|
||||||
layout.hAlign: right
|
layout.hAlign: right
|
||||||
views:
|
views:
|
||||||
- $type: haxework.view.ButtonView
|
- $type: haxework.view.ButtonView
|
||||||
skinId: button.simple
|
skinId: button.simple
|
||||||
text: Cancel
|
text: Cancel
|
||||||
+onPress: $code:reject('cancel')
|
+onPress: $code:reject('cancel')
|
||||||
|
|||||||
@@ -2,34 +2,34 @@
|
|||||||
layout.hAlign: center
|
layout.hAlign: center
|
||||||
layout.vAlign: middle
|
layout.vAlign: middle
|
||||||
view:
|
view:
|
||||||
$type: haxework.view.VGroupView
|
$type: haxework.view.VGroupView
|
||||||
layout.hAlign: center
|
layout.hAlign: center
|
||||||
geometry.size.width: 400
|
geometry.size.width: 400
|
||||||
geometry.size.height: 400
|
geometry.size.height: 400
|
||||||
skinId: window
|
skinId: window
|
||||||
views:
|
views:
|
||||||
- $type: haxework.view.HGroupView
|
- $type: haxework.view.HGroupView
|
||||||
geometry.size.width: 100%
|
geometry.size.width: 100%
|
||||||
geometry.padding: 10
|
geometry.padding: 10
|
||||||
layout.vAlign: middle
|
layout.vAlign: middle
|
||||||
views:
|
views:
|
||||||
- id: name
|
- id: name
|
||||||
$type: haxework.view.LabelView
|
$type: haxework.view.LabelView
|
||||||
geometry.size.width: 100%
|
geometry.size.width: 100%
|
||||||
geometry.margin.left: 10
|
geometry.margin.left: 10
|
||||||
layout.hAlign: left
|
layout.hAlign: left
|
||||||
skinId: text
|
skinId: text
|
||||||
- $type: haxework.view.ButtonView
|
- $type: haxework.view.ButtonView
|
||||||
skinId: window.close
|
skinId: window.close
|
||||||
+onPress: $code:reject('close')
|
+onPress: $code:reject('close')
|
||||||
- $type: haxework.view.SpriteView
|
- $type: haxework.view.SpriteView
|
||||||
geometry.size.height: 100%
|
geometry.size.height: 100%
|
||||||
- id: presets
|
- id: presets
|
||||||
$type: haxework.view.DataView
|
$type: haxework.view.DataView
|
||||||
factory: $this:presetViewFactory
|
factory: $this:presetViewFactory
|
||||||
+onDataSelect: $this:onPresetSelect
|
+onDataSelect: $this:onPresetSelect
|
||||||
layout:
|
layout:
|
||||||
$type: haxework.view.layout.HorizontalLayout
|
$type: haxework.view.layout.HorizontalLayout
|
||||||
hAlign: center
|
hAlign: center
|
||||||
margin: 5
|
margin: 5
|
||||||
skinId: panel
|
skinId: panel
|
||||||
|
|||||||
47
src/client/haxe/ru/m/tankz/view/popup/LoginPopup.hx
Normal file
47
src/client/haxe/ru/m/tankz/view/popup/LoginPopup.hx
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package ru.m.tankz.view.popup;
|
||||||
|
|
||||||
|
import haxework.log.BaseLogger.LoggerUtil;
|
||||||
|
import haxework.view.InputView;
|
||||||
|
import haxework.view.popup.PopupView;
|
||||||
|
import haxework.view.TextView;
|
||||||
|
import ru.m.tankz.network.NetworkManager;
|
||||||
|
|
||||||
|
@:template class LoginPopup extends PopupView<User> {
|
||||||
|
|
||||||
|
@:view var username:InputView;
|
||||||
|
@:view var password:InputView;
|
||||||
|
@:view var error:TextView;
|
||||||
|
|
||||||
|
@:provide static var network:NetworkManager;
|
||||||
|
|
||||||
|
override private function onShow():Void {
|
||||||
|
super.onShow();
|
||||||
|
network.stateSignal.connect(onStateChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
override private function onClose():Void {
|
||||||
|
super.onClose();
|
||||||
|
network.stateSignal.disconnect(onStateChange);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function onStateChange(state:ConnectionState):Void {
|
||||||
|
switch state {
|
||||||
|
case ONLINE(user): close(user);
|
||||||
|
case ERROR(error): this.error.text = LoggerUtil.printError(error);
|
||||||
|
case _: this.error.text = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function submit():Void {
|
||||||
|
network.login(username.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static var instance(get, null):LoginPopup;
|
||||||
|
|
||||||
|
private static function get_instance():LoginPopup {
|
||||||
|
if (instance == null) {
|
||||||
|
instance = new LoginPopup();
|
||||||
|
}
|
||||||
|
return instance;
|
||||||
|
}
|
||||||
|
}
|
||||||
64
src/client/haxe/ru/m/tankz/view/popup/LoginPopup.yaml
Normal file
64
src/client/haxe/ru/m/tankz/view/popup/LoginPopup.yaml
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
---
|
||||||
|
layout.hAlign: center
|
||||||
|
layout.vAlign: middle
|
||||||
|
view:
|
||||||
|
$type: haxework.view.VGroupView
|
||||||
|
layout.hAlign: center
|
||||||
|
geometry.size.width: 400
|
||||||
|
# geometry.size.height: 400
|
||||||
|
skinId: window
|
||||||
|
views:
|
||||||
|
- $type: haxework.view.HGroupView
|
||||||
|
geometry.size.width: 100%
|
||||||
|
geometry.padding: 10
|
||||||
|
layout.vAlign: middle
|
||||||
|
views:
|
||||||
|
- id: name
|
||||||
|
$type: haxework.view.LabelView
|
||||||
|
geometry.size.width: 100%
|
||||||
|
geometry.margin.left: 10
|
||||||
|
layout.hAlign: left
|
||||||
|
skinId: text
|
||||||
|
text: Login
|
||||||
|
- $type: haxework.view.ButtonView
|
||||||
|
skinId: window.close
|
||||||
|
+onPress: $code:reject('close')
|
||||||
|
- $type: haxework.view.VGroupView
|
||||||
|
geometry.size.width: 100%
|
||||||
|
# geometry.size.stretch: true
|
||||||
|
geometry.padding: 20
|
||||||
|
layout.margin: 5
|
||||||
|
views:
|
||||||
|
- $type: haxework.view.LabelView
|
||||||
|
geometry.size.width: 100%
|
||||||
|
skinId: text
|
||||||
|
text: Username
|
||||||
|
- id: username
|
||||||
|
$type: haxework.view.InputView
|
||||||
|
geometry.size.width: 100%
|
||||||
|
geometry.size.height: 28
|
||||||
|
skinId: text.box
|
||||||
|
- $type: haxework.view.LabelView
|
||||||
|
geometry.size.width: 100%
|
||||||
|
skinId: text
|
||||||
|
text: Password
|
||||||
|
- id: password
|
||||||
|
$type: haxework.view.InputView
|
||||||
|
textField.displayAsPassword: true
|
||||||
|
geometry.size.width: 100%
|
||||||
|
geometry.size.height: 28
|
||||||
|
skinId: text.box
|
||||||
|
- id: error
|
||||||
|
$type: haxework.view.TextView
|
||||||
|
geometry.size.width: 100%
|
||||||
|
skinId: text
|
||||||
|
fill: false
|
||||||
|
- $type: haxework.view.HGroupView
|
||||||
|
layout.hAlign: center
|
||||||
|
layout.margin: 5
|
||||||
|
skinId: panel
|
||||||
|
views:
|
||||||
|
- $type: haxework.view.ButtonView
|
||||||
|
skinId: button.simple
|
||||||
|
text: Submit
|
||||||
|
+onPress: $code:submit()
|
||||||
1
src/client/resources/image/icon/sign-in-solid.svg
Normal file
1
src/client/resources/image/icon/sign-in-solid.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="sign-in" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-sign-in fa-w-16 fa-2x"><path fill="currentColor" d="M137.2 110.3l21.9-21.9c9.3-9.3 24.5-9.4 33.9-.1L344.9 239c9.5 9.4 9.5 24.7 0 34.1L193 423.7c-9.4 9.3-24.5 9.3-33.9-.1l-21.9-21.9c-9.7-9.7-9.3-25.4.8-34.7l77.6-71.1H24c-13.3 0-24-10.7-24-24v-32c0-13.3 10.7-24 24-24h191.5l-77.6-71.1c-10-9.1-10.4-24.9-.7-34.5zM512 352V160c0-53-43-96-96-96h-84c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h84c17.7 0 32 14.3 32 32v192c0 17.7-14.3 32-32 32h-84c-6.6 0-12 5.4-12 12v40c0 6.6 5.4 12 12 12h84c53 0 96-43 96-96z" class=""></path></svg>
|
||||||
|
After Width: | Height: | Size: 698 B |
1
src/client/resources/image/icon/sign-out-solid.svg
Normal file
1
src/client/resources/image/icon/sign-out-solid.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="sign-out" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" class="svg-inline--fa fa-sign-out fa-w-16 fa-2x"><path fill="currentColor" d="M180 448H96c-53 0-96-43-96-96V160c0-53 43-96 96-96h84c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12H96c-17.7 0-32 14.3-32 32v192c0 17.7 14.3 32 32 32h84c6.6 0 12 5.4 12 12v40c0 6.6-5.4 12-12 12zm117.9-303.1l77.6 71.1H184c-13.3 0-24 10.7-24 24v32c0 13.3 10.7 24 24 24h191.5l-77.6 71.1c-10.1 9.2-10.4 25-.8 34.7l21.9 21.9c9.3 9.3 24.5 9.4 33.9.1l152-150.8c9.5-9.4 9.5-24.7 0-34.1L353 88.3c-9.4-9.3-24.5-9.3-33.9.1l-21.9 21.9c-9.7 9.6-9.3 25.4.7 34.6z" class=""></path></svg>
|
||||||
|
After Width: | Height: | Size: 695 B |
@@ -7,7 +7,6 @@ import promhx.Promise;
|
|||||||
import protohx.Message;
|
import protohx.Message;
|
||||||
import ru.m.connect.IConnection;
|
import ru.m.connect.IConnection;
|
||||||
|
|
||||||
|
|
||||||
class BaseConnection<O:Message, I:Message> implements IConnection<O, I> {
|
class BaseConnection<O:Message, I:Message> implements IConnection<O, I> {
|
||||||
public var handler(default, null):Signal<ConnectionEvent>;
|
public var handler(default, null):Signal<ConnectionEvent>;
|
||||||
public var sendHandler(default, null):Signal<O>;
|
public var sendHandler(default, null):Signal<O>;
|
||||||
@@ -17,12 +16,11 @@ class BaseConnection<O:Message, I:Message> implements IConnection<O, I> {
|
|||||||
|
|
||||||
private var connectDeferred:Deferred<IConnection<O, I>>;
|
private var connectDeferred:Deferred<IConnection<O, I>>;
|
||||||
|
|
||||||
public function new(i:Class<I>) {
|
public function new(inputFactory:Class<I>) {
|
||||||
queue = new PacketQueue<I>(i);
|
queue = new PacketQueue<I>(inputFactory);
|
||||||
handler = new Signal<ConnectionEvent>();
|
handler = new Signal<ConnectionEvent>();
|
||||||
sendHandler = new Signal<O>();
|
sendHandler = new Signal<O>();
|
||||||
receiveHandler = new Signal<I>();
|
receiveHandler = new Signal<I>();
|
||||||
connectDeferred = new Deferred();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function connect():Promise<IConnection<O, I>> {
|
public function connect():Promise<IConnection<O, I>> {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import haxe.io.Bytes;
|
|||||||
import promhx.Promise;
|
import promhx.Promise;
|
||||||
import protohx.Message;
|
import protohx.Message;
|
||||||
|
|
||||||
|
|
||||||
enum ConnectionEvent {
|
enum ConnectionEvent {
|
||||||
CONNECTED;
|
CONNECTED;
|
||||||
DISCONNECTED;
|
DISCONNECTED;
|
||||||
|
|||||||
78
src/common/haxe/ru/m/connect/desktop/DesktopConnection.hx
Normal file
78
src/common/haxe/ru/m/connect/desktop/DesktopConnection.hx
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
package ru.m.connect.desktop;
|
||||||
|
|
||||||
|
import cpp.vm.Thread;
|
||||||
|
import haxe.io.BytesOutput;
|
||||||
|
import haxe.Timer;
|
||||||
|
import promhx.Deferred;
|
||||||
|
import promhx.Promise;
|
||||||
|
import protohx.Message;
|
||||||
|
import ru.m.connect.IConnection;
|
||||||
|
import sys.net.Host;
|
||||||
|
import sys.net.Socket;
|
||||||
|
|
||||||
|
class DesktopConnection<O:Message, I:Message> extends BaseConnection<O, I> {
|
||||||
|
|
||||||
|
private var host:String;
|
||||||
|
private var port:Int;
|
||||||
|
private var socket:Socket;
|
||||||
|
private var reader:Thread;
|
||||||
|
|
||||||
|
public function new(host:String, port:Int, inputFactory:Class<I>) {
|
||||||
|
super(inputFactory);
|
||||||
|
this.host = host;
|
||||||
|
this.port = port;
|
||||||
|
connected = false;
|
||||||
|
socket = new Socket();
|
||||||
|
socket.setFastSend(true);
|
||||||
|
socket.output.bigEndian = false;
|
||||||
|
socket.input.bigEndian = false;
|
||||||
|
sendHandler.connect(_send);
|
||||||
|
}
|
||||||
|
|
||||||
|
override public function connect():Promise<IConnection<O, I>> {
|
||||||
|
connectDeferred = new Deferred();
|
||||||
|
try {
|
||||||
|
if (connected) {
|
||||||
|
connectDeferred.resolve(this);
|
||||||
|
} else {
|
||||||
|
socket.connect(new Host(host), port);
|
||||||
|
connected = true;
|
||||||
|
reader = Thread.create(_read);
|
||||||
|
connectDeferred.resolve(this);
|
||||||
|
}
|
||||||
|
} catch (error:Dynamic) {
|
||||||
|
Timer.delay(function() connectDeferred.throwError(error), 1);
|
||||||
|
}
|
||||||
|
return connectDeferred.promise();
|
||||||
|
}
|
||||||
|
|
||||||
|
override public function disconnect():Void {
|
||||||
|
socket.close();
|
||||||
|
connected = false;
|
||||||
|
handler.emit(DISCONNECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function _read():Void {
|
||||||
|
try {
|
||||||
|
while (connected) {
|
||||||
|
socket.waitForRead();
|
||||||
|
var size = socket.input.readUInt16();
|
||||||
|
var data = socket.input.read(size);
|
||||||
|
var packet:I = Type.createInstance(queue.packetClass, []);
|
||||||
|
packet.mergeFrom(data);
|
||||||
|
receiveHandler.emit(packet);
|
||||||
|
}
|
||||||
|
} catch (error:Dynamic) {
|
||||||
|
handler.emit(ERROR(error));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function _send(packet:O):Void {
|
||||||
|
var out = new BytesOutput();
|
||||||
|
packet.writeTo(out);
|
||||||
|
var bytes = out.getBytes();
|
||||||
|
socket.output.writeUInt16(bytes.length);
|
||||||
|
socket.output.write(bytes);
|
||||||
|
socket.output.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,18 +1,18 @@
|
|||||||
package ru.m.connect.flash;
|
package ru.m.connect.flash;
|
||||||
|
|
||||||
import ru.m.connect.IConnection.ConnectionEvent;
|
|
||||||
import promhx.Promise;
|
|
||||||
import flash.utils.Endian;
|
|
||||||
import haxe.io.BytesOutput;
|
|
||||||
import protohx.Message;
|
|
||||||
import haxe.io.Bytes;
|
|
||||||
import flash.events.ErrorEvent;
|
import flash.events.ErrorEvent;
|
||||||
import flash.events.ProgressEvent;
|
|
||||||
import flash.events.Event;
|
import flash.events.Event;
|
||||||
import flash.events.SecurityErrorEvent;
|
|
||||||
import flash.events.IOErrorEvent;
|
import flash.events.IOErrorEvent;
|
||||||
|
import flash.events.ProgressEvent;
|
||||||
|
import flash.events.SecurityErrorEvent;
|
||||||
import flash.net.Socket;
|
import flash.net.Socket;
|
||||||
|
import flash.utils.Endian;
|
||||||
|
import haxe.io.Bytes;
|
||||||
|
import haxe.io.BytesOutput;
|
||||||
|
import promhx.Deferred;
|
||||||
|
import promhx.Promise;
|
||||||
|
import protohx.Message;
|
||||||
|
import ru.m.connect.IConnection;
|
||||||
|
|
||||||
class FlashConnection<O:Message, I:Message> extends BaseConnection<O, I> {
|
class FlashConnection<O:Message, I:Message> extends BaseConnection<O, I> {
|
||||||
|
|
||||||
@@ -20,8 +20,8 @@ class FlashConnection<O:Message, I:Message> extends BaseConnection<O, I> {
|
|||||||
private var port:Int;
|
private var port:Int;
|
||||||
private var socket:Socket;
|
private var socket:Socket;
|
||||||
|
|
||||||
public function new(host:String, port:Int, i:Class<I>) {
|
public function new(host:String, port:Int, inputFactory:Class<I>) {
|
||||||
super(i);
|
super(inputFactory);
|
||||||
this.host = host;
|
this.host = host;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
connected = false;
|
connected = false;
|
||||||
@@ -37,14 +37,15 @@ class FlashConnection<O:Message, I:Message> extends BaseConnection<O, I> {
|
|||||||
|
|
||||||
override public function connect():Promise<IConnection<O, I>> {
|
override public function connect():Promise<IConnection<O, I>> {
|
||||||
socket.connect(host, port);
|
socket.connect(host, port);
|
||||||
|
connectDeferred = new Deferred();
|
||||||
return connectDeferred.promise();
|
return connectDeferred.promise();
|
||||||
}
|
}
|
||||||
|
|
||||||
override public function disconnect():Void {
|
override public function disconnect():Void {
|
||||||
if (socket.connected) {
|
if (socket.connected) {
|
||||||
socket.close();
|
socket.close();
|
||||||
//connected = false;
|
connected = false;
|
||||||
//handler.emit(ConnectionEvent.DISCONNECTED);
|
handler.emit(ConnectionEvent.DISCONNECTED);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,13 +53,19 @@ class FlashConnection<O:Message, I:Message> extends BaseConnection<O, I> {
|
|||||||
socket.close();
|
socket.close();
|
||||||
connected = false;
|
connected = false;
|
||||||
handler.emit(ConnectionEvent.ERROR(event));
|
handler.emit(ConnectionEvent.ERROR(event));
|
||||||
connectDeferred.throwError(event);
|
if (connectDeferred != null) {
|
||||||
|
connectDeferred.throwError(event);
|
||||||
|
connectDeferred = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function onConnect(_):Void {
|
private function onConnect(_):Void {
|
||||||
connected = true;
|
connected = true;
|
||||||
handler.emit(ConnectionEvent.CONNECTED);
|
handler.emit(ConnectionEvent.CONNECTED);
|
||||||
connectDeferred.resolve(this);
|
if (connectDeferred != null) {
|
||||||
|
connectDeferred.resolve(this);
|
||||||
|
connectDeferred = null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function onClose(_):Void {
|
private function onClose(_):Void {
|
||||||
|
|||||||
@@ -2,11 +2,11 @@ package ru.m.connect.js;
|
|||||||
|
|
||||||
import js.Browser;
|
import js.Browser;
|
||||||
import js.html.WebSocket;
|
import js.html.WebSocket;
|
||||||
|
import promhx.Deferred;
|
||||||
import promhx.Promise;
|
import promhx.Promise;
|
||||||
import protohx.Message;
|
import protohx.Message;
|
||||||
import ru.m.Base64;
|
import ru.m.Base64;
|
||||||
import ru.m.connect.IConnection.ConnectionEvent;
|
import ru.m.connect.IConnection;
|
||||||
|
|
||||||
|
|
||||||
class JsConnection<O:Message, I:Message> extends BaseConnection<O, I> {
|
class JsConnection<O:Message, I:Message> extends BaseConnection<O, I> {
|
||||||
|
|
||||||
@@ -14,8 +14,8 @@ class JsConnection<O:Message, I:Message> extends BaseConnection<O, I> {
|
|||||||
private var port:Int;
|
private var port:Int;
|
||||||
private var socket:WebSocket;
|
private var socket:WebSocket;
|
||||||
|
|
||||||
public function new(host:String, port:Int, i:Class<I>) {
|
public function new(host:String, port:Int, inputFactory:Class<I>) {
|
||||||
super(i);
|
super(inputFactory);
|
||||||
this.host = host;
|
this.host = host;
|
||||||
this.port = port;
|
this.port = port;
|
||||||
connected = false;
|
connected = false;
|
||||||
@@ -38,11 +38,12 @@ class JsConnection<O:Message, I:Message> extends BaseConnection<O, I> {
|
|||||||
socket.onclose = this.onClose;
|
socket.onclose = this.onClose;
|
||||||
socket.onerror = this.onError;
|
socket.onerror = this.onError;
|
||||||
socket.onmessage = this.onSocketData;
|
socket.onmessage = this.onSocketData;
|
||||||
|
connectDeferred = new Deferred();
|
||||||
return connectDeferred.promise();
|
return connectDeferred.promise();
|
||||||
}
|
}
|
||||||
|
|
||||||
override public function disconnect():Void {
|
override public function disconnect():Void {
|
||||||
socket.close();
|
socket.close(1000);
|
||||||
connected = false;
|
connected = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import haxe.io.BytesOutput;
|
|||||||
import protohx.Message;
|
import protohx.Message;
|
||||||
import sys.net.Socket;
|
import sys.net.Socket;
|
||||||
|
|
||||||
|
|
||||||
class NekoConnection<O:Message, I:Message> extends BaseConnection<O, I> {
|
class NekoConnection<O:Message, I:Message> extends BaseConnection<O, I> {
|
||||||
|
|
||||||
public var socket(default, null):Socket;
|
public var socket(default, null):Socket;
|
||||||
|
|||||||
@@ -2,11 +2,10 @@ package ru.m.connect.neko;
|
|||||||
|
|
||||||
import haxe.crypto.BaseCode;
|
import haxe.crypto.BaseCode;
|
||||||
import haxe.crypto.Sha1;
|
import haxe.crypto.Sha1;
|
||||||
import protohx.Message;
|
|
||||||
import haxe.io.Bytes;
|
import haxe.io.Bytes;
|
||||||
|
import protohx.Message;
|
||||||
import sys.net.Socket;
|
import sys.net.Socket;
|
||||||
|
|
||||||
|
|
||||||
class NekoWebConnection<O:Message, I:Message> extends NekoConnection<O, I> {
|
class NekoWebConnection<O:Message, I:Message> extends NekoConnection<O, I> {
|
||||||
|
|
||||||
private var opened:Bool;
|
private var opened:Bool;
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
package ru.m.tankz.network;
|
|
||||||
|
|
||||||
import ru.m.tankz.game.Game;
|
|
||||||
import ru.m.tankz.proto.core.GameProto;
|
|
||||||
|
|
||||||
class NetworkGame extends Game {
|
|
||||||
|
|
||||||
private static var TAG(default, never):String = 'NetworkGame';
|
|
||||||
|
|
||||||
public function load(proto:GameProto):Void {
|
|
||||||
L.w(TAG, 'load: ${proto}');
|
|
||||||
// ToDo:
|
|
||||||
}
|
|
||||||
|
|
||||||
public function export():GameProto {
|
|
||||||
return new GameProto();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -11,12 +11,12 @@ import ru.m.tankz.bundle.IConfigBundle;
|
|||||||
import ru.m.tankz.bundle.ILevelBundle;
|
import ru.m.tankz.bundle.ILevelBundle;
|
||||||
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.session.Session;
|
import ru.m.tankz.server.session._Session;
|
||||||
import sys.net.Socket;
|
import sys.net.Socket;
|
||||||
#if debug import haxework.log.SocketLogger; #end
|
#if debug import haxework.log.SocketLogger; #end
|
||||||
|
|
||||||
|
|
||||||
class Server extends ThreadServer<Session, Bytes> {
|
class Server extends ThreadServer<_Session, Bytes> {
|
||||||
|
|
||||||
private static inline var TAG = 'Server';
|
private static inline var TAG = 'Server';
|
||||||
|
|
||||||
@@ -24,23 +24,23 @@ class Server extends ThreadServer<Session, Bytes> {
|
|||||||
super();
|
super();
|
||||||
}
|
}
|
||||||
|
|
||||||
override public function clientConnected(s:Socket):Session {
|
override public function clientConnected(s:Socket):_Session {
|
||||||
var session = new Session(s);
|
var session = new _Session(s);
|
||||||
L.d(TAG, 'Client connected');
|
L.d(TAG, 'Client connected');
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
override public function clientDisconnected(session:Session) {
|
override public function clientDisconnected(session:_Session) {
|
||||||
L.d(TAG, 'Client disconnected');
|
L.d(TAG, 'Client disconnected');
|
||||||
session.connection.handler.emit(ConnectionEvent.DISCONNECTED);
|
session.connection.handler.emit(ConnectionEvent.DISCONNECTED);
|
||||||
}
|
}
|
||||||
|
|
||||||
override public function readClientMessage(session:Session, buf:Bytes, pos:Int, len:Int) {
|
override public function readClientMessage(session:_Session, buf:Bytes, pos:Int, len:Int) {
|
||||||
//L.d(TAG, 'Client message: ${buf}');
|
//L.d(TAG, 'Client message: ${buf}');
|
||||||
return {msg: buf.sub(pos, len), bytes: len};
|
return {msg: buf.sub(pos, len), bytes: len};
|
||||||
}
|
}
|
||||||
|
|
||||||
override public function clientMessage(session:Session, bytes:Bytes) {
|
override public function clientMessage(session:_Session, bytes:Bytes) {
|
||||||
try {
|
try {
|
||||||
session.pushData(bytes);
|
session.pushData(bytes);
|
||||||
} catch (error:Dynamic) {
|
} catch (error:Dynamic) {
|
||||||
|
|||||||
46
src/server/haxe/ru/m/tankz/server/TestServer.hx
Executable file
46
src/server/haxe/ru/m/tankz/server/TestServer.hx
Executable file
@@ -0,0 +1,46 @@
|
|||||||
|
package ru.m.tankz.server;
|
||||||
|
|
||||||
|
import haxe.io.Bytes;
|
||||||
|
import haxework.log.TraceLogger;
|
||||||
|
import neko.net.ThreadServer;
|
||||||
|
import ru.m.tankz.server.session.GameSession;
|
||||||
|
import sys.net.Socket;
|
||||||
|
|
||||||
|
class TestServer extends ThreadServer<GameSession, Bytes> {
|
||||||
|
|
||||||
|
private static inline var TAG = 'Server';
|
||||||
|
|
||||||
|
public function new() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
override public function clientConnected(socket:Socket):GameSession {
|
||||||
|
var session = new GameSession(socket);
|
||||||
|
L.d(TAG, 'Client connected');
|
||||||
|
return session;
|
||||||
|
}
|
||||||
|
|
||||||
|
override public function clientDisconnected(session:GameSession) {
|
||||||
|
L.d(TAG, 'Client disconnected');
|
||||||
|
session.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
override public function readClientMessage(session:GameSession, buf:Bytes, pos:Int, len:Int) {
|
||||||
|
//L.d(TAG, 'Client message: ${buf}');
|
||||||
|
return {msg: buf.sub(pos, len), bytes: len};
|
||||||
|
}
|
||||||
|
|
||||||
|
override public function clientMessage(session:GameSession, bytes:Bytes) {
|
||||||
|
session.pushData(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function main() {
|
||||||
|
L.push(new TraceLogger());
|
||||||
|
L.d(TAG, 'Running');
|
||||||
|
var host:String = Sys.args().length > 0 ? Sys.args()[0] : "localhost";
|
||||||
|
var port:Int = Sys.args().length > 1 ? Std.parseInt(Sys.args()[1]) : 5000;
|
||||||
|
var wserver = new TestServer();
|
||||||
|
L.i(TAG, 'Start on ${host}:${port}');
|
||||||
|
wserver.run(host, port);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -8,7 +8,6 @@ import sys.io.File;
|
|||||||
import yaml.Parser;
|
import yaml.Parser;
|
||||||
import yaml.Yaml;
|
import yaml.Yaml;
|
||||||
|
|
||||||
|
|
||||||
class ServerConfigBundle implements IConfigBundle {
|
class ServerConfigBundle implements IConfigBundle {
|
||||||
|
|
||||||
public function new() {}
|
public function new() {}
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
package ru.m.tankz.server.game;
|
package ru.m.tankz.server.game;
|
||||||
|
|
||||||
|
import ru.m.tankz.game.Game;
|
||||||
|
import ru.m.tankz.game.IGame;
|
||||||
import ru.m.tankz.game.GameState;
|
import ru.m.tankz.game.GameState;
|
||||||
import ru.m.tankz.network.NetworkGame;
|
|
||||||
import ru.m.tankz.preset.ClassicGame;
|
import ru.m.tankz.preset.ClassicGame;
|
||||||
import ru.m.tankz.proto.pack.StartGameResponse;
|
import ru.m.tankz.proto.pack.StartGameResponse;
|
||||||
import ru.m.tankz.proto.pack.LeaveGameResponse;
|
import ru.m.tankz.proto.pack.LeaveGameResponse;
|
||||||
@@ -13,7 +14,7 @@ import ru.m.tankz.proto.core.GameStateProto;
|
|||||||
import ru.m.tankz.proto.core.GameInfoProto;
|
import ru.m.tankz.proto.core.GameInfoProto;
|
||||||
import ru.m.tankz.proto.core.UserProto;
|
import ru.m.tankz.proto.core.UserProto;
|
||||||
import ru.m.tankz.server.session.Thread;
|
import ru.m.tankz.server.session.Thread;
|
||||||
import ru.m.tankz.server.session.Session;
|
import ru.m.tankz.server.session._Session;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -58,7 +59,7 @@ class GameManager {
|
|||||||
private static var idCounter:Int = 0;
|
private static var idCounter:Int = 0;
|
||||||
|
|
||||||
public var gameInfo(default, null):GameInfoProto;
|
public var gameInfo(default, null):GameInfoProto;
|
||||||
public var game(default, null):NetworkGame;
|
public var game(default, null):IGame;
|
||||||
|
|
||||||
private var timer:NekoTimer;
|
private var timer:NekoTimer;
|
||||||
|
|
||||||
@@ -83,14 +84,14 @@ class GameManager {
|
|||||||
public function broadcastGames() {
|
public function broadcastGames() {
|
||||||
var packet = new Response().setListGame(new ListGameResponse().setGames(getReadyGames()));
|
var packet = new Response().setListGame(new ListGameResponse().setGames(getReadyGames()));
|
||||||
for (personId in subscribers.keys()) {
|
for (personId in subscribers.keys()) {
|
||||||
var session:Session = Session.sessions.get(personId);
|
var session:_Session = _Session.sessions.get(personId);
|
||||||
session.send(packet);
|
session.send(packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function broadcast(packet:Response) {
|
public function broadcast(packet:Response) {
|
||||||
for (player in gameInfo.players) {
|
for (player in gameInfo.players) {
|
||||||
var session:Session = Session.sessions.get(player.uuid);
|
var session:_Session = _Session.sessions.get(player.uuid);
|
||||||
session.send(packet);
|
session.send(packet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -105,7 +106,7 @@ class GameManager {
|
|||||||
gameInfo.setPlayers(gameInfo.players.filter(function(p:UserProto) return p.uuid != user.uuid));
|
gameInfo.setPlayers(gameInfo.players.filter(function(p:UserProto) return p.uuid != user.uuid));
|
||||||
byPersonId.remove(user.uuid);
|
byPersonId.remove(user.uuid);
|
||||||
var packet = new Response().setLeaveGame(new LeaveGameResponse().setGame(gameInfo));
|
var packet = new Response().setLeaveGame(new LeaveGameResponse().setGame(gameInfo));
|
||||||
Session.sessions.get(user.uuid).send(packet);
|
_Session.sessions.get(user.uuid).send(packet);
|
||||||
if (gameInfo.players.length == 0/* || person.id == game.creator.id*/) {
|
if (gameInfo.players.length == 0/* || person.id == game.creator.id*/) {
|
||||||
stop();
|
stop();
|
||||||
} else {
|
} else {
|
||||||
@@ -115,8 +116,9 @@ class GameManager {
|
|||||||
|
|
||||||
public function start() {
|
public function start() {
|
||||||
gameInfo.setState(GameStateProto.STARTED);
|
gameInfo.setState(GameStateProto.STARTED);
|
||||||
game = new NetworkGame(ClassicGame.TYPE);
|
var state = new GameState(ClassicGame.TYPE);
|
||||||
game.start(new GameState(ClassicGame.TYPE,ClassicGame.PLAYER1));
|
game = new Game(state);
|
||||||
|
//game.start(new GameState(ClassicGame.TYPE,ClassicGame.PLAYER1));
|
||||||
timer = new NekoTimer(30);
|
timer = new NekoTimer(30);
|
||||||
timer.run = update;
|
timer.run = update;
|
||||||
broadcast(new Response().setStartGame(new StartGameResponse().setGame(gameInfo)));
|
broadcast(new Response().setStartGame(new StartGameResponse().setGame(gameInfo)));
|
||||||
@@ -136,7 +138,7 @@ class GameManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private function update() {
|
private function update() {
|
||||||
game.engine.update();
|
//game.engine.update();
|
||||||
/*var changes = engine.update();
|
/*var changes = engine.update();
|
||||||
changes = this.changes.concat(changes);
|
changes = this.changes.concat(changes);
|
||||||
this.changes = [];
|
this.changes = [];
|
||||||
|
|||||||
42
src/server/haxe/ru/m/tankz/server/session/GameSession.hx
Normal file
42
src/server/haxe/ru/m/tankz/server/session/GameSession.hx
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
package ru.m.tankz.server.session;
|
||||||
|
|
||||||
|
import ru.m.tankz.proto.pack.LogoutResponse;
|
||||||
|
import ru.m.tankz.proto.pack.LogoutRequest;
|
||||||
|
import com.hurlant.crypto.extra.UUID;
|
||||||
|
import com.hurlant.crypto.prng.Random;
|
||||||
|
import ru.m.tankz.proto.core.UserProto;
|
||||||
|
import ru.m.tankz.proto.pack.LoginRequest;
|
||||||
|
import ru.m.tankz.proto.pack.LoginResponse;
|
||||||
|
import ru.m.tankz.proto.pack.Request;
|
||||||
|
import ru.m.tankz.proto.pack.Response;
|
||||||
|
import sys.net.Socket;
|
||||||
|
|
||||||
|
class GameSession extends ProtoSession<Response, Request> {
|
||||||
|
private static inline var TAG = "Session";
|
||||||
|
|
||||||
|
public var user(default, null):UserProto;
|
||||||
|
|
||||||
|
public function new(socket:Socket) {
|
||||||
|
super(socket, Request);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function onLogin(request:LoginRequest):LoginResponse {
|
||||||
|
user = new UserProto()
|
||||||
|
.setUuid(request.uuid != null ? request.uuid : UUID.generateRandom(new Random()).toString())
|
||||||
|
.setName(request.name);
|
||||||
|
return new LoginResponse().setUser(user);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function onLogout(request:LogoutRequest):LogoutResponse {
|
||||||
|
return new LogoutResponse();
|
||||||
|
}
|
||||||
|
|
||||||
|
override private function onRequest(request:Request):Void {
|
||||||
|
L.d(TAG, 'onRequest: ${request}');
|
||||||
|
if (request.hasLogin()) {
|
||||||
|
send(new Response().setLogin(onLogin(request.login)));
|
||||||
|
} else if (request.hasLogout()) {
|
||||||
|
send(new Response().setLogout(onLogout(request.logout)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
8
src/server/haxe/ru/m/tankz/server/session/ISession.hx
Normal file
8
src/server/haxe/ru/m/tankz/server/session/ISession.hx
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
package ru.m.tankz.server.session;
|
||||||
|
|
||||||
|
import haxe.io.Bytes;
|
||||||
|
|
||||||
|
interface ISession {
|
||||||
|
public function pushData(bytes:Bytes):Void;
|
||||||
|
public function disconnect():Void;
|
||||||
|
}
|
||||||
73
src/server/haxe/ru/m/tankz/server/session/ProtoSession.hx
Normal file
73
src/server/haxe/ru/m/tankz/server/session/ProtoSession.hx
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
package ru.m.tankz.server.session;
|
||||||
|
|
||||||
|
import ru.m.connect.neko.NekoWebConnection;
|
||||||
|
import haxe.io.Bytes;
|
||||||
|
import protohx.Message;
|
||||||
|
import ru.m.connect.IConnection;
|
||||||
|
import ru.m.connect.neko.NekoConnection;
|
||||||
|
import sys.net.Socket;
|
||||||
|
|
||||||
|
class ProtoSession<O:Message, I:Message> implements ISession {
|
||||||
|
private static inline var TAG = "Session";
|
||||||
|
|
||||||
|
private static var POLICY_FILE:String = [
|
||||||
|
"<?xml version=\"1.0\"?>",
|
||||||
|
"<!DOCTYPE cross-domain-policy SYSTEM \"http://www.adobe.com/xml/dtds/cross-domain-policy.dtd\">",
|
||||||
|
"<cross-domain-policy>",
|
||||||
|
"<site-control permitted-cross-domain-policies=\"master-only\"/>",
|
||||||
|
"<allow-access-from domain=\"*\" to-ports=\"*\"/>",
|
||||||
|
"</cross-domain-policy>"
|
||||||
|
].join("\n");
|
||||||
|
|
||||||
|
public var connection(default, null):IConnection<O, I>;
|
||||||
|
private var socket:Socket;
|
||||||
|
private var request:Class<I>;
|
||||||
|
|
||||||
|
public function new(socket:Socket, request:Class<I>) {
|
||||||
|
this.socket = socket;
|
||||||
|
this.request = request;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function buildConnection(bytes:Bytes):IConnection<O, I> {
|
||||||
|
var str:String = bytes.getString(0, bytes.length);
|
||||||
|
if (str == "<policy-file-request/>" + String.fromCharCode(0)) {
|
||||||
|
L.d(TAG, "policy-file-request");
|
||||||
|
socket.output.writeString(POLICY_FILE + String.fromCharCode(0));
|
||||||
|
socket.output.flush();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (StringTools.startsWith(str, "GET")) {
|
||||||
|
connection = new NekoWebConnection<O, I>(socket, request);
|
||||||
|
} else {
|
||||||
|
connection = new NekoConnection<O, I>(socket, request);
|
||||||
|
}
|
||||||
|
connection.handler.connect(onConnectionEvent);
|
||||||
|
connection.receiveHandler.connect(onRequest);
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function send(packet:O):Void {
|
||||||
|
connection.send(packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function pushData(bytes:Bytes):Void {
|
||||||
|
if (connection == null) {
|
||||||
|
connection = buildConnection(bytes);
|
||||||
|
}
|
||||||
|
if (connection != null) {
|
||||||
|
connection.pushData(bytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function disconnect():Void {
|
||||||
|
connection.handler.emit(ConnectionEvent.DISCONNECTED);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function onConnectionEvent(event:ConnectionEvent):Void {
|
||||||
|
L.d(TAG, 'onConnectionEvent: ${event}');
|
||||||
|
}
|
||||||
|
|
||||||
|
private function onRequest(request:I):Void {
|
||||||
|
L.d(TAG, 'onRequest: ${request}');
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -31,7 +31,7 @@ import sys.net.Socket;
|
|||||||
|
|
||||||
typedef ServerConnection = IConnection<Response, Request>;
|
typedef ServerConnection = IConnection<Response, Request>;
|
||||||
|
|
||||||
class Session {
|
class _Session {
|
||||||
private static inline var TAG = 'Session';
|
private static inline var TAG = 'Session';
|
||||||
|
|
||||||
private static var POLICY_FILE:String = [
|
private static var POLICY_FILE:String = [
|
||||||
@@ -43,7 +43,7 @@ class Session {
|
|||||||
'</cross-domain-policy>'
|
'</cross-domain-policy>'
|
||||||
].join('\n');
|
].join('\n');
|
||||||
|
|
||||||
public static var sessions:Map<String, Session> = new Map<String, Session>();
|
public static var sessions:Map<String, _Session> = new Map<String, _Session>();
|
||||||
|
|
||||||
public var user(default, null):UserProto;
|
public var user(default, null):UserProto;
|
||||||
public var gameId(default, null):Int = -1;
|
public var gameId(default, null):Int = -1;
|
||||||
@@ -150,6 +150,7 @@ class Session {
|
|||||||
|
|
||||||
private function game(request:GameRequest):GameResponse {
|
private function game(request:GameRequest):GameResponse {
|
||||||
var gameManager:GameManager = GameManager.byPersonId.get(user.uuid);
|
var gameManager:GameManager = GameManager.byPersonId.get(user.uuid);
|
||||||
return new GameResponse().setGame(gameManager.game.export());
|
return new GameResponse();
|
||||||
|
//return new GameResponse().setGame(gameManager.game.export());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user