Skip to content

Commit

Permalink
feat: New run comparison API and set from leaderboard entry
Browse files Browse the repository at this point in the history
  • Loading branch information
jason-e committed Nov 1, 2024
1 parent b968dd6 commit c8b575d
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 133 deletions.
14 changes: 14 additions & 0 deletions scripts/common/timer.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
type Gamemode = import('common/web').Gamemode;

/* eslint-disable @typescript-eslint/naming-convention */
export enum TimerEvent_OLD {
STARTED = 0,
Expand Down Expand Up @@ -104,6 +106,18 @@ export interface RunSplits {
segments: RunSegment[];
}

export interface RunMetadata {
filePath: string,
timestamp: number,
gameMode: Gamemode,
tickInterval: float,
playerSteamId: number,
playerName: string,
trackId: TrackID,
runTime: double,
runSplits: RunSplits | null,
}

/** Enum for why end of run is being shown */
export enum EndOfRunShowReason {
PLAYER_FINISHED_RUN = 0,
Expand Down
136 changes: 19 additions & 117 deletions scripts/hud/comparisons.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import { PanelHandler } from 'util/module-helpers';
import { TimerEvent_OLD, TimerState_OLD } from 'common/timer';
import { Comparison_OLD, RunStats_OLD, Split_OLD } from 'common/timer';
import { RunMetadata } from 'common/timer';

@PanelHandler()
class HudComparisonsHandler {
runFinished = false;
currentZone = 0;
runStatsZoneIndex = 0;
comparison: RunMetadata = null;

readonly maxActiveSplits = 12;
readonly newSplitTransitionDuration = 2;
Expand All @@ -17,129 +14,34 @@ class HudComparisonsHandler {
};

constructor() {
$.RegisterEventHandler('HudCompare_Update', $.GetContextPanel(), () => this.updateComparisons());
$.RegisterForUnhandledEvent('OnMomentumTimerStateChange', (arg, arg2) => this.onTimerEvent(arg, arg2));
$.RegisterForUnhandledEvent('ComparisonRunUpdated', () => this.onComparisonRunUpdated());
$.RegisterForUnhandledEvent('OnObservedTimerStateChange', () => this.updateComparisons());
$.RegisterForUnhandledEvent('OnObservedTimerCheckpointProgressed', () => this.updateComparisons());
$.RegisterForUnhandledEvent('OnObservedTimerReplaced', () => this.updateComparisons());
}

clearComparisons() {
// this.panels.compare.RemoveAndDeleteChildren();
this.panels.splits.RemoveAndDeleteChildren();
this.runFinished = false;
this.currentZone = 0;
this.runStatsZoneIndex = 0;
}
onComparisonRunUpdated() {
this.comparison = RunComparisonsAPI.GetComparisonRun();

$.Msg(`Got comparison run ${this.comparison?.filePath ?? "NONE"}`);

onTimerEvent(_ent: any, eventType: any) {
if (eventType === TimerEvent_OLD.STARTED) {
this.clearComparisons();
if (this.comparison) {
$.Msg(`jumps: ${this.comparison.runSplits.trackStats.jumps}`)
}

this.updateComparisons();
}

updateComparisons() {
/* TODO
const currentData = $.GetContextPanel<HudComparisons>().currentRunData;
const currentStats = $.GetContextPanel<HudComparisons>().currentRunStats;
const comparisonRun = RunComparisonsAPI.GetLoadedComparison();
const hasCompare = !!comparisonRun.compareRun;
if (
!currentData ||
!currentData.isInZone ||
!currentStats ||
currentData.currentZone === 1 ||
currentData.timerState === TimerState_OLD.PRACTICE
) {
return;
}
// Here, this.currentZone tracks how far into the run we are, so we can compare against currentData.currentZone,
// so we don't fire on stage we've already hit.
// this.runStatsZoneIndex tracks the correct index into the runStats array
const timerStatus = MomentumTimerAPI.GetObservedTimerStatus();
const runSplits = MomentumTimerAPI.GetObservedTimerRunSplits();

if (currentData.timerState === TimerState_OLD.NOT_RUNNING) {
// The only time we care about comparisons when timer is not running is if you just
// hit the end zone *for the first time*
if (!this.runFinished && currentData.currentZone === 0) {
// We're at the last zone, set index to last in the RunStats zone array
this.runStatsZoneIndex = currentStats.numZones - 1;
this.currentZone = 0;
if (timerStatus.trackId.type === this.comparison.trackId.type && timerStatus.trackId.number === this.comparison.trackId.number) {

// Track that we've finished so this never runs again
this.runFinished = true;
} else {
return;
}
} else {
// Return out if you went back a zone
if (currentData.currentZone <= this.currentZone) {
return;
} else {
// This is the first time you hit this zone
this.currentZone = currentData.currentZone;
this.runStatsZoneIndex = currentData.currentZone - 2; // -2 but currentZone is offset by the end and start zones
}
}
// Track differs -- could maybe do a best-effort comparison if one is a stage and one is the main track,
// otherwise make sure the comparison HUD is cleared

const splitPanels = this.panels.splits.Children().reverse();
if (splitPanels.length > this.maxActiveSplits) {
for (const panel of splitPanels.filter((_, i) => splitPanels.length - i > this.maxActiveSplits))
panel.RemoveAndDeleteChildren();
}
const data = hasCompare
? Comparison_OLD.generateSplits(
new RunStats_OLD(currentStats, currentData.tickRate),
new RunStats_OLD(comparisonRun.compareRun.stats, currentData.tickRate)
// this.runStatsZoneIndex + 1 TODO: this was being passed to generateSplits, but that only takes two args. What was this for?
)[this.runStatsZoneIndex]
: new RunStats_OLD(currentStats, currentData.tickRate, this.runStatsZoneIndex + 1).zones[
this.runStatsZoneIndex
];
const wrapper = $.CreatePanel('Panel', this.panels.splits, `Split${data.name}`, {
class: 'hud-comparisons__split'
});
if (this.runStatsZoneIndex > 0) {
const lastSplit = this.panels.splits.GetFirstChild().GetFirstChild();
lastSplit?.RemoveClass('split--latest');
}
this.panels.splits.MoveChildBefore(wrapper, this.panels.splits.Children()[0]);
const panel = $.CreatePanel('Split', wrapper, '', { class: 'split--hud split--latest' });
// Animation code I might try in 0.9.2
// Avoids hardcoding a height value. Waits for one split to spawn and have correct height, then tracks it.
// Means first one won't animate height but that's fine as there's nothing for it to push upwards
// $.Schedule(0.05, () => (this.latestSplitHeight ??= panel.actuallayoutheight / panel.actualuiscale_y));
// if (!this.latestSplitHeight) return;
// panel.style.height = `${this.latestSplitHeight}px`;
// wrapper.style.transitionDuration = '0s';
// wrapper.style.height = '0px';
// wrapper.style.transitionDuration = `${NEW_SPLIT_TRANSITION_DURATION}s`;
// wrapper.style.height = `${this.latestSplitHeight}px`;
Object.assign(
panel,
hasCompare
? {
name: data.name,
time: data.accumulateTime,
isFirst: false,
diff: (data as Split_OLD).diff,
delta: (data as Split_OLD).delta
}
: {
name: data.name,
time: data.accumulateTime,
isFirst: true
}
);
*/
}
}
6 changes: 3 additions & 3 deletions scripts/pages/end-of-run/end-of-run.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ class EndOfRunHandler {
selectedSplit: Split_OLD;

constructor() {
$.RegisterForUnhandledEvent('EndOfRun_CompareRuns', (baseRun, compareRun) =>
this.setComparison(baseRun, compareRun)
);
// $.RegisterForUnhandledEvent('EndOfRun_CompareRuns', (baseRun, compareRun) =>
// this.setComparison(baseRun, compareRun)
// );
$.RegisterForUnhandledEvent('EndOfRun_Show', (reason) => this.showNewEndOfRun(reason));
$.RegisterForUnhandledEvent('EndOfRun_Result_RunUpload', (uploaded, cosXP, rankXP, lvlGain) =>
this.updateRunUploadStatus(uploaded, cosXP, rankXP, lvlGain)
Expand Down
9 changes: 9 additions & 0 deletions scripts/pages/leaderboards/entry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,15 @@ class LeaderboardEntryHandler {
$.DispatchEvent('LeaderboardEntry_PlayReplay', index);
}
});

items.push({
label: $.Localize('#Action_SetComparisonRun'),
icon: 'file://{images}/chart-timeline.svg',
style: 'icon-color-light-blue',
jsCallback: () => {
$.DispatchEvent('LeaderboardEntry_SetComparisonRun', index);
}
});
}

if (timeData.type === LeaderboardEntryType.ONLINE || timeData.type === LeaderboardEntryType.ONLINE_CACHED) {
Expand Down
7 changes: 2 additions & 5 deletions scripts/types-mom/apis.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
type RunMetadata = import('common/timer').RunMetadata;
type Gamemode = import('common/web').Gamemode;

declare namespace MomentumAPI {
Expand Down Expand Up @@ -280,12 +281,8 @@ declare namespace SpectatorAPI {
function GetSpecList(): steamID[];
}

/** Probably changing soon, doing weak types. */
declare namespace RunComparisonsAPI {
function GetLoadedComparison(): any;
function IsComparisonLoaded(): any;
function GetLoadedComparisonSpeed(...args: any[]): any;
function GetLoadedComparisonOverallDiff(arg: any): any;
function GetComparisonRun(): RunMetadata;
}

declare namespace ZonesAPI {
Expand Down
11 changes: 3 additions & 8 deletions scripts/types-mom/events.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ interface GlobalEventNameMap {

OnNewChatEntry: (panel: GenericPanel & { message: string; author_name: string; author_xuid: string }) => void;

/** Fired when the JS panel should update what it's showing */
HudCompare_Update: () => void;
ComparisonRunUpdated: () => void;

// TODO: Old, remove after rio stuff is in
OnMomentumTimerStateChange: (arg1: any, arg2: any) => any;
Expand Down Expand Up @@ -271,12 +270,6 @@ interface GlobalEventNameMap {
/** Fired when the end of run panel should be hidden */
EndOfRun_Hide: () => void;

/** Fired when the end of run panel should set the two runs to compare. baseRun is compared to compareRun */
EndOfRun_CompareRuns: (
baseRun: import('common/timer').CPPRun_OLD,
compareRun: import('common/timer').CPPRun_OLD
) => void;

/** Fired when the replay recording finishes and passes whether writing the file was successful */
EndOfRun_Result_RunSave: (saved: boolean) => void;

Expand Down Expand Up @@ -322,6 +315,8 @@ interface GlobalEventNameMap {

LeaderboardEntry_PlayReplay: (itemIndex: int32) => void;

LeaderboardEntry_SetComparisonRun: (itemIndex: int32) => void;

LeaderboardEntry_DeleteReplay: (itemIndex: int32) => void;

/**
Expand Down

0 comments on commit c8b575d

Please sign in to comment.