package src; import haxe.io.BytesInput; import haxe.zip.Reader; import hxd.res.Image; import haxe.Json; import src.Mission; import src.Http; import src.ResourceLoader; import src.Console; import src.MarbleGame; class Marbleland { public static var goldMissions = []; public static var ultraMissions = []; public static var platinumMissions = []; public static var multiplayerMissions = []; public static var missions:Map = []; public static function init() { Http.get('https://marbleland.vaniverse.io/api/level/list', (b) -> { parseMissionList(b.toString()); Console.log('Loaded gold customs: ${goldMissions.length}'); Console.log('Loaded ultra customs: ${ultraMissions.length}'); Console.log('Loaded platinum customs: ${platinumMissions.length}'); Console.log('Loaded multiplayer customs: ${multiplayerMissions.length}'); // Load the marbleland level from JS #if js var urlParams = new js.html.URLSearchParams(js.Browser.window.location.search); var playParam = urlParams.get("play"); if (playParam != null) { var intParam = Std.parseInt(playParam); if (intParam != null) { var mission = missions.get(intParam); if (mission != null) { MarbleGame.instance.playMission(mission); } } } #end }, (e) -> { Console.log('Error getting custom list from marbleland.'); }); } static function parseMissionList(s:String) { var claJson:Array = Json.parse(s); var platDupes = new Map(); for (missionData in claJson) { // filter if (missionData.datablockCompatibility != 'mbw' && missionData.datablockCompatibility != 'mbg') continue; if (!['gold', 'platinum', 'ultra', 'platinumquest'].contains(missionData.modification)) continue; if (missionData.gameMode != null && !(missionData.gameMode == 'null' || missionData.gameMode.toLowerCase() == 'hunt')) continue; var isMultiplayer = missionData.gameType == 'multi'; if (isMultiplayer && (missionData.gameMode == null || missionData.gameMode.toLowerCase() != 'hunt')) continue; var mission = new Mission(); mission.id = missionData.id; mission.path = 'missions/' + missionData.baseName; #if (hl && !android) mission.path = 'data/' + mission.path; #end mission.path = mission.path.toLowerCase(); mission.title = missionData.name; mission.artist = missionData.artist != null ? missionData.artist : "Unknown Author"; mission.description = missionData.desc != null ? missionData.desc : ""; mission.qualifyTime = (missionData.qualifyingTime != null && missionData.qualifyingTime != 0) ? missionData.qualifyingTime / 1000 : Math.POSITIVE_INFINITY; mission.goldTime = missionData.goldTime != null ? missionData.goldTime / 1000 : 0; if (missionData.modification == 'platinumquest') missionData.modification = 'platinum'; // play PQ levels compatible with web pls mission.game = missionData.modification; if (missionData.modification == 'platinum') mission.goldTime = missionData.platinumTime != null ? missionData.platinumTime / 1000 : mission.goldTime; mission.ultimateTime = missionData.ultimateTime != null ? missionData.ultimateTime / 1000 : 0; mission.hasEgg = missionData.hasEgg; mission.isClaMission = true; mission.addedAt = missionData.addedAt; mission.gameMode = missionData.gameMode; if (mission.gameMode != null) mission.gameMode = mission.gameMode.toLowerCase(); var game = missionData.modification; if (isMultiplayer) { game = 'multiplayer'; } if (game == 'platinum') { if (platDupes.exists(mission.title + mission.description)) continue; else platDupes.set(mission.title + mission.description, true); } switch (game) { case 'gold': goldMissions.push(mission); case 'ultra': ultraMissions.push(mission); case 'platinum': platinumMissions.push(mission); case 'multiplayer': multiplayerMissions.push(mission); } missions.set(mission.id, mission); } // sort according to name goldMissions.sort((x, y) -> x.title > y.title ? 1 : (x.title < y.title ? -1 : 0)); for (i in 0...goldMissions.length - 1) { @:privateAccess goldMissions[i].next = goldMissions[i + 1]; goldMissions[i].index = i; } @:privateAccess goldMissions[goldMissions.length - 1].next = goldMissions[0]; goldMissions[goldMissions.length - 1].index = goldMissions.length - 1; platinumMissions.sort((x, y) -> x.title > y.title ? 1 : (x.title < y.title ? -1 : 0)); for (i in 0...platinumMissions.length - 1) { @:privateAccess platinumMissions[i].next = platinumMissions[i + 1]; platinumMissions[i].index = i; } @:privateAccess platinumMissions[platinumMissions.length - 1].next = platinumMissions[0]; platinumMissions[platinumMissions.length - 1].index = platinumMissions.length - 1; ultraMissions.sort((x, y) -> x.title > y.title ? 1 : (x.title < y.title ? -1 : 0)); for (i in 0...ultraMissions.length - 1) { @:privateAccess ultraMissions[i].next = ultraMissions[i + 1]; ultraMissions[i].index = i; } @:privateAccess ultraMissions[ultraMissions.length - 1].next = ultraMissions[0]; ultraMissions[ultraMissions.length - 1].index = ultraMissions.length - 1; multiplayerMissions.sort((x, y) -> x.title > y.title ? 1 : (x.title < y.title ? -1 : 0)); for (i in 0...multiplayerMissions.length - 1) { @:privateAccess multiplayerMissions[i].next = multiplayerMissions[i + 1]; multiplayerMissions[i].index = i; } @:privateAccess multiplayerMissions[multiplayerMissions.length - 1].next = multiplayerMissions[0]; multiplayerMissions[multiplayerMissions.length - 1].index = multiplayerMissions.length - 1; } public static function getMissionImage(id:Int, cb:Image->Void) { return Http.get('https://marbleland.vaniverse.io/api/level/${id}/image?width=258&height=194', (imageBytes) -> { var res = new Image(new hxd.fs.BytesFileSystem.BytesFileEntry('${id}.png', imageBytes)); cb(res); }, (e) -> { cb(null); }); } public static function download(id:Int, cb:Array->Void) { Http.get('https://marbleland.vaniverse.io/api/level/${id}/zip?assuming=none', (zipData -> { var reader = new Reader(new BytesInput(zipData)); var entries:Array = null; try { entries = [for (x in reader.read()) x]; } catch (e) {} cb(entries); }), (e) -> { cb(null); }); } }