{"version":3,"sources":["../../../src/engine/multiplayer/ige.ts"],"sourcesContent":["import { polyfills } from \"../utils\";\n\ninterface GarbageRecord {\n  amount: number;\n  iid: number;\n}\n\ninterface PlayerData {\n  incoming: number;\n  outgoing: GarbageRecord[];\n}\n\nexport interface IGEHandlerSnapshot {\n  iid: number;\n  players: { [key: number]: string };\n}\n/**\n * Manages network IGE cancelling\n */\nexport class IGEHandler {\n  /** @hidden */\n  private players: polyfills.Map<\n    number,\n    // { incoming: number; outgoing: GarbageRecord[] }\n    //! there was an issue where as an object some garbage numbers would magically turn into other numbers, wtf js\n    string\n  >;\n  /** @hidden */\n  private iid = 0;\n\n  /** @hidden */\n  private extract(data: string): PlayerData {\n    return JSON.parse(data);\n  }\n\n  /** @hidden */\n  private stringify(data: PlayerData): string {\n    return JSON.stringify(data);\n  }\n\n  /**\n   * Manages network IGE cancelling\n   * @param players - list of player ids\n   */\n  constructor(players: number[]) {\n    this.players = new polyfills.Map();\n    players.forEach((player) => {\n      this.players.set(player, this.stringify({ incoming: 0, outgoing: [] }));\n    });\n  }\n\n  /**\n   * Sends a message to a player.\n   * @param options - info on sending player\n   * @param options.playerID - The ID of the player to send the message to.\n   * @param options.amount - The amount of the message.\n   * @throws {Error} If the player is not found.\n   */\n  send({ playerID, amount }: { playerID: number; amount: number }) {\n    if (amount === 0) return;\n    const player = this.players.get(playerID);\n    const iid = ++this.iid;\n\n    if (!player)\n      throw new Error(\n        `player not found: player with id ${playerID} not in ${[\n          ...(this.players.keys() as any)\n        ].join(\", \")}`\n      );\n\n    this.players.set(\n      playerID,\n      JSON.stringify({\n        incoming: JSON.parse(player).incoming,\n        outgoing: [...this.extract(player).outgoing, { iid, amount }]\n      })\n    );\n\n    // console.log(\n    //   \"send\",\n    //   playerID,\n    //   Object.fromEntries(\n    //     [...this.players.entries()].map(([k, v]) => [k, this.extract(v)])\n    //   )\n    // );\n  }\n\n  /**\n   * Receives a garbage from a player and processes it.\n   * @param garbage - garbage object of data\n   * @param garbage.playerID - The ID of the player sending the garbage.\n   * @param garbage.ackiid - The IID of the last acknowledged item.\n   * @param garbage.iid - The IID of the incoming item.\n   * @param garbage.amount - The amount of the incoming item.\n   * @returns The remaining amount after processing the message.\n   * @throws {Error} If the player is not found.\n   */\n  receive({\n    playerID,\n    ackiid,\n    iid,\n    amount\n  }: {\n    playerID: number;\n    ackiid: number;\n    iid: number;\n    amount: number;\n  }) {\n    const player = this.players.get(playerID);\n    if (!player)\n      throw new Error(\n        `player not found: player with id ${playerID} not in ${[\n          ...(this.players.keys() as any)\n        ].join(\", \")}`\n      );\n\n    const p = this.extract(player);\n\n    const incomingIID = Math.max(iid, p.incoming ?? 0);\n\n    const newIGEs: GarbageRecord[] = [];\n\n    let runningAmount = amount;\n    p.outgoing.forEach((item) => {\n      if (item.iid <= ackiid) return;\n      const amt = Math.min(item.amount, runningAmount);\n      item.amount -= amt;\n      runningAmount -= amt;\n      if (item.amount > 0) newIGEs.push(item);\n    });\n\n    this.players.set(\n      playerID,\n      this.stringify({ incoming: incomingIID, outgoing: newIGEs })\n    );\n\n    // console.log(\n    //   \"receive\",\n    //   playerID,\n    //   Object.fromEntries(\n    //     [...this.players.entries()].map(([k, v]) => [k, this.extract(v)])\n    //   )\n    // );\n\n    return runningAmount;\n  }\n\n  snapshot(): IGEHandlerSnapshot {\n    return {\n      players: Object.fromEntries(this.players.entries()),\n      iid: this.iid\n    };\n  }\n\n  fromSnapshot(snapshot: IGEHandlerSnapshot) {\n    this.players = new polyfills.Map(\n      Object.entries(snapshot.players).map(([k, v]) => [Number(k), v])\n    );\n    this.iid = snapshot.iid;\n  }\n}\n"],"names":["polyfills","IGEHandler","players","iid","extract","data","JSON","parse","stringify","Map","forEach","player","set","incoming","outgoing","send","playerID","amount","get","Error","keys","join","receive","ackiid","p","incomingIID","Math","max","newIGEs","runningAmount","item","amt","min","push","snapshot","Object","fromEntries","entries","fromSnapshot","map","k","v","Number"],"mappings":"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"}