trucoshi 0.0.14 → 0.0.15

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.
@@ -11,6 +11,6 @@ export interface IGameLoop {
11
11
  onTurn: (callback: ITurnCallback) => IGameLoop;
12
12
  onWinner: (callback: IWinnerCallback) => IGameLoop;
13
13
  onTruco: (callback: ITrucoCallback) => IGameLoop;
14
- begin: () => void;
14
+ begin: () => Promise<void>;
15
15
  }
16
16
  export declare function Lobby(teamSize?: 1 | 2 | 3): ILobby;
package/dist/lib/index.js CHANGED
@@ -101,11 +101,11 @@ var GameLoop = function (match) {
101
101
  return gameloop;
102
102
  };
103
103
  function Lobby(teamSize) {
104
- var trucoshi = {
104
+ var lobby = {
105
105
  lastTeamIdx: 1,
106
106
  _players: new Map(),
107
107
  get players() {
108
- return Array.from(trucoshi._players.values());
108
+ return Array.from(lobby._players.values());
109
109
  },
110
110
  teams: [],
111
111
  table: null,
@@ -114,65 +114,55 @@ function Lobby(teamSize) {
114
114
  ready: false,
115
115
  gameLoop: undefined,
116
116
  calculateReady: function () {
117
- trucoshi.ready = trucoshi.players.reduce(function (prev, curr) { return prev && curr.ready; }, true);
118
- return trucoshi.ready;
117
+ lobby.ready = lobby.players.reduce(function (prev, curr) { return prev && curr.ready; }, true);
118
+ return lobby.ready;
119
119
  },
120
120
  calculateFull: function () {
121
- trucoshi.full = trucoshi._players.size >= trucoshi.maxPlayers;
122
- return trucoshi.full;
121
+ lobby.full = lobby._players.size >= lobby.maxPlayers;
122
+ return lobby.full;
123
123
  },
124
124
  addPlayer: function (id, session, teamIdx) {
125
125
  var maxSize = teamSize ? teamSize : 3;
126
- if (trucoshi.full || trucoshi.players.filter(function (p) { return p.teamIdx === teamIdx; }).length > maxSize) {
126
+ if (lobby.full || lobby.players.filter(function (p) { return p.teamIdx === teamIdx; }).length > maxSize) {
127
127
  throw new Error(constants_1.GAME_ERROR.TEAM_IS_FULL);
128
128
  }
129
- var player = (0, Player_1.Player)(id, teamIdx !== undefined ? teamIdx : Number(!trucoshi.lastTeamIdx));
129
+ var player = (0, Player_1.Player)(id, teamIdx !== undefined ? teamIdx : Number(!lobby.lastTeamIdx));
130
130
  player.setSession(session);
131
- trucoshi.lastTeamIdx = Number(!trucoshi.lastTeamIdx);
132
- trucoshi._players.set(id, player);
133
- trucoshi.calculateFull();
134
- trucoshi.calculateReady();
131
+ lobby.lastTeamIdx = Number(!lobby.lastTeamIdx);
132
+ lobby._players.set(id, player);
133
+ lobby.calculateFull();
134
+ lobby.calculateReady();
135
135
  return player;
136
136
  },
137
137
  removePlayer: function (id) {
138
- trucoshi._players.delete(id);
139
- trucoshi.calculateFull();
140
- trucoshi.calculateReady();
141
- return trucoshi;
138
+ lobby._players.delete(id);
139
+ lobby.calculateFull();
140
+ lobby.calculateReady();
141
+ return lobby;
142
142
  },
143
143
  startMatch: function (matchPoint) {
144
144
  if (matchPoint === void 0) { matchPoint = 9; }
145
- trucoshi.calculateReady();
146
- var teamSize = trucoshi._players.size / 2;
145
+ lobby.calculateReady();
146
+ var teamSize = lobby._players.size / 2;
147
147
  if (!constants_1.TEAM_SIZE_VALUES.includes(teamSize)) {
148
148
  throw new Error(constants_1.GAME_ERROR.UNEXPECTED_TEAM_SIZE);
149
149
  }
150
- if (!trucoshi.ready) {
150
+ if (!lobby.ready) {
151
151
  throw new Error(constants_1.GAME_ERROR.TEAM_NOT_READY);
152
152
  }
153
- trucoshi.teams = [
154
- (0, Team_1.Team)(trucoshi.players.filter(function (p) { return p.teamIdx === 0; })),
155
- (0, Team_1.Team)(trucoshi.players.filter(function (p) { return p.teamIdx === 1; })),
153
+ lobby.teams = [
154
+ (0, Team_1.Team)(lobby.players.filter(function (p) { return p.teamIdx === 0; })),
155
+ (0, Team_1.Team)(lobby.players.filter(function (p) { return p.teamIdx === 1; })),
156
156
  ];
157
- if (trucoshi.teams[0].players.length !== teamSize ||
158
- trucoshi.teams[1].players.length !== teamSize) {
157
+ if (lobby.teams[0].players.length !== teamSize ||
158
+ lobby.teams[1].players.length !== teamSize) {
159
159
  throw new Error(constants_1.GAME_ERROR.UNEXPECTED_TEAM_SIZE);
160
160
  }
161
- trucoshi.table = (0, Table_1.Table)(trucoshi.players, trucoshi.teams);
162
- trucoshi.gameLoop = GameLoop((0, Match_1.Match)(trucoshi.table, trucoshi.teams, matchPoint));
163
- return trucoshi.gameLoop;
161
+ lobby.table = (0, Table_1.Table)(lobby.players, lobby.teams);
162
+ lobby.gameLoop = GameLoop((0, Match_1.Match)(lobby.table, lobby.teams, matchPoint));
163
+ return lobby.gameLoop;
164
164
  },
165
165
  };
166
- return {
167
- addPlayer: trucoshi.addPlayer,
168
- removePlayer: trucoshi.removePlayer,
169
- startMatch: trucoshi.startMatch,
170
- teams: trucoshi.teams,
171
- get players() {
172
- return Array.from(trucoshi._players.values());
173
- },
174
- full: trucoshi.full,
175
- ready: trucoshi.ready,
176
- };
166
+ return lobby;
177
167
  }
178
168
  exports.Lobby = Lobby;
@@ -163,7 +163,7 @@ export interface IPrivateLobby {
163
163
  calculateFull(): boolean;
164
164
  startMatch(matchPoint?: 9 | 12 | 15): IGameLoop;
165
165
  }
166
- export interface ILobby extends Pick<IPrivateLobby, "addPlayer" | "removePlayer" | "startMatch" | "ready" | "full" | "teams" | "players" | "gameLoop"> {
166
+ export interface ILobby extends Pick<IPrivateLobby, "addPlayer" | "removePlayer" | "startMatch" | "ready" | "full" | "teams" | "players" | "gameLoop" | "table"> {
167
167
  }
168
168
  export interface ITable {
169
169
  forehandIdx: number;
@@ -4,13 +4,17 @@ import { ILobby, IPlayedCard } from "../../lib/types";
4
4
  export interface IPublicMatch {
5
5
  teams: Array<IPublicTeam>;
6
6
  players: Array<IPublicPlayer>;
7
- hands: Array<Array<Array<IPlayedCard>>>;
7
+ rounds: IPlayedCard[][];
8
+ state: EMatchTableState;
8
9
  }
9
10
  export interface IMatchTable {
10
11
  matchSessionId: string;
12
+ currentPlayer: IPublicPlayer | null;
11
13
  lobby: ILobby;
12
14
  state: EMatchTableState;
13
15
  setState(state: EMatchTableState): void;
16
+ setCurrentPlayer(player: IPublicPlayer): void;
17
+ isSessionPlaying(session: string): IPublicPlayer | null;
14
18
  getPublicMatch(session?: string): IPublicMatch;
15
19
  }
16
20
  export declare enum EMatchTableState {
@@ -22,24 +22,35 @@ var EMatchTableState;
22
22
  function MatchTable(matchSessionId, teamSize) {
23
23
  var matchTable = {
24
24
  matchSessionId: matchSessionId,
25
+ currentPlayer: null,
25
26
  lobby: (0, lib_1.Lobby)(teamSize),
26
27
  state: EMatchTableState.UNREADY,
27
28
  setState: function (state) {
28
29
  matchTable.state = state;
29
30
  },
31
+ setCurrentPlayer: function (player) {
32
+ matchTable.currentPlayer = player;
33
+ },
34
+ isSessionPlaying: function (session) {
35
+ var lobby = matchTable.lobby;
36
+ var search = lobby.players.find(function (player) { return player.session === session; });
37
+ return search || null;
38
+ },
30
39
  getPublicMatch: function (userSession) {
31
- var _a;
32
- console.log(matchTable.lobby.gameLoop);
40
+ var _a, _b, _c;
41
+ var lobby = matchTable.lobby;
42
+ var lastHand = (((_a = lobby.gameLoop) === null || _a === void 0 ? void 0 : _a.hands.length) || 1) - 1;
43
+ var rounds = (_c = (_b = lobby.gameLoop) === null || _b === void 0 ? void 0 : _b.hands[lastHand]) === null || _c === void 0 ? void 0 : _c.rounds.map(function (round) { return round.cards; });
33
44
  return {
34
45
  matchSessionId: matchSessionId,
46
+ state: matchTable.state,
35
47
  teams: [],
36
- players: matchTable.lobby.players.map(function (player) {
48
+ players: lobby.players.map(function (player) {
37
49
  return player.session === userSession
38
50
  ? player
39
51
  : __assign(__assign({}, player), { hand: player.hand.map(function () { return "xx"; }) });
40
52
  }),
41
- hands: ((_a = matchTable.lobby.gameLoop) === null || _a === void 0 ? void 0 : _a.hands.map(function (hand) { return hand.rounds.map(function (round) { return round.cards; }); })) ||
42
- [],
53
+ rounds: rounds || [[]],
43
54
  };
44
55
  },
45
56
  };
@@ -52,6 +52,7 @@ var io = new socket_io_1.Server(httpServer, {
52
52
  });
53
53
  var users = new Map(); // sessionId, user
54
54
  var tables = new Map(); // sessionId, table
55
+ var turns = new Map(); // sessionId, play instance
55
56
  var getUser = function (session) {
56
57
  var user = users.get(session);
57
58
  if (user) {
@@ -68,7 +69,6 @@ var getTable = function (matchSessionId) {
68
69
  };
69
70
  io.on("connection", function (_socket) {
70
71
  var socket = _socket;
71
- console.error("New connection");
72
72
  var getTableSockets = function (table, callback) {
73
73
  return new Promise(function (resolve) { return __awaiter(void 0, void 0, void 0, function () {
74
74
  var sockets, _i, sockets_1, socket_1;
@@ -114,19 +114,18 @@ io.on("connection", function (_socket) {
114
114
  */
115
115
  socket.on(types_1.EClientEvent.CREATE_MATCH, function (callback) {
116
116
  if (socket.session) {
117
- var user = getUser(socket.session);
118
- var existingTable = tables.get(socket.session);
119
- if (existingTable) {
120
- return callback({
121
- success: false,
122
- match: existingTable.getPublicMatch(socket.session),
123
- });
124
- }
125
117
  try {
118
+ var user = getUser(socket.session);
119
+ var existingTable = tables.get(socket.session);
120
+ if (existingTable) {
121
+ return callback({
122
+ success: false,
123
+ match: existingTable.getPublicMatch(socket.session),
124
+ });
125
+ }
126
126
  var table = (0, MatchTable_1.MatchTable)(socket.session);
127
127
  table.lobby.addPlayer(user.id, socket.session);
128
128
  tables.set(socket.session, table);
129
- console.log("creating match", socket.session, table.state);
130
129
  return callback({ success: true, match: table.getPublicMatch(user.id) });
131
130
  }
132
131
  catch (e) {
@@ -136,54 +135,95 @@ io.on("connection", function (_socket) {
136
135
  }
137
136
  callback({ success: false, error: new Error("Can't create match without an ID") });
138
137
  });
139
- /**
140
- * Start Match
141
- */
142
- socket.on(types_1.EClientEvent.START_MATCH, function (callback) {
143
- if (socket.session && users.has(socket.session)) {
138
+ var sendWaitingForPlay = function (table, session, play) { return __awaiter(void 0, void 0, void 0, function () {
139
+ return __generator(this, function (_a) {
140
+ switch (_a.label) {
141
+ case 0: return [4 /*yield*/, getTableSockets(table, function (playerSocket) { return __awaiter(void 0, void 0, void 0, function () {
142
+ return __generator(this, function (_a) {
143
+ playerSocket.emit(types_1.EServerEvent.UPDATE_MATCH, table.getPublicMatch(playerSocket.session));
144
+ return [2 /*return*/];
145
+ });
146
+ }); })];
147
+ case 1:
148
+ _a.sent();
149
+ return [4 /*yield*/, getTableSockets(table, function (playerSocket) {
150
+ return new Promise(function (resolve) {
151
+ if (playerSocket.session === session) {
152
+ playerSocket.emit(types_1.EServerEvent.WAITING_PLAY, table.getPublicMatch(session));
153
+ playerSocket.once(types_1.EClientEvent.PLAY, function (_a) {
154
+ var cardIdx = _a.cardIdx, command = _a.command;
155
+ if (cardIdx !== undefined) {
156
+ var playedCard = play.use(cardIdx);
157
+ if (playedCard) {
158
+ return resolve();
159
+ }
160
+ return console.error("ERROR", new Error("Couldnt play card"));
161
+ }
162
+ if (command) {
163
+ var saidCommand = play.say(command);
164
+ if (saidCommand) {
165
+ return resolve();
166
+ }
167
+ return console.error("ERROR", new Error("Couldnt say command"));
168
+ }
169
+ return console.error("ERROR", new Error("Play callback didn't have data"));
170
+ });
171
+ }
172
+ else {
173
+ resolve();
174
+ }
175
+ });
176
+ })];
177
+ case 2:
178
+ _a.sent();
179
+ return [2 /*return*/];
180
+ }
181
+ });
182
+ }); };
183
+ var startMatch = function () { return __awaiter(void 0, void 0, void 0, function () {
184
+ var tableId_1, table_1;
185
+ return __generator(this, function (_a) {
144
186
  try {
145
- var table_1 = getTable(socket.session);
187
+ tableId_1 = socket.session;
188
+ table_1 = getTable(tableId_1);
146
189
  if (table_1 && !table_1.lobby.gameLoop) {
147
190
  table_1.setState(MatchTable_1.EMatchTableState.STARTED);
148
- var game = table_1.lobby
191
+ table_1.lobby
149
192
  .startMatch()
150
- .onTurn(function (play) { return __awaiter(void 0, void 0, void 0, function () {
151
- var session, user;
152
- var _a;
153
- return __generator(this, function (_b) {
154
- switch (_b.label) {
155
- case 0: return [4 /*yield*/, getTableSockets(table_1, function (socket) { return __awaiter(void 0, void 0, void 0, function () {
156
- return __generator(this, function (_a) {
157
- socket.emit(types_1.EServerEvent.UPDATE_MATCH, table_1.getPublicMatch(socket.session));
158
- return [2 /*return*/];
159
- });
160
- }); })];
161
- case 1:
162
- _b.sent();
163
- session = (_a = play.player) === null || _a === void 0 ? void 0 : _a.session;
164
- if (!session) {
165
- throw new Error("Unexpected Error");
166
- }
167
- user = users.get(session);
168
- if (!user) {
169
- throw new Error("Unexpected Error");
170
- }
171
- return [4 /*yield*/, getTableSockets(table_1, function (socket) {
172
- return new Promise(function (resolve) {
173
- if (socket.session === session) {
174
- socket.emit(types_1.EServerEvent.UPDATE_MATCH, table_1.getPublicMatch(session));
175
- socket.on(types_1.EClientEvent.PLAY, function () {
176
- resolve();
177
- });
178
- }
179
- });
180
- })];
181
- case 2:
182
- _b.sent();
183
- return [2 /*return*/];
184
- }
185
- });
186
- }); })
193
+ .onTurn(function (play) {
194
+ return new Promise(function (resolve) { return __awaiter(void 0, void 0, void 0, function () {
195
+ var session, user, e_1;
196
+ var _a;
197
+ return __generator(this, function (_b) {
198
+ switch (_b.label) {
199
+ case 0:
200
+ table_1.setCurrentPlayer(play.player);
201
+ turns.set(tableId_1, { play: play, resolve: resolve });
202
+ _b.label = 1;
203
+ case 1:
204
+ _b.trys.push([1, 3, , 4]);
205
+ session = (_a = play.player) === null || _a === void 0 ? void 0 : _a.session;
206
+ if (!session) {
207
+ throw new Error("Unexpected Error");
208
+ }
209
+ user = users.get(session);
210
+ if (!user) {
211
+ throw new Error("Unexpected Error");
212
+ }
213
+ return [4 /*yield*/, sendWaitingForPlay(table_1, session, play)];
214
+ case 2:
215
+ _b.sent();
216
+ resolve();
217
+ return [3 /*break*/, 4];
218
+ case 3:
219
+ e_1 = _b.sent();
220
+ console.error("ERROR", e_1);
221
+ return [3 /*break*/, 4];
222
+ case 4: return [2 /*return*/];
223
+ }
224
+ });
225
+ }); });
226
+ })
187
227
  .onTruco(function (play) { return __awaiter(void 0, void 0, void 0, function () { return __generator(this, function (_a) {
188
228
  return [2 /*return*/];
189
229
  }); }); })
@@ -191,16 +231,22 @@ io.on("connection", function (_socket) {
191
231
  return [2 /*return*/];
192
232
  }); }); })
193
233
  .begin();
194
- emitMatchUpdate(table_1);
195
- return callback({ success: true, match: table_1.getPublicMatch(socket.session) });
234
+ return [2 /*return*/, tables.set(socket.session, table_1)];
196
235
  }
197
236
  console.error("ASL:KDJALSk");
198
- callback({ success: false, match: table_1.getPublicMatch(socket.session) });
199
237
  }
200
238
  catch (e) {
201
239
  console.error("ERROR", e);
202
- callback({ success: false, error: e });
203
240
  }
241
+ return [2 /*return*/];
242
+ });
243
+ }); };
244
+ /**
245
+ * Start Match
246
+ */
247
+ socket.on(types_1.EClientEvent.START_MATCH, function () {
248
+ if (socket.session && users.has(socket.session)) {
249
+ startMatch();
204
250
  }
205
251
  });
206
252
  /**
@@ -242,6 +288,43 @@ io.on("connection", function (_socket) {
242
288
  };
243
289
  users.set(session, updatedUser);
244
290
  socket.session = session;
291
+ tables.forEach(function (table, id) { return __awaiter(void 0, void 0, void 0, function () {
292
+ var _a, play, resolve, session_1, user_2, e_2;
293
+ var _b, _c;
294
+ return __generator(this, function (_d) {
295
+ switch (_d.label) {
296
+ case 0:
297
+ if (!table.isSessionPlaying(session)) return [3 /*break*/, 5];
298
+ socket.join(id);
299
+ if (!(session === ((_b = table.currentPlayer) === null || _b === void 0 ? void 0 : _b.session))) return [3 /*break*/, 4];
300
+ _d.label = 1;
301
+ case 1:
302
+ _d.trys.push([1, 3, , 4]);
303
+ _a = turns.get(id) || {}, play = _a.play, resolve = _a.resolve;
304
+ session_1 = (_c = play === null || play === void 0 ? void 0 : play.player) === null || _c === void 0 ? void 0 : _c.session;
305
+ if (!play || !session_1) {
306
+ throw new Error("Unexpected Error");
307
+ }
308
+ user_2 = users.get(session_1);
309
+ if (!user_2) {
310
+ throw new Error("Unexpected Error");
311
+ }
312
+ return [4 /*yield*/, sendWaitingForPlay(table, session_1, play)];
313
+ case 2:
314
+ _d.sent();
315
+ resolve === null || resolve === void 0 ? void 0 : resolve();
316
+ return [3 /*break*/, 4];
317
+ case 3:
318
+ e_2 = _d.sent();
319
+ console.error("ERROR", e_2);
320
+ return [3 /*break*/, 4];
321
+ case 4:
322
+ socket.emit(types_1.EServerEvent.UPDATE_MATCH, table.getPublicMatch(session));
323
+ _d.label = 5;
324
+ case 5: return [2 /*return*/];
325
+ }
326
+ });
327
+ }); });
245
328
  return callback({ success: true, session: session });
246
329
  }
247
330
  var newSession = (0, crypto_1.randomUUID)();
@@ -1,4 +1,5 @@
1
1
  import { Socket } from "socket.io";
2
+ import { ECommand } from "../lib/types";
2
3
  export declare enum EClientEvent {
3
4
  PING = "PING",
4
5
  PLAY = "PLAY",
@@ -11,7 +12,8 @@ export declare enum EClientEvent {
11
12
  }
12
13
  export declare enum EServerEvent {
13
14
  PONG = "PONG",
14
- UPDATE_MATCH = "UPDATE_MATCH"
15
+ UPDATE_MATCH = "UPDATE_MATCH",
16
+ WAITING_PLAY = "WAITING_PLAY"
15
17
  }
16
18
  export interface TrucoshiSocket extends Socket {
17
19
  session?: string;
@@ -21,3 +23,11 @@ export declare enum ETrucoshiMatchState {
21
23
  STARTED = 1,
22
24
  FINISHED = 2
23
25
  }
26
+ export type IWaitingPlayData = {
27
+ cardIdx: number;
28
+ command?: undefined;
29
+ } | {
30
+ cardIdx?: undefined;
31
+ command: ECommand;
32
+ };
33
+ export type IWaitingPlayCallback = (data: IWaitingPlayData) => void | null;
@@ -16,6 +16,7 @@ var EServerEvent;
16
16
  (function (EServerEvent) {
17
17
  EServerEvent["PONG"] = "PONG";
18
18
  EServerEvent["UPDATE_MATCH"] = "UPDATE_MATCH";
19
+ EServerEvent["WAITING_PLAY"] = "WAITING_PLAY";
19
20
  })(EServerEvent = exports.EServerEvent || (exports.EServerEvent = {}));
20
21
  var ETrucoshiMatchState;
21
22
  (function (ETrucoshiMatchState) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "trucoshi",
3
- "version": "0.0.14",
3
+ "version": "0.0.15",
4
4
  "main": "build/lib/trucoshi.js",
5
5
  "license": "GPL-3.0",
6
6
  "scripts": {