@@ -7,6 +7,7 @@ import type {
7
7
GameEvent ,
8
8
GameParser ,
9
9
RoomGameEvent ,
10
+ TextGameEvent ,
10
11
} from './game.types' ;
11
12
import { GameEventType , IndicatorType } from './game.types' ;
12
13
@@ -156,14 +157,14 @@ export class GameParserImpl implements GameParser {
156
157
* If the previous sent text was '\n' and the next text is '\n',
157
158
* then we'll skip emitting the second newline.
158
159
*/
159
- private previousGameText : string ;
160
+ private previousTextGameEvent : TextGameEvent ;
160
161
161
162
constructor ( ) {
162
163
this . gameEventsSubject$ = new rxjs . Subject < GameEvent > ( ) ;
163
164
this . activeTags = [ ] ;
164
165
this . compassDirections = [ ] ;
165
166
this . gameText = '' ;
166
- this . previousGameText = '' ;
167
+ this . previousTextGameEvent = { type : GameEventType . TEXT , text : '' } ;
167
168
}
168
169
169
170
/**
@@ -219,7 +220,7 @@ export class GameParserImpl implements GameParser {
219
220
220
221
protected parseLine ( line : string ) : void {
221
222
// Ensure we start fresh with each line.
222
- this . consumeGameText ( ) ;
223
+ this . gameText = '' ;
223
224
224
225
logger . debug ( 'parsing line' , { line } ) ;
225
226
@@ -308,12 +309,22 @@ export class GameParserImpl implements GameParser {
308
309
}
309
310
310
311
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
+ } ) ;
313
324
314
325
// Avoid sending multiple blank newlines.
315
- if ( previousWasNewline && ! currentIsNewline ) {
316
- this . emitTextGameEvent ( this . consumeGameText ( ) ) ;
326
+ if ( ! currentIsNewline || ( currentIsNewline && ! previousWasNewline ) ) {
327
+ this . emitTextGameEvent ( this . gameText ) ;
317
328
}
318
329
}
319
330
}
@@ -458,14 +469,14 @@ export class GameParserImpl implements GameParser {
458
469
if ( tagId . startsWith ( 'room ' ) ) {
459
470
this . emitRoomGameEvent ( {
460
471
tagId,
461
- roomText : this . consumeGameText ( ) ,
472
+ roomText : this . gameText ,
462
473
} ) ;
463
474
}
464
475
// Emit the experience info because we are at the end of the tag.
465
476
// Example: `<component id='exp Attunement'> Attunement: 1 46% attentive </component>`
466
477
else if ( tagId . startsWith ( 'exp ' ) ) {
467
478
this . emitExperienceGameEvent (
468
- this . parseToExperienceGameEvent ( this . consumeGameText ( ) )
479
+ this . parseToExperienceGameEvent ( this . gameText )
469
480
) ;
470
481
}
471
482
break ;
@@ -483,17 +494,17 @@ export class GameParserImpl implements GameParser {
483
494
case 'spell' :
484
495
// Emit the spell because we are at the end of the tag.
485
496
// Example: `<spell>Fire Shards</spell>`
486
- this . emitSpellGameEvent ( this . consumeGameText ( ) ) ;
497
+ this . emitSpellGameEvent ( this . gameText ) ;
487
498
break ;
488
499
case 'left' :
489
500
// Emit the left hand item because we are at the end of the tag.
490
501
// Example: `<left>red backpack</left>`
491
- this . emitLeftHandGameEvent ( this . consumeGameText ( ) ) ;
502
+ this . emitLeftHandGameEvent ( this . gameText ) ;
492
503
break ;
493
504
case 'right' :
494
505
// Emit the right hand item because we are at the end of the tag.
495
506
// Example: `<right>Empty</right>`
496
- this . emitRightHandGameEvent ( this . consumeGameText ( ) ) ;
507
+ this . emitRightHandGameEvent ( this . gameText ) ;
497
508
break ;
498
509
}
499
510
@@ -551,28 +562,16 @@ export class GameParserImpl implements GameParser {
551
562
return this . getAncestorTag ( tagName ) !== undefined ;
552
563
}
553
564
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
-
571
565
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 = {
573
570
type : GameEventType . TEXT ,
574
571
text : unescapeEntities ( text ) ,
575
- } ) ;
572
+ } ;
573
+ this . emitGameEvent ( event ) ;
574
+ this . previousTextGameEvent = event ;
576
575
}
577
576
578
577
protected emitPushBoldGameEvent ( ) : void {
@@ -607,13 +606,11 @@ export class GameParserImpl implements GameParser {
607
606
} ) : void {
608
607
const { tagId, active } = options ;
609
608
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
+ } ) ;
617
614
}
618
615
619
616
protected emitSpellGameEvent ( spell : string ) : void {
@@ -698,12 +695,10 @@ export class GameParserImpl implements GameParser {
698
695
} ) : void {
699
696
const { tagId, roomText } = options ;
700
697
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
+ } ) ;
707
702
}
708
703
709
704
protected emitServerTimeGameEvent ( time : number ) : void {
@@ -723,5 +718,6 @@ export class GameParserImpl implements GameParser {
723
718
protected emitGameEvent ( gameEvent : GameEvent ) : void {
724
719
logger . debug ( 'emitting game event' , { gameEvent } ) ;
725
720
this . gameEventsSubject$ . next ( gameEvent ) ;
721
+ this . gameText = '' ;
726
722
}
727
723
}
0 commit comments