summaryrefslogtreecommitdiff
path: root/engine/systems/NetworkUpdate.ts
blob: 6d135747cc93dcf54a451cb175a07ecd4297b7fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import { System, SystemNames } from '.';
import { Game } from '../Game';
import { ComponentNames } from '../components';
import {
  type MessageQueueProvider,
  type MessagePublisher,
  type MessageProcessor,
  MessageType,
  EntityUpdateBody
} from '../network';

export class NetworkUpdate extends System {
  private queueProvider: MessageQueueProvider;
  private publisher: MessagePublisher;
  private messageProcessor: MessageProcessor;

  private entityUpdateTimers: Map<string, number>;

  constructor(
    queueProvider: MessageQueueProvider,
    publisher: MessagePublisher,
    messageProcessor: MessageProcessor
  ) {
    super(SystemNames.NetworkUpdate);

    this.queueProvider = queueProvider;
    this.publisher = publisher;
    this.messageProcessor = messageProcessor;

    this.entityUpdateTimers = new Map();
  }

  public update(dt: number, game: Game) {
    // 1. process new messages
    this.queueProvider
      .getNewMessages()
      .forEach((message) => this.messageProcessor.process(message));
    this.queueProvider.clearMessages();

    // 2. send entity updates
    const updateMessages: EntityUpdateBody[] = [];
    game.forEachEntityWithComponent(
      ComponentNames.NetworkUpdateable,
      (entity) => {
        let timer = this.entityUpdateTimers.get(entity.id) ?? dt;
        timer -= dt;
        this.entityUpdateTimers.set(entity.id, timer);

        if (timer > 0) return;
        this.entityUpdateTimers.set(entity.id, this.getNextUpdateTimeMs());

        if (entity.hasComponent(ComponentNames.NetworkUpdateable)) {
          updateMessages.push({
            id: entity.id,
            args: entity.serialize()
          });
        }
      }
    );
    this.publisher.addMessage({
      type: MessageType.UPDATE_ENTITIES,
      body: updateMessages
    });

    // 3. publish changes
    this.publisher.publish();
  }

  private getNextUpdateTimeMs() {
    return Math.random() * 70 + 50;
  }
}