diff --git a/package.json b/package.json index 8af3038..ec70268 100644 --- a/package.json +++ b/package.json @@ -8,7 +8,7 @@ "gulp-add": "0.0.2", "gulp-clean": "^0.4.0", "gulp-cli": "^2.2.0", - "gulp-haxetool": "0.1.7", + "gulp-haxetool": "0.1.8", "yargs": "^13.2.4" }, "haxeDependencies": { diff --git a/src/app/haxe/ru/m/puzzlez/PuzzlezApp.hx b/src/app/haxe/ru/m/puzzlez/PuzzlezApp.hx index a64f630..f017dd6 100644 --- a/src/app/haxe/ru/m/puzzlez/PuzzlezApp.hx +++ b/src/app/haxe/ru/m/puzzlez/PuzzlezApp.hx @@ -3,6 +3,7 @@ package ru.m.puzzlez; import hw.app.App; import hw.app.Const; import hw.log.TraceLogger; +import ru.m.puzzlez.render.part.IPartBuilder; import ru.m.puzzlez.storage.GameStorage; import ru.m.puzzlez.storage.ImageStorage; import ru.m.puzzlez.storage.SettingsStorage; @@ -18,6 +19,7 @@ class PuzzlezApp { GameStorage; ImageStorage; SettingsStorage; + IPartBuilder; L.push(new TraceLogger()); updater = new Updater(Const.instance.VERSION, "https://shmyga.ru/repo/puzzlez/packages.json"); var app = new App(); diff --git a/src/app/haxe/ru/m/puzzlez/net/Network.hx b/src/app/haxe/ru/m/puzzlez/net/Network.hx index aa18ce5..00a2410 100644 --- a/src/app/haxe/ru/m/puzzlez/net/Network.hx +++ b/src/app/haxe/ru/m/puzzlez/net/Network.hx @@ -31,7 +31,7 @@ import ru.m.puzzlez.proto.pack.Response; connection = ConnectionFactory.buildClientConnection("127.0.0.1", 5000, Response); connection.handler.connect(onConnectionChange); connection.receiveHandler.connect(onReceivePacket); - connection.connect(); + connection.connect().catchError(_ -> {}); } public function login():Void { diff --git a/src/app/haxe/ru/m/puzzlez/render/CompleteView.hx b/src/app/haxe/ru/m/puzzlez/render/CompleteView.hx index a522ff6..43445fe 100644 --- a/src/app/haxe/ru/m/puzzlez/render/CompleteView.hx +++ b/src/app/haxe/ru/m/puzzlez/render/CompleteView.hx @@ -3,12 +3,15 @@ package ru.m.puzzlez.render; import flash.display.Shape; import flash.geom.Matrix; import ru.m.puzzlez.core.GamePreset; +import ru.m.puzzlez.render.part.IPartBuilder; class CompleteView extends Shape { public var parts:Array; public var preset:GamePreset; + @:provide static var builder:IPartBuilder; + public function new() { super(); parts = []; @@ -51,7 +54,7 @@ class CompleteView extends Shape { var rect = part.rect.clone(); rect.x = part.gridX * part.rect.width; rect.y = part.gridY * part.rect.height; - var path = RenderUtil.builder.build(rect, part.bounds); + var path = builder.build(rect, part.bounds); for (value in RenderUtil.borderSettings) { graphics.lineStyle(1, value.color, value.opacity); path.move(value.offset.x, value.offset.y).draw(graphics); diff --git a/src/app/haxe/ru/m/puzzlez/render/PartView.hx b/src/app/haxe/ru/m/puzzlez/render/PartView.hx index 519d713..3751998 100644 --- a/src/app/haxe/ru/m/puzzlez/render/PartView.hx +++ b/src/app/haxe/ru/m/puzzlez/render/PartView.hx @@ -6,7 +6,9 @@ import flash.display.PixelSnapping; import flash.display.Sprite; import hw.geom.Point; import ru.m.puzzlez.core.Part; +import ru.m.puzzlez.core.Id; import ru.m.puzzlez.render.RenderUtil; +import ru.m.puzzlez.render.part.IPartBuilder; class PartView extends Sprite { @@ -42,6 +44,16 @@ class PartView extends Sprite { public var size(default, null):Point; + public var playerId(default, set):Null; + + private function set_playerId(value:Null):Null { + if (playerId != value) { + playerId = value; + redraw(); + } + return playerId; + } + public function new(part:Part) { super(); this.id = part.id; @@ -63,6 +75,7 @@ class PartView extends Sprite { public function complete():Void { position = target; + playerId = null; completed = true; refresh(); redraw(); @@ -75,6 +88,8 @@ class PartView extends Sprite { class SpritePartView extends PartView { + @:provide static var builder:IPartBuilder; + override private function redraw():Void { if (image == null) { return; @@ -84,6 +99,15 @@ class SpritePartView extends PartView { graphics.beginBitmapFill(image, null, false, true); graphics.drawRect(0, 0, image.width, image.height); graphics.endFill(); + + if (playerId != null) { + var rect = part.rect.clone(); + rect.x += (image.width - size.x) / 2; + rect.y += (image.height - size.y) / 2; + var path = builder.build(rect, part.bounds); + graphics.lineStyle(4, 0xffff00, 0.3); + path.draw(graphics); + } } } diff --git a/src/app/haxe/ru/m/puzzlez/render/Render.hx b/src/app/haxe/ru/m/puzzlez/render/Render.hx index a4f2278..41a48a2 100644 --- a/src/app/haxe/ru/m/puzzlez/render/Render.hx +++ b/src/app/haxe/ru/m/puzzlez/render/Render.hx @@ -1,5 +1,7 @@ package ru.m.puzzlez.render; +import ru.m.puzzlez.core.Id; +import ru.m.puzzlez.net.Network; import flash.display.BitmapData; import flash.display.PNGEncoderOptions; import flash.display.Sprite; @@ -26,6 +28,13 @@ class Render extends SpriteView implements IRender { public var manager(default, null):RenderManager; @:provide static var settings:SettingsStorage; + @:provide static var network:Network; + + private var playerId(get, never):PlayerId; + + private function get_playerId():PlayerId { + return network.user.uuid; + } private function get_scale():Float { return tableView.scaleX; @@ -76,6 +85,11 @@ class Render extends SpriteView implements IRender { case CHANGE(PART_UPDATE(id, TABLE(point))): var part:PartView = parts[id]; part.position = point; + part.playerId = null; + case CHANGE(PART_UPDATE(id, HAND(playerId, point))): + var part:PartView = parts[id]; + part.position = point; + part.playerId = playerId; case CHANGE(PART_UPDATE(id, IMAGE)): var part:PartView = parts[id]; part.complete(); @@ -189,21 +203,21 @@ class Render extends SpriteView implements IRender { activePoint = RenderUtil.convertPoint(tableView.globalToLocal(point)); tableView.stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); tableView.stage.addEventListener(MouseEvent.MOUSE_UP, onMouseUp); - signal.emit(ACTION(PART_TAKE(activePart.id))); + signal.emit(ACTION(PART_TAKE(playerId, activePart.id))); } } private function onMouseMove(event:MouseEvent):Void { var newPoint:Point = RenderUtil.convertPoint(tableView.globalToLocal(new FlashPoint(event.stageX, event.stageY))); var partPosition = activePart.position.add(newPoint).subtract(activePoint); - signal.emit(ACTION(PART_MOVE(activePart.id, partPosition.clone()))); + signal.emit(ACTION(PART_MOVE(playerId, activePart.id, partPosition.clone()))); activePoint = newPoint; } private function onMouseUp(event:MouseEvent):Void { var newPoint:Point = RenderUtil.convertPoint(tableView.globalToLocal(new FlashPoint(event.stageX, event.stageY))); var partPosition = activePart.position.add(newPoint).subtract(activePoint); - signal.emit(ACTION(PART_PUT(activePart.id, partPosition.clone()))); + signal.emit(ACTION(PART_PUT(playerId, activePart.id, partPosition.clone()))); tableView.stage.removeEventListener(MouseEvent.MOUSE_MOVE, onMouseMove); tableView.stage.removeEventListener(MouseEvent.MOUSE_UP, onMouseUp); activePart = null; diff --git a/src/app/haxe/ru/m/puzzlez/render/RenderUtil.hx b/src/app/haxe/ru/m/puzzlez/render/RenderUtil.hx index b54ddc7..ccf559a 100644 --- a/src/app/haxe/ru/m/puzzlez/render/RenderUtil.hx +++ b/src/app/haxe/ru/m/puzzlez/render/RenderUtil.hx @@ -8,7 +8,6 @@ import hw.geom.Point; import hw.geom.Rectangle; import ru.m.draw.DrawPath; import ru.m.puzzlez.core.Part; -import ru.m.puzzlez.render.part.ClassicPartBuilder; import ru.m.puzzlez.render.part.IPartBuilder; import ru.m.puzzlez.render.part.PartMask; @@ -34,7 +33,7 @@ class RenderUtil { {offset: new Point(1, 1), color: 0xcccccc, opacity: 0.4}, ]; - public static var builder(default, null):IPartBuilder = new ClassicPartBuilder(); + @:provide static var builder:IPartBuilder; public static function cropImage(source:BitmapData, rect:Rectangle):BitmapData { var image = new BitmapData(Std.int(rect.width), Std.int(rect.height)); diff --git a/src/app/haxe/ru/m/puzzlez/render/part/IPartBuilder.hx b/src/app/haxe/ru/m/puzzlez/render/part/IPartBuilder.hx index c53a143..00a74bc 100644 --- a/src/app/haxe/ru/m/puzzlez/render/part/IPartBuilder.hx +++ b/src/app/haxe/ru/m/puzzlez/render/part/IPartBuilder.hx @@ -4,6 +4,6 @@ import hw.geom.Rectangle; import ru.m.draw.DrawPath; import ru.m.puzzlez.core.Part; -interface IPartBuilder { +@:provide(ClassicPartBuilder) interface IPartBuilder { public function build(rect:Rectangle, bound:PartBounds):DrawPath; } diff --git a/src/app/haxe/ru/m/puzzlez/view/common/PresetView.hx b/src/app/haxe/ru/m/puzzlez/view/common/PresetView.hx index d0a7dbf..3d573b1 100644 --- a/src/app/haxe/ru/m/puzzlez/view/common/PresetView.hx +++ b/src/app/haxe/ru/m/puzzlez/view/common/PresetView.hx @@ -1,15 +1,17 @@ package ru.m.puzzlez.view.common; -import flash.display.BitmapData; import flash.display.Graphics; +import flash.display.BitmapData; import flash.display.Shape; import hw.view.group.GroupView; import ru.m.puzzlez.core.GameState; +import ru.m.puzzlez.render.part.IPartBuilder; import ru.m.puzzlez.render.RenderUtil; import ru.m.puzzlez.storage.ImageStorage; class PresetView extends GroupView { @:provide var imageStorage:ImageStorage; + @:provide static var builder:IPartBuilder; public var scale(get, set):Float; @@ -67,7 +69,7 @@ class PresetView extends GroupView { var rect = part.rect.clone(); rect.x = part.gridX * part.rect.width; rect.y = part.gridY * part.rect.height; - var path = RenderUtil.builder.build(rect, part.bounds); + var path = builder.build(rect, part.bounds); for (value in RenderUtil.borderSettings) { graphics.lineStyle(1, value.color, value.opacity); path.move(value.offset.x, value.offset.y).draw(graphics); diff --git a/src/common/haxe/ru/m/puzzlez/core/Game.hx b/src/common/haxe/ru/m/puzzlez/core/Game.hx index 02cbe59..edfa170 100644 --- a/src/common/haxe/ru/m/puzzlez/core/Game.hx +++ b/src/common/haxe/ru/m/puzzlez/core/Game.hx @@ -64,25 +64,37 @@ class Game implements IGame { private function onGameEvent(event:GameEvent):Void { switch event { - case ACTION(PART_MOVE(id, point)): - var part = partsById[id]; - part.location = TABLE(point); - signal.emit(CHANGE(PART_UPDATE(id, part.location))); - case ACTION(PART_PUT(id, point)): - var part:Part = partsById[id]; + case ACTION(PART_TAKE(playerId, partId)): + var part = partsById[partId]; + switch part.location { + case TABLE(point): + part.location = HAND(playerId, point); + signal.emit(CHANGE(PART_UPDATE(partId, part.location))); + case _: + } + case ACTION(PART_MOVE(playerId, partId, point)): + var part = partsById[partId]; + switch part.location { + case HAND(currentPlayerId, _) if (currentPlayerId == playerId): + part.location = HAND(playerId, point); + signal.emit(CHANGE(PART_UPDATE(partId, part.location))); + case _: + } + case ACTION(PART_PUT(playerId, partId, point)): + var part:Part = partsById[partId]; var target:Point = state.preset.imageRect.position.clone(); target = target.add(new Point(part.gridX * part.rect.width, part.gridY * part.rect.height)); var d = distance(target, point); if (d < 70) { part.location = IMAGE; - signal.emit(CHANGE(PART_UPDATE(id, part.location))); + signal.emit(CHANGE(PART_UPDATE(partId, part.location))); if (checkIsComplete()) { state.status = COMPLETE; signal.emit(COMPLETE); } } else { part.location = TABLE(point); - signal.emit(CHANGE(PART_UPDATE(id, part.location))); + signal.emit(CHANGE(PART_UPDATE(partId, part.location))); } case _: } diff --git a/src/common/haxe/ru/m/puzzlez/core/GameEvent.hx b/src/common/haxe/ru/m/puzzlez/core/GameEvent.hx index 90165c4..b9f3509 100644 --- a/src/common/haxe/ru/m/puzzlez/core/GameEvent.hx +++ b/src/common/haxe/ru/m/puzzlez/core/GameEvent.hx @@ -1,11 +1,12 @@ package ru.m.puzzlez.core; +import ru.m.puzzlez.core.Id; import hw.geom.Point; enum GameAction { - PART_TAKE(id:Int); - PART_MOVE(id:Int, point:Point); - PART_PUT(id:Int, point:Point); + PART_TAKE(playerId:PlayerId, partId:PartId); + PART_MOVE(playerId:PlayerId, partId:PartId, point:Point); + PART_PUT(playerId:PlayerId, partId:PartId, point:Point); } enum GameChange { diff --git a/src/common/haxe/ru/m/puzzlez/core/Id.hx b/src/common/haxe/ru/m/puzzlez/core/Id.hx index e3260d3..c9d8f58 100644 --- a/src/common/haxe/ru/m/puzzlez/core/Id.hx +++ b/src/common/haxe/ru/m/puzzlez/core/Id.hx @@ -24,3 +24,7 @@ abstract ImageId({source:SourceId, id:String}) { return '${this.source}_${this.id}'; } } + +typedef PlayerId = String; + +typedef PartId = Int; diff --git a/src/common/haxe/ru/m/puzzlez/core/PartLocation.hx b/src/common/haxe/ru/m/puzzlez/core/PartLocation.hx index 8346347..58979f0 100644 --- a/src/common/haxe/ru/m/puzzlez/core/PartLocation.hx +++ b/src/common/haxe/ru/m/puzzlez/core/PartLocation.hx @@ -1,9 +1,10 @@ package ru.m.puzzlez.core; import hw.geom.Point; +import ru.m.puzzlez.core.Id; enum PartLocation { - //PANEL(index:Int); + HAND(playerId:PlayerId, point:Point); TABLE(point:Point); IMAGE; } diff --git a/src/server/haxe/ru/m/puzzlez/PuzzlezServer.hx b/src/server/haxe/ru/m/puzzlez/PuzzlezServer.hx index b4fdc43..686415a 100644 --- a/src/server/haxe/ru/m/puzzlez/PuzzlezServer.hx +++ b/src/server/haxe/ru/m/puzzlez/PuzzlezServer.hx @@ -28,7 +28,7 @@ class PuzzlezServer extends ThreadServer { } override public function readClientMessage(session:GameSession, buf:Bytes, pos:Int, len:Int): ClientMessage { - L.d(TAG, 'Client message: ${buf}'); + //L.d(TAG, 'Client message: ${buf}'); return {msg: buf.sub(pos, len), bytes: len}; } @@ -38,7 +38,6 @@ class PuzzlezServer extends ThreadServer { public static function main():Void { L.push(new TraceLogger()); - L.d(TAG, 'Running'); L.i(TAG, 'Build: ${CompilationOption.get("build")}'); var host:String = Sys.args().length > 0 ? Sys.args()[0] : "0.0.0.0"; var port:Int = Sys.args().length > 1 ? Std.parseInt(Sys.args()[1]) : 5000;