Skip to content

Commit

Permalink
raidboss: Add support for netregexes in timelines (#5939)
Browse files Browse the repository at this point in the history
Closes #5145

Obviously needs plenty of testing etc.

Example added to `test.txt` timeline, can be triggered with `/e
testNetRegexTimeline`.

Took the opportunity to refactor the `TimelineParser.parse` function to
extract out some of the line matching, so there wasn't a need for a
30+-space-indented set of lines, and to allow reusing some of the logic
for the rest of the line matching after the regex.
  • Loading branch information
valarnin authored Nov 29, 2023
1 parent b4e5b8c commit 7b2adb3
Show file tree
Hide file tree
Showing 7 changed files with 307 additions and 101 deletions.
3 changes: 3 additions & 0 deletions ui/raidboss/data/00-misc/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,7 @@ const triggerSet: TriggerSet<Data> = {
timelineReplace: [
{
locale: 'de',
missingTranslations: true,
replaceSync: {
'You bid farewell to the striking dummy': 'Du winkst der Trainingspuppe zum Abschied zu',
'You bow courteously to the striking dummy':
Expand Down Expand Up @@ -514,6 +515,7 @@ const triggerSet: TriggerSet<Data> = {
},
{
locale: 'cn',
missingTranslations: true,
replaceSync: {
'You bid farewell to the striking dummy': '.*向木人告别',
'You bow courteously to the striking dummy': '.*恭敬地对木人行礼',
Expand Down Expand Up @@ -552,6 +554,7 @@ const triggerSet: TriggerSet<Data> = {
},
{
locale: 'ko',
missingTranslations: true,
replaceSync: {
'You bid farewell to the striking dummy': '.*나무인형에게 작별 인사를 합니다',
'You bow courteously to the striking dummy': '.*나무인형에게 공손하게 인사합니다',
Expand Down
1 change: 1 addition & 0 deletions ui/raidboss/data/00-misc/test.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ hideall "--sync--"

0 "--Reset--" sync /You bid farewell to the striking dummy/ window 10000 jump 0

0 "--sync--" GameLog { "line": "testNetRegexTimeline" } window 100000,100000
0 "--sync--" sync /:Engage!/ window 100000,100000
0 "--sync--" sync /:You bow courteously to the striking dummy/ window 0,1
3 "Almagest"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { UnreachableCode } from '../../../../resources/not_reached';
import { LogEvent } from '../../../../types/event';
import { EventResponses, LogEvent } from '../../../../types/event';
import { LooseTimelineTrigger } from '../../../../types/trigger';
import { TimelineController } from '../../timeline';
import { TimelineReplacement, TimelineStyle } from '../../timeline_parser';
Expand Down Expand Up @@ -63,12 +63,17 @@ export default class RaidEmulatorTimelineController extends TimelineController {
throw new UnreachableCode();
}

public override OnNetLog(_e: EventResponses['LogLine']): void {
throw new UnreachableCode();
}

public onEmulatorLogEvent(logs: LineEvent[]): void {
if (!this.activeTimeline)
return;

for (const line of logs) {
this.activeTimeline.OnLogLine(line.convertedLine, line.timestamp);
this.activeTimeline.OnNetLogLine(line.networkLine, line.timestamp);
// Only call _OnUpdateTimer if we have a timebase from the previous call to OnLogLine
// This avoids spamming the console with a ton of messages
if (this.activeTimeline.timebase)
Expand Down
4 changes: 4 additions & 0 deletions ui/raidboss/raidboss.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,8 @@ UserConfig.getUserConfigLocation('raidboss', defaultOptions, () => {
addOverlayListener('onLogEvent', (e) => {
timelineController.OnLogEvent(e);
});

addOverlayListener('LogLine', (e) => {
timelineController.OnNetLog(e);
});
});
61 changes: 47 additions & 14 deletions ui/raidboss/timeline.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { commonNetRegex } from '../../resources/netregexes';
import { UnreachableCode } from '../../resources/not_reached';
import { LocaleRegex } from '../../resources/translations';
import { LogEvent } from '../../types/event';
import { EventResponses, LogEvent } from '../../types/event';
import { CactbotBaseRegExp } from '../../types/net_trigger';
import { LooseTimelineTrigger, RaidbossFileData } from '../../types/trigger';

Expand Down Expand Up @@ -137,6 +137,7 @@ export class Timeline {
private activeText: string;

protected activeSyncs: Sync[];
protected activeNetSyncs: Sync[];
private activeEvents: Event[];
private keepAliveEvents: {
event: Event;
Expand Down Expand Up @@ -184,6 +185,7 @@ export class Timeline {

// Not sorted.
this.activeSyncs = [];
this.activeNetSyncs = [];
// Sorted by event occurrence time.
this.activeEvents = [];
// Events that are no longer active but we are keeping on screen briefly.
Expand Down Expand Up @@ -281,36 +283,57 @@ export class Timeline {

private _CollectActiveSyncs(fightNow: number): void {
this.activeSyncs = [];
this.activeNetSyncs = [];
for (let i = this.nextSyncEnd; i < this.syncEnds.length; ++i) {
const syncEnd = this.syncEnds[i];
if (syncEnd && syncEnd.start <= fightNow)
this.activeSyncs.push(syncEnd);
if (syncEnd && syncEnd.start <= fightNow) {
if (syncEnd.regexType === 'parsed')
this.activeSyncs.push(syncEnd);
else
this.activeNetSyncs.push(syncEnd);
}
}

if (
this.activeLastForceJumpSync !== undefined &&
this.activeLastForceJumpSync.start <= fightNow &&
this.activeLastForceJumpSync.end > fightNow
) {
this.activeSyncs.push(this.activeLastForceJumpSync);
if (this.activeLastForceJumpSync.regexType === 'parsed')
this.activeSyncs.push(this.activeLastForceJumpSync);
else
this.activeNetSyncs.push(this.activeLastForceJumpSync);
} else {
this.activeLastForceJumpSync = undefined;
}
}

public OnLogLineJump(sync: Sync, currentTime: number): void {
if ('jump' in sync) {
if (!sync.jump) {
this.SyncTo(0, currentTime, sync);
this.Stop();
} else {
this.SyncTo(sync.jump, currentTime, sync);
}
} else {
this.SyncTo(sync.time, currentTime, sync);
}
}

public OnLogLine(line: string, currentTime: number): void {
for (const sync of this.activeSyncs) {
if (sync.regex.test(line)) {
if ('jump' in sync) {
if (!sync.jump) {
this.SyncTo(0, currentTime, sync);
this.Stop();
} else {
this.SyncTo(sync.jump, currentTime, sync);
}
} else {
this.SyncTo(sync.time, currentTime, sync);
}
this.OnLogLineJump(sync, currentTime);
break;
}
}
}

public OnNetLogLine(line: string, currentTime: number): void {
for (const sync of this.activeNetSyncs) {
if (sync.regex.test(line)) {
this.OnLogLineJump(sync, currentTime);
break;
}
}
Expand Down Expand Up @@ -723,6 +746,16 @@ export class TimelineController {
}
}

OnNetLog(e: EventResponses['LogLine']): void {
if (!this.activeTimeline)
return;

const currentTime = Date.now();

// TODO: Check for the countdown => wipe => engage logic for network lines
this.activeTimeline.OnNetLogLine(e.rawLine, currentTime);
}

public SetActiveTimeline(
timelineFiles: string[],
timelines: string[],
Expand Down
Loading

0 comments on commit 7b2adb3

Please sign in to comment.