Skip to content

Commit c5b74c6

Browse files
committed
feat: avoid emitting back to back newline text events
1 parent 06c0923 commit c5b74c6

File tree

1 file changed

+40
-44
lines changed

1 file changed

+40
-44
lines changed

electron/main/game/game.parser.ts

+40-44
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type {
77
GameEvent,
88
GameParser,
99
RoomGameEvent,
10+
TextGameEvent,
1011
} from './game.types';
1112
import { GameEventType, IndicatorType } from './game.types';
1213

@@ -156,14 +157,14 @@ export class GameParserImpl implements GameParser {
156157
* If the previous sent text was '\n' and the next text is '\n',
157158
* then we'll skip emitting the second newline.
158159
*/
159-
private previousGameText: string;
160+
private previousTextGameEvent: TextGameEvent;
160161

161162
constructor() {
162163
this.gameEventsSubject$ = new rxjs.Subject<GameEvent>();
163164
this.activeTags = [];
164165
this.compassDirections = [];
165166
this.gameText = '';
166-
this.previousGameText = '';
167+
this.previousTextGameEvent = { type: GameEventType.TEXT, text: '' };
167168
}
168169

169170
/**
@@ -219,7 +220,7 @@ export class GameParserImpl implements GameParser {
219220

220221
protected parseLine(line: string): void {
221222
// Ensure we start fresh with each line.
222-
this.consumeGameText();
223+
this.gameText = '';
223224

224225
logger.debug('parsing line', { line });
225226

@@ -308,12 +309,22 @@ export class GameParserImpl implements GameParser {
308309
}
309310

310311
if (this.gameText.length > 0) {
311-
const previousWasNewline = this.previousGameText === '\n';
312-
const currentIsNewline = this.gameText === '\n';
312+
const previousText = this.previousTextGameEvent.text;
313+
const currentText = this.gameText;
314+
315+
const previousWasNewline = /^(\n+)$/.test(previousText);
316+
const currentIsNewline = /^(\n+)$/.test(currentText);
317+
318+
logger.debug('comparing previous and current game text', {
319+
previousText,
320+
currentText,
321+
previousWasNewline,
322+
currentIsNewline,
323+
});
313324

314325
// Avoid sending multiple blank newlines.
315-
if (previousWasNewline && !currentIsNewline) {
316-
this.emitTextGameEvent(this.consumeGameText());
326+
if (!currentIsNewline || (currentIsNewline && !previousWasNewline)) {
327+
this.emitTextGameEvent(this.gameText);
317328
}
318329
}
319330
}
@@ -458,14 +469,14 @@ export class GameParserImpl implements GameParser {
458469
if (tagId.startsWith('room ')) {
459470
this.emitRoomGameEvent({
460471
tagId,
461-
roomText: this.consumeGameText(),
472+
roomText: this.gameText,
462473
});
463474
}
464475
// Emit the experience info because we are at the end of the tag.
465476
// Example: `<component id='exp Attunement'> Attunement: 1 46% attentive </component>`
466477
else if (tagId.startsWith('exp ')) {
467478
this.emitExperienceGameEvent(
468-
this.parseToExperienceGameEvent(this.consumeGameText())
479+
this.parseToExperienceGameEvent(this.gameText)
469480
);
470481
}
471482
break;
@@ -483,17 +494,17 @@ export class GameParserImpl implements GameParser {
483494
case 'spell':
484495
// Emit the spell because we are at the end of the tag.
485496
// Example: `<spell>Fire Shards</spell>`
486-
this.emitSpellGameEvent(this.consumeGameText());
497+
this.emitSpellGameEvent(this.gameText);
487498
break;
488499
case 'left':
489500
// Emit the left hand item because we are at the end of the tag.
490501
// Example: `<left>red backpack</left>`
491-
this.emitLeftHandGameEvent(this.consumeGameText());
502+
this.emitLeftHandGameEvent(this.gameText);
492503
break;
493504
case 'right':
494505
// Emit the right hand item because we are at the end of the tag.
495506
// Example: `<right>Empty</right>`
496-
this.emitRightHandGameEvent(this.consumeGameText());
507+
this.emitRightHandGameEvent(this.gameText);
497508
break;
498509
}
499510

@@ -551,28 +562,16 @@ export class GameParserImpl implements GameParser {
551562
return this.getAncestorTag(tagName) !== undefined;
552563
}
553564

554-
/**
555-
* Returns the current value of game text then clears it.
556-
* Moves the old value to the previous game text variable.
557-
* This is a convenience method for performing these two steps.
558-
*/
559-
protected consumeGameText(): string {
560-
const oldValue = this.gameText; // what we're consuming
561-
const newValue = ''; // what to reset to
562-
563-
// Track the previous consumed game text.
564-
// This is how we mitigate sending multiple blank newlines.
565-
this.previousGameText = oldValue;
566-
this.gameText = newValue;
567-
568-
return oldValue;
569-
}
570-
571565
protected emitTextGameEvent(text: string): void {
572-
this.emitGameEvent({
566+
// Keep track of the last text game event so we can avoid sending
567+
// multiple blank newlines. Before sending a new text game event,
568+
// we compare the outgoing text with the previously sent.
569+
const event: GameEvent = {
573570
type: GameEventType.TEXT,
574571
text: unescapeEntities(text),
575-
});
572+
};
573+
this.emitGameEvent(event);
574+
this.previousTextGameEvent = event;
576575
}
577576

578577
protected emitPushBoldGameEvent(): void {
@@ -607,13 +606,11 @@ export class GameParserImpl implements GameParser {
607606
}): void {
608607
const { tagId, active } = options;
609608
const indicator = INDICATOR_ID_TO_TYPE_MAP[tagId];
610-
if (indicator) {
611-
this.emitGameEvent({
612-
type: GameEventType.INDICATOR,
613-
indicator,
614-
active,
615-
});
616-
}
609+
this.emitGameEvent({
610+
type: GameEventType.INDICATOR,
611+
indicator,
612+
active,
613+
});
617614
}
618615

619616
protected emitSpellGameEvent(spell: string): void {
@@ -698,12 +695,10 @@ export class GameParserImpl implements GameParser {
698695
}): void {
699696
const { tagId, roomText } = options;
700697
const roomProperty = ROOM_ID_TO_EVENT_PROPERTY_MAP[tagId];
701-
if (roomProperty) {
702-
this.emitGameEvent({
703-
type: GameEventType.ROOM,
704-
[roomProperty]: unescapeEntities(roomText),
705-
});
706-
}
698+
this.emitGameEvent({
699+
type: GameEventType.ROOM,
700+
[roomProperty]: unescapeEntities(roomText),
701+
});
707702
}
708703

709704
protected emitServerTimeGameEvent(time: number): void {
@@ -723,5 +718,6 @@ export class GameParserImpl implements GameParser {
723718
protected emitGameEvent(gameEvent: GameEvent): void {
724719
logger.debug('emitting game event', { gameEvent });
725720
this.gameEventsSubject$.next(gameEvent);
721+
this.gameText = '';
726722
}
727723
}

0 commit comments

Comments
 (0)