MBHaxe/src/Mission.hx
2023-07-07 21:57:11 +05:30

252 lines
7.5 KiB
Haxe

package src;
import src.Http.HttpRequest;
import gui.Canvas;
import gui.MessageBoxOkDlg;
import haxe.Json;
import mis.MissionElement.MissionElementItem;
import haxe.io.BytesBuffer;
import h2d.Tile;
import hxd.BitmapData;
import mis.MisParser;
import mis.MissionElement.MissionElementScriptObject;
import mis.MissionElement.MissionElementType;
import mis.MisFile;
import mis.MissionElement.MissionElementSimGroup;
import src.ResourceLoader;
import hxd.res.Image;
import src.Resource;
import src.Util;
import src.Console;
import src.Marbleland;
import src.MarbleGame;
import src.Http;
class Mission {
public var root:MissionElementSimGroup;
public var title:String;
public var artist:String;
public var description:String;
public var qualifyTime = Math.POSITIVE_INFINITY;
public var goldTime:Float = 0;
public var ultimateTime:Float = 0;
public var type:String;
public var path:String;
public var missionInfo:MissionElementScriptObject;
public var index:Int;
public var difficultyIndex:Int;
public var id:Int;
public var isClaMission:Bool;
public var game:String;
public var hasEgg:Bool;
public var isCustom:Bool;
var next:Mission;
var imageResources:Array<Resource<Image>> = [];
var imgFileEntry:hxd.fs.FileEntry;
#if sys
static var _previewRequest:HttpRequest;
#else
static var _previewRequest:Int;
#end
static var _previewCache:Map<Mission, h2d.Tile> = [];
public function new() {}
public function load() {
var entry = ResourceLoader.getFileEntry(this.path).entry;
var misText = entry.getText();
trace('Loading ${this.path}');
var misParser = new MisParser(misText);
var contents = misParser.parse();
root = contents.root;
function scanMission(simGroup:MissionElementSimGroup) {
for (element in simGroup.elements) {
if (this.hasEgg)
break;
if (element._type == MissionElementType.Item) {
var so:MissionElementItem = cast element;
if (so.datablock.toLowerCase() == 'easteregg')
this.hasEgg = true;
} else if (element._type == MissionElementType.SimGroup && !this.hasEgg) {
scanMission(cast element);
}
if (element._name == 'MissionInfo')
missionInfo = cast element;
}
};
scanMission(root); // Scan for egg
}
public function dispose() {
for (imageResource in imageResources) {
imageResource.release();
}
}
public static function fromMissionInfo(path:String, mInfo:MissionElementScriptObject) {
var mission = new Mission();
mission.path = path;
mission.missionInfo = mInfo;
var missionInfo = mInfo;
mission.title = missionInfo.name;
mission.artist = missionInfo.artist == null ? '' : missionInfo.artist;
mission.description = missionInfo.desc == null ? '' : missionInfo.desc;
if (missionInfo.time != null && missionInfo.time != "0")
mission.qualifyTime = MisParser.parseNumber(missionInfo.time) / 1000;
if (missionInfo.goldtime != null) {
mission.goldTime = MisParser.parseNumber(missionInfo.goldtime) / 1000;
}
if (missionInfo.ultimatetime != null) {
mission.ultimateTime = MisParser.parseNumber(missionInfo.ultimatetime) / 1000;
}
mission.type = missionInfo.type.toLowerCase();
mission.missionInfo = missionInfo;
return mission;
}
public function toJSON() {
return Json.stringify({
artist: this.artist,
description: this.description,
goldTime: this.goldTime,
ultimateTime: this.ultimateTime,
qualifyTime: this.qualifyTime,
hasEgg: this.hasEgg,
title: this.title,
type: this.type,
path: this.path,
});
}
public static function fromJSON(jsonData:String) {
var jdata = Json.parse(jsonData);
var mission = new Mission();
mission.artist = jdata.artist;
mission.description = jdata.description;
mission.goldTime = jdata.goldTime;
mission.ultimateTime = jdata.ultimateTime;
mission.qualifyTime = jdata.qualifyTime;
mission.hasEgg = jdata.hasEgg;
mission.title = jdata.title;
mission.type = jdata.type;
mission.path = jdata.path;
return mission;
}
public function getNextMission() {
return this.next;
}
public function getPreviewImage(onLoaded:h2d.Tile->Void) {
if (!this.isClaMission) {
var basename = haxe.io.Path.withoutExtension(this.path);
if (ResourceLoader.fileSystem.exists(basename + ".png")) {
imgFileEntry = ResourceLoader.fileSystem.get(basename + ".png");
imgFileEntry.load(() -> {
var ret = ResourceLoader.getResource(basename + ".png", ResourceLoader.getImage, this.imageResources).toTile();
onLoaded(ret);
});
return imgFileEntry.path;
}
if (ResourceLoader.fileSystem.exists(basename + ".jpg")) {
imgFileEntry = ResourceLoader.fileSystem.get(basename + ".jpg");
imgFileEntry.load(() -> {
var ret = ResourceLoader.getResource(basename + ".jpg", ResourceLoader.getImage, this.imageResources).toTile();
onLoaded(ret);
});
return imgFileEntry.path;
}
Console.error("Preview image not found for " + this.path);
var img = new BitmapData(1, 1);
img.setPixel(0, 0, 0);
onLoaded(Tile.fromBitmap(img));
return null;
} else {
if (_previewRequest != null #if sys && !_previewRequest.fulfilled #end) {
Http.cancel(_previewRequest); // Cancel the previous request to save dequeing
}
if (_previewCache.exists(this)) {
var t = _previewCache.get(this);
onLoaded(t);
return t.getTexture().name;
}
_previewRequest = Marbleland.getMissionImage(this.id, (im) -> {
if (im != null) {
var t = im.toTile();
_previewCache.set(this, t);
onLoaded(t);
} else {
Console.error("Preview image not found for " + this.path);
var img = new BitmapData(1, 1);
img.setPixel(0, 0, 0);
onLoaded(Tile.fromBitmap(img));
}
});
return null;
}
}
public function getDifPath(rawElementPath:String) {
if (StringTools.contains(rawElementPath, "$usermods")) {
rawElementPath = rawElementPath.split("@").slice(1).map(x -> {
var a = StringTools.trim(x);
a = Util.unescape(a.substr(1, a.length - 2));
return a;
}).join('');
}
var fname = rawElementPath.substring(rawElementPath.lastIndexOf('/') + 1);
rawElementPath = rawElementPath.toLowerCase();
if (StringTools.startsWith(rawElementPath, "./")) {
rawElementPath = rawElementPath.substring(2);
rawElementPath = haxe.io.Path.directory(this.path) + '/' + rawElementPath;
}
var path = StringTools.replace(rawElementPath.substring(rawElementPath.indexOf('data/')), "\"", "");
#if (js || android)
path = StringTools.replace(path, "data/", "");
#end
if (!StringTools.endsWith(path, ".dif"))
path += ".dif";
if (ResourceLoader.exists(path))
return path;
if (StringTools.contains(path, 'interiors_mbg/'))
path = StringTools.replace(path, 'interiors_mbg/', 'interiors/');
var dirpath = path.substring(0, path.lastIndexOf('/') + 1);
if (ResourceLoader.exists(path))
return path;
if (ResourceLoader.exists(dirpath + fname))
return dirpath + fname;
if (game == 'gold') {
path = StringTools.replace(path, 'interiors/', 'interiors_mbg/');
if (ResourceLoader.exists(path))
return path;
}
path = StringTools.replace(path, "lbinteriors", "interiors"); // This shit ew
if (ResourceLoader.exists(path))
return path;
Console.error("Interior resource not found: " + rawElementPath);
return "";
}
public function download(onFinish:Void->Void) {
if (this.isClaMission) {
Marbleland.download(this.id, (zipEntries) -> {
if (zipEntries != null) {
ResourceLoader.loadZip(zipEntries, game);
onFinish();
} else {
MarbleGame.canvas.pushDialog(new MessageBoxOkDlg("Failed to download mission"));
}
});
}
}
}