leaderboards impl

This commit is contained in:
RandomityGuy 2024-11-05 00:01:09 +05:30
parent a92b0eb1b6
commit e1e882098b
8 changed files with 373 additions and 45 deletions

View file

@ -11,6 +11,7 @@ typedef HttpRequest = {
var fulfilled:Bool; var fulfilled:Bool;
var post:Bool; var post:Bool;
var postData:String; var postData:String;
var ?file:haxe.io.Bytes;
}; };
class Http { class Http {
@ -52,13 +53,18 @@ class Http {
}; };
if (req.post) { if (req.post) {
http.setHeader('User-Agent', 'MBHaxe/1.0 ${Util.getPlatform()}'); http.setHeader('User-Agent', 'MBHaxe/1.0 ${Util.getPlatform()}');
http.setHeader('Content-Type', "application/json"); // support json data only (for now) if (req.file == null) {
http.setPostData(req.postData); http.setHeader('Content-Type', "application/json"); // support json data only (for now)
http.setPostData(req.postData);
}
}
if (req.post && req.file != null) {
http.fileTransfer("hxfile", "hxfilename", new haxe.io.BytesInput(req.file), req.file.length);
} }
hl.Gc.enable(false); hl.Gc.enable(false);
hl.Gc.blocking(true); // Wtf is this shit // hl.Gc.blocking(true); // Wtf is this shit
http.request(req.post); http.request(req.post);
hl.Gc.blocking(false); // hl.Gc.blocking(false);
hl.Gc.enable(true); hl.Gc.enable(true);
} }
} }
@ -114,6 +120,37 @@ class Http {
#end #end
} }
// Returns HTTPRequest on sys, Int on js
public static function uploadFile(url:String, data:haxe.io.Bytes, callback:haxe.io.Bytes->Void, errCallback:String->Void) {
var req = {
url: url,
callback: callback,
errCallback: errCallback,
cancelled: false,
fulfilled: false,
post: true,
postData: null,
file: data,
};
#if sys
requests.add(req);
return req;
#else
// TODO
return js.Browser.window.setTimeout(() -> {
js.Browser.window.fetch(url,
{
method: "POST",
headers: {
"User-Agent": js.Browser.window.navigator.userAgent,
"Content-Type": "application/octet-stream",
},
body: data.getData()
}).then(r -> r.arrayBuffer().then(b -> callback(haxe.io.Bytes.ofData(b))), e -> errCallback(e.toString()));
}, 75);
#end
}
public static function loop() { public static function loop() {
#if sys #if sys
var resp = responses.pop(false); var resp = responses.pop(false);

74
src/Leaderboards.hx Normal file
View file

@ -0,0 +1,74 @@
package src;
import net.Net;
import haxe.Json;
import src.Http;
import src.Console;
import src.Settings;
typedef LBScore = {
name:String,
has_rec:Int,
score:Float,
platform:Int,
rewind:Int,
}
class Leaderboards {
static var host = "http://127.0.0.1:7000";
static var game = "Platinum";
public static function submitScore(mission:String, score:Float, rewindUsed:Bool, needsReplayCb:(Bool, Int) -> Void) {
if (!StringTools.startsWith(mission, "data/"))
mission = "data/" + mission;
Http.post('${host}/api/submit', Json.stringify({
mission: mission,
score: score,
game: game,
name: Settings.highscoreName,
uid: Settings.userId,
rewind: rewindUsed ? 1 : 0,
platform: Net.getPlatform()
}), (b) -> {
var s = b.toString();
var jd = Json.parse(s);
var status = jd.status;
Console.log("Score submitted");
needsReplayCb(status == "new_record", status == "new_record" ? jd.rowid : 0);
}, (e) -> {
Console.log("Score submission failed: " + e);
});
}
public static function getScores(mission:String, cb:Array<LBScore>->Void) {
if (!StringTools.startsWith(mission, "data/"))
mission = "data/" + mission;
return Http.get('${host}/api/scores?mission=${StringTools.urlEncode(mission)}&game=${game}', (b) -> {
var s = b.toString();
var scores:Array<LBScore> = Json.parse(s).scores;
cb(scores);
}, (e) -> {
Console.log("Failed to get scores: " + e);
cb([]);
});
}
public static function submitReplay(ref:Int, replay:haxe.io.Bytes) {
return Http.uploadFile('${host}/api/record?ref=${ref}', replay, (b) -> {
Console.log("Replay submitted");
}, (e) -> {
Console.log("Replay submission failed: " + e);
});
}
public static function watchTopReplay(mission:String, cb:haxe.io.Bytes->Void) {
if (!StringTools.startsWith(mission, "data/"))
mission = "data/" + mission;
return Http.get('${host}/api/replay?mission=${StringTools.urlEncode(mission)}&game=${game}', (b) -> {
cb(b);
}, (e) -> {
Console.log("Failed to get replay: " + e);
cb(null);
});
}
}

View file

@ -283,7 +283,7 @@ class MarbleGame {
exitGameDlg = new ExitGameDlg((sender) -> { exitGameDlg = new ExitGameDlg((sender) -> {
canvas.popDialog(exitGameDlg); canvas.popDialog(exitGameDlg);
var w = getWorld(); var w = getWorld();
if (w.isRecording) { if (MarbleGame.instance.toRecord) {
MarbleGame.canvas.pushDialog(new ReplayNameDlg(() -> { MarbleGame.canvas.pushDialog(new ReplayNameDlg(() -> {
quitMission(); quitMission();
})); }));
@ -373,7 +373,7 @@ class MarbleGame {
world.dispose(); world.dispose();
} }
Analytics.trackLevelPlay(mission.title, mission.path); Analytics.trackLevelPlay(mission.title, mission.path);
world = new MarbleWorld(scene, scene2d, mission, toRecord, multiplayer); world = new MarbleWorld(scene, scene2d, mission, true, multiplayer);
world.init(); world.init();
} }

View file

@ -216,6 +216,7 @@ class MarbleWorld extends Scheduler {
// Rewind // Rewind
public var rewindManager:RewindManager; public var rewindManager:RewindManager;
public var rewinding:Bool = false; public var rewinding:Bool = false;
public var rewindUsed:Bool = false;
public var inputRecorder:InputRecorder; public var inputRecorder:InputRecorder;
public var isReplayingMovement:Bool = false; public var isReplayingMovement:Bool = false;
@ -682,6 +683,7 @@ class MarbleWorld extends Scheduler {
this.replay.rewind(); this.replay.rewind();
this.rewindManager.clear(); this.rewindManager.clear();
this.rewindUsed = false;
if (!this.isMultiplayer || _skipPreGame) { if (!this.isMultiplayer || _skipPreGame) {
setCursorLock(true); setCursorLock(true);
@ -1834,6 +1836,7 @@ class MarbleWorld extends Scheduler {
var actualDt = timeState.currentAttemptTime - rframe.timeState.currentAttemptTime - dt * rewindManager.timeScale; var actualDt = timeState.currentAttemptTime - rframe.timeState.currentAttemptTime - dt * rewindManager.timeScale;
dt = actualDt; dt = actualDt;
rewindManager.applyFrame(rframe); rewindManager.applyFrame(rframe);
rewindUsed = true;
} }
} }
if (dt < 0) if (dt < 0)

View file

@ -497,6 +497,9 @@ class Replay {
var compressed = stream.finalize(); var compressed = stream.finalize();
#end #end
if (this.name == null)
this.name = this.mission;
var finalB = new BytesBuffer(); var finalB = new BytesBuffer();
finalB.addByte(version); finalB.addByte(version);
finalB.addByte(this.name.length); finalB.addByte(this.name.length);

View file

@ -1,5 +1,6 @@
package src; package src;
import net.Uuid;
import h3d.Vector; import h3d.Vector;
import haxe.ds.Option; import haxe.ds.Option;
import gui.Canvas; import gui.Canvas;
@ -220,6 +221,7 @@ class Settings {
public static var levelStatistics:Map<String, PlayStatistics> = []; public static var levelStatistics:Map<String, PlayStatistics> = [];
public static var highscoreName = ""; public static var highscoreName = "";
public static var userId = "";
public static var uiScale = 1.0; public static var uiScale = 1.0;
@ -274,6 +276,7 @@ class Settings {
stats: playStatistics, stats: playStatistics,
server: serverSettings, server: serverSettings,
highscoreName: highscoreName, highscoreName: highscoreName,
userId: userId,
marbleIndex: optionsSettings.marbleIndex, marbleIndex: optionsSettings.marbleIndex,
marbleSkin: optionsSettings.marbleSkin, marbleSkin: optionsSettings.marbleSkin,
marbleModel: optionsSettings.marbleModel, marbleModel: optionsSettings.marbleModel,
@ -454,6 +457,13 @@ class Settings {
} }
#end #end
highscoreName = json.highscoreName; highscoreName = json.highscoreName;
if (highscoreName == null) {
highscoreName = "";
}
userId = json.userId;
if (userId == null) {
userId = Uuid.v4();
}
} else { } else {
Console.warn("Settings file does not exist"); Console.warn("Settings file does not exist");
save(); save();

View file

@ -1,5 +1,6 @@
package gui; package gui;
import src.Leaderboards;
import hxd.BitmapData; import hxd.BitmapData;
import h2d.Tile; import h2d.Tile;
import src.MarbleGame; import src.MarbleGame;
@ -422,6 +423,11 @@ class EndGameGui extends GuiControl {
} }
Settings.saveScore(mission.path, myScore); Settings.saveScore(mission.path, myScore);
Leaderboards.submitScore(mission.path, myScore.time, MarbleGame.instance.world.rewindUsed, (sendReplay, rowId) -> {
if (sendReplay) {
Leaderboards.submitReplay(rowId, MarbleGame.instance.world.replay.write());
}
});
scoreSubmitted = true; scoreSubmitted = true;
}); });

View file

@ -1,5 +1,8 @@
package gui; package gui;
import src.Http;
import src.Leaderboards;
import net.ClientConnection.NetPlatform;
import src.Marbleland; import src.Marbleland;
import h2d.filter.DropShadow; import h2d.filter.DropShadow;
import src.Replay; import src.Replay;
@ -52,9 +55,12 @@ class PlayMissionGui extends GuiImage {
#if js #if js
var previewTimeoutHandle:Option<Int> = None; var previewTimeoutHandle:Option<Int> = None;
var lbRequest:Int = 0;
#end #end
#if hl #if hl
var previewToken:Int = 0; var previewToken:Int = 0;
var lbToken:Int = 0;
var lbRequest:src.Http.HttpRequest = null;
#end #end
public function new() { public function new() {
@ -117,6 +123,7 @@ class PlayMissionGui extends GuiImage {
var arial14b = new BitmapFont(arial14fontdata.entry); var arial14b = new BitmapFont(arial14fontdata.entry);
@:privateAccess arial14b.loader = ResourceLoader.loader; @:privateAccess arial14b.loader = ResourceLoader.loader;
var arial14 = arial14b.toSdfFont(cast 12 * Settings.uiScale, MultiChannel); var arial14 = arial14b.toSdfFont(cast 12 * Settings.uiScale, MultiChannel);
var arial12 = arial14b.toSdfFont(cast 10 * Settings.uiScale, MultiChannel);
var arialb14fontdata = ResourceLoader.getFileEntry("data/font/Arial Bold.fnt"); var arialb14fontdata = ResourceLoader.getFileEntry("data/font/Arial Bold.fnt");
var arialb14b = new BitmapFont(arialb14fontdata.entry); var arialb14b = new BitmapFont(arialb14fontdata.entry);
@ -129,6 +136,7 @@ class PlayMissionGui extends GuiImage {
var markerFelt32 = markerFelt32b.toSdfFont(cast 26 * Settings.uiScale, MultiChannel); var markerFelt32 = markerFelt32b.toSdfFont(cast 26 * Settings.uiScale, MultiChannel);
var markerFelt24 = markerFelt32b.toSdfFont(cast 20 * Settings.uiScale, MultiChannel); var markerFelt24 = markerFelt32b.toSdfFont(cast 20 * Settings.uiScale, MultiChannel);
var markerFelt20 = markerFelt32b.toSdfFont(cast 18.5 * Settings.uiScale, MultiChannel); var markerFelt20 = markerFelt32b.toSdfFont(cast 18.5 * Settings.uiScale, MultiChannel);
var markerFelt16 = markerFelt32b.toSdfFont(cast 14 * Settings.uiScale, MultiChannel);
var markerFelt18 = markerFelt32b.toSdfFont(cast 17 * Settings.uiScale, MultiChannel); var markerFelt18 = markerFelt32b.toSdfFont(cast 17 * Settings.uiScale, MultiChannel);
var markerFelt26 = markerFelt32b.toSdfFont(cast 22 * Settings.uiScale, MultiChannel); var markerFelt26 = markerFelt32b.toSdfFont(cast 22 * Settings.uiScale, MultiChannel);
@ -136,6 +144,8 @@ class PlayMissionGui extends GuiImage {
switch (text) { switch (text) {
case "DomCasual24": case "DomCasual24":
return domcasual24; return domcasual24;
case "Arial12":
return arial14;
case "Arial14": case "Arial14":
return arial14; return arial14;
case "ArialBold14": case "ArialBold14":
@ -155,6 +165,30 @@ class PlayMissionGui extends GuiImage {
} }
} }
function imgLoader(path:String) {
var t = switch (path) {
case "pc":
ResourceLoader.getResource("data/ui/mp/play/platform_desktop_white.png", ResourceLoader.getImage, this.imageResources).toTile();
case "mac":
ResourceLoader.getResource("data/ui/mp/play/platform_mac_white.png", ResourceLoader.getImage, this.imageResources).toTile();
case "web":
ResourceLoader.getResource("data/ui/mp/play/platform_web_white.png", ResourceLoader.getImage, this.imageResources).toTile();
case "android":
ResourceLoader.getResource("data/ui/mp/play/platform_android_white.png", ResourceLoader.getImage, this.imageResources).toTile();
case "unknown":
ResourceLoader.getResource("data/ui/mp/play/platform_unknown_white.png", ResourceLoader.getImage, this.imageResources).toTile();
case "rewind":
ResourceLoader.getResource("data/ui/mp/play/rewind_ico.png", ResourceLoader.getImage, this.imageResources).toTile();
case "watch":
ResourceLoader.getResource("data/ui/play/record.png", ResourceLoader.getImage, this.imageResources).toTile();
case _:
return null;
};
if (t != null)
t.scaleToSize(t.width * (Settings.uiScale), t.height * (Settings.uiScale));
return t;
}
var pmBox = new GuiImage(ResourceLoader.getResource('data/ui/play/window.png', ResourceLoader.getImage, this.imageResources).toTile()); var pmBox = new GuiImage(ResourceLoader.getResource('data/ui/play/window.png', ResourceLoader.getImage, this.imageResources).toTile());
pmBox.horizSizing = Center; pmBox.horizSizing = Center;
pmBox.vertSizing = Center; pmBox.vertSizing = Center;
@ -775,6 +809,114 @@ class PlayMissionGui extends GuiImage {
}; };
pmMorePopDlg.addChild(pmRecord); pmMorePopDlg.addChild(pmRecord);
var scoreScroll = new GuiScrollCtrl(ResourceLoader.getResource("data/ui/common/philscroll.png", ResourceLoader.getImage, this.imageResources)
.toTile());
scoreScroll.position = new Vector(110, 170);
scoreScroll.extent = new Vector(407, 143);
scoreScroll.childrenHandleScroll = true;
scoreScroll.scrollToBottom = true;
// window.addChild(chatScroll);
var scoreBox = new GuiMLText(markerFelt16, mlFontLoader);
scoreBox.text.loadImage = imgLoader;
scoreBox.text.onHyperlink = (url) -> {
if (url == "watch") {
var currentMission = currentList[currentSelection];
Leaderboards.watchTopReplay(currentMission.path, (b) -> {
if (b != null) {
var replayF = new Replay("");
if (replayF.read(b)) {
var repmis = replayF.mission;
// Strip data/ from the mission name
if (StringTools.startsWith(repmis, "data/")) {
repmis = repmis.substr(5);
}
var mi = replayF.customId == 0 ? MissionList.missions.get(repmis) : Marbleland.missions.get(replayF.customId);
// try with data/ added
if (mi == null && replayF.customId == 0) {
if (!StringTools.contains(repmis, "data/"))
repmis = "data/" + repmis;
mi = MissionList.missions.get(repmis);
}
if (mi.isClaMission) {
mi.download(() -> {
MarbleGame.instance.watchMissionReplay(mi, replayF);
});
} else {
MarbleGame.instance.watchMissionReplay(mi, replayF);
}
} else {
MarbleGame.canvas.pushDialog(new MessageBoxOkDlg("Could not load replay for this level."));
}
} else {
MarbleGame.canvas.pushDialog(new MessageBoxOkDlg("No top replay found for this level."));
}
});
}
}
scoreBox.text.textColor = 0xF4E4CE;
scoreBox.text.dropShadow = {
dx: 1 * Settings.uiScale,
dy: 1 * Settings.uiScale,
alpha: 0.5,
color: 0
};
scoreBox.text.lineSpacing = -1;
scoreBox.horizSizing = Width;
scoreBox.position = new Vector(0, 0);
scoreBox.extent = new Vector(407, 1184);
var scores = [
'1. <offset value="15">Nardo Polo</offset><offset value="215">99:59:999</offset><offset value="279"><img src="unknown"/></offset>',
'2. <offset value="15">Nardo Polo</offset><offset value="215">99:59:999</offset><offset value="279"><img src="pc"/></offset>',
'3. <offset value="15">Nardo Polo</offset><offset value="215">99:59:999</offset><offset value="279"><img src="mac"/></offset>',
'4. <offset value="15">Nardo Polo</offset><offset value="215">99:59:999</offset><offset value="279"><img src="web"/></offset>',
'5. <offset value="15">Nardo Polo</offset><offset value="215">99:59:999</offset><offset value="279"><img src="android"/></offset>',
];
scoreBox.text.text = '<p align="center">Loading scores</p>'; // scores.join('<br/>');
scoreBox.text.imageVerticalAlign = Top;
scoreScroll.addChild(scoreBox);
var lbImgs = loadButtonImages("data/ui/play/lb");
var infoImgs = loadButtonImages("data/ui/play/info");
var showLBs = false;
var pmLBToggle = new GuiButton(lbImgs);
pmLBToggle.position = new Vector(118, 98);
pmLBToggle.extent = new Vector(43, 43);
pmLBToggle.pressedAction = (e) -> {
showLBs = !showLBs;
if (!showLBs) {
@:privateAccess pmLBToggle.anim.frames = lbImgs;
} else {
@:privateAccess pmLBToggle.anim.frames = infoImgs;
}
pmScoreButton.disabled = showLBs;
pmScoreText.text.visible = !showLBs;
setSelectedFunc(currentSelection);
if (showLBs) {
pmBox.addChild(scoreScroll);
} else {
pmBox.removeChild(scoreScroll);
}
pmBox.render(MarbleGame.canvas.scene2d, pmBox.parent._flow);
// setCategoryFunc(currentGame, currentCategoryStatic, currentSortType == 1 ? "date" : "alpha");
// MarbleGame.canvas.pushDialog(new SearchGui(currentGame, currentCategory == "custom"));
}
if (!showLBs) {
@:privateAccess pmLBToggle.anim.frames = lbImgs;
} else {
@:privateAccess pmLBToggle.anim.frames = infoImgs;
}
pmBox.addChild(pmLBToggle);
// var replayPlayButton = new GuiImage(ResourceLoader.getResource("data/ui/play/playback.png", ResourceLoader.getImage, this.imageResources).toTile()); // var replayPlayButton = new GuiImage(ResourceLoader.getResource("data/ui/play/playback.png", ResourceLoader.getImage, this.imageResources).toTile());
// replayPlayButton.position = new Vector(38, 315); // replayPlayButton.position = new Vector(38, 315);
// replayPlayButton.extent = new Vector(18, 18); // replayPlayButton.extent = new Vector(18, 18);
@ -931,6 +1073,8 @@ class PlayMissionGui extends GuiImage {
} }
} }
var lbToken:Int = 0;
setSelectedFunc = function setSelected(index:Int) { setSelectedFunc = function setSelected(index:Int) {
if (index > currentList.length - 1) { if (index > currentList.length - 1) {
index = currentList.length - 1; index = currentList.length - 1;
@ -1011,38 +1155,74 @@ class PlayMissionGui extends GuiImage {
var descText = '<font color="#FDFEFE" face="MarkerFelt26"><p align="center">#${currentList.indexOf(currentMission) + 1}: ${currentMission.title}</p></font>'; var descText = '<font color="#FDFEFE" face="MarkerFelt26"><p align="center">#${currentList.indexOf(currentMission) + 1}: ${currentMission.title}</p></font>';
if (this.scoreShowing) { if (!showLBs) {
var scoreData:Array<Score> = Settings.getScores(currentMission.path); if (this.scoreShowing) {
while (scoreData.length < 5) { var scoreData:Array<Score> = Settings.getScores(currentMission.path);
scoreData.push({name: "Matan W.", time: 5999.999}); while (scoreData.length < 5) {
} scoreData.push({name: "Matan W.", time: 5999.999});
var rightText = '<font color="#FDFEFE" face="MarkerFelt26"><br/></font><font color="#F4EFE3" face="MarkerFelt18"></font>';
for (i in 0...5) {
var score = scoreData[i];
var scoreColor = "#FFFFFF";
if (score.time < currentMission.ultimateTime) {
scoreColor = "#FFCC33";
} else if (score.time < currentMission.goldTime) {
if (currentMission.game == "gold" || currentMission.game.toLowerCase() == "ultra")
scoreColor = "#FFFF00";
else
scoreColor = "#CCCCCC";
} }
var scoreTextTime = '<p align="right"><font color="${scoreColor}" face="MarkerFelt18">${Util.formatTime(score.time)}</font></p>'; var rightText = '<font color="#FDFEFE" face="MarkerFelt26"><br/></font><font color="#F4EFE3" face="MarkerFelt18"></font>';
rightText += scoreTextTime;
descText += '<font color="#F4E4CE" face="MarkerFelt18">${i + 1}. <font color="#FFFFFF">${StringTools.htmlEscape(score.name)}</font></font><br/>'; for (i in 0...5) {
var score = scoreData[i];
var scoreColor = "#FFFFFF";
if (score.time < currentMission.ultimateTime) {
scoreColor = "#FFCC33";
} else if (score.time < currentMission.goldTime) {
if (currentMission.game == "gold" || currentMission.game.toLowerCase() == "ultra")
scoreColor = "#FFFF00";
else
scoreColor = "#CCCCCC";
}
var scoreTextTime = '<p align="right"><font color="${scoreColor}" face="MarkerFelt18">${Util.formatTime(score.time)}</font></p>';
rightText += scoreTextTime;
descText += '<font color="#F4E4CE" face="MarkerFelt18">${i + 1}. <font color="#FFFFFF">${StringTools.htmlEscape(score.name)}</font></font><br/>';
}
pmDescriptionRight.text.text = rightText;
} else {
descText += '<font color="#F4EFE3" face="MarkerFelt18"><p align="center">Author: ${StringTools.htmlEscape(currentMission.artist)}</p></font>';
descText += '<font color="#F4E4CE" face="MarkerFelt18">${StringTools.htmlEscape(currentMission.description)}</font>';
pmDescriptionRight.text.text = '';
} }
pmDescriptionRight.text.text = rightText;
} else { } else {
descText += '<font color="#F4EFE3" face="MarkerFelt18"><p align="center">Author: ${StringTools.htmlEscape(currentMission.artist)}</p></font>';
descText += '<font color="#F4E4CE" face="MarkerFelt18">${StringTools.htmlEscape(currentMission.description)}</font>';
pmDescriptionRight.text.text = ''; pmDescriptionRight.text.text = '';
#if hl
if (lbRequest != null)
Http.cancel(lbRequest);
#end
#if js
if (lbRequest != 0)
Http.cancel(lbRequest);
#end
var lTok = lbToken++;
var req = Leaderboards.getScores(currentMission.path, (scoreList) -> {
if (lTok + 1 != lbToken || !showLBs)
return;
var sFmt = [];
var i = 1;
for (score in scoreList) {
sFmt.push('${i}.
<offset value="15">${score.name}</offset>
<offset value="215">${Util.formatTime(score.score)}</offset>
<offset value="279"><img src="${platformToString(score.platform)}"/></offset>
${score.rewind == 1 ? '<offset value="299"><img src="rewind"/></offset> ' : ""}');
i++;
}
scoreBox.text.text = '<font color="#FDFEFE" face="MarkerFelt18">Leaderboards</font>
${scoreList.length != 0 ? '<offset value="220">Top Replay:<a href="watch"><img src="watch" /></a></offset>' : ""}
<br/>'
+ sFmt.join('<br/>');
});
lbRequest = req;
scoreBox.text.text = '<font color="#FDFEFE" face="MarkerFelt18">Leaderboards</font><br/><p align="center">Loading scores</p>';
scoreScroll.setScrollMax(scoreBox.text.textHeight);
scoreScroll.updateScrollVisual();
} }
pmDescription.text.text = descText; pmDescription.text.text = descText;
@ -1058,21 +1238,26 @@ class PlayMissionGui extends GuiImage {
alpha: 0.5, alpha: 0.5,
color: 0 color: 0
}; };
if (this.scoreShowing) { if (!showLBs) {
if (currentMission.game == "platinum") { if (this.scoreShowing) {
pmParText.text.text = '<font color="#FFE3E3" face="MarkerFelt20">Platinum: <font color="#CCCCCC">${Util.formatTime(currentMission.goldTime)}</font></font>'; if (currentMission.game == "platinum") {
pmParTextRight.text.text = '<p align="right"><font color="#FFE3E3" face="MarkerFelt20">Ultimate: <font color="#FFCC33">${Util.formatTime(currentMission.ultimateTime)}</font></font></p>'; pmParText.text.text = '<font color="#FFE3E3" face="MarkerFelt20">Platinum: <font color="#CCCCCC">${Util.formatTime(currentMission.goldTime)}</font></font>';
} pmParTextRight.text.text = '<p align="right"><font color="#FFE3E3" face="MarkerFelt20">Ultimate: <font color="#FFCC33">${Util.formatTime(currentMission.ultimateTime)}</font></font></p>';
if (currentMission.game == "gold") { }
pmParText.text.text = '<font color="#FFE3E3" face="MarkerFelt20">Qualify: <font color="#FFFFFF">${(currentMission.qualifyTime != Math.POSITIVE_INFINITY) ? Util.formatTime(currentMission.qualifyTime) : "N/A"}</font></font>'; if (currentMission.game == "gold") {
pmParTextRight.text.text = '<p align="right"><font color="#FFE3E3" face="MarkerFelt20">Gold: <font color="#FFFF00">${Util.formatTime(currentMission.goldTime)}</font></font></p>'; pmParText.text.text = '<font color="#FFE3E3" face="MarkerFelt20">Qualify: <font color="#FFFFFF">${(currentMission.qualifyTime != Math.POSITIVE_INFINITY) ? Util.formatTime(currentMission.qualifyTime) : "N/A"}</font></font>';
} pmParTextRight.text.text = '<p align="right"><font color="#FFE3E3" face="MarkerFelt20">Gold: <font color="#FFFF00">${Util.formatTime(currentMission.goldTime)}</font></font></p>';
if (currentMission.game.toLowerCase() == "ultra") { }
pmParText.text.text = '<font color="#FFE3E3" face="MarkerFelt20">Gold: <font color="#FFFF00">${Util.formatTime(currentMission.goldTime)}</font></font>'; if (currentMission.game.toLowerCase() == "ultra") {
pmParTextRight.text.text = '<p align="right"><font color="#FFE3E3" face="MarkerFelt20">Ultimate: <font color="#FFCC33">${Util.formatTime(currentMission.ultimateTime)}</font></font></p>'; pmParText.text.text = '<font color="#FFE3E3" face="MarkerFelt20">Gold: <font color="#FFFF00">${Util.formatTime(currentMission.goldTime)}</font></font>';
pmParTextRight.text.text = '<p align="right"><font color="#FFE3E3" face="MarkerFelt20">Ultimate: <font color="#FFCC33">${Util.formatTime(currentMission.ultimateTime)}</font></font></p>';
}
} else {
pmParText.text.text = '<font color="#FFE3E3" face="MarkerFelt24"><p align="center">${currentMission.game == "gold" ? "Qualify" : "Par"} Time: <font color="#FFFFFF">${(currentMission.qualifyTime != Math.POSITIVE_INFINITY) ? Util.formatTime(currentMission.qualifyTime) : "N/A"}</font></p></font>';
pmParTextRight.text.text = '';
} }
} else { } else {
pmParText.text.text = '<font color="#FFE3E3" face="MarkerFelt24"><p align="center">${currentMission.game == "gold" ? "Qualify" : "Par"} Time: <font color="#FFFFFF">${(currentMission.qualifyTime != Math.POSITIVE_INFINITY) ? Util.formatTime(currentMission.qualifyTime) : "N/A"}</font></p></font>'; pmParText.text.text = '';
pmParTextRight.text.text = ''; pmParTextRight.text.text = '';
} }
@ -1167,4 +1352,14 @@ class PlayMissionGui extends GuiImage {
scoreButtonHover = false; scoreButtonHover = false;
} }
} }
inline function platformToString(platform:NetPlatform) {
return switch (platform) {
case Unknown: return "unknown";
case Android: return "android";
case MacOS: return "mac";
case PC: return "pc";
case Web: return "web";
}
}
} }