From f7f6423938a70a5927492717916f05b3601f4937 Mon Sep 17 00:00:00 2001 From: shmyga Date: Mon, 25 May 2020 17:29:31 +0300 Subject: [PATCH] [proto] update --- src/app/haxe/ru/m/puzzlez/net/Network.hx | 32 +++++++++-- src/app/haxe/ru/m/puzzlez/net/NetworkGame.hx | 41 ++++++++++++++ src/app/haxe/ru/m/puzzlez/view/GameFrame.hx | 7 ++- src/app/haxe/ru/m/puzzlez/view/PresetFrame.hx | 5 +- .../haxe/ru/m/puzzlez/view/PresetFrame.yaml | 5 ++ src/app/haxe/ru/m/puzzlez/view/StartFrame.hx | 8 ++- .../haxe/ru/m/puzzlez/view/StartFrame.yaml | 8 ++- src/common/haxe/ru/m/IdUtil.hx | 10 ++++ .../haxe/ru/m/puzzlez/core/GameState.hx | 2 + src/common/haxe/ru/m/puzzlez/core/GameUtil.hx | 1 + src/common/haxe/ru/m/puzzlez/core/IGame.hx | 2 - src/common/proto/core.proto | 26 +++++++-- src/common/proto/pack.proto | 4 +- src/server/haxe/ru/m/puzzlez/GameSession.hx | 56 ++++++++----------- .../haxe/ru/m/puzzlez/game/GameManager.hx | 24 ++++---- .../haxe/ru/m/puzzlez/game/IGameManager.hx | 9 ++- .../haxe/ru/m/puzzlez/game/ServerGame.hx | 9 ++- 17 files changed, 178 insertions(+), 71 deletions(-) create mode 100644 src/app/haxe/ru/m/puzzlez/net/NetworkGame.hx create mode 100644 src/common/haxe/ru/m/IdUtil.hx diff --git a/src/app/haxe/ru/m/puzzlez/net/Network.hx b/src/app/haxe/ru/m/puzzlez/net/Network.hx index d3602b6..04c372e 100644 --- a/src/app/haxe/ru/m/puzzlez/net/Network.hx +++ b/src/app/haxe/ru/m/puzzlez/net/Network.hx @@ -1,20 +1,24 @@ package ru.m.puzzlez.net; import haxe.Unserializer; -import com.hurlant.crypto.extra.UUID; -import com.hurlant.crypto.prng.Random; import hw.connect.ConnectionFactory; import hw.connect.IConnection; import hw.signal.Signal; import hw.storage.SharedObjectStorage; +import promhx.Promise; +import ru.m.data.IDataSource; import ru.m.puzzlez.core.GameEvent; +import ru.m.puzzlez.core.GameState; +import ru.m.puzzlez.core.Id; import ru.m.puzzlez.proto.core.GameProto; import ru.m.puzzlez.proto.core.UserProto; +import ru.m.puzzlez.proto.pack.GameCreateRequest; +import ru.m.puzzlez.proto.pack.GameJoinRequest; import ru.m.puzzlez.proto.pack.LoginRequest; import ru.m.puzzlez.proto.pack.Request; import ru.m.puzzlez.proto.pack.Response; -@:provide class Network { +@:provide class Network implements IDataIndex { public var user(default, null):UserProto; public var userSignal(default, null):Signal = new Signal(); @@ -33,11 +37,11 @@ import ru.m.puzzlez.proto.pack.Response; public function new() { gameList = []; - storage = new SharedObjectStorage("netwok"); + storage = new SharedObjectStorage("network"); if (storage.exists(USER_KEY)) { user = storage.read(USER_KEY); } else { - user = new UserProto().setName('Anonimus #${UUID.generateRandom(new Random()).toString().split("-").shift()}'); + user = new UserProto().setName('Anonimus #${IdUtil.generate()}'); storage.write(USER_KEY, user); } connection = ConnectionFactory.buildClientConnection("127.0.0.1", 5000, Response); @@ -50,6 +54,14 @@ import ru.m.puzzlez.proto.pack.Response; connection.send(new Request().setLogin(new LoginRequest().setUser(user))); } + public function startGame(state:GameState):Void { + connection.send(new Request().setGameCreate(new GameCreateRequest().setImageId(state.preset.imageId))); + } + + public function joinGame(state:GameState):Void { + connection.send(new Request().setGameJoin(new GameJoinRequest().setGameId(state.id))); + } + private function onConnectionChange(event:ConnectionEvent):Void { L.i("network", '${event}'); switch event { @@ -82,4 +94,14 @@ import ru.m.puzzlez.proto.pack.Response; } } } + + public function getIndexPage(page:Page):Promise> { + // ToDo: return gameList + var data = { + page: page, + total: 1, + data: [new ImageId('asset', 'resources/image/raccoon.jpg')], + } + return Promise.promise(data); + } } diff --git a/src/app/haxe/ru/m/puzzlez/net/NetworkGame.hx b/src/app/haxe/ru/m/puzzlez/net/NetworkGame.hx new file mode 100644 index 0000000..75762a4 --- /dev/null +++ b/src/app/haxe/ru/m/puzzlez/net/NetworkGame.hx @@ -0,0 +1,41 @@ +package ru.m.puzzlez.net; + +import hw.signal.Signal; +import ru.m.puzzlez.core.GameState; +import ru.m.puzzlez.core.GameEvent; +import ru.m.puzzlez.core.IGame; + +class NetworkGame implements IGame { + public var state(default, null):GameState; + public var signal(default, null):Signal; + + @:provide private var network:Network; + + public function new(state:GameState) { + this.state = state; + signal = new Signal(); + } + + private function onEvent(event:GameEvent):Void { + signal.emit(event); + } + + public function start():Void { + network.gameEventSignal.connect(onEvent); + switch state.status { + case READY: + network.startGame(state); + case _: + network.joinGame(state); + } + } + + public function stop():Void { + network.gameEventSignal.disconnect(onEvent); + } + + public function dispose():Void { + stop(); + signal.dispose(); + } +} diff --git a/src/app/haxe/ru/m/puzzlez/view/GameFrame.hx b/src/app/haxe/ru/m/puzzlez/view/GameFrame.hx index 72a922d..a37fffa 100644 --- a/src/app/haxe/ru/m/puzzlez/view/GameFrame.hx +++ b/src/app/haxe/ru/m/puzzlez/view/GameFrame.hx @@ -9,6 +9,7 @@ import ru.m.puzzlez.core.Game; import ru.m.puzzlez.core.GameEvent; import ru.m.puzzlez.core.GameState; import ru.m.puzzlez.core.IGame; +import ru.m.puzzlez.net.NetworkGame; import ru.m.puzzlez.render.IRender; import ru.m.puzzlez.storage.GameStorage; import ru.m.puzzlez.storage.SettingsStorage; @@ -32,7 +33,11 @@ import ru.m.puzzlez.view.popup.PreviewPopup; override public function onShow(state:GameState):Void { onHide(); - game = new Game(state); + if (state.online) { + game = new NetworkGame(state); + } else { + game = new Game(state); + } game.signal.connect(render.onGameEvent); game.signal.connect(onGameEvent); render.signal.connect(game.signal.emit); diff --git a/src/app/haxe/ru/m/puzzlez/view/PresetFrame.hx b/src/app/haxe/ru/m/puzzlez/view/PresetFrame.hx index d4c2a7d..11ce281 100644 --- a/src/app/haxe/ru/m/puzzlez/view/PresetFrame.hx +++ b/src/app/haxe/ru/m/puzzlez/view/PresetFrame.hx @@ -1,5 +1,6 @@ package ru.m.puzzlez.view; +import ru.m.puzzlez.net.Network; import hw.geom.IntPoint; import hw.view.data.DataView; import hw.view.form.ToggleButtonView; @@ -18,6 +19,7 @@ import ru.m.puzzlez.view.common.PresetView; @:provide var imageStorage:ImageStorage; @:provide var switcher:FrameSwitcher; + @:provide var network:Network; private var imageId:ImageId; @@ -53,7 +55,8 @@ import ru.m.puzzlez.view.common.PresetView; selectSize(sizesView.data[sizesView.data.length - 1]); } - private function start():Void { + private function start(online:Bool = false):Void { + imageView.state.online = online; switcher.change(GameFrame.ID, imageView.state); } diff --git a/src/app/haxe/ru/m/puzzlez/view/PresetFrame.yaml b/src/app/haxe/ru/m/puzzlez/view/PresetFrame.yaml index f3adc65..94c5ead 100644 --- a/src/app/haxe/ru/m/puzzlez/view/PresetFrame.yaml +++ b/src/app/haxe/ru/m/puzzlez/view/PresetFrame.yaml @@ -24,6 +24,11 @@ views: geometry.margin.left: 15 text: Start +onPress: ~start() + - $type: hw.view.form.ButtonView + style: button.active + geometry.margin.left: 15 + text: Network + +onPress: ~start(true) - id: image $type: ru.m.puzzlez.view.common.PresetView geometry.stretch: true diff --git a/src/app/haxe/ru/m/puzzlez/view/StartFrame.hx b/src/app/haxe/ru/m/puzzlez/view/StartFrame.hx index 86f498e..3e297b4 100644 --- a/src/app/haxe/ru/m/puzzlez/view/StartFrame.hx +++ b/src/app/haxe/ru/m/puzzlez/view/StartFrame.hx @@ -1,5 +1,6 @@ package ru.m.puzzlez.view; +import ru.m.puzzlez.net.Network; import hw.view.data.DataView; import hw.view.form.ButtonView; import hw.view.frame.FrameSwitcher; @@ -26,6 +27,7 @@ import ru.m.update.Updater; @:provide var storage:ImageStorage; @:provide var switcher:FrameSwitcher; @:provide var gameStorage:GameStorage; + @:provide var network:Network; @:provide static var appUpdater:Updater; public function new() { @@ -75,7 +77,11 @@ import ru.m.update.Updater; switcher.change(ImageListFrame.ID, source); } - private function games(status:GameStatus):Void { + private function openGames(status:GameStatus):Void { switcher.change(ImageListFrame.ID, gameStorage.statusSource(status)); } + + private function openNetwork():Void { + switcher.change(ImageListFrame.ID, {title: 'Network', source: network}); + } } diff --git a/src/app/haxe/ru/m/puzzlez/view/StartFrame.yaml b/src/app/haxe/ru/m/puzzlez/view/StartFrame.yaml index f498e1c..e0b5d43 100644 --- a/src/app/haxe/ru/m/puzzlez/view/StartFrame.yaml +++ b/src/app/haxe/ru/m/puzzlez/view/StartFrame.yaml @@ -35,11 +35,15 @@ views: - id: load $type: hw.view.form.ButtonView text: Load - +onPress: ~games('started') + +onPress: ~openGames('started') - id: complete $type: hw.view.form.ButtonView text: Complete - +onPress: ~games('complete') + +onPress: ~openGames('complete') + - id: network + $type: hw.view.form.ButtonView + text: Network + +onPress: ~openNetwork() - $type: hw.view.SpriteView geometry.width: 100% - $type: hw.view.form.LabelView diff --git a/src/common/haxe/ru/m/IdUtil.hx b/src/common/haxe/ru/m/IdUtil.hx new file mode 100644 index 0000000..6c90e29 --- /dev/null +++ b/src/common/haxe/ru/m/IdUtil.hx @@ -0,0 +1,10 @@ +package ru.m; + +import com.hurlant.crypto.prng.Random; +import com.hurlant.crypto.extra.UUID; + +class IdUtil { + public static function generate():String { + return UUID.generateRandom(new Random()).toString().split("-").shift(); + } +} diff --git a/src/common/haxe/ru/m/puzzlez/core/GameState.hx b/src/common/haxe/ru/m/puzzlez/core/GameState.hx index 89e68d7..bf63087 100644 --- a/src/common/haxe/ru/m/puzzlez/core/GameState.hx +++ b/src/common/haxe/ru/m/puzzlez/core/GameState.hx @@ -7,7 +7,9 @@ enum abstract GameStatus(String) from String to String { } typedef GameState = { + var id:String; var status:GameStatus; var preset:GamePreset; var parts:Array; + @:optional var online:Bool; } diff --git a/src/common/haxe/ru/m/puzzlez/core/GameUtil.hx b/src/common/haxe/ru/m/puzzlez/core/GameUtil.hx index cdbd132..4bd121d 100644 --- a/src/common/haxe/ru/m/puzzlez/core/GameUtil.hx +++ b/src/common/haxe/ru/m/puzzlez/core/GameUtil.hx @@ -129,6 +129,7 @@ class GameUtil { } } return { + id: IdUtil.generate(), status: READY, preset: preset, parts: parts, diff --git a/src/common/haxe/ru/m/puzzlez/core/IGame.hx b/src/common/haxe/ru/m/puzzlez/core/IGame.hx index de99f5f..4b7d823 100644 --- a/src/common/haxe/ru/m/puzzlez/core/IGame.hx +++ b/src/common/haxe/ru/m/puzzlez/core/IGame.hx @@ -10,7 +10,5 @@ interface IGame { public function stop():Void; - public function shuffle():Void; - public function dispose():Void; } diff --git a/src/common/proto/core.proto b/src/common/proto/core.proto index f92a5a1..0eeff50 100644 --- a/src/common/proto/core.proto +++ b/src/common/proto/core.proto @@ -7,11 +7,29 @@ message UserProto { string name = 2; } +message PuzzlezPartProto { + +} + +message PuzzlezGridProto { + int32 width = 1; + int32 height = 2; +} + +message GamePresetProto { + string imageId = 1; + PuzzlezGridProto grid = 2; +} + +message GameStateProto { + string id = 1; + GamePresetProto preset = 2; + repeated PuzzlezPartProto parts = 3; +} + message GameProto { - int32 id = 1; - string imageId = 2; - string status = 3; - repeated UserProto users = 4; + GameStateProto state = 2; + repeated UserProto users = 3; } message GameEventProto { diff --git a/src/common/proto/pack.proto b/src/common/proto/pack.proto index ef5613d..9a7b756 100644 --- a/src/common/proto/pack.proto +++ b/src/common/proto/pack.proto @@ -26,7 +26,7 @@ message GameCreateRequest { } message GameJoinRequest { - int32 gameId = 1; + string gameId = 1; } message GameLeaveRequest {} @@ -57,7 +57,7 @@ message Request { LogoutRequest logout = 2; GameCreateRequest gameCreate = 10; - GameLeaveRequest gameJoin = 11; + GameJoinRequest gameJoin = 11; GameLeaveRequest gameLeave = 12; GameListRequest gameList = 20; diff --git a/src/server/haxe/ru/m/puzzlez/GameSession.hx b/src/server/haxe/ru/m/puzzlez/GameSession.hx index 6fa902c..6e982f9 100644 --- a/src/server/haxe/ru/m/puzzlez/GameSession.hx +++ b/src/server/haxe/ru/m/puzzlez/GameSession.hx @@ -27,18 +27,17 @@ class GameSession extends ProtoSession implements GameManager @:provide static var gameManager:IGameManager; public var user(default, null):UserProto; - public var gameId(default, null):Int; + public var gameId(default, null):String; private var subscribed:Bool; private var tag(get, never):String; private function get_tag():String { - return '[${id}|${user == null ? '-' : user.name}|${gameId == -1 ? '-' : Std.string(gameId)}]'; + return '[${id}|${user == null ? '-' : user.name}|${gameId == null ? '-' : gameId}]'; } public function new(socket:Socket) { super(socket, Request); - gameId = -1; } private function sendError(code:Int, message:String):Void { @@ -60,7 +59,7 @@ class GameSession extends ProtoSession implements GameManager } private function logout(leave:Bool = true):Void { - gameId = -1; + gameId = null; gameManager.disconnect(this); if (user != null && leave) { gameManager.leave(user); @@ -68,13 +67,10 @@ class GameSession extends ProtoSession implements GameManager } } - private function join(gameId:Int, restore:Bool):Void { + private function join(gameId:String):Void { this.gameId = gameId; gameManager.join(gameId, user); var game = gameManager.gamesById[gameId]; - if (restore) { - // ToDo: restore - } } override private function onRequest(request:Request):Void { @@ -86,41 +82,35 @@ class GameSession extends ProtoSession implements GameManager // login if (request.hasLogin()) { user = new UserProto() - .setUuid(request.login.uuid != null ? request.login.uuid : UUID.generateRandom(new Random()).toString()) - .setName(request.login.name); + .setUuid(request.login.user.uuid != null ? request.login.user.uuid : UUID.generateRandom(new Random()).toString()) + .setName(request.login.user.name); gameManager.connect(this); send(new Response().setLogin(new LoginResponse().setUser(user))); if (gameManager.gamesByUser.exists(user.uuid)) { - join(gameManager.gamesByUser[user.uuid].id, false); + join(gameManager.gamesByUser[user.uuid].id); } // logout } else if (request.hasLogout()) { logout(); send(new Response().setLogout(new LogoutResponse())); - // room - } else if (request.hasRoom()) { - if (request.room.hasCreate()) { - var game = gameManager.create(user); - gameId = game.id; - send(new Response().setRoom(new RoomResponse().setRoom(game.room))); - } else if (request.room.hasJoin()) { - join(request.room.join.gameId, request.room.join.restore); - } else if (request.room.hasLeave()) { - gameManager.leave(user); - } else if (request.room.hasSlot()) { - gameManager.slot(user, request.room.slot.slot); - } else if (request.room.hasStart()) { - gameManager.start(gameId); - } - // room list - } else if (request.hasRoomList()) { - subscribed = request.roomList.subscribe; + // game + } else if (request.hasGameCreate()) { + var game = gameManager.create(user, request.gameCreate.imageId); + gameId = game.id; + send(new Response().setGame(new GameResponse().setGame(game.proto))); + } else if (request.hasGameJoin()) { + join(request.gameJoin.gameId); + } else if (request.hasGameLeave()) { + gameManager.leave(user); + // game list + } else if (request.hasGameList()) { + subscribed = request.gameList.subscribe; if (subscribed) { - send(new Response().setRoomList(listGame())); + send(new Response().setGameList(listGame())); } } else if (request.hasGameEvent()) { if (gameManager.gamesById.exists(gameId)) { - var event:GameEvent = Unserializer.run(request.gameEvent.event.event); + var events:Array = cast request.gameEvent.events.map(item -> Unserializer.run(item.event)); // ToDo: emit event ///gameManager.gamesById[gameId].gameEventSignal.emit(event); } @@ -148,7 +138,7 @@ class GameSession extends ProtoSession implements GameManager switch change { case LEAVE(user): if (user.uuid == this.user.uuid) { - gameId = -1; + gameId = null; send(new Response().setGame(new GameResponse())); return; } @@ -163,7 +153,7 @@ class GameSession extends ProtoSession implements GameManager public function onDelete(game:ServerGame):Void { if (gameId == game.id) { - gameId = -1; + gameId = null; send(new Response().setGame(new GameResponse())); } if (subscribed) { diff --git a/src/server/haxe/ru/m/puzzlez/game/GameManager.hx b/src/server/haxe/ru/m/puzzlez/game/GameManager.hx index b7b1134..bd1a4c0 100644 --- a/src/server/haxe/ru/m/puzzlez/game/GameManager.hx +++ b/src/server/haxe/ru/m/puzzlez/game/GameManager.hx @@ -1,5 +1,8 @@ package ru.m.puzzlez.game; +import ru.m.puzzlez.proto.core.GamePresetProto; +import ru.m.puzzlez.proto.core.GameStateProto; +import ru.m.puzzlez.core.GameState; import ru.m.puzzlez.core.Id; import ru.m.puzzlez.core.GameEvent; import ru.m.puzzlez.game.IGameManager; @@ -34,24 +37,21 @@ class _GameListener implements GameListener { @:dispatcher(GameManagerListener) class GameManager implements IGameManager { public var games(default, null):Array; - public var gamesById(default, null):Map; + public var gamesById(default, null):Map; public var gamesByUser(default, null):Map; - private var counter:Int; - public function new() { - counter = 0; games = []; gamesById = new Map(); gamesByUser = new Map(); } public function create(user:UserProto, imageId:ImageId):ServerGame { - if (gamesByCreator.exists(user.uuid)) { - delete(gamesByCreator[user.uuid].id); - } - var gameProto = new GameProto().setId(++counter).setImageId(imageId); - gameProto.users.push(user); + var gameProto = new GameProto().setState( + new GameStateProto() + .setId(IdUtil.generate()) + .setPreset(new GamePresetProto().setImageId(imageId)) + ); var game = new ServerGame(gameProto); games.push(game); gamesById[game.id] = game; @@ -60,7 +60,7 @@ class _GameListener implements GameListener { return game; } - public function join(gameId:Int, user:UserProto):Void { + public function join(gameId:String, user:UserProto):Void { if (gamesById.exists(gameId)) { var game = gamesById[gameId]; game.join(user); @@ -69,7 +69,7 @@ class _GameListener implements GameListener { } } - public function delete(gameId:Int):Void { + public function delete(gameId:String):Void { if (gamesById.exists(gameId)) { var game = gamesById[gameId]; games.remove(game); @@ -87,7 +87,7 @@ class _GameListener implements GameListener { } } - public function start(gameId:Int):Void { + public function start(gameId:String):Void { if (gamesById.exists(gameId)) { var game:ServerGame = gamesById[gameId]; changeSignal.emit(game, START); diff --git a/src/server/haxe/ru/m/puzzlez/game/IGameManager.hx b/src/server/haxe/ru/m/puzzlez/game/IGameManager.hx index 17481b1..70c1a0a 100644 --- a/src/server/haxe/ru/m/puzzlez/game/IGameManager.hx +++ b/src/server/haxe/ru/m/puzzlez/game/IGameManager.hx @@ -20,8 +20,7 @@ interface GameManagerListener { @:provide(GameManager) interface IGameManager { public var games(default, null):Array; - public var gamesById(default, null):Map; - public var gamesByCreator(default, null):Map; + public var gamesById(default, null):Map; public var gamesByUser(default, null):Map; private var createSignal(default, null):Signal; @@ -35,8 +34,8 @@ interface GameManagerListener { public function disconnect(listener:GameManagerListener):Void; public function create(user:UserProto, imageId:ImageId):ServerGame; - public function delete(gameId:Int):Void; - public function join(gameId:Int, user:UserProto):Void; + public function delete(gameId:String):Void; + public function join(gameId:String, user:UserProto):Void; public function leave(user:UserProto):Void; - public function start(gameId:Int):Void; + public function start(gameId:String):Void; } diff --git a/src/server/haxe/ru/m/puzzlez/game/ServerGame.hx b/src/server/haxe/ru/m/puzzlez/game/ServerGame.hx index 4ef6a64..2efaf91 100644 --- a/src/server/haxe/ru/m/puzzlez/game/ServerGame.hx +++ b/src/server/haxe/ru/m/puzzlez/game/ServerGame.hx @@ -1,5 +1,6 @@ package ru.m.puzzlez.game; +import ru.m.puzzlez.core.GameUtil; import haxe.Timer; import ru.m.puzzlez.core.Game; import ru.m.puzzlez.proto.core.GameProto; @@ -7,17 +8,19 @@ import ru.m.puzzlez.proto.core.UserProto; @:dispatcher(GameListener) class ServerGame extends Game { - public var id(get, null):Int; + public var id(get, null):String; public var proto(default, default):GameProto; private var timer:Timer; public function new(proto:GameProto) { + // ToDo: + super(GameUtil.buildState(GameUtil.buildPreset(proto.state.preset.imageId))); this.proto = proto; } - private inline function get_id():Int { - return proto.id; + private inline function get_id():String { + return proto.state.id; } public function contains(user:UserProto):Bool {