[client] add GameRoomFrame
This commit is contained in:
@@ -78,6 +78,7 @@ const client = new Project(
|
|||||||
height: 768,
|
height: 768,
|
||||||
},
|
},
|
||||||
flags: [
|
flags: [
|
||||||
|
//'proto_debug',
|
||||||
//'dom',
|
//'dom',
|
||||||
//'dev_layout',
|
//'dev_layout',
|
||||||
//'bitmap_text',
|
//'bitmap_text',
|
||||||
@@ -125,7 +126,8 @@ const server = new Project(
|
|||||||
name: 'server',
|
name: 'server',
|
||||||
sources: ['src/server/haxe'],
|
sources: ['src/server/haxe'],
|
||||||
main: 'ru.m.tankz.server.Server',
|
main: 'ru.m.tankz.server.Server',
|
||||||
})
|
}),
|
||||||
|
module.exports.generate
|
||||||
).bind(module, gulp);
|
).bind(module, gulp);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package ru.m.tankz.network;
|
package ru.m.tankz.network;
|
||||||
|
|
||||||
|
import ru.m.tankz.proto.core.UserProto;
|
||||||
import haxework.signal.Signal;
|
import haxework.signal.Signal;
|
||||||
import ru.m.connect.IConnection;
|
import ru.m.connect.IConnection;
|
||||||
import ru.m.tankz.control.Control;
|
import ru.m.tankz.control.Control;
|
||||||
import ru.m.tankz.proto.core.GameProto;
|
import ru.m.tankz.proto.core.GameProto;
|
||||||
import ru.m.tankz.proto.game.GameActionTypeProto;
|
|
||||||
import ru.m.tankz.proto.game.GameChangeProto;
|
import ru.m.tankz.proto.game.GameChangeProto;
|
||||||
import ru.m.tankz.proto.pack.CreateGameRequest;
|
import ru.m.tankz.proto.pack.CreateGameRequest;
|
||||||
import ru.m.tankz.proto.pack.JoinGameRequest;
|
import ru.m.tankz.proto.pack.JoinGameRequest;
|
||||||
@@ -31,6 +31,9 @@ enum ConnectionState {
|
|||||||
class NetworkManager {
|
class NetworkManager {
|
||||||
|
|
||||||
public var state(default, null):ConnectionState;
|
public var state(default, null):ConnectionState;
|
||||||
|
public var game(default, null):GameProto;
|
||||||
|
public var user(default, null):UserProto;
|
||||||
|
|
||||||
public var stateSignal:Signal<ConnectionState>;
|
public var stateSignal:Signal<ConnectionState>;
|
||||||
public var listGameSignal:Signal<Array<GameProto>>;
|
public var listGameSignal:Signal<Array<GameProto>>;
|
||||||
public var gameSignal:Signal<GameProto>;
|
public var gameSignal:Signal<GameProto>;
|
||||||
@@ -80,8 +83,8 @@ class NetworkManager {
|
|||||||
connection.send(new Request().setListGame(new ListGameRequest()));
|
connection.send(new Request().setListGame(new ListGameRequest()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function createGame(type:String):Void {
|
public function createGame(type:String, level:Int):Void {
|
||||||
connection.send(new Request().setCreateGame(new CreateGameRequest().setType(type)));
|
connection.send(new Request().setCreateGame(new CreateGameRequest().setType(type).setLevel(level)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function joinGame(gameId:Int):Void {
|
public function joinGame(gameId:Int):Void {
|
||||||
@@ -116,9 +119,10 @@ class NetworkManager {
|
|||||||
|
|
||||||
private function onResponse(packet:Response):Void {
|
private function onResponse(packet:Response):Void {
|
||||||
if (packet.hasLogin()) {
|
if (packet.hasLogin()) {
|
||||||
|
this.user = packet.login.user;
|
||||||
var user = {
|
var user = {
|
||||||
uuid: packet.login.user.uuid,
|
uuid: this.user.uuid,
|
||||||
name: packet.login.user.name,
|
name: this.user.name,
|
||||||
};
|
};
|
||||||
storage.user = user;
|
storage.user = user;
|
||||||
updateState(ONLINE(user));
|
updateState(ONLINE(user));
|
||||||
@@ -128,11 +132,17 @@ class NetworkManager {
|
|||||||
} 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()) {
|
||||||
|
game = packet.createGame.game;
|
||||||
gameSignal.emit(packet.createGame.game);
|
gameSignal.emit(packet.createGame.game);
|
||||||
} else if (packet.hasJoinGame()) {
|
} else if (packet.hasJoinGame()) {
|
||||||
|
game = packet.createGame.game;
|
||||||
gameSignal.emit(packet.joinGame.game);
|
gameSignal.emit(packet.joinGame.game);
|
||||||
} else if (packet.hasLeaveGame()) {
|
} else if (packet.hasLeaveGame()) {
|
||||||
gameSignal.emit(null);
|
if (packet.leaveGame.user.uuid == user.uuid) {
|
||||||
|
gameSignal.emit(null);
|
||||||
|
} else {
|
||||||
|
gameSignal.emit(packet.leaveGame.game);
|
||||||
|
}
|
||||||
} else if (packet.hasStartGame()) {
|
} else if (packet.hasStartGame()) {
|
||||||
gameSignal.emit(packet.startGame.game);
|
gameSignal.emit(packet.startGame.game);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,3 +17,5 @@ views:
|
|||||||
$type: ru.m.tankz.view.RecordFrame
|
$type: ru.m.tankz.view.RecordFrame
|
||||||
- id: game_list
|
- id: game_list
|
||||||
$type: ru.m.tankz.view.network.GameListFrame
|
$type: ru.m.tankz.view.network.GameListFrame
|
||||||
|
- id: game_room
|
||||||
|
$type: ru.m.tankz.view.network.GameRoomFrame
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package ru.m.tankz.view.network;
|
package ru.m.tankz.view.network;
|
||||||
|
|
||||||
import haxework.view.list.VListView;
|
|
||||||
import ru.m.tankz.proto.core.GameProto;
|
|
||||||
import ru.m.tankz.network.NetworkManager;
|
|
||||||
import haxework.view.frame.FrameSwitcher;
|
import haxework.view.frame.FrameSwitcher;
|
||||||
|
import haxework.view.list.VListView;
|
||||||
import haxework.view.VGroupView;
|
import haxework.view.VGroupView;
|
||||||
|
import ru.m.tankz.network.NetworkManager;
|
||||||
|
import ru.m.tankz.proto.core.GameProto;
|
||||||
|
|
||||||
@:template class GameListFrame extends VGroupView {
|
@:template class GameListFrame extends VGroupView {
|
||||||
public static inline var ID = "game_list";
|
public static inline var ID = "game_list";
|
||||||
@@ -16,14 +16,37 @@ import haxework.view.VGroupView;
|
|||||||
|
|
||||||
public function onShow():Void {
|
public function onShow():Void {
|
||||||
network.listGameSignal.connect(onGameList);
|
network.listGameSignal.connect(onGameList);
|
||||||
|
network.gameSignal.connect(onGame);
|
||||||
|
network.stateSignal.connect(onState);
|
||||||
network.listGame();
|
network.listGame();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onHide():Void {
|
public function onHide():Void {
|
||||||
network.listGameSignal.disconnect(onGameList);
|
network.listGameSignal.disconnect(onGameList);
|
||||||
|
network.gameSignal.disconnect(onGame);
|
||||||
|
network.stateSignal.disconnect(onState);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function create():Void {
|
||||||
|
network.createGame("classic", 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function onState(state:ConnectionState):Void {
|
||||||
|
switch state {
|
||||||
|
case ONLINE(_):
|
||||||
|
case _: switcher.change(StartFrame.ID);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private function onGameList(data:Array<GameProto>):Void {
|
private function onGameList(data:Array<GameProto>):Void {
|
||||||
games.data = data;
|
games.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function onGame(game:GameProto):Void {
|
||||||
|
switcher.change(GameRoomFrame.ID);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function selectGame(game:GameProto):Void {
|
||||||
|
network.joinGame(game.id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,14 +6,19 @@ views:
|
|||||||
views:
|
views:
|
||||||
- id: header
|
- id: header
|
||||||
$type: haxework.view.LabelView
|
$type: haxework.view.LabelView
|
||||||
|
geometry.margin.bottom: 20
|
||||||
skinId: text.header
|
skinId: text.header
|
||||||
text: Games List
|
text: Games List
|
||||||
|
- $type: haxework.view.ButtonView
|
||||||
|
skinId: button.simple
|
||||||
|
text: Create
|
||||||
|
+onPress: $code:create()
|
||||||
- id: games
|
- id: games
|
||||||
$type: haxework.view.list.VListView
|
$type: haxework.view.list.VListView
|
||||||
geometry.size.stretch: true
|
geometry.size.stretch: true
|
||||||
geometry.margin.top: 20
|
|
||||||
factory: $code:ru.m.tankz.view.network.GameItemView.factory
|
factory: $code:ru.m.tankz.view.network.GameItemView.factory
|
||||||
geometry.margin: 10
|
geometry.margin: 10
|
||||||
|
+onItemSelect: $code:function(item) selectGame(item.data)
|
||||||
- $type: haxework.view.HGroupView
|
- $type: haxework.view.HGroupView
|
||||||
skinId: panel
|
skinId: panel
|
||||||
views:
|
views:
|
||||||
|
|||||||
45
src/client/haxe/ru/m/tankz/view/network/GameRoomFrame.hx
Normal file
45
src/client/haxe/ru/m/tankz/view/network/GameRoomFrame.hx
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
package ru.m.tankz.view.network;
|
||||||
|
|
||||||
|
import haxework.view.frame.FrameSwitcher;
|
||||||
|
import haxework.view.TextView;
|
||||||
|
import haxework.view.VGroupView;
|
||||||
|
import ru.m.tankz.network.NetworkManager;
|
||||||
|
import ru.m.tankz.proto.core.GameProto;
|
||||||
|
|
||||||
|
@:template class GameRoomFrame extends VGroupView {
|
||||||
|
|
||||||
|
public static inline var ID = "game_room";
|
||||||
|
|
||||||
|
@:view var info:TextView;
|
||||||
|
|
||||||
|
@:provide var switcher:FrameSwitcher;
|
||||||
|
@:provide var network:NetworkManager;
|
||||||
|
|
||||||
|
private function refresh(game:GameProto):Void {
|
||||||
|
info.text = '${game.id}. ${game.type}';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onShow():Void {
|
||||||
|
refresh(network.game);
|
||||||
|
network.gameSignal.connect(onGame);
|
||||||
|
network.stateSignal.connect(onState);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onHide():Void {
|
||||||
|
network.gameSignal.disconnect(onGame);
|
||||||
|
network.stateSignal.disconnect(onState);
|
||||||
|
network.leaveGame();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function onGame(game:GameProto):Void {
|
||||||
|
refresh(game);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function onState(state:ConnectionState):Void {
|
||||||
|
switch state {
|
||||||
|
case ONLINE(_):
|
||||||
|
case _: switcher.change(StartFrame.ID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
20
src/client/haxe/ru/m/tankz/view/network/GameRoomFrame.yaml
Normal file
20
src/client/haxe/ru/m/tankz/view/network/GameRoomFrame.yaml
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
views:
|
||||||
|
- $type: haxework.view.VGroupView
|
||||||
|
skinId: container
|
||||||
|
geometry.padding: 20
|
||||||
|
views:
|
||||||
|
- id: header
|
||||||
|
$type: haxework.view.LabelView
|
||||||
|
geometry.margin.bottom: 20
|
||||||
|
skinId: text.header
|
||||||
|
text: Game Room
|
||||||
|
- id: info
|
||||||
|
$type: haxework.view.TextView
|
||||||
|
geometry.size.stretch: true
|
||||||
|
- $type: haxework.view.HGroupView
|
||||||
|
skinId: panel
|
||||||
|
views:
|
||||||
|
- $type: haxework.view.ButtonView
|
||||||
|
skinId: button.close
|
||||||
|
+onPress: $code:switcher.change('start')
|
||||||
60
src/common/haxe/ru/m/Timer.hx
Normal file
60
src/common/haxe/ru/m/Timer.hx
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
package ru.m;
|
||||||
|
|
||||||
|
#if neko
|
||||||
|
|
||||||
|
import haxe.Log;
|
||||||
|
import haxe.PosInfos;
|
||||||
|
import neko.vm.Thread;
|
||||||
|
|
||||||
|
class Timer {
|
||||||
|
|
||||||
|
private var sleep:Float;
|
||||||
|
private var stopped:Bool;
|
||||||
|
|
||||||
|
public function new(time_ms:Int) {
|
||||||
|
this.sleep = time_ms / 1000.0;
|
||||||
|
this.stopped = false;
|
||||||
|
Thread.create(function() {
|
||||||
|
while (!stopped) {
|
||||||
|
Sys.sleep(sleep);
|
||||||
|
try {
|
||||||
|
run();
|
||||||
|
} catch (error:Dynamic) {
|
||||||
|
trace(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stop() {
|
||||||
|
stopped = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public dynamic function run() {}
|
||||||
|
|
||||||
|
public static function delay(f:Void -> Void, time_ms:Int) {
|
||||||
|
var t = new Timer(time_ms);
|
||||||
|
t.run = function() {
|
||||||
|
t.stop();
|
||||||
|
f();
|
||||||
|
};
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function measure<T>(f:Void -> T, ?pos:PosInfos):T {
|
||||||
|
var t0 = stamp();
|
||||||
|
var r = f();
|
||||||
|
Log.trace((stamp() - t0) + "s", pos);
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static inline function stamp():Float {
|
||||||
|
return Sys.time();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
typedef Timer = haxe.Timer;
|
||||||
|
|
||||||
|
#end
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
package ru.m.tankz.core;
|
package ru.m.tankz.core;
|
||||||
|
|
||||||
import haxe.Timer;
|
|
||||||
import haxework.signal.Signal;
|
import haxework.signal.Signal;
|
||||||
|
import ru.m.Timer;
|
||||||
|
|
||||||
class Modificator extends Signal2<Int, Bool> {
|
class Modificator extends Signal2<Int, Bool> {
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package ru.m.tankz.game;
|
package ru.m.tankz.game;
|
||||||
|
|
||||||
import haxe.ds.Option;
|
import haxe.ds.Option;
|
||||||
import haxe.Timer;
|
|
||||||
import haxework.signal.Signal;
|
import haxework.signal.Signal;
|
||||||
import ru.m.geom.Line;
|
import ru.m.geom.Line;
|
||||||
import ru.m.geom.Point;
|
import ru.m.geom.Point;
|
||||||
@@ -18,6 +17,7 @@ import ru.m.tankz.game.GameEvent;
|
|||||||
import ru.m.tankz.game.IGame;
|
import ru.m.tankz.game.IGame;
|
||||||
import ru.m.tankz.game.Spawner;
|
import ru.m.tankz.game.Spawner;
|
||||||
import ru.m.tankz.Type;
|
import ru.m.tankz.Type;
|
||||||
|
import ru.m.Timer;
|
||||||
|
|
||||||
class GameRunner implements EngineListener implements GameListener {
|
class GameRunner implements EngineListener implements GameListener {
|
||||||
@:provide var controlFactory:IControlFactory;
|
@:provide var controlFactory:IControlFactory;
|
||||||
|
|||||||
@@ -13,7 +13,10 @@ class State {
|
|||||||
public var hits:Int;
|
public var hits:Int;
|
||||||
|
|
||||||
public function new() {
|
public function new() {
|
||||||
|
score = 0;
|
||||||
|
frags = 0;
|
||||||
|
shots = 0;
|
||||||
|
hits = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function add(state:State) {
|
public function add(state:State) {
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
package ru.m.tankz.game;
|
package ru.m.tankz.game;
|
||||||
|
|
||||||
import haxe.Timer;
|
|
||||||
import ru.m.tankz.config.Config;
|
import ru.m.tankz.config.Config;
|
||||||
import ru.m.tankz.Type;
|
import ru.m.tankz.Type;
|
||||||
|
import ru.m.Timer;
|
||||||
|
|
||||||
typedef SpawnTask = {
|
typedef SpawnTask = {
|
||||||
var point:SpawnPoint;
|
var point:SpawnPoint;
|
||||||
|
|||||||
@@ -50,6 +50,7 @@ message JoinGameRequest {
|
|||||||
|
|
||||||
message JoinGameResponse {
|
message JoinGameResponse {
|
||||||
ru.m.tankz.proto.core.GameProto game = 1;
|
ru.m.tankz.proto.core.GameProto game = 1;
|
||||||
|
ru.m.tankz.proto.core.UserProto user = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Leave Game
|
// Leave Game
|
||||||
@@ -57,6 +58,7 @@ message LeaveGameRequest {}
|
|||||||
|
|
||||||
message LeaveGameResponse {
|
message LeaveGameResponse {
|
||||||
ru.m.tankz.proto.core.GameProto game = 1;
|
ru.m.tankz.proto.core.GameProto game = 1;
|
||||||
|
ru.m.tankz.proto.core.UserProto user = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start Game
|
// Start Game
|
||||||
@@ -89,5 +91,7 @@ message Response {
|
|||||||
JoinGameResponse joinGame = 5;
|
JoinGameResponse joinGame = 5;
|
||||||
LeaveGameResponse leaveGame = 6;
|
LeaveGameResponse leaveGame = 6;
|
||||||
StartGameResponse startGame = 7;
|
StartGameResponse startGame = 7;
|
||||||
|
|
||||||
|
ErrorResponse error = 999;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,12 @@ import haxework.provider.Provider;
|
|||||||
import neko.net.ThreadServer;
|
import neko.net.ThreadServer;
|
||||||
import ru.m.tankz.bundle.IConfigBundle;
|
import ru.m.tankz.bundle.IConfigBundle;
|
||||||
import ru.m.tankz.bundle.ILevelBundle;
|
import ru.m.tankz.bundle.ILevelBundle;
|
||||||
|
import ru.m.tankz.control.IControlFactory;
|
||||||
|
import ru.m.tankz.control.NoneControlFactory;
|
||||||
import ru.m.tankz.server.bundle.ServerConfigBundle;
|
import ru.m.tankz.server.bundle.ServerConfigBundle;
|
||||||
import ru.m.tankz.server.bundle.ServerLevelBundle;
|
import ru.m.tankz.server.bundle.ServerLevelBundle;
|
||||||
|
import ru.m.tankz.server.game.GameManager;
|
||||||
|
import ru.m.tankz.server.game.IGameManager;
|
||||||
import ru.m.tankz.server.session.GameSession;
|
import ru.m.tankz.server.session.GameSession;
|
||||||
import sys.net.Socket;
|
import sys.net.Socket;
|
||||||
|
|
||||||
@@ -35,6 +39,8 @@ class Server extends ThreadServer<GameSession, Bytes> {
|
|||||||
session.pushData(bytes);
|
session.pushData(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@:provide static var gameManager:IGameManager;
|
||||||
|
|
||||||
public static function main() {
|
public static function main() {
|
||||||
L.push(new TraceLogger());
|
L.push(new TraceLogger());
|
||||||
#if debug
|
#if debug
|
||||||
@@ -44,7 +50,8 @@ class Server extends ThreadServer<GameSession, Bytes> {
|
|||||||
L.i(TAG, 'Build: ${CompilationOption.get("build")}');
|
L.i(TAG, 'Build: ${CompilationOption.get("build")}');
|
||||||
Provider.setFactory(IConfigBundle, ServerConfigBundle);
|
Provider.setFactory(IConfigBundle, ServerConfigBundle);
|
||||||
Provider.setFactory(ILevelBundle, ServerLevelBundle);
|
Provider.setFactory(ILevelBundle, ServerLevelBundle);
|
||||||
//Provider.setFactory(IControlFactory, NoneControlFactory);
|
Provider.setFactory(IControlFactory, NoneControlFactory);
|
||||||
|
gameManager = new GameManager();
|
||||||
var host:String = Sys.args().length > 0 ? Sys.args()[0] : "localhost";
|
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 port:Int = Sys.args().length > 1 ? Std.parseInt(Sys.args()[1]) : 5000;
|
||||||
var wserver = new Server();
|
var wserver = new Server();
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
package ru.m.tankz.server.db;
|
|
||||||
|
|
||||||
import ru.m.tankz.db.Orm;
|
|
||||||
import ru.m.tankz.proto.Person;
|
|
||||||
import ru.m.tankz.proto.Account;
|
|
||||||
|
|
||||||
class DbProvider {
|
|
||||||
|
|
||||||
private var orm:Orm;
|
|
||||||
|
|
||||||
public function new() {
|
|
||||||
var db = new orm.Db("mysql://shmyga:password@localhost:3306/armageddon");
|
|
||||||
orm = new Orm(db);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getAccount(login:String, password:String):Null<Account> {
|
|
||||||
var account = null;
|
|
||||||
var accountModel = orm.account.getByLogin(login);
|
|
||||||
if (accountModel != null && accountModel.password == password) {
|
|
||||||
account = new Account().setLogin(accountModel.login);
|
|
||||||
var personsModels = orm.person.getByAccount_id(accountModel.id);
|
|
||||||
for (personModel in personsModels) {
|
|
||||||
account.addPersons(new Person().setId(personModel.id).setName(personModel.name));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return account;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getPerson(person_id:Int):Null<Person> {
|
|
||||||
var person = null;
|
|
||||||
var personModel = orm.person.get(person_id);
|
|
||||||
if (personModel != null) {
|
|
||||||
person = new Person().setId(personModel.id).setName(personModel.name);
|
|
||||||
}
|
|
||||||
return person;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,149 +1,79 @@
|
|||||||
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.preset.ClassicGame;
|
|
||||||
import ru.m.tankz.proto.pack.StartGameResponse;
|
|
||||||
import ru.m.tankz.proto.pack.LeaveGameResponse;
|
|
||||||
import ru.m.tankz.proto.pack.JoinGameResponse;
|
|
||||||
import ru.m.tankz.proto.pack.ListGameResponse;
|
|
||||||
import ru.m.tankz.proto.pack.CreateGameResponse;
|
|
||||||
import ru.m.tankz.proto.pack.Response;
|
|
||||||
import ru.m.tankz.proto.core.GameStateProto;
|
import ru.m.tankz.proto.core.GameStateProto;
|
||||||
import ru.m.tankz.proto.core.GameInfoProto;
|
import ru.m.tankz.game.GameState;
|
||||||
|
import ru.m.tankz.proto.core.GameProto;
|
||||||
import ru.m.tankz.proto.core.UserProto;
|
import ru.m.tankz.proto.core.UserProto;
|
||||||
import ru.m.tankz.server.session.Thread;
|
import ru.m.tankz.server.game.IGameManager;
|
||||||
import ru.m.tankz.server.session._Session;
|
|
||||||
|
|
||||||
|
@:dispatcher(GameManagerListener) class GameManager implements IGameManager {
|
||||||
|
public var games(default, null):Array<ServerGame>;
|
||||||
|
public var gamesById(default, null):Map<Int, ServerGame>;
|
||||||
|
public var gamesByCreator(default, null):Map<String, ServerGame>;
|
||||||
|
public var gamesByUser(default, null):Map<String, ServerGame>;
|
||||||
|
|
||||||
/**
|
private var counter:Int;
|
||||||
*
|
|
||||||
**/
|
|
||||||
class NekoTimer {
|
|
||||||
|
|
||||||
private var sleep:Float;
|
public function new() {
|
||||||
private var stopped:Bool;
|
counter = 0;
|
||||||
|
games = [];
|
||||||
public function new(time_ms:Int) {
|
gamesById = new Map();
|
||||||
this.sleep = time_ms / 1000.0;
|
gamesByCreator = new Map();
|
||||||
this.stopped = false;
|
gamesByUser = new Map();
|
||||||
Thread.create(function() {
|
|
||||||
while (!stopped) {
|
|
||||||
Sys.sleep(sleep);
|
|
||||||
try {
|
|
||||||
run();
|
|
||||||
} catch (error:Dynamic) {
|
|
||||||
trace(error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public dynamic function run() {}
|
public function create(user:UserProto, type:String, level:Int):ServerGame {
|
||||||
|
if (gamesByCreator.exists(user.uuid)) {
|
||||||
|
delete(gamesByCreator[user.uuid].proto.id);
|
||||||
|
}
|
||||||
|
var proto = new GameProto()
|
||||||
|
.setId(++counter)
|
||||||
|
.setCreator(user)
|
||||||
|
.setType(type)
|
||||||
|
.setLevel(level)
|
||||||
|
.setPlayers([user]);
|
||||||
|
var game = new ServerGame(proto);
|
||||||
|
games.push(game);
|
||||||
|
gamesById[game.proto.id] = game;
|
||||||
|
gamesByCreator[game.proto.creator.uuid] = game;
|
||||||
|
createSignal.emit(game);
|
||||||
|
return game;
|
||||||
|
}
|
||||||
|
|
||||||
public function stop() {
|
public function join(gameId:Int, user:UserProto):Void {
|
||||||
stopped = true;
|
if (gamesById.exists(gameId)) {
|
||||||
}
|
var game = gamesById[gameId];
|
||||||
}
|
game.proto.players.push(user);
|
||||||
|
gamesByUser[user.uuid] = game;
|
||||||
/**
|
changeSignal.emit(game, JOIN(user));
|
||||||
*
|
}
|
||||||
**/
|
}
|
||||||
class GameManager {
|
|
||||||
|
public function delete(gameId:Int):Void {
|
||||||
public static var byGameId:Map<Int, GameManager> = new Map<Int, GameManager>();
|
if (gamesById.exists(gameId)) {
|
||||||
public static var byPersonId:Map<String, GameManager> = new Map<String, GameManager>();
|
var game = gamesById[gameId];
|
||||||
public static var subscribers:Map<String, Bool> = new Map<String, Bool>();
|
games.remove(game);
|
||||||
|
gamesById.remove(game.proto.id);
|
||||||
private static var idCounter:Int = 0;
|
gamesByCreator.remove(game.proto.creator.uuid);
|
||||||
|
deleteSignal.emit(game);
|
||||||
public var gameInfo(default, null):GameInfoProto;
|
}
|
||||||
public var game(default, null):IGame;
|
}
|
||||||
|
|
||||||
private var timer:NekoTimer;
|
public function leave(user:UserProto):Void {
|
||||||
|
if (gamesByCreator.exists(user.uuid)) {
|
||||||
//private var changes:Array<GameChange> = new Array<GameChange>();
|
delete(gamesByCreator[user.uuid].proto.id);
|
||||||
|
} else if (gamesByUser.exists(user.uuid)) {
|
||||||
public function new(creator:UserProto) {
|
var game = gamesByUser[user.uuid];
|
||||||
gameInfo = new GameInfoProto()
|
game.proto.setPlayers(game.proto.players.filter(function(player) return player.uuid != user.uuid));
|
||||||
.setId(idCounter++)
|
changeSignal.emit(game, LEAVE(user));
|
||||||
.setState(GameStateProto.READY)
|
}
|
||||||
.setCreator(creator);
|
}
|
||||||
gameInfo.addPlayers(creator);
|
|
||||||
byGameId.set(gameInfo.id, this);
|
public function start(gameId:Int):Void {
|
||||||
byPersonId.set(creator.uuid, this);
|
if (gamesById.exists(gameId)) {
|
||||||
broadcast(new Response().setCreateGame(new CreateGameResponse().setGame(gameInfo)));
|
var game = gamesById[gameId];
|
||||||
broadcastGames();
|
game.proto.setState(GameStateProto.STARTED);
|
||||||
}
|
changeSignal.emit(game, START);
|
||||||
|
}
|
||||||
public static function getReadyGames():Array<GameInfoProto> {
|
|
||||||
return Lambda.array(Lambda.filter(Lambda.map(GameManager.byGameId, function(gm) return gm.gameInfo), function(game) return game.state == GameStateProto.READY));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function broadcastGames() {
|
|
||||||
var packet = new Response().setListGame(new ListGameResponse().setGames(getReadyGames()));
|
|
||||||
for (personId in subscribers.keys()) {
|
|
||||||
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);
|
|
||||||
session.send(packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function join(user:UserProto) {
|
|
||||||
gameInfo.addPlayers(user);
|
|
||||||
byPersonId.set(user.uuid, this);
|
|
||||||
broadcast(new Response().setJoinGame(new JoinGameResponse().setGame(gameInfo)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function leave(user:UserProto) {
|
|
||||||
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);
|
|
||||||
if (gameInfo.players.length == 0/* || person.id == game.creator.id*/) {
|
|
||||||
stop();
|
|
||||||
} else {
|
|
||||||
broadcast(packet);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function start() {
|
|
||||||
gameInfo.setState(GameStateProto.STARTED);
|
|
||||||
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)));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function stop() {
|
|
||||||
gameInfo.setState(GameStateProto.ENDED);
|
|
||||||
gameInfo.setPlayers([]);
|
|
||||||
byGameId.remove(gameInfo.id);
|
|
||||||
for (p in gameInfo.players) byPersonId.remove(p.uuid);
|
|
||||||
if (timer != null) {
|
|
||||||
timer.stop();
|
|
||||||
timer = null;
|
|
||||||
}
|
|
||||||
broadcast(new Response().setLeaveGame(new LeaveGameResponse().setGame(gameInfo)));
|
|
||||||
broadcastGames();
|
|
||||||
}
|
|
||||||
|
|
||||||
private function update() {
|
|
||||||
//game.engine.update();
|
|
||||||
/*var changes = engine.update();
|
|
||||||
changes = this.changes.concat(changes);
|
|
||||||
this.changes = [];
|
|
||||||
if (changes.length > 0) {
|
|
||||||
broadcast(new GameUpdateResponse().setChanges(changes));
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
35
src/server/haxe/ru/m/tankz/server/game/IGameManager.hx
Normal file
35
src/server/haxe/ru/m/tankz/server/game/IGameManager.hx
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
package ru.m.tankz.server.game;
|
||||||
|
|
||||||
|
import haxework.signal.Signal;
|
||||||
|
import ru.m.tankz.proto.core.UserProto;
|
||||||
|
|
||||||
|
enum GameChange {
|
||||||
|
JOIN(user:UserProto);
|
||||||
|
LEAVE(user:UserProto);
|
||||||
|
START();
|
||||||
|
}
|
||||||
|
|
||||||
|
interface GameManagerListener {
|
||||||
|
public function onCreate(game:ServerGame):Void;
|
||||||
|
public function onChange(game:ServerGame, change:GameChange):Void;
|
||||||
|
public function onDelete(game:ServerGame):Void;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface IGameManager {
|
||||||
|
public var games(default, null):Array<ServerGame>;
|
||||||
|
public var gamesById(default, null):Map<Int, ServerGame>;
|
||||||
|
public var gamesByCreator(default, null):Map<String, ServerGame>;
|
||||||
|
|
||||||
|
private var createSignal(default, null):Signal<ServerGame>;
|
||||||
|
private var changeSignal(default, null):Signal2<ServerGame, GameChange>;
|
||||||
|
private var deleteSignal(default, null):Signal<ServerGame>;
|
||||||
|
|
||||||
|
public function connect(listener:GameManagerListener):Void;
|
||||||
|
public function disconnect(listener:GameManagerListener):Void;
|
||||||
|
|
||||||
|
public function create(user:UserProto, type:String, level:Int):ServerGame;
|
||||||
|
public function delete(gameId:Int):Void;
|
||||||
|
public function join(gameId:Int, user:UserProto):Void;
|
||||||
|
public function leave(user:UserProto):Void;
|
||||||
|
public function start(gameId:Int):Void;
|
||||||
|
}
|
||||||
18
src/server/haxe/ru/m/tankz/server/game/ServerGame.hx
Normal file
18
src/server/haxe/ru/m/tankz/server/game/ServerGame.hx
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
package ru.m.tankz.server.game;
|
||||||
|
|
||||||
|
import ru.m.tankz.game.Game;
|
||||||
|
//import ru.m.tankz.game.GameRunner;
|
||||||
|
import ru.m.tankz.game.GameState;
|
||||||
|
import ru.m.tankz.proto.core.GameProto;
|
||||||
|
|
||||||
|
class ServerGame extends Game {
|
||||||
|
|
||||||
|
//public var runner(default, null):GameRunner;
|
||||||
|
public var proto(default, null):GameProto;
|
||||||
|
|
||||||
|
public function new(proto:GameProto) {
|
||||||
|
super(new GameState(proto.type, 0, proto.level));
|
||||||
|
this.proto = proto;
|
||||||
|
//runner = new GameRunner(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,69 +2,128 @@ package ru.m.tankz.server.session;
|
|||||||
|
|
||||||
import com.hurlant.crypto.extra.UUID;
|
import com.hurlant.crypto.extra.UUID;
|
||||||
import com.hurlant.crypto.prng.Random;
|
import com.hurlant.crypto.prng.Random;
|
||||||
import ru.m.tankz.proto.core.GameProto;
|
import haxework.log.BaseLogger.LoggerUtil;
|
||||||
import ru.m.tankz.proto.core.UserProto;
|
import ru.m.tankz.proto.core.UserProto;
|
||||||
import ru.m.tankz.proto.pack.CreateGameRequest;
|
|
||||||
import ru.m.tankz.proto.pack.CreateGameResponse;
|
import ru.m.tankz.proto.pack.CreateGameResponse;
|
||||||
import ru.m.tankz.proto.pack.ListGameRequest;
|
import ru.m.tankz.proto.pack.ErrorResponse;
|
||||||
|
import ru.m.tankz.proto.pack.JoinGameResponse;
|
||||||
|
import ru.m.tankz.proto.pack.LeaveGameResponse;
|
||||||
import ru.m.tankz.proto.pack.ListGameResponse;
|
import ru.m.tankz.proto.pack.ListGameResponse;
|
||||||
import ru.m.tankz.proto.pack.LoginRequest;
|
|
||||||
import ru.m.tankz.proto.pack.LoginResponse;
|
import ru.m.tankz.proto.pack.LoginResponse;
|
||||||
import ru.m.tankz.proto.pack.LogoutRequest;
|
|
||||||
import ru.m.tankz.proto.pack.LogoutResponse;
|
import ru.m.tankz.proto.pack.LogoutResponse;
|
||||||
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.StartGameResponse;
|
||||||
|
import ru.m.tankz.server.game.IGameManager;
|
||||||
|
import ru.m.tankz.server.game.ServerGame;
|
||||||
import sys.net.Socket;
|
import sys.net.Socket;
|
||||||
|
|
||||||
class GameSession extends ProtoSession<Response, Request> {
|
class GameSession extends ProtoSession<Response, Request> implements GameManagerListener {
|
||||||
private static inline var TAG = "Session";
|
private static inline var TAG = "Session";
|
||||||
|
|
||||||
|
@:provide static var gameManager:IGameManager;
|
||||||
|
|
||||||
public var user(default, null):UserProto;
|
public var user(default, null):UserProto;
|
||||||
|
public var gameId(default, null):Int;
|
||||||
|
|
||||||
public function new(socket:Socket) {
|
public function new(socket:Socket) {
|
||||||
super(socket, Request);
|
super(socket, Request);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function onLogin(request:LoginRequest):LoginResponse {
|
private function sendError(code:Int, message:String):Void {
|
||||||
user = new UserProto()
|
send(new Response().setError(new ErrorResponse().setCode(code).setMessage(message)));
|
||||||
.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 {
|
private function listGame():ListGameResponse {
|
||||||
return new LogoutResponse();
|
var games = gameManager.games;
|
||||||
|
return new ListGameResponse().setGames([for (game in games) game.proto]);
|
||||||
}
|
}
|
||||||
|
|
||||||
private function onCreateGame(request:CreateGameRequest):CreateGameResponse {
|
override public function send(packet:Response):Void {
|
||||||
var game = new GameProto()
|
L.d(TAG, 'send: ${user == null ? '' : user.name} - ${packet}');
|
||||||
.setId(1)
|
super.send(packet);
|
||||||
.setCreator(user)
|
|
||||||
.setType(request.type)
|
|
||||||
.setLevel(request.level);
|
|
||||||
return new CreateGameResponse().setGame(game);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function onListGame(request:ListGameRequest):ListGameResponse {
|
|
||||||
// ToDo: test games
|
|
||||||
var games = [for (i in 0...5) new GameProto()
|
|
||||||
.setId(i)
|
|
||||||
.setCreator(user)
|
|
||||||
.setType("classic")
|
|
||||||
.setLevel(i)];
|
|
||||||
return new ListGameResponse().setGames(games);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override private function onRequest(request:Request):Void {
|
override private function onRequest(request:Request):Void {
|
||||||
L.d(TAG, 'onRequest: ${request}');
|
L.d(TAG, 'onRequest: ${user == null ? '' : user.name} - ${request}');
|
||||||
if (request.hasLogin()) {
|
try {
|
||||||
send(new Response().setLogin(onLogin(request.login)));
|
if (!request.hasLogin() && user == null) {
|
||||||
} else if (request.hasLogout()) {
|
throw "Not Authorized";
|
||||||
send(new Response().setLogout(onLogout(request.logout)));
|
}
|
||||||
} else if (request.hasCreateGame()) {
|
// login
|
||||||
send(new Response().setCreateGame(onCreateGame(request.createGame)));
|
if (request.hasLogin()) {
|
||||||
} else if (request.hasListGame()) {
|
user = new UserProto()
|
||||||
send(new Response().setListGame(onListGame(request.listGame)));
|
.setUuid(request.login.uuid != null ? request.login.uuid : UUID.generateRandom(new Random()).toString())
|
||||||
|
.setName(request.login.name);
|
||||||
|
gameManager.connect(this);
|
||||||
|
send(new Response().setLogin(new LoginResponse().setUser(user)));
|
||||||
|
// logout
|
||||||
|
} else if (request.hasLogout()) {
|
||||||
|
gameManager.disconnect(this);
|
||||||
|
if (user != null) {
|
||||||
|
gameManager.leave(user);
|
||||||
|
user = null;
|
||||||
|
}
|
||||||
|
send(new Response().setLogout(new LogoutResponse()));
|
||||||
|
// create
|
||||||
|
} else if (request.hasCreateGame()) {
|
||||||
|
var game = gameManager.create(user, request.createGame.type, request.createGame.level);
|
||||||
|
gameId = game.proto.id;
|
||||||
|
send(new Response().setCreateGame(new CreateGameResponse().setGame(game.proto)));
|
||||||
|
// list
|
||||||
|
} else if (request.hasListGame()) {
|
||||||
|
send(new Response().setListGame(listGame()));
|
||||||
|
// join
|
||||||
|
} else if (request.hasJoinGame()) {
|
||||||
|
gameId = request.joinGame.gameId;
|
||||||
|
gameManager.join(request.joinGame.gameId, user);
|
||||||
|
// leave
|
||||||
|
} else if (request.hasLeaveGame()) {
|
||||||
|
gameManager.leave(user);
|
||||||
|
// start
|
||||||
|
} else if (request.hasStartGame()) {
|
||||||
|
gameManager.start(gameId);
|
||||||
|
}
|
||||||
|
} catch (error:Dynamic) {
|
||||||
|
L.e(TAG, "onRequest ", error);
|
||||||
|
sendError(500, LoggerUtil.printError(error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override public function disconnect():Void {
|
||||||
|
gameId = null;
|
||||||
|
gameManager.disconnect(this);
|
||||||
|
if (user != null) {
|
||||||
|
gameManager.leave(user);
|
||||||
|
user = null;
|
||||||
|
}
|
||||||
|
super.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onCreate(game:ServerGame):Void {
|
||||||
|
send(new Response().setListGame(listGame()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onChange(game:ServerGame, change:GameChange):Void {
|
||||||
|
if (gameId == game.proto.id) {
|
||||||
|
switch change {
|
||||||
|
case JOIN(user):
|
||||||
|
if (user.uuid == this.user.uuid) {
|
||||||
|
gameId = gameId = game.proto.id;
|
||||||
|
}
|
||||||
|
send(new Response().setJoinGame(new JoinGameResponse().setGame(game.proto).setUser(user)));
|
||||||
|
case LEAVE(user):
|
||||||
|
if (user.uuid == this.user.uuid) {
|
||||||
|
gameId = null;
|
||||||
|
}
|
||||||
|
send(new Response().setLeaveGame(new LeaveGameResponse().setGame(game.proto).setUser(user)));
|
||||||
|
case START:
|
||||||
|
send(new Response().setStartGame(new StartGameResponse().setGame(game.proto)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function onDelete(game:ServerGame):Void {
|
||||||
|
send(new Response().setListGame(listGame()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,112 +0,0 @@
|
|||||||
package ru.m.tankz.server.session;
|
|
||||||
|
|
||||||
enum ThreadHandle {
|
|
||||||
}
|
|
||||||
|
|
||||||
class Thread {
|
|
||||||
|
|
||||||
var handle:ThreadHandle;
|
|
||||||
|
|
||||||
function new(h) {
|
|
||||||
handle = h;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Send a message to the thread queue. This message can be readed by using [readMessage].
|
|
||||||
**/
|
|
||||||
public function sendMessage(msg:Dynamic) {
|
|
||||||
thread_send(handle, msg);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Returns the current thread.
|
|
||||||
**/
|
|
||||||
public static function current() {
|
|
||||||
return new Thread(thread_current());
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Creates a new thread that will execute the [callb] function, then exit.
|
|
||||||
**/
|
|
||||||
public static function create(callb:Void -> Void) {
|
|
||||||
return new Thread(thread_create(function(_) { return callb(); }, null));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Reads a message from the thread queue. If [block] is true, the function
|
|
||||||
blocks until a message is available. If [block] is false, the function
|
|
||||||
returns [null] if no message is available.
|
|
||||||
**/
|
|
||||||
public static function readMessage(block:Bool):Dynamic {
|
|
||||||
return thread_read_message(block);
|
|
||||||
}
|
|
||||||
|
|
||||||
@:keep function __compare(t) {
|
|
||||||
return untyped __dollar__compare(handle, t.handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Starts an OS message loop after [osInitialize] has been done.
|
|
||||||
In that state, the UI handled by this thread will be updated and
|
|
||||||
[sync] calls can be performed. The loop returns when [exitLoop] is
|
|
||||||
called for this thread.
|
|
||||||
**
|
|
||||||
public static function osLoop() {
|
|
||||||
if( os_loop == null ) throw "Please call osInitialize() first";
|
|
||||||
os_loop();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
The function [f] will be called by this thread if it's in [osLoop].
|
|
||||||
[sync] returns immediatly. See [osInitialize] remarks.
|
|
||||||
**
|
|
||||||
public function sync( f : Void -> Void ) {
|
|
||||||
os_sync(handle,f);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
The function [f] will be called by this thread and the calling thread
|
|
||||||
will wait until the result is available then return its value.
|
|
||||||
**
|
|
||||||
public function syncResult<T>( f : Void -> T ) : T {
|
|
||||||
if( this == current() )
|
|
||||||
return f();
|
|
||||||
var v = new neko.vm.Lock();
|
|
||||||
var r = null;
|
|
||||||
sync(function() {
|
|
||||||
r = f();
|
|
||||||
v.release();
|
|
||||||
});
|
|
||||||
v.wait();
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Exit from [osLoop].
|
|
||||||
**
|
|
||||||
public function exitLoop() {
|
|
||||||
os_loop_stop(handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
If you want to use the [osLoop], [sync] and [syncResult] methods, you
|
|
||||||
need to call [osInitialize] before creating any thread or calling [current].
|
|
||||||
This will load [os.ndll] library and initialize UI methods for each thread.
|
|
||||||
**
|
|
||||||
public static function osInitialize() {
|
|
||||||
os_loop = neko.Lib.load("os","os_loop",0);
|
|
||||||
os_loop_stop = neko.Lib.load("os","os_loop_stop",1);
|
|
||||||
os_sync = neko.Lib.load("os","os_sync",2);
|
|
||||||
}
|
|
||||||
|
|
||||||
static var os_loop = null;
|
|
||||||
static var os_loop_stop = null;
|
|
||||||
static var os_sync = null;
|
|
||||||
*/
|
|
||||||
|
|
||||||
static var thread_create = neko.Lib.load("std", "thread_create", 2);
|
|
||||||
static var thread_current = neko.Lib.load("std", "thread_current", 0);
|
|
||||||
static var thread_send = neko.Lib.load("std", "thread_send", 2);
|
|
||||||
static var thread_read_message = neko.Lib.load("std", "thread_read_message", 1);
|
|
||||||
}
|
|
||||||
@@ -1,156 +0,0 @@
|
|||||||
package ru.m.tankz.server.session;
|
|
||||||
|
|
||||||
import ru.m.tankz.proto.pack.GameResponse;
|
|
||||||
import ru.m.tankz.proto.pack.GameRequest;
|
|
||||||
import com.hurlant.crypto.extra.UUID;
|
|
||||||
import com.hurlant.crypto.prng.Random;
|
|
||||||
import haxe.io.Bytes;
|
|
||||||
import ru.m.connect.IConnection;
|
|
||||||
import ru.m.connect.neko.NekoConnection;
|
|
||||||
import ru.m.connect.neko.NekoWSConnection;
|
|
||||||
import ru.m.tankz.proto.core.UserProto;
|
|
||||||
import ru.m.tankz.proto.pack.CreateGameRequest;
|
|
||||||
import ru.m.tankz.proto.pack.CreateGameResponse;
|
|
||||||
import ru.m.tankz.proto.pack.JoinGameRequest;
|
|
||||||
import ru.m.tankz.proto.pack.JoinGameResponse;
|
|
||||||
import ru.m.tankz.proto.pack.LeaveGameRequest;
|
|
||||||
import ru.m.tankz.proto.pack.LeaveGameResponse;
|
|
||||||
import ru.m.tankz.proto.pack.ListGameRequest;
|
|
||||||
import ru.m.tankz.proto.pack.ListGameResponse;
|
|
||||||
import ru.m.tankz.proto.pack.LoginRequest;
|
|
||||||
import ru.m.tankz.proto.pack.LoginResponse;
|
|
||||||
import ru.m.tankz.proto.pack.LogoutRequest;
|
|
||||||
import ru.m.tankz.proto.pack.LogoutResponse;
|
|
||||||
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.proto.pack.StartGameResponse;
|
|
||||||
import ru.m.tankz.server.game.GameManager;
|
|
||||||
import sys.net.Socket;
|
|
||||||
|
|
||||||
|
|
||||||
typedef ServerConnection = IConnection<Response, Request>;
|
|
||||||
|
|
||||||
class _Session {
|
|
||||||
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 static var sessions:Map<String, _Session> = new Map<String, _Session>();
|
|
||||||
|
|
||||||
public var user(default, null):UserProto;
|
|
||||||
public var gameId(default, null):Int = -1;
|
|
||||||
|
|
||||||
public var connection(default, null):ServerConnection;
|
|
||||||
|
|
||||||
private var socket:Socket;
|
|
||||||
|
|
||||||
public function new(socket:Socket) {
|
|
||||||
this.socket = socket;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function send(packet:Response):Void {
|
|
||||||
connection.send(packet);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function pushData(bytes:Bytes):Void {
|
|
||||||
if (connection != null) {
|
|
||||||
connection.pushData(bytes);
|
|
||||||
} else {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
if (StringTools.startsWith(str, "GET")) {
|
|
||||||
connection = new NekoWSConnection<Response, Request>(socket, Request);
|
|
||||||
} else {
|
|
||||||
connection = new NekoConnection<Response, Request>(socket, Request);
|
|
||||||
}
|
|
||||||
connection.handler.connect(onConnectionEvent);
|
|
||||||
connection.receiveHandler.connect(onRequest);
|
|
||||||
connection.pushData(bytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function onConnectionEvent(event:ConnectionEvent):Void {
|
|
||||||
L.d(TAG, '${event}');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function onRequest(request:Request):Void {
|
|
||||||
if (request.hasLogin()) {
|
|
||||||
send(new Response().setLogin(login(request.login)));
|
|
||||||
} else if (request.hasLogout()) {
|
|
||||||
send(new Response().setLogout(logout(request.logout)));
|
|
||||||
} else if (request.hasListGame()) {
|
|
||||||
send(new Response().setListGame(listGame(request.listGame)));
|
|
||||||
} else if (request.hasCreateGame()) {
|
|
||||||
send(new Response().setCreateGame(createGame(request.createGame)));
|
|
||||||
} else if (request.hasJoinGame()) {
|
|
||||||
send(new Response().setJoinGame(joinGame(request.joinGame)));
|
|
||||||
} else if (request.hasLeaveGame()) {
|
|
||||||
send(new Response().setLeaveGame(leaveGame(request.leaveGame)));
|
|
||||||
} else if (request.hasStartGame()) {
|
|
||||||
send(new Response().setStartGame(startGame(request.startGame)));
|
|
||||||
}else if (request.hasGame()) {
|
|
||||||
send(new Response().setGame(game(request.game)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private function login(request:LoginRequest):LoginResponse {
|
|
||||||
user = new UserProto()
|
|
||||||
.setUuid(request.uuid != null ? request.uuid : UUID.generateRandom(new Random()).toString())
|
|
||||||
.setName(request.name);
|
|
||||||
sessions.set(user.uuid, this);
|
|
||||||
GameManager.subscribers.set(user.uuid, true);
|
|
||||||
return new LoginResponse().setUser(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function logout(request:LogoutRequest):LogoutResponse {
|
|
||||||
GameManager.subscribers.remove(user.uuid);
|
|
||||||
user = null;
|
|
||||||
return new LogoutResponse();
|
|
||||||
}
|
|
||||||
|
|
||||||
private function listGame(request:ListGameRequest):ListGameResponse {
|
|
||||||
return new ListGameResponse().setGames(GameManager.getReadyGames());
|
|
||||||
}
|
|
||||||
|
|
||||||
private function createGame(request:CreateGameRequest):CreateGameResponse {
|
|
||||||
var gameManager:GameManager = new GameManager(user);
|
|
||||||
return new CreateGameResponse().setGame(gameManager.gameInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function joinGame(request:JoinGameRequest):JoinGameResponse {
|
|
||||||
var gameManager:GameManager = GameManager.byGameId.get(request.gameId);
|
|
||||||
gameManager.join(user);
|
|
||||||
return new JoinGameResponse().setGame(gameManager.gameInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function leaveGame(request:LeaveGameRequest):LeaveGameResponse {
|
|
||||||
var gameManager:GameManager = GameManager.byPersonId.get(user.uuid);
|
|
||||||
gameManager.leave(user);
|
|
||||||
return new LeaveGameResponse().setGame(gameManager.gameInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function startGame(request:StartGameRequest):StartGameResponse {
|
|
||||||
var gameManager:GameManager = GameManager.byPersonId.get(user.uuid);
|
|
||||||
gameManager.start();
|
|
||||||
return new StartGameResponse().setGame(gameManager.gameInfo);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function game(request:GameRequest):GameResponse {
|
|
||||||
var gameManager:GameManager = GameManager.byPersonId.get(user.uuid);
|
|
||||||
return new GameResponse();
|
|
||||||
//return new GameResponse().setGame(gameManager.game.export());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user