Skip to content

Commit

Permalink
Refactor GameStateEventSubscriber to use individual handlers
Browse files Browse the repository at this point in the history
Still need to figure out injection and write tests
  • Loading branch information
dshaneg committed Mar 1, 2018
1 parent 5b8b600 commit 17ff3b1
Show file tree
Hide file tree
Showing 9 changed files with 96 additions and 19 deletions.
2 changes: 1 addition & 1 deletion src/domain/event-publisher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export interface EventPublisher {
export class Publisher implements EventPublisher {
constructor(private subscribers: EventSubscriber[]) {}

publish (event: any): void {
publish(event: any): void {
this.subscribers.forEach(subscriber => {
subscriber.handle(event);
});
Expand Down
23 changes: 6 additions & 17 deletions src/domain/game-state-event-subscriber.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,16 @@

import { EventSubscriber } from './event-subscriber';
import { GameState } from '../state/game-state';
import { GameMap } from '../domain/game-map';
import { StateChangeHandler } from './state-change-handler/state-change-handler';

export class GameStateEventSubscriber implements EventSubscriber {
constructor(private map: GameMap, private gameState: GameState) {}
constructor(private gameState: GameState, private handlers: StateChangeHandler[]) {}

handle(event: any): void {
switch (event.topic) {
case 'player.location.moved':
this.gameState.setCurrentLocation(this.map.get(event.currentNode.id));
break;
case 'player.inventory.added':
this.gameState.addInventory(event.item, event.count);
break;
case 'player.inventory.item-equipped':
this.gameState.equip(event.item);
break;
case 'game.started':
this.gameState.start();
break;
case 'game.stopped':
this.gameState.stop();
const handler = this.handlers.find(element => element.handles(event));

if (handler) {
handler.handle(event, this.gameState);
}
}
}
12 changes: 12 additions & 0 deletions src/domain/state-change-handler/game-started-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { StateChangeHandler } from './state-change-handler';
import { GameState } from '../../state/game-state';

export class GameStartedHandler implements StateChangeHandler {
public handles(event: any): boolean {
return event.topic === 'game.started';
}

public handle(event: any, gameState: GameState): void {
gameState.start();
}
}
12 changes: 12 additions & 0 deletions src/domain/state-change-handler/game-stopped-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { StateChangeHandler } from './state-change-handler';
import { GameState } from '../../state/game-state';

export class GameStoppedHandler implements StateChangeHandler {
public handles(event: any): boolean {
return event.topic === 'game.stopped';
}

public handle(event: any, gameState: GameState): void {
gameState.stop();
}
}
12 changes: 12 additions & 0 deletions src/domain/state-change-handler/player-inventory-added-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { StateChangeHandler } from './state-change-handler';
import { GameState } from '../../state/game-state';

export class PlayerInventoryAddedHandler implements StateChangeHandler {
public handles(event: any): boolean {
return event.topic === 'player.inventory.added';
}

public handle(event: any, gameState: GameState): void {
gameState.addInventory(event.item, event.count);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { StateChangeHandler } from './state-change-handler';
import { GameState } from '../../state/game-state';

export class PlayerInventoryEquippedHandler implements StateChangeHandler {
public handles(event: any): boolean {
return event.topic === 'player.inventory.equipped';
}

public handle(event: any, gameState: GameState): void {
gameState.equip(event.item);
}
}
16 changes: 16 additions & 0 deletions src/domain/state-change-handler/player-location-moved-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { StateChangeHandler } from './state-change-handler';
import { GameState } from '../../state/game-state';
import { MapNodeRepository } from '../../map-node-repository';

export class PlayerLocationMovedHandler implements StateChangeHandler {
constructor(private mapNodeRepository: MapNodeRepository) {}

public handles(event: any): boolean {
return event.topic === 'player.location.moved';
}

public handle(event: any, gameState: GameState): void {
const targetNode = this.mapNodeRepository.getMap().get(event.currentNode.id);
gameState.setCurrentLocation(targetNode);
}
}
6 changes: 6 additions & 0 deletions src/domain/state-change-handler/state-change-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { GameState } from '../../state/game-state';

export interface StateChangeHandler {
handles(event: any): boolean;
handle(event: any, gameState: GameState): void;
}
20 changes: 19 additions & 1 deletion src/game-engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ import { QueueingEventSubscriber } from './domain/queueing-event-subscriber';
import { GameStateEventSubscriber } from './domain/game-state-event-subscriber';
import { Publisher } from './domain/event-publisher';

import { GameStartedHandler } from './domain/state-change-handler/game-started-handler';
import { GameStoppedHandler } from './domain/state-change-handler/game-stopped-handler';
import { PlayerInventoryAddedHandler } from './domain/state-change-handler/player-inventory-added-handler';
import { PlayerInventoryEquippedHandler } from './domain/state-change-handler/player-inventory-equipped-handler';
import { PlayerLocationMovedHandler } from './domain/state-change-handler/player-location-moved-handler';

// game command handlers
export class GameEngine {
constructor(
Expand All @@ -32,7 +38,7 @@ export class GameEngine {
// this subscriber queues events for the current command then those events are returned at the end of the function
const queueingSubscriber = new QueueingEventSubscriber();
// this subscriber updates the gamestate each time an event is published. Giving event sourcing a try, but have to only let the events drive changes to the state
const stateSubscriber = new GameStateEventSubscriber(this.mapNodeRepository.getMap(), gameState);
const stateSubscriber = this.createStateSubscriber(gameState);
const publisher = new Publisher([queueingSubscriber, stateSubscriber]);

const command = this.parser.parse(inputText);
Expand All @@ -50,4 +56,16 @@ export class GameEngine {

return { command: inputText, session: gameState.sessionToken, events: queueingSubscriber.events };
}

private createStateSubscriber(gameState: GameState) {
const handlers = [
new PlayerLocationMovedHandler(this.mapNodeRepository),
new PlayerInventoryAddedHandler(),
new PlayerInventoryEquippedHandler(),
new GameStartedHandler(),
new GameStoppedHandler()
];

return new GameStateEventSubscriber(gameState, handlers);
}
}

0 comments on commit 17ff3b1

Please sign in to comment.