@zaisma/game-server 1.8.0 → 1.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/room.d.ts CHANGED
@@ -98,7 +98,8 @@ export interface Room {
98
98
  /**
99
99
  * When Zaisma will end this match, an ISO time, or null. Set once the game's hosting on Zaisma rooms
100
100
  * pauses for the month (its free allowance, or its developer's budget or credit, is used), an hour after
101
- * the pause, so your game can save and tell its players (onEnding runs then); never set on your own server.
101
+ * the pause, so your game can save and tell its players (onEnding runs then); back to null when Zaisma calls the
102
+ * end off because the game's hosting started again (onEndingCancelled runs then). Never set on your own server.
102
103
  */
103
104
  readonly endsAt: string | null;
104
105
  /** Shown in room lists (the game page and Zaisma.rooms.list). A hidden room still works by code and link. */
@@ -541,6 +542,12 @@ export interface GameServer<S = any> {
541
542
  * the "ending" event. Never runs on your own server.
542
543
  */
543
544
  onEnding?(state: S, room: Room): HandlerResult<S>;
545
+ /**
546
+ * Zaisma called off the end onEnding announced, because the game's hosting started again (credit came in, its
547
+ * budget was raised or the month reset): room.endsAt is null again, the match goes on and takes new players.
548
+ * Runs once; each player's game also gets the "endingCancelled" event. Never runs on your own server.
549
+ */
550
+ onEndingCancelled?(state: S, room: Room): HandlerResult<S>;
544
551
  /**
545
552
  * The room restarted (Zaisma restarts its rooms on every update, and your own server may restart) and
546
553
  * came back with the state it last saved: restoreInfo.savedAt says when, and restoreInfo.lostDurationSec
@@ -634,7 +641,7 @@ export declare function readJoinAnswer(answer: unknown): {
634
641
  mistake: GameServerError;
635
642
  };
636
643
  /** Everything a game server object may have, in the order the docs give them. Anything else is refused. */
637
- export declare const GAME_SERVER_OPTIONS: readonly ["maximumPlayerCount", "maximumSpectatorCount", "ticksPerSec", "hostControlsEnabled", "idleCheck", "idleTimeoutSec", "awayMode", "seatHoldDurationSec", "stateSyncEnabled", "adultChatFilterEnabled", "reconnectTimeoutSec", "maximumRoomCountPerPlayer", "stateSaveIntervalSec", "setup", "onJoin", "canJoin", "onChat", "onMoved", "onLeave", "onSpectatorJoin", "onSpectatorLeave", "onAway", "onBack", "onMessage", "onBytes", "onPurchase", "onRefund", "onTick", "onEnding", "onRestored", "stateView", "onVersionUpdate", "onRequest", "schedules", "onSchedule", "onWebhook"];
644
+ export declare const GAME_SERVER_OPTIONS: readonly ["maximumPlayerCount", "maximumSpectatorCount", "ticksPerSec", "hostControlsEnabled", "idleCheck", "idleTimeoutSec", "awayMode", "seatHoldDurationSec", "stateSyncEnabled", "adultChatFilterEnabled", "reconnectTimeoutSec", "maximumRoomCountPerPlayer", "stateSaveIntervalSec", "setup", "onJoin", "canJoin", "onChat", "onMoved", "onLeave", "onSpectatorJoin", "onSpectatorLeave", "onAway", "onBack", "onMessage", "onBytes", "onPurchase", "onRefund", "onTick", "onEnding", "onEndingCancelled", "onRestored", "stateView", "onVersionUpdate", "onRequest", "schedules", "onSchedule", "onWebhook"];
638
645
  export declare const ROOM_LIMITS: {
639
646
  /** Players in one room: what one room carries at 60 ticks a second (test/load/room-load.test.ts). */
640
647
  readonly maximumPlayerCount: 100;
@@ -843,6 +850,8 @@ export type ServerMessage = {
843
850
  } | {
844
851
  type: "ending";
845
852
  endsAt: string;
853
+ } | {
854
+ type: "ending_cancelled";
846
855
  } | {
847
856
  type: "version_update";
848
857
  step: "coming" | "now";
@@ -883,6 +892,8 @@ export type ServerMessage = {
883
892
  } | {
884
893
  type: "blocks";
885
894
  playerIds: string[];
895
+ } | {
896
+ type: "friend_request";
886
897
  } | {
887
898
  type: "chat";
888
899
  fromPlayerId: string;
@@ -950,6 +961,9 @@ export type ClientMessage = {
950
961
  } | {
951
962
  type: "unblock";
952
963
  playerId: string;
964
+ } | {
965
+ type: "friend_request";
966
+ playerId: string;
953
967
  } | {
954
968
  type: "probe_answer";
955
969
  probeNumber: number;
@@ -1418,6 +1432,12 @@ export declare class RoomCore<S = any> {
1418
1432
  private tellBlocks;
1419
1433
  /** A player's game blocked a player in the room (a guest's block, or one just made), or took one back. */
1420
1434
  private sessionBlock;
1435
+ /**
1436
+ * A player's game page just sent another player here a friend request, or accepted theirs (docs/DECISIONS.md,
1437
+ * "Friend requests in games"): the room tells that player's game to have their page look now, rather than at its next check-in.
1438
+ * Zaisma's record is the request; this says only "look", never who it's from, so a lying client gains nothing.
1439
+ */
1440
+ private friendRequestTold;
1421
1441
  /** Players in the match who haven't walked away: what room lists and "playing now" count. */
1422
1442
  get playingCount(): number;
1423
1443
  /**
@@ -1664,6 +1684,11 @@ export declare class RoomCore<S = any> {
1664
1684
  * Only Zaisma rooms call it, when the game's hosting pauses.
1665
1685
  */
1666
1686
  startEnding(endsAt: string): void;
1687
+ /**
1688
+ * Zaisma calls off the end startEnding announced, since the game's hosting started again: endsAt is null, every
1689
+ * player hears it and onEndingCancelled runs, once. Only Zaisma rooms call it.
1690
+ */
1691
+ cancelEnding(): void;
1667
1692
  /** End the match: everyone hears message and why (endReason), and their connections close. */
1668
1693
  end(message: string, endReason: EndReason): void;
1669
1694
  /** The players as every player's game lists them, with why each isn't playing. */
package/src/room.js CHANGED
@@ -94,6 +94,7 @@ export const GAME_SERVER_OPTIONS = [
94
94
  "onRefund",
95
95
  "onTick",
96
96
  "onEnding",
97
+ "onEndingCancelled",
97
98
  "onRestored",
98
99
  "stateView",
99
100
  "onVersionUpdate",
@@ -1070,6 +1071,20 @@ export class RoomCore {
1070
1071
  this.tellBlocks();
1071
1072
  return null;
1072
1073
  }
1074
+ /**
1075
+ * A player's game page just sent another player here a friend request, or accepted theirs (docs/DECISIONS.md,
1076
+ * "Friend requests in games"): the room tells that player's game to have their page look now, rather than at its next check-in.
1077
+ * Zaisma's record is the request; this says only "look", never who it's from, so a lying client gains nothing.
1078
+ */
1079
+ friendRequestTold(playerId, message) {
1080
+ const otherPlayerId = message.playerId;
1081
+ if (typeof otherPlayerId !== "string" || otherPlayerId === playerId || !this.players.has(otherPlayerId))
1082
+ return "bad_message";
1083
+ if (this.hasBlockBetween(playerId, otherPlayerId))
1084
+ return null;
1085
+ this.sendText(otherPlayerId, JSON.stringify({ type: "friend_request" }));
1086
+ return null;
1087
+ }
1073
1088
  /** Players in the match who haven't walked away: what room lists and "playing now" count. */
1074
1089
  get playingCount() {
1075
1090
  return this.players.size - this.kept.size;
@@ -1690,6 +1705,8 @@ export class RoomCore {
1690
1705
  return this.sessionBlock(playerId, message, true);
1691
1706
  case "unblock":
1692
1707
  return this.sessionBlock(playerId, message, false);
1708
+ case "friend_request":
1709
+ return this.friendRequestTold(playerId, message);
1693
1710
  default:
1694
1711
  // A type this room doesn't know, maybe from a newer SDK: counted and limited above, then ignored.
1695
1712
  return typeof message.type === "string" ? null : "bad_message";
@@ -2210,6 +2227,19 @@ export class RoomCore {
2210
2227
  if (this.server.onEnding)
2211
2228
  this.run(() => this.server.onEnding(this.state, this.api), "onEnding");
2212
2229
  }
2230
+ /**
2231
+ * Zaisma calls off the end startEnding announced, since the game's hosting started again: endsAt is null, every
2232
+ * player hears it and onEndingCancelled runs, once. Only Zaisma rooms call it.
2233
+ */
2234
+ cancelEnding() {
2235
+ if (this.ended || this.endsAt === null)
2236
+ return;
2237
+ this.endsAt = null;
2238
+ this.dirty = true;
2239
+ this.sendEach(this.everyone(), JSON.stringify({ type: "ending_cancelled" }));
2240
+ if (this.server.onEndingCancelled)
2241
+ this.run(() => this.server.onEndingCancelled(this.state, this.api), "onEndingCancelled");
2242
+ }
2213
2243
  /** End the match: everyone hears message and why (endReason), and their connections close. */
2214
2244
  end(message, endReason) {
2215
2245
  if (this.ended)