Skip to content

Instantly share code, notes, and snippets.

@jefvel
Last active January 6, 2021 00:45
Show Gist options
  • Save jefvel/6a152077bd8f441d093e130f796c9166 to your computer and use it in GitHub Desktop.
Save jefvel/6a152077bd8f441d093e130f796c9166 to your computer and use it in GitHub Desktop.
HashLink + Heaps game launcher with auto updating using bintray
package;
import hxd.Event;
import sys.io.Process;
import haxe.io.BytesInput;
import format.zip.Reader;
import haxe.Http;
import haxe.Json;
import sys.FileSystem;
import sys.io.File;
import hxd.Window;
import sys.thread.Thread;
import hxd.res.DefaultFont;
import h2d.Text;
typedef ManifestData = {
?gameVersion:String,
}
typedef BintrayVersion = {
name:String,
}
typedef ThreadMsg = {
type:String,
data:Dynamic,
}
class Main extends hxd.App {
// Your bintray username
static final bintrayUser = "jefvel";
// The bintray repo to look in
static final bintrayRepo = "karanten";
// The bintray package to look for
// Versions should contain one file,
// which is a zip containing the compiled game data file
static final bintrayPackage = "data";
// set this to either "hl", or "./hl" or "./yourgame" or whatever you named the hashlink executable
static final hashlinkExecutable = "hl";
// The local game file will be called this
static final gameFile = "game.dat";
// Local manifest info file
static final manifestFile = "manifest.json";
var bintrayAPI = 'https://api.bintray.com/packages/$bintrayUser/$bintrayRepo';
var bintrayDLURL = 'https://dl.bintray.com/$bintrayUser/$bintrayRepo';
var text:Text;
var localManifest:ManifestData;
var gameReady = false;
var mainThread:Thread;
public override function init() {
hl.UI.closeConsole();
text = new Text(DefaultFont.get(), s2d);
text.textColor = 0xFFFFFF;
mainThread = Thread.current();
loadLocalManifest();
downloadFun();
Window.getInstance().addEventTarget(onEvent);
}
function onEvent(e:Event) {
if (e.kind == EPush) {
launchGame();
}
}
function loadLocalManifest() {
localManifest = {};
if (FileSystem.exists(manifestFile)) {
var mstring = File.getContent(manifestFile);
try {
localManifest = Json.parse(mstring);
} catch (e) {}
}
if (localManifest.gameVersion != null) {
log('Local version is ${localManifest.gameVersion}');
} else {
log("No local version detected");
}
}
override function update(dt:Float) {
super.update(dt);
var msg:ThreadMsg = Thread.readMessage(false);
if (msg != null) {
if (msg.type == "log") {
log(msg.data);
}
if (msg.type == "newManifest") {
var m:ManifestData = msg.data;
File.saveContent(manifestFile, Json.stringify(m));
}
if (msg.type == "gameReady") {
gameReady = true;
log("Click to start");
}
}
}
function log(msg) {
text.text += '$msg\n';
}
function sendGameReady() {
mainThread.sendMessage({
type: "gameReady",
});
}
function downloadFun() {
log("Getting latest version...");
Thread.create(() -> {
function log(msg) {
mainThread.sendMessage({
type: "log",
data: msg,
});
}
var latestVersion = "";
// Fetch latest version info from bintray
var http = new haxe.Http('$bintrayAPI/$bintrayPackage/versions/_latest');
http.onData = function(data:String) {
var result:BintrayVersion = haxe.Json.parse(data);
latestVersion = result.name;
}
http.request();
if (latestVersion != localManifest.gameVersion) {
log("Downloading latest version...");
} else {
log("Game is up to date");
sendGameReady();
return;
}
// Fetch file path for latest version from bintray
http = new Http('$bintrayAPI/$bintrayPackage/versions/$latestVersion/files');
var filePath = "";
http.onData = data -> {
var blob = Json.parse(data);
var f = blob[0];
filePath = f.path;
}
http.request();
// Download latest binary
http = new Http('$bintrayDLURL/$filePath');
var redirectURL = "";
http.onStatus = s -> {
if (s == 302) {
redirectURL = http.responseHeaders.get("Location");
}
}
http.request();
http = new Http(redirectURL);
http.request();
log("Downloaded binary. Uncompressing...");
File.saveBytes(filePath, http.responseBytes);
var fi = sys.io.File.read(filePath);
var r = new haxe.zip.Reader(fi);
var f = r.read();
for (handle in f) {
var r = new haxe.zip.Reader(new BytesInput(handle.data));
trace(handle.compressed);
var bytes = Reader.unzip(handle);
File.saveBytes(gameFile, bytes);
}
fi.close();
FileSystem.deleteFile(filePath);
log("Uncompressed latest version");
var m:ManifestData = {
gameVersion: latestVersion,
}
mainThread.sendMessage({
type: "newManifest",
data: m,
});
sendGameReady();
});
}
function launchGame() {
if (!gameReady) {
return;
}
new Process(hashlinkExecutable, [gameFile, '--savedir=${Sys.getCwd()}'], true);
Sys.exit(0);
}
static function main() {
new Main();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment