[common] add DesktopConnection
This commit is contained in:
@@ -79,7 +79,7 @@ class Init {
|
||||
#elseif html5
|
||||
connection = new ru.m.connect.js.JsConnection<Request, Response>(host, 5000, Response);
|
||||
#else
|
||||
connection = new ru.m.connect.fake.FakeConnection<Request, Response>(Response);
|
||||
connection = new ru.m.connect.desktop.DesktopConnection<Request, Response>(host, 5000, Response);
|
||||
#end
|
||||
networkManager = new NetworkManager();
|
||||
}
|
||||
|
||||
@@ -146,5 +146,7 @@ class Style {
|
||||
registerButton("close", "times-circle-solid.svg");
|
||||
registerButton("next", "arrow-alt-circle-right-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;
|
||||
|
||||
import ru.m.tankz.storage.MultiplayerStorage;
|
||||
import haxework.storage.IStorage;
|
||||
import haxework.signal.Signal;
|
||||
import ru.m.tankz.proto.pack.GameRequest;
|
||||
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.connect.IConnection;
|
||||
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.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.LoginRequest;
|
||||
import ru.m.tankz.proto.pack.LogoutRequest;
|
||||
import ru.m.tankz.proto.pack.Request;
|
||||
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>;
|
||||
|
||||
enum ConnectionState {
|
||||
OFFLINE;
|
||||
CONNECT;
|
||||
CONNECTED;
|
||||
LOGIN;
|
||||
ONLINE(user:User);
|
||||
ERROR(error:Dynamic);
|
||||
}
|
||||
|
||||
class NetworkManager {
|
||||
|
||||
public var state(default, null):String;
|
||||
public var stateSignal:Signal<String>;
|
||||
public var state(default, null):ConnectionState;
|
||||
public var stateSignal:Signal<ConnectionState>;
|
||||
public var listGameSignal:Signal<Array<GameInfoProto>>;
|
||||
public var gameSignal:Signal<GameInfoProto>;
|
||||
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 storage:MultiplayerStorage;
|
||||
|
||||
public function new() {
|
||||
stateSignal = new Signal<String>();
|
||||
listGameSignal = new Signal<Array<GameInfoProto>>();
|
||||
gameSignal = new Signal<GameInfoProto>();
|
||||
gameUpdateSignal = new Signal<Array<GameChangeProto>>();
|
||||
updateState('offline');
|
||||
stateSignal = new Signal();
|
||||
listGameSignal = new Signal();
|
||||
gameSignal = new Signal();
|
||||
gameUpdateSignal = new Signal();
|
||||
updateState(OFFLINE);
|
||||
connection.handler.connect(onConnectionEvent);
|
||||
connection.receiveHandler.connect(onResponse);
|
||||
user = storage.user;
|
||||
if (user == null) {
|
||||
user = {name: 'User', uuid: null};
|
||||
var user = storage.user;
|
||||
if (user != null) {
|
||||
login(user.name, user.uuid);
|
||||
}
|
||||
}
|
||||
|
||||
private function updateState(value:String):Void {
|
||||
private function updateState(value:ConnectionState):Void {
|
||||
state = value;
|
||||
stateSignal.emit(value);
|
||||
}
|
||||
|
||||
public function login(name:String):Void {
|
||||
user.name = name;
|
||||
updateState('connect...');
|
||||
public function login(name:String, uuid:String = null):Void {
|
||||
updateState(CONNECT);
|
||||
connection.connect().then(function(c:ClientConnection) {
|
||||
updateState('login...');
|
||||
updateState(LOGIN);
|
||||
c.send(new Request().setLogin(
|
||||
new LoginRequest()
|
||||
.setUuid(user.uuid)
|
||||
.setName(user.name)
|
||||
.setUuid(uuid)
|
||||
.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 {
|
||||
@@ -108,30 +118,30 @@ class NetworkManager {
|
||||
}
|
||||
|
||||
private function onConnectionEvent(event:ConnectionEvent):Void {
|
||||
updateState(switch (event) {
|
||||
case ConnectionEvent.CONNECTED:
|
||||
updateState(switch event {
|
||||
case CONNECTED:
|
||||
L.d('Network', '$event');
|
||||
'connected';
|
||||
case ConnectionEvent.DISCONNECTED:
|
||||
CONNECTED;
|
||||
case DISCONNECTED:
|
||||
L.d('Network', '$event');
|
||||
'offline';
|
||||
case ConnectionEvent.ERROR(error):
|
||||
OFFLINE;
|
||||
case ERROR(error):
|
||||
L.e('Network', '$error', error);
|
||||
'error';
|
||||
ERROR(error);
|
||||
});
|
||||
}
|
||||
|
||||
private function onResponse(packet:Response):Void {
|
||||
if (packet.hasLogin()) {
|
||||
user = {
|
||||
var user = {
|
||||
uuid: packet.login.user.uuid,
|
||||
name: packet.login.user.name,
|
||||
};
|
||||
storage.user = user;
|
||||
updateState('online');
|
||||
updateState(ONLINE(user));
|
||||
} else if (packet.hasLogout()) {
|
||||
user = null;
|
||||
updateState('connected');
|
||||
storage.user = null;
|
||||
updateState(CONNECTED);
|
||||
} else if (packet.hasListGame()) {
|
||||
listGameSignal.emit(packet.listGame.games);
|
||||
} else if (packet.hasCreateGame()) {
|
||||
@@ -145,13 +155,7 @@ class NetworkManager {
|
||||
} else if (packet.hasUpdateGame()) {
|
||||
gameUpdateSignal.emit(packet.updateGame.changes);
|
||||
} 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;
|
||||
|
||||
import haxework.view.ButtonView;
|
||||
import haxework.view.LabelView;
|
||||
import haxework.view.frame.FrameSwitcher;
|
||||
import haxework.view.VGroupView;
|
||||
import ru.m.tankz.game.GameState;
|
||||
import ru.m.tankz.network.NetworkManager;
|
||||
import ru.m.tankz.Type.GameType;
|
||||
import ru.m.tankz.view.popup.FontPopup;
|
||||
import ru.m.tankz.view.popup.LoginPopup;
|
||||
|
||||
@:template class StartFrame extends VGroupView {
|
||||
|
||||
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 switcher:FrameSwitcher;
|
||||
@:provide var network:NetworkManager;
|
||||
|
||||
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 {
|
||||
state = new GameState(type);
|
||||
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 {
|
||||
if (fontPopup == null) {
|
||||
fontPopup = new FontPopup();
|
||||
|
||||
@@ -1,40 +1,63 @@
|
||||
---
|
||||
views:
|
||||
- $type: haxework.view.VGroupView
|
||||
skinId: container
|
||||
layout.margin: 10
|
||||
views:
|
||||
- $type: haxework.view.LabelView
|
||||
text: Tank'z
|
||||
skinId: font
|
||||
fontSize: 100
|
||||
geometry.margin.bottom: 30
|
||||
- $type: haxework.view.ButtonView
|
||||
skinId: button
|
||||
+onPress: $code:startGame('classic')
|
||||
text: Classic
|
||||
- $type: haxework.view.ButtonView
|
||||
skinId: button
|
||||
+onPress: $code:startGame('dota')
|
||||
text: DotA
|
||||
- $type: haxework.view.ButtonView
|
||||
skinId: button
|
||||
+onPress: $code:startGame('death')
|
||||
text: DeathMatch
|
||||
- $type: haxework.view.ButtonView
|
||||
skinId: button
|
||||
+onPress: $code:switcher.change('record')
|
||||
text: Records
|
||||
- $type: haxework.view.HGroupView
|
||||
skinId: panel
|
||||
views:
|
||||
- id: settings
|
||||
$type: haxework.view.ButtonView
|
||||
skinId: button.settings
|
||||
+onPress: $code:switcher.change('settings')
|
||||
- $type: haxework.view.SpriteView
|
||||
geometry.size.width: 100%
|
||||
- $type: haxework.view.LabelView
|
||||
geometry.padding: [20, 5]
|
||||
skinId: text.box
|
||||
text: $r:text:version
|
||||
- $type: haxework.view.VGroupView
|
||||
skinId: container
|
||||
layout.margin: 10
|
||||
views:
|
||||
- $type: haxework.view.LabelView
|
||||
text: Tank'z
|
||||
skinId: font
|
||||
fontSize: 100
|
||||
geometry.margin.bottom: 30
|
||||
- $type: haxework.view.ButtonView
|
||||
skinId: button
|
||||
+onPress: $code:startGame('classic')
|
||||
text: Classic
|
||||
- $type: haxework.view.ButtonView
|
||||
skinId: button
|
||||
+onPress: $code:startGame('dota')
|
||||
text: DotA
|
||||
- $type: haxework.view.ButtonView
|
||||
skinId: button
|
||||
+onPress: $code:startGame('death')
|
||||
text: DeathMatch
|
||||
- $type: haxework.view.ButtonView
|
||||
skinId: button
|
||||
+onPress: $code:switcher.change('record')
|
||||
text: Records
|
||||
- id: network
|
||||
$type: haxework.view.ButtonView
|
||||
skinId: button
|
||||
# +onPress: $code:switcher.change('record')
|
||||
text: Network
|
||||
disabled: true
|
||||
- $type: haxework.view.HGroupView
|
||||
skinId: panel
|
||||
views:
|
||||
- id: settings
|
||||
$type: haxework.view.ButtonView
|
||||
skinId: button.settings
|
||||
+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:
|
||||
$type: haxework.view.VGroupView
|
||||
geometry.size.width: 400
|
||||
geometry.size.height: 80%
|
||||
geometry.padding: 10
|
||||
geometry.hAlign: center
|
||||
geometry.vAlign: middle
|
||||
skinId: dark
|
||||
views:
|
||||
- id: fonts
|
||||
$type: haxework.view.list.VListView
|
||||
geometry.size.stretch: true
|
||||
factory: $this:fontViewFactory
|
||||
+onItemSelect: $code:function(item) close(item.data)
|
||||
scroll:
|
||||
$type: haxework.view.list.VScrollBarView
|
||||
skinId: scroll.vertical
|
||||
- $type: haxework.view.HGroupView
|
||||
geometry.size.width: 100%
|
||||
geometry.margin.top: 10
|
||||
layout.hAlign: right
|
||||
views:
|
||||
- $type: haxework.view.ButtonView
|
||||
skinId: button.simple
|
||||
text: Cancel
|
||||
+onPress: $code:reject('cancel')
|
||||
$type: haxework.view.VGroupView
|
||||
geometry.size.width: 400
|
||||
geometry.size.height: 80%
|
||||
geometry.padding: 10
|
||||
geometry.hAlign: center
|
||||
geometry.vAlign: middle
|
||||
skinId: dark
|
||||
views:
|
||||
- id: fonts
|
||||
$type: haxework.view.list.VListView
|
||||
geometry.size.stretch: true
|
||||
factory: $this:fontViewFactory
|
||||
+onItemSelect: $code:function(item) close(item.data)
|
||||
scroll:
|
||||
$type: haxework.view.list.VScrollBarView
|
||||
skinId: scroll.vertical
|
||||
- $type: haxework.view.HGroupView
|
||||
geometry.size.width: 100%
|
||||
geometry.margin.top: 10
|
||||
layout.hAlign: right
|
||||
views:
|
||||
- $type: haxework.view.ButtonView
|
||||
skinId: button.simple
|
||||
text: Cancel
|
||||
+onPress: $code:reject('cancel')
|
||||
|
||||
@@ -2,34 +2,34 @@
|
||||
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
|
||||
- $type: haxework.view.ButtonView
|
||||
skinId: window.close
|
||||
+onPress: $code:reject('close')
|
||||
- $type: haxework.view.SpriteView
|
||||
geometry.size.height: 100%
|
||||
- id: presets
|
||||
$type: haxework.view.DataView
|
||||
factory: $this:presetViewFactory
|
||||
+onDataSelect: $this:onPresetSelect
|
||||
layout:
|
||||
$type: haxework.view.layout.HorizontalLayout
|
||||
hAlign: center
|
||||
margin: 5
|
||||
skinId: panel
|
||||
$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
|
||||
- $type: haxework.view.ButtonView
|
||||
skinId: window.close
|
||||
+onPress: $code:reject('close')
|
||||
- $type: haxework.view.SpriteView
|
||||
geometry.size.height: 100%
|
||||
- id: presets
|
||||
$type: haxework.view.DataView
|
||||
factory: $this:presetViewFactory
|
||||
+onDataSelect: $this:onPresetSelect
|
||||
layout:
|
||||
$type: haxework.view.layout.HorizontalLayout
|
||||
hAlign: center
|
||||
margin: 5
|
||||
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 ru.m.connect.IConnection;
|
||||
|
||||
|
||||
class BaseConnection<O:Message, I:Message> implements IConnection<O, I> {
|
||||
public var handler(default, null):Signal<ConnectionEvent>;
|
||||
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>>;
|
||||
|
||||
public function new(i:Class<I>) {
|
||||
queue = new PacketQueue<I>(i);
|
||||
public function new(inputFactory:Class<I>) {
|
||||
queue = new PacketQueue<I>(inputFactory);
|
||||
handler = new Signal<ConnectionEvent>();
|
||||
sendHandler = new Signal<O>();
|
||||
receiveHandler = new Signal<I>();
|
||||
connectDeferred = new Deferred();
|
||||
}
|
||||
|
||||
public function connect():Promise<IConnection<O, I>> {
|
||||
|
||||
@@ -5,7 +5,6 @@ import haxe.io.Bytes;
|
||||
import promhx.Promise;
|
||||
import protohx.Message;
|
||||
|
||||
|
||||
enum ConnectionEvent {
|
||||
CONNECTED;
|
||||
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;
|
||||
|
||||
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.ProgressEvent;
|
||||
import flash.events.Event;
|
||||
import flash.events.SecurityErrorEvent;
|
||||
import flash.events.IOErrorEvent;
|
||||
import flash.events.ProgressEvent;
|
||||
import flash.events.SecurityErrorEvent;
|
||||
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> {
|
||||
|
||||
@@ -20,8 +20,8 @@ class FlashConnection<O:Message, I:Message> extends BaseConnection<O, I> {
|
||||
private var port:Int;
|
||||
private var socket:Socket;
|
||||
|
||||
public function new(host:String, port:Int, i:Class<I>) {
|
||||
super(i);
|
||||
public function new(host:String, port:Int, inputFactory:Class<I>) {
|
||||
super(inputFactory);
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
connected = false;
|
||||
@@ -37,14 +37,15 @@ class FlashConnection<O:Message, I:Message> extends BaseConnection<O, I> {
|
||||
|
||||
override public function connect():Promise<IConnection<O, I>> {
|
||||
socket.connect(host, port);
|
||||
connectDeferred = new Deferred();
|
||||
return connectDeferred.promise();
|
||||
}
|
||||
|
||||
override public function disconnect():Void {
|
||||
if (socket.connected) {
|
||||
socket.close();
|
||||
//connected = false;
|
||||
//handler.emit(ConnectionEvent.DISCONNECTED);
|
||||
connected = false;
|
||||
handler.emit(ConnectionEvent.DISCONNECTED);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,13 +53,19 @@ class FlashConnection<O:Message, I:Message> extends BaseConnection<O, I> {
|
||||
socket.close();
|
||||
connected = false;
|
||||
handler.emit(ConnectionEvent.ERROR(event));
|
||||
connectDeferred.throwError(event);
|
||||
if (connectDeferred != null) {
|
||||
connectDeferred.throwError(event);
|
||||
connectDeferred = null;
|
||||
}
|
||||
}
|
||||
|
||||
private function onConnect(_):Void {
|
||||
connected = true;
|
||||
handler.emit(ConnectionEvent.CONNECTED);
|
||||
connectDeferred.resolve(this);
|
||||
if (connectDeferred != null) {
|
||||
connectDeferred.resolve(this);
|
||||
connectDeferred = null;
|
||||
}
|
||||
}
|
||||
|
||||
private function onClose(_):Void {
|
||||
@@ -86,4 +93,4 @@ class FlashConnection<O:Message, I:Message> extends BaseConnection<O, I> {
|
||||
socket.writeBytes(cast bytes.getData());
|
||||
socket.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,11 @@ package ru.m.connect.js;
|
||||
|
||||
import js.Browser;
|
||||
import js.html.WebSocket;
|
||||
import promhx.Deferred;
|
||||
import promhx.Promise;
|
||||
import protohx.Message;
|
||||
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> {
|
||||
|
||||
@@ -14,8 +14,8 @@ class JsConnection<O:Message, I:Message> extends BaseConnection<O, I> {
|
||||
private var port:Int;
|
||||
private var socket:WebSocket;
|
||||
|
||||
public function new(host:String, port:Int, i:Class<I>) {
|
||||
super(i);
|
||||
public function new(host:String, port:Int, inputFactory:Class<I>) {
|
||||
super(inputFactory);
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
connected = false;
|
||||
@@ -38,11 +38,12 @@ class JsConnection<O:Message, I:Message> extends BaseConnection<O, I> {
|
||||
socket.onclose = this.onClose;
|
||||
socket.onerror = this.onError;
|
||||
socket.onmessage = this.onSocketData;
|
||||
connectDeferred = new Deferred();
|
||||
return connectDeferred.promise();
|
||||
}
|
||||
|
||||
override public function disconnect():Void {
|
||||
socket.close();
|
||||
socket.close(1000);
|
||||
connected = false;
|
||||
}
|
||||
|
||||
@@ -78,4 +79,4 @@ class JsConnection<O:Message, I:Message> extends BaseConnection<O, I> {
|
||||
super.send(packet);
|
||||
socket.send(WebSocketTools.packet2string(packet));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import haxe.io.BytesOutput;
|
||||
import protohx.Message;
|
||||
import sys.net.Socket;
|
||||
|
||||
|
||||
class NekoConnection<O:Message, I:Message> extends BaseConnection<O, I> {
|
||||
|
||||
public var socket(default, null):Socket;
|
||||
@@ -30,4 +29,4 @@ class NekoConnection<O:Message, I:Message> extends BaseConnection<O, I> {
|
||||
L.e('Proto', 'Error send packet: ${packet}', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,10 @@ package ru.m.connect.neko;
|
||||
|
||||
import haxe.crypto.BaseCode;
|
||||
import haxe.crypto.Sha1;
|
||||
import protohx.Message;
|
||||
import haxe.io.Bytes;
|
||||
import protohx.Message;
|
||||
import sys.net.Socket;
|
||||
|
||||
|
||||
class NekoWebConnection<O:Message, I:Message> extends NekoConnection<O, I> {
|
||||
|
||||
private var opened:Bool;
|
||||
@@ -180,4 +179,4 @@ class NekoWebConnection<O:Message, I:Message> extends NekoConnection<O, I> {
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.server.bundle.ServerConfigBundle;
|
||||
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;
|
||||
#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';
|
||||
|
||||
@@ -24,23 +24,23 @@ class Server extends ThreadServer<Session, Bytes> {
|
||||
super();
|
||||
}
|
||||
|
||||
override public function clientConnected(s:Socket):Session {
|
||||
var session = new Session(s);
|
||||
override public function clientConnected(s:Socket):_Session {
|
||||
var session = new _Session(s);
|
||||
L.d(TAG, 'Client connected');
|
||||
return session;
|
||||
}
|
||||
|
||||
override public function clientDisconnected(session:Session) {
|
||||
override public function clientDisconnected(session:_Session) {
|
||||
L.d(TAG, 'Client 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}');
|
||||
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 {
|
||||
session.pushData(bytes);
|
||||
} catch (error:Dynamic) {
|
||||
@@ -64,4 +64,4 @@ class Server extends ThreadServer<Session, Bytes> {
|
||||
L.i(TAG, 'Start on ${host}:${port}');
|
||||
wserver.run(host, port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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.Yaml;
|
||||
|
||||
|
||||
class ServerConfigBundle implements IConfigBundle {
|
||||
|
||||
public function new() {}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
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.network.NetworkGame;
|
||||
import ru.m.tankz.preset.ClassicGame;
|
||||
import ru.m.tankz.proto.pack.StartGameResponse;
|
||||
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.UserProto;
|
||||
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;
|
||||
|
||||
public var gameInfo(default, null):GameInfoProto;
|
||||
public var game(default, null):NetworkGame;
|
||||
public var game(default, null):IGame;
|
||||
|
||||
private var timer:NekoTimer;
|
||||
|
||||
@@ -83,14 +84,14 @@ class GameManager {
|
||||
public function broadcastGames() {
|
||||
var packet = new Response().setListGame(new ListGameResponse().setGames(getReadyGames()));
|
||||
for (personId in subscribers.keys()) {
|
||||
var session:Session = Session.sessions.get(personId);
|
||||
var session:_Session = _Session.sessions.get(personId);
|
||||
session.send(packet);
|
||||
}
|
||||
}
|
||||
|
||||
public function broadcast(packet:Response) {
|
||||
for (player in gameInfo.players) {
|
||||
var session:Session = Session.sessions.get(player.uuid);
|
||||
var session:_Session = _Session.sessions.get(player.uuid);
|
||||
session.send(packet);
|
||||
}
|
||||
}
|
||||
@@ -105,7 +106,7 @@ class GameManager {
|
||||
gameInfo.setPlayers(gameInfo.players.filter(function(p:UserProto) return p.uuid != user.uuid));
|
||||
byPersonId.remove(user.uuid);
|
||||
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*/) {
|
||||
stop();
|
||||
} else {
|
||||
@@ -115,8 +116,9 @@ class GameManager {
|
||||
|
||||
public function start() {
|
||||
gameInfo.setState(GameStateProto.STARTED);
|
||||
game = new NetworkGame(ClassicGame.TYPE);
|
||||
game.start(new GameState(ClassicGame.TYPE,ClassicGame.PLAYER1));
|
||||
var state = new GameState(ClassicGame.TYPE);
|
||||
game = new Game(state);
|
||||
//game.start(new GameState(ClassicGame.TYPE,ClassicGame.PLAYER1));
|
||||
timer = new NekoTimer(30);
|
||||
timer.run = update;
|
||||
broadcast(new Response().setStartGame(new StartGameResponse().setGame(gameInfo)));
|
||||
@@ -136,7 +138,7 @@ class GameManager {
|
||||
}
|
||||
|
||||
private function update() {
|
||||
game.engine.update();
|
||||
//game.engine.update();
|
||||
/*var changes = engine.update();
|
||||
changes = this.changes.concat(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>;
|
||||
|
||||
class Session {
|
||||
class _Session {
|
||||
private static inline var TAG = 'Session';
|
||||
|
||||
private static var POLICY_FILE:String = [
|
||||
@@ -43,7 +43,7 @@ class Session {
|
||||
'</cross-domain-policy>'
|
||||
].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 gameId(default, null):Int = -1;
|
||||
@@ -150,6 +150,7 @@ class Session {
|
||||
|
||||
private function game(request:GameRequest):GameResponse {
|
||||
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