@haelp/teto
Version:
A typescript-based controllable TETR.IO client.
117 lines (116 loc) • 3.83 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "IGEHandler", {
enumerable: true,
get: function() {
return IGEHandler;
}
});
const _utils = require("../utils");
class IGEHandler {
/** @hidden */ players;
/** @hidden */ iid = 0;
/** @hidden */ extract(data) {
return JSON.parse(data);
}
/** @hidden */ stringify(data) {
return JSON.stringify(data);
}
/**
* Manages network IGE cancelling
* @param players - list of player ids
*/ constructor(players){
this.players = new _utils.polyfills.Map();
players.forEach((player)=>{
this.players.set(player, this.stringify({
incoming: 0,
outgoing: []
}));
});
}
/**
* Sends a message to a player.
* @param options - info on sending player
* @param options.playerID - The ID of the player to send the message to.
* @param options.amount - The amount of the message.
* @throws {Error} If the player is not found.
*/ send({ playerID, amount }) {
if (amount === 0) return;
const player = this.players.get(playerID);
const iid = ++this.iid;
if (!player) throw new Error(`player not found: player with id ${playerID} not in ${[
...this.players.keys()
].join(", ")}`);
this.players.set(playerID, JSON.stringify({
incoming: JSON.parse(player).incoming,
outgoing: [
...this.extract(player).outgoing,
{
iid,
amount
}
]
}));
// console.log(
// "send",
// playerID,
// Object.fromEntries(
// [...this.players.entries()].map(([k, v]) => [k, this.extract(v)])
// )
// );
}
/**
* Receives a garbage from a player and processes it.
* @param garbage - garbage object of data
* @param garbage.playerID - The ID of the player sending the garbage.
* @param garbage.ackiid - The IID of the last acknowledged item.
* @param garbage.iid - The IID of the incoming item.
* @param garbage.amount - The amount of the incoming item.
* @returns The remaining amount after processing the message.
* @throws {Error} If the player is not found.
*/ receive({ playerID, ackiid, iid, amount }) {
const player = this.players.get(playerID);
if (!player) throw new Error(`player not found: player with id ${playerID} not in ${[
...this.players.keys()
].join(", ")}`);
const p = this.extract(player);
const incomingIID = Math.max(iid, p.incoming ?? 0);
const newIGEs = [];
let runningAmount = amount;
p.outgoing.forEach((item)=>{
if (item.iid <= ackiid) return;
const amt = Math.min(item.amount, runningAmount);
item.amount -= amt;
runningAmount -= amt;
if (item.amount > 0) newIGEs.push(item);
});
this.players.set(playerID, this.stringify({
incoming: incomingIID,
outgoing: newIGEs
}));
// console.log(
// "receive",
// playerID,
// Object.fromEntries(
// [...this.players.entries()].map(([k, v]) => [k, this.extract(v)])
// )
// );
return runningAmount;
}
snapshot() {
return {
players: Object.fromEntries(this.players.entries()),
iid: this.iid
};
}
fromSnapshot(snapshot) {
this.players = new _utils.polyfills.Map(Object.entries(snapshot.players).map(([k, v])=>[
Number(k),
v
]));
this.iid = snapshot.iid;
}
}
//# sourceMappingURL=ige.js.map