-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
RankifyInstanceMainFacet.sol
300 lines (267 loc) · 10.3 KB
/
RankifyInstanceMainFacet.sol
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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import {LibTBG} from "../libraries/LibTurnBasedGame.sol";
import {IRankifyInstanceCommons} from "../interfaces/IRankifyInstanceCommons.sol";
import {IERC1155Receiver} from "../interfaces/IERC1155Receiver.sol";
import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import "../abstracts/DiamondReentrancyGuard.sol";
import {LibRankify} from "../libraries/LibRankify.sol";
import {LibCoinVending} from "../libraries/LibCoinVending.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";
import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "../abstracts/draft-EIP712Diamond.sol";
import "hardhat/console.sol";
contract RankifyInstanceMainFacet is
IRankifyInstanceCommons,
IERC1155Receiver,
DiamondReentrancyGuard,
IERC721Receiver,
EIP712
{
using LibTBG for LibTBG.GameInstance;
using LibTBG for uint256;
using LibTBG for LibTBG.GameSettings;
using LibRankify for uint256;
function RInstanceStorage() internal pure returns (RInstanceSettings storage bog) {
bytes32 position = LibTBG.getDataStorage();
assembly {
bog.slot := position
}
}
/**
* @dev Creates a new game with the provided game master, game ID, and game rank. Optionally, additional ranks can be provided. `gameMaster` is the address of the game master. `gameId` is the ID of the new game. `gameRank` is the rank of the new game. `additionalRanks` is the array of additional ranks.
*
* emits a _GameCreated_ event.
*
* Requirements:
* There are some game price requirments that must be met under gameId.newGame function that are set during the contract initialization and refer to the contract maintainer benefits.
*
* Modifies:
*
* - Calls the `newGame` function with `gameMaster`, `gameRank`, and `msg.sender`.
* - Configures the coin vending with `gameId` and an empty configuration.
* - If `additionalRanks` is not empty, mints rank tokens for each additional rank and sets the additional ranks of the game with `gameId` to `additionalRanks`.
*/
function createGame(address gameMaster, uint256 gameId, uint256 gameRank) public nonReentrant {
gameId.newGame(gameMaster, gameRank, msg.sender);
LibCoinVending.ConfigPosition memory emptyConfig;
LibCoinVending.configure(bytes32(gameId), emptyConfig);
emit gameCreated(gameId, gameMaster, msg.sender, gameRank);
}
function createGame(address gameMaster, uint256 gameRank) public {
LibRankify.enforceIsInitialized();
RInstanceSettings storage settings = RInstanceStorage();
createGame(gameMaster, settings.numGames + 1, gameRank);
}
/**
* @dev Handles a player quitting a game with the provided game ID. `gameId` is the ID of the game. `player` is the address of the player.
*
* emits a _PlayerLeft_ event.
*
* Modifies:
*
* - Refunds the coins for `player` in the game with `gameId`.
*/
function onPlayerQuit(uint256 gameId, address player) private {
LibCoinVending.refund(bytes32(gameId), player);
emit PlayerLeft(gameId, player);
}
/**
* @dev Cancels a game with the provided game ID. `gameId` is the ID of the game.
*
* Modifies:
*
* - Calls the `enforceIsGameCreator` function with `msg.sender`.
*
* Requirements:
*
* - The caller must be the game creator of the game with `gameId`.
* - Game must not be started.
*/
function cancelGame(uint256 gameId) public nonReentrant {
gameId.enforceIsGameCreator(msg.sender);
gameId.cancelGame(onPlayerQuit, LibDiamond.contractOwner());
emit GameClosed(gameId);
}
/**
* @dev Allows a player to leave a game with the provided game ID. `gameId` is the ID of the game.
*
* Modifies:
*
* - Calls the `quitGame` function with `msg.sender`, `true`, and `onPlayerQuit`.
*
* Requirements:
*
* - The caller must be a player in the game with `gameId`.
* - Game must not be started.
*/
function leaveGame(uint256 gameId) public nonReentrant {
gameId.quitGame(msg.sender, true, onPlayerQuit);
}
/**
* @dev Opens registration for a game with the provided game ID. `gameId` is the ID of the game.
*
* emits a _RegistrationOpen_ event.
*
* Modifies:
*
* - Calls the `enforceIsGameCreator` function with `msg.sender`.
* - Calls the `enforceIsPreRegistrationStage` function.
* - Calls the `openRegistration` function.
*
* Requirements:
*
* - The caller must be the game creator of the game with `gameId`.
* - The game with `gameId` must be in the pre-registration stage.
*/
function openRegistration(uint256 gameId) public {
gameId.enforceIsGameCreator(msg.sender);
gameId.enforceIsPreRegistrationStage();
gameId.openRegistration();
emit RegistrationOpen(gameId);
}
/**
* @dev Allows a player to join a game with the provided game ID. `gameId` is the ID of the game.
*
* emits a _PlayerJoined_ event.
*
* Modifies:
*
* - Calls the `joinGame` function with `msg.sender`.
* - Calls the `fund` function with `bytes32(gameId)`.
*
* Requirements:
*
* - The caller must not be a player in the game with `gameId`.
* - Game phase must be registration.
* - Caller must be able to fulfill funding requirements.
*/
function joinGame(uint256 gameId) public payable nonReentrant {
gameId.joinGame(msg.sender);
LibCoinVending.fund(bytes32(gameId));
emit PlayerJoined(gameId, msg.sender);
}
/**
* @dev Starts a game with the provided game ID early. `gameId` is the ID of the game.
*
* emits a _GameStarted_ event.
*
* Modifies:
*
* - Calls the `enforceGameExists` function.
* - Calls the `startGameEarly` function.
*
* Requirements:
*
* - The game with `gameId` must exist.
*/
function startGame(uint256 gameId) public {
gameId.enforceGameExists();
gameId.startGameEarly();
emit GameStarted(gameId);
}
function onERC1155Received(
address operator,
address,
uint256,
uint256,
bytes calldata
) public view override returns (bytes4) {
LibRankify.enforceIsInitialized();
if (operator == address(this)) {
return bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"));
}
return bytes4("");
}
function onERC1155BatchReceived(
address operator,
address,
uint256[] calldata,
uint256[] calldata,
bytes calldata
) external view override returns (bytes4) {
LibRankify.enforceIsInitialized();
if (operator == address(this)) {
return bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"));
}
return bytes4("");
}
function onERC721Received(
address operator,
address,
uint256,
bytes calldata
) external view override returns (bytes4) {
LibRankify.enforceIsInitialized();
if (operator == address(this)) {
return IERC721Receiver.onERC721Received.selector;
}
return bytes4("");
}
function getContractState() public view returns (RInstanceState memory) {
RInstanceSettings storage settings = RInstanceStorage();
LibTBG.GameSettings memory tbgSettings = LibTBG.getGameSettings();
return (RInstanceState({BestOfState: settings, TBGSEttings: tbgSettings}));
}
function getTurn(uint256 gameId) public view returns (uint256) {
return gameId.getTurn();
}
function getGM(uint256 gameId) public view returns (address) {
return gameId.getGM();
}
function getScores(uint256 gameId) public view returns (address[] memory, uint256[] memory) {
return gameId.getScores();
}
function isOvertime(uint256 gameId) public view returns (bool) {
return gameId.isOvertime();
}
function isGameOver(uint256 gameId) public view returns (bool) {
return gameId.isGameOver();
}
function getPlayersGame(address player) public view returns (uint256) {
return LibTBG.getPlayersGame(player);
}
function isLastTurn(uint256 gameId) public view returns (bool) {
return gameId.isLastTurn();
}
function isRegistrationOpen(uint256 gameId) public view returns (bool) {
return gameId.isRegistrationOpen();
}
function gameCreator(uint256 gameId) public view returns (address) {
return gameId.getGameStorage().createdBy;
}
function getGameRank(uint256 gameId) public view returns (uint256) {
return gameId.getGameStorage().rank;
}
function getPlayers(uint256 gameId) public view returns (address[] memory) {
return gameId.getPlayers();
}
function canStartGame(uint256 gameId) public view returns (bool) {
return gameId.canStartEarly();
}
function canEndTurn(uint256 gameId) public view returns (bool) {
return gameId.canEndTurnEarly();
}
function isPlayerTurnComplete(uint256 gameId, address player) public view returns (bool) {
return gameId.isPlayerTurnComplete(player);
}
function getPlayerVotedArray(uint256 gameId) public view returns (bool[] memory) {
IRankifyInstanceCommons.RInstance storage game = gameId.getGameStorage();
address[] memory players = gameId.getPlayers();
bool[] memory playerVoted = new bool[](players.length);
for (uint256 i = 0; i < players.length; ++i) {
playerVoted[i] = game.playerVoted[players[i]];
}
return playerVoted;
}
function getPlayersMoved(uint256 gameId) public view returns (bool[] memory, uint256) {
LibTBG.GameInstance storage game = gameId._getGame();
address[] memory players = gameId.getPlayers();
bool[] memory playersMoved = new bool[](players.length);
for (uint256 i = 0; i < players.length; ++i) {
playersMoved[i] = game.madeMove[players[i]];
}
return (playersMoved, game.numPlayersMadeMove);
}
}