[common] add DesktopConnection

This commit is contained in:
2019-05-21 17:44:48 +03:00
parent 7984d8282c
commit a5722dfa9d
29 changed files with 646 additions and 217 deletions

View File

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

View File

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

View File

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

View File

@@ -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();

View File

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

View File

@@ -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')

View File

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

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

View 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()