[update] big update

This commit is contained in:
2020-02-18 16:58:54 +03:00
parent 6550975a4e
commit ec259bb9e2
19 changed files with 367 additions and 112 deletions

View File

@@ -1,6 +1,6 @@
{
"name": "puzzlez",
"version": "0.3.1",
"version": "0.3.2",
"private": true,
"devDependencies": {
"dateformat": "^3.0.3",

44
src/haxe/ru/m/Device.hx Normal file
View File

@@ -0,0 +1,44 @@
package ru.m;
@:enum abstract Platform(String) from String to String {
var ANDROID = "android";
var LINUX = "linux";
var WINDOWS = "windows";
}
class Device {
public static var platform(get, null):Platform;
private static function get_platform():Platform {
#if android
return ANDROID;
#elseif linux
return LINUX;
#elseif windows
return WINDOWS;
#else
return null;
#end
}
private static var MOBILES(default, never):Array<String> = [
"Android", "webOS", "iPhone", "iPad", "iPod", "BlackBerry", "Windows Phone",
];
public static function isMobile():Bool {
#if android
return true;
#elseif js
var userAgent = js.Browser.navigator.userAgent;
for (mobile in MOBILES) {
if (userAgent.indexOf(mobile) > -1) {
return true;
}
}
return false;
#else
return false;
#end
}
}

View File

@@ -5,14 +5,18 @@ import haxework.log.TraceLogger;
import ru.m.puzzlez.storage.GameStorage;
import ru.m.puzzlez.storage.ImageStorage;
import ru.m.puzzlez.view.PuzzlezAppView;
import ru.m.update.Updater;
class PuzzlezApp extends App {
@:provide static var updater:Updater;
public static function main() {
// ToDo: fix @:provide macro
GameStorage;
ImageStorage;
L.push(new TraceLogger());
updater = new Updater(Const.VERSION, "https://shmyga.ru/repo/puzzlez/packages.json");
var app = new PuzzlezApp(new PuzzlezTheme(), openfl.Assets.getBitmapData("resources/icon.png"));
var view = new PuzzlezAppView();
app.start(view);

View File

@@ -3,9 +3,10 @@ package ru.m.puzzlez.core;
import haxework.geom.Point;
import haxework.geom.Rectangle;
import ru.m.puzzlez.core.BoundType;
import ru.m.puzzlez.core.GameState.GameStatus;
import ru.m.puzzlez.core.GameState;
import ru.m.puzzlez.core.Id;
import ru.m.puzzlez.core.Part;
import ru.m.puzzlez.core.PartLocation;
import ru.m.puzzlez.core.Side;
class BoundsMap {
@@ -66,11 +67,13 @@ class BoundsMap {
class GameUtil {
private static function normilizeSize(size:Int, maxValue:Int = 8):Int {
private static inline var MAX_SIZE = 20;
private static function normilizeSize(size:Int, maxValue:Int = MAX_SIZE):Int {
return Math.isNaN(size) ? maxValue : size < 1 ? 1 : size > maxValue ? maxValue : size;
}
public static function buildPreset(imageId:ImageId, width:Int = 8, height:Int = 8):GamePreset {
public static function buildPreset(imageId:ImageId, width:Int = 8, height:Int = MAX_SIZE):GamePreset {
width = normilizeSize(width);
height = normilizeSize(height);
var offsetX = 500;
@@ -119,7 +122,7 @@ class GameUtil {
id: id,
gridX: x,
gridY: y,
location: PartLocation.TABLE(position),
location: TABLE(position),
bounds: bounds,
rect: new Rectangle(0, 0, partWidth, partHeight),
});
@@ -136,7 +139,7 @@ class GameUtil {
var complete = 0;
for (part in state.parts) {
switch part.location {
case PartLocation.IMAGE: complete++;
case IMAGE: complete++;
case _:
}
}

View File

@@ -1,5 +1,6 @@
package ru.m.puzzlez.render;
import ru.m.puzzlez.render.RenderUtil;
import flash.display.BitmapData;
import haxe.Timer;
import promhx.PublicStream;
@@ -8,7 +9,7 @@ import ru.m.puzzlez.core.Part;
typedef Result = {
var part:Part;
var image:BitmapData;
var image:PartImage;
}
class ImagePartBuilder {
@@ -25,8 +26,8 @@ class ImagePartBuilder {
return;
}
var part = parts[i];
var partImage = RenderUtil.cropImagePart(image, part);
stream.update({part: part, image: partImage});
var image = RenderUtil.cropImagePart(image, part);
stream.update({part: part, image: image});
}
Timer.delay(() -> buildPart(index + count, count, parts, stream), 0);
}

View File

@@ -1,11 +1,11 @@
package ru.m.puzzlez.render;
import flash.display.Bitmap;
import flash.display.BitmapData;
import flash.display.PixelSnapping;
import flash.display.Sprite;
import haxework.geom.Point;
import ru.m.puzzlez.core.Part;
import ru.m.puzzlez.render.RenderUtil;
class PartView extends Sprite {
@@ -20,9 +20,9 @@ class PartView extends Sprite {
return position;
}
public var image(default, set):BitmapData;
public var image(default, set):PartImage;
private function set_image(value:BitmapData):BitmapData {
private function set_image(value:PartImage):PartImage {
image = value;
redraw();
refresh();
@@ -44,14 +44,15 @@ class PartView extends Sprite {
private function refresh():Void {
if (position != null && image != null) {
x = position.x - (image.width - size.x) / 2;
y = position.y - (image.height - size.y) / 2;
x = position.x - (image.borderedImage.width - size.x) / 2;
y = position.y - (image.borderedImage.height - size.y) / 2;
}
}
public function complete():Void {
position = target;
completed = true;
redraw();
}
public static function factory(part:Part):PartView {
@@ -62,6 +63,10 @@ class PartView extends Sprite {
class SpritePartView extends PartView {
override private function redraw():Void {
if (image == null) {
return;
}
var image = completed ? image.borderedImage : image.shadedImage;
graphics.clear();
graphics.beginBitmapFill(image, null, false, true);
graphics.drawRect(0, 0, image.width, image.height);
@@ -79,6 +84,6 @@ class BitmapPartView extends PartView {
}
override private function redraw():Void {
bitmap.bitmapData = image;
bitmap.bitmapData = completed ? image.borderedImage : image.shadedImage;
}
}

View File

@@ -1,6 +1,5 @@
package ru.m.puzzlez.render;
import haxework.geom.Point;
import flash.display.BitmapData;
import flash.display.PNGEncoderOptions;
import flash.display.Sprite;
@@ -9,12 +8,14 @@ import flash.geom.Point as FlashPoint;
import flash.geom.Rectangle;
import flash.net.FileReference;
import flash.utils.ByteArray;
import haxework.geom.Point;
import haxework.signal.Signal;
import haxework.view.popup.AlertView;
import haxework.view.SpriteView;
import ru.m.puzzlez.core.GameEvent;
import ru.m.puzzlez.core.GameState;
import ru.m.puzzlez.core.PartLocation;
import ru.m.puzzlez.render.ImagePartBuilder;
import ru.m.puzzlez.storage.ImageStorage;
class Render extends SpriteView implements IRender {
@@ -110,7 +111,7 @@ class Render extends SpriteView implements IRender {
this.image = RenderUtil.cropImage(image, state.preset.imageRect);
var builder = new ImagePartBuilder(this.image);
var i = 0;
builder.build(state.parts).then(function(result) {
builder.build(state.parts).then((result:Result) -> {
parts[result.part.id].image = result.image;
progress.setProgress(++i, state.parts.length);
if (i >= state.parts.length - 1) {
@@ -166,7 +167,7 @@ class Render extends SpriteView implements IRender {
private function save(part:PartView):Void {
var file = new FileReference();
var image = part.image;
var image = part.image.shadedImage;
var data = new ByteArray();
image.encode(new Rectangle(0, 0, image.width, image.height), new PNGEncoderOptions(), data);
file.save(data, "icon.png");

View File

@@ -1,17 +1,40 @@
package ru.m.puzzlez.render;
import ru.m.draw.DrawPath;
import flash.display.BitmapData;
import flash.display.Shape;
import flash.geom.Matrix;
import haxework.color.Color;
import haxework.geom.Point;
import haxework.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;
typedef DrawSetting = {
var offset:Point;
var color:Color;
var opacity:Float;
}
typedef PartImage = {
var borderedImage:BitmapData;
var shadedImage:BitmapData;
}
class RenderUtil {
private static var builder:IPartBuilder = new ClassicPartBuilder();
public static var shadowSettings(default, null):Array<DrawSetting> = [
{offset: new Point(-2, -2), color: 0x000000, opacity: 0.4},
{offset: new Point(2, 2), color: 0xffffff, opacity: 0.4},
];
public static var borderSettings(default, null):Array<DrawSetting> = [
{offset: new Point(-1, -1), color: 0x555555, opacity: 0.4},
{offset: new Point(1, 1), color: 0xcccccc, opacity: 0.4},
];
public static var builder(default, null):IPartBuilder = new ClassicPartBuilder();
public static function cropImage(source:BitmapData, rect:Rectangle):BitmapData {
var image = new BitmapData(Std.int(rect.width), Std.int(rect.height));
@@ -37,17 +60,14 @@ class RenderUtil {
return {rect:rect, drawRect:drawRect};
}
private static function drawShadow(source:BitmapData, path:DrawPath):BitmapData {
var shadow = 2;
var opacity = 0.4;
private static function drawShadow(source:BitmapData, path:DrawPath, values:Array<DrawSetting>):BitmapData {
var canvas = new Shape();
canvas.cacheAsBitmap = true;
canvas.graphics.beginFill(0x000000, opacity);
path.move(-shadow, -shadow).draw(canvas.graphics);
canvas.graphics.endFill();
canvas.graphics.beginFill(0xffffff, opacity);
path.move(shadow, shadow).draw(canvas.graphics);
canvas.graphics.endFill();
for (value in values) {
canvas.graphics.beginFill(value.color, value.opacity);
path.move(value.offset.x, value.offset.y).draw(canvas.graphics);
canvas.graphics.endFill();
}
canvas.graphics.beginBitmapFill(source, null, false, true);
canvas.graphics.drawRect(0, 0, source.width, source.height);
canvas.graphics.endFill();
@@ -56,7 +76,23 @@ class RenderUtil {
return image;
}
public static function cropImagePart(source:BitmapData, part:Part):BitmapData {
private static function drawBorder(source:BitmapData, path:DrawPath, values:Array<DrawSetting>):BitmapData {
var canvas = new Shape();
canvas.cacheAsBitmap = true;
for (value in values) {
canvas.graphics.lineStyle(2, value.color, value.opacity);
path.move(value.offset.x, value.offset.y).draw(canvas.graphics);
canvas.graphics.lineStyle();
}
canvas.graphics.beginBitmapFill(source, null, false, true);
canvas.graphics.drawRect(0, 0, source.width, source.height);
canvas.graphics.endFill();
var image = new BitmapData(source.width, source.height, true, 0x00000000);
image.draw(canvas, null, null, null, null, true);
return image;
}
public static function cropImagePart(source:BitmapData, part:Part, completed:Bool = false):PartImage {
var geometry = buildPartGeometry(part);
var path = builder.build(geometry.drawRect, part.bounds);
var canvas:Shape = new Shape();
@@ -69,7 +105,9 @@ class RenderUtil {
canvas.graphics.endFill();
var image = new BitmapData(Std.int(geometry.rect.width), Std.int(geometry.rect.height), true, 0x00000000);
image.draw(canvas, null, null, null, null, true);
return drawShadow(image, path);
var shadedImage = drawShadow(image, path, shadowSettings);
var borderedImage = drawBorder(image, path, borderSettings);
return {borderedImage: borderedImage, shadedImage: shadedImage};
}
public static function containRectangle(source:Rectangle, target:Rectangle):Rectangle {

View File

@@ -10,8 +10,8 @@ class BasePartBuilder implements IPartBuilder {
public function new() {
}
private function createAngle(path:DrawPath, x:Float, y:Float):Void {
path.commands.push(LINE_TO(x, y));
private function createAngle(path:DrawPath, x:Float, y:Float, first: Bool = false):Void {
path.commands.push(first ? MOVE_TO(x, y) : LINE_TO(x, y));
}
private function createBound(path:DrawPath, fromX:Float, fromY:Float, toX:Float, toY:Float, bound:PartBound):Void {
@@ -19,7 +19,7 @@ class BasePartBuilder implements IPartBuilder {
public function build(rect:Rectangle, bounds:PartBounds):DrawPath {
var path = new DrawPath();
createAngle(path, rect.left, rect.top);
createAngle(path, rect.left, rect.top, true);
createBound(path, rect.left, rect.top, rect.right, rect.top, bounds.top);
createAngle(path, rect.right, rect.top);
createBound(path, rect.right, rect.top, rect.right, rect.bottom, bounds.right);

View File

@@ -44,7 +44,10 @@ import ru.m.puzzlez.core.Id;
}
public function delete(imageId:ImageId):Void {
Reflect.deleteField(statusData.data, imageId);
var gameData = SharedObject.getLocal('${path}/${imageId}');
gameData.clear();
var data:DynamicAccess<GameStatus> = statusData.data;
data.remove(imageId);
statusData.flush();
}

View File

@@ -1,5 +1,6 @@
package ru.m.puzzlez.view;
import haxe.Timer;
import haxework.view.frame.FrameSwitcher;
import haxework.view.frame.FrameView;
import ru.m.puzzlez.core.Game;
@@ -17,7 +18,7 @@ import ru.m.puzzlez.storage.GameStorage;
@:provide var switcher:FrameSwitcher;
@:provide var storage:GameStorage;
private var toSave:Bool;
private var saveTimer:Timer;
public function new() {
super(ID);
@@ -33,6 +34,7 @@ import ru.m.puzzlez.storage.GameStorage;
}
override public function onHide():Void {
save();
if (game != null) {
render.signal.disconnect(game.signal.emit);
game.stop();
@@ -41,12 +43,28 @@ import ru.m.puzzlez.storage.GameStorage;
}
}
private function toSave():Void {
if (saveTimer != null) {
saveTimer = Timer.delay(save, 500);
}
}
private function save():Void {
if (saveTimer != null) {
saveTimer.stop();
saveTimer = null;
}
if (game != null) {
storage.save(game.state);
}
}
private function onGameEvent(event:GameEvent):Void {
switch event {
case START(state):
storage.save(state);
toSave();
case ACTION(PART_PUT(_, _)):
storage.save(game.state);
toSave();
case _:
}
}

View File

@@ -1,8 +1,10 @@
package ru.m.puzzlez.view;
import haxework.view.form.InputView;
import haxework.geom.IntPoint;
import haxework.view.data.DataView;
import haxework.view.form.ToggleButtonView;
import haxework.view.frame.FrameSwitcher;
import haxework.view.frame.FrameView;
import haxework.view.list.ScrollBarView;
import ru.m.puzzlez.core.GameUtil;
import ru.m.puzzlez.core.Id;
import ru.m.puzzlez.storage.ImageStorage;
@@ -11,9 +13,7 @@ import ru.m.puzzlez.storage.ImageStorage;
public static var ID = "preset";
@:view("image") var imageView:PresetView;
@:view("scroll") var scrollView:ScrollBarView;
@:view("width") var widthView:InputView;
@:view("height") var heightView:InputView;
@:view("sizes") var sizesView:DataView<IntPoint, ToggleButtonView>;
@:provide var imageStorage:ImageStorage;
@:provide var switcher:FrameSwitcher;
@@ -22,32 +22,38 @@ import ru.m.puzzlez.storage.ImageStorage;
public function new() {
super(ID);
widthView.text = "8";
heightView.text = "8";
scrollView.position = 0.8;
widthView.update();
heightView.update();
sizesView.data = [
new IntPoint(3, 2),
new IntPoint(4, 3),
new IntPoint(5, 4),
new IntPoint(6, 5),
new IntPoint(7, 6),
new IntPoint(8, 7),
new IntPoint(10, 8),
];
}
private function factory(index:Int, size:IntPoint):ToggleButtonView {
var result = new ToggleButtonView();
result.text = '${size.x}x${size.y}';
return result;
}
private function selectSize(size:IntPoint):Void {
imageView.state = GameUtil.buildState(GameUtil.buildPreset(imageId, size.x, size.y));
for (i in 0...sizesView.dataViews.length) {
sizesView.dataViews[i].on = size == sizesView.data[i];
}
}
override public function onShow(data:ImageId):Void {
super.onShow(data);
imageId = data;
updatePreset();
}
private function updateGrid(value:Float):Void {
var size = 2 + Std.int(value * 8);
widthView.text = Std.string(size);
heightView.text = Std.string(size);
imageView.preset = GameUtil.buildPreset(imageId, size, size);
}
private function updatePreset():Void {
imageView.preset = GameUtil.buildPreset(imageId, Std.parseInt(widthView.text), Std.parseInt(heightView.text));
selectSize(sizesView.data[sizesView.data.length - 1]);
}
private function start():Void {
switcher.change(GameFrame.ID, GameUtil.buildState(imageView.preset));
switcher.change(GameFrame.ID, imageView.state);
}
private function back():Void {

View File

@@ -1,32 +1,25 @@
---
style: frame
layout.margin: 10
views:
- $type: haxework.view.group.HGroupView
geometry.width: 100%
layout.hAlign: center
layout.vAlign: middle
views:
- id: width
$type: haxework.view.form.InputView
geometry.width: 100
+onChange: ~updatePreset()
- $type: haxework.view.form.LabelView
text: x
- id: height
$type: haxework.view.form.InputView
geometry.width: 100
+onChange: ~updatePreset()
- $type: haxework.view.form.ButtonView
geometry.margin.left: 15
text: Start
+onPress: ~start()
- id: scroll
$type: haxework.view.list.HScrollBarView
- id: sizes
$type: haxework.view.data.DataView
geometry.width: 100%
geometry.height: 20
ratio: 0.2
position: 0.8
+onScroll: ~updateGrid
layout:
$type: haxework.view.layout.TailLayout
hAlign: center
margin: 5
factory: ~factory
+onDataSelect: ~selectSize
- id: image
$type: ru.m.puzzlez.view.PresetView
geometry.stretch: true

View File

@@ -5,7 +5,7 @@ import flash.display.Graphics;
import flash.display.Shape;
import flash.geom.Matrix;
import haxework.view.group.GroupView;
import ru.m.puzzlez.core.GamePreset;
import ru.m.puzzlez.core.GameState;
import ru.m.puzzlez.render.RenderUtil;
import ru.m.puzzlez.storage.ImageStorage;
@@ -20,23 +20,23 @@ class PresetView extends GroupView {
private function set_scale(value:Float):Float {
var result = table.scaleX = table.scaleY = value;
table.x = (width - preset.tableRect.width * value) / 2;
table.y = (height - preset.tableRect.height * value) / 2;
table.x = (width - state.preset.tableRect.width * value) / 2;
table.y = (height - state.preset.tableRect.height * value) / 2;
return result;
}
public var preset(default, set):GamePreset;
public var state(default, set):GameState;
private function set_preset(value:GamePreset) {
preset = value;
private function set_state(value:GameState):GameState {
state = value;
this.image = null;
table.graphics.clear();
loading.promise = imageStorage.resolve(preset.imageId).then(image -> {
this.image = RenderUtil.cropImage(image, preset.imageRect);
loading.promise = imageStorage.resolve(state.preset.imageId).then(image -> {
this.image = RenderUtil.cropImage(image, state.preset.imageRect);
toRedraw();
toUpdate();
});
return preset;
return state;
}
private var loading:LoadingWrapper;
@@ -52,9 +52,10 @@ class PresetView extends GroupView {
private var image:BitmapData;
override public function redraw():Void {
if (preset == null || image == null) {
if (state == null || image == null) {
return;
}
var preset = state.preset;
var partWidth = preset.imageRect.width / preset.grid.width;
var partHeight = preset.imageRect.height / preset.grid.height;
var graphics:Graphics = table.graphics;
@@ -64,32 +65,24 @@ class PresetView extends GroupView {
graphics.beginBitmapFill(image, matrix, false, true);
graphics.drawRect(preset.imageRect.x, preset.imageRect.y, preset.imageRect.width, preset.imageRect.height);
graphics.endFill();
graphics.lineStyle(1, 0x555555);
for (x in 0...preset.grid.width + 1) {
graphics.moveTo(preset.imageRect.x + x * partWidth, preset.imageRect.y);
graphics.lineTo(preset.imageRect.x + x * partWidth, preset.imageRect.y + preset.imageRect.height);
for (part in state.parts) {
var rect = part.rect.clone();
rect.x = preset.imageRect.x + part.gridX * part.rect.width;
rect.y = preset.imageRect.y + part.gridY * part.rect.height;
var path = RenderUtil.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);
graphics.lineStyle();
}
}
for (y in 0...preset.grid.height + 1) {
graphics.moveTo(preset.imageRect.x, preset.imageRect.y + y * partHeight);
graphics.lineTo(preset.imageRect.x + preset.imageRect.width, preset.imageRect.y + y * partHeight);
}
graphics.lineStyle(1, 0xcccccc);
var offset = 1;
for (x in 0...preset.grid.width + 1) {
graphics.moveTo(offset + preset.imageRect.x + x * partWidth, preset.imageRect.y);
graphics.lineTo(offset + preset.imageRect.x + x * partWidth, preset.imageRect.y + preset.imageRect.height);
}
for (y in 0...preset.grid.height + 1) {
graphics.moveTo(preset.imageRect.x, offset + preset.imageRect.y + y * partHeight);
graphics.lineTo(preset.imageRect.x + preset.imageRect.width, offset + preset.imageRect.y + y * partHeight);
}
graphics.lineStyle();
}
override public function update():Void {
super.update();
if (preset != null) {
scale = Math.min(width / preset.tableRect.width, height / preset.tableRect.height);
if (state != null) {
scale = Math.min(width / state.preset.tableRect.width, height / state.preset.tableRect.height);
}
}
}

View File

@@ -1,5 +1,6 @@
package ru.m.puzzlez.view;
import ru.m.update.Updater;
import haxework.view.data.DataView;
import haxework.view.form.ButtonView;
import haxework.view.frame.FrameSwitcher;
@@ -18,10 +19,12 @@ import ru.m.puzzlez.storage.ImageStorage;
@:view var sources:DataView<ImageListSource<Dynamic>, ButtonView>;
@:view("load") var loadButton:ButtonView;
@:view("complete") var completeButton:ButtonView;
@:view("update") var updateButton:ButtonView;
@:provide var storage:ImageStorage;
@:provide var switcher:FrameSwitcher;
@:provide var gameStorage:GameStorage;
@:provide static var appUpdater:Updater;
public function new() {
super(ID);
@@ -45,6 +48,12 @@ import ru.m.puzzlez.storage.ImageStorage;
override public function onShow(data:Dynamic):Void {
refresh();
appUpdater.check().then((info:Null<PackageInfo>) -> {
if (info != null) {
updateButton.visible = true;
updateButton.text = 'Update ${info.version}';
}
});
}
private function sourceViewFactory(index:Int, source:ImageListSource<Dynamic>):ButtonView {

View File

@@ -38,6 +38,11 @@ views:
text: Clean
+onPress: ~clean()
visible: false
- id: update
$type: haxework.view.form.ButtonView
style: button.active
+onPress: ~appUpdater.download()
visible: false
- $type: haxework.view.form.LabelView
text: $r:text:version
geometry.position: absolute

View File

@@ -0,0 +1,83 @@
package ru.m.update;
import haxework.net.JsonLoader;
import openfl.Lib;
import openfl.net.URLRequest;
import promhx.Promise;
import ru.m.Device;
import ru.m.update.Version;
@:enum abstract PackageType(String) from String to String {
var APK = "apk";
var DEB = "deb";
var EXE = "exe";
var ARCHIVE = "archive";
}
typedef PackageInfo = {
var platform:Platform;
var type:PackageType;
var path:String;
var filename:String;
var url:String;
var version:String;
}
typedef PackagesBundle = {
var name:String;
var version:String;
var packages:Array<PackageInfo>;
}
class Updater {
private static inline var TAG = "Update";
public var type(get, null):PackageType;
public var bundle(get, null):Promise<PackagesBundle>;
private function get_bundle():Promise<PackagesBundle> {
if (bundle == null) {
bundle = new JsonLoader().GET(url);
}
return bundle;
}
private var url:String;
private var version:Version;
public function new(version:String, url:String) {
this.url = url;
this.version = version;
}
private function get_type():PackageType {
return switch Device.platform {
case ANDROID: APK;
case LINUX: DEB;
case WINDOWS: EXE;
case _: null;
}
}
public function check():Promise<Null<PackageInfo>> {
return bundle.then((bundle:PackagesBundle) -> Lambda.find(bundle.packages, item -> (
item.platform == Device.platform &&
item.type == type &&
version < Version.fromString(item.version)
)));
}
public function download():Promise<Bool> {
return bundle.then((bundle:PackagesBundle) -> {
for (item in bundle.packages) {
if (item.platform == Device.platform && item.type == type) {
L.i(TAG, 'download: ${item.url}');
Lib.getURL(new URLRequest(item.url));
return true;
}
}
return false;
});
}
}

View File

@@ -0,0 +1,52 @@
package ru.m.update;
abstract Version(Array<Int>) {
public function new(mayor:Int, minor:Int, patch:Int, snapshot:Bool = false) {
this = [
mayor,
minor,
patch,
snapshot ? -1 : 0,
];
}
@:arrayAccess public inline function get(key:Int) return this[key];
public function compare(other:Version):Int {
if (other == null) {
return 1;
}
for (i in 0...4) {
var d = this[i] - other[i];
if (d != 0) {
return d;
}
}
return 0;
}
@:op(A > B) static function gt(a:Version, b:Version):Bool return a.compare(b) > 0;
@:op(A == B) static function eq(a:Version, b:Version):Bool return a.compare(b) == 0;
@:op(A < B) static function lt(a:Version, b:Version):Bool return a.compare(b) < 0;
@:from public static function fromString(value:String):Version {
var r = ~/(\d+)\.(\d+)\.(\d+)(-SNAPSHOT)?/;
return if (r.match(value)) {
new Version(
Std.parseInt(r.matched(1)),
Std.parseInt(r.matched(2)),
Std.parseInt(r.matched(3)),
r.matched(4) != null
);
} else {
new Version(0, 0, 0);
}
}
@:to public function toString():String {
return '${this[0]}.${this[1]}.${this[2]}${this[3] < 0 ? "-SNAPSHOT" : ""}';
}
}

View File

@@ -1,6 +1,3 @@
* win event
* save game state
* load user images
* background settings
* grid settings
* preset frame improve
* parts groups