Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1# -*- coding: utf-8 -*- 

2from __future__ import annotations 

3 

4# -- stdlib -- 

5from typing import Any, ClassVar, Dict, List, Optional, Type, TypeVar 

6from typing_extensions import TypedDict 

7 

8# -- third party -- 

9from dataclasses import dataclass 

10import dataclasses 

11 

12# -- own -- 

13from . import model 

14 

15 

16# -- code -- 

17class ServerToClient: 

18 pass 

19 

20 

21class ClientToServer: 

22 pass 

23 

24 

25class BiDirectional(ServerToClient, ClientToServer): 

26 pass 

27 

28 

29class Message: 

30 types: ClassVar[Dict[str, Type[Message]]] = {} 

31 op: str 

32 

33 def __init__(self, *args, **kwargs): 

34 raise Exception('Abstract') 

35 

36 def encode(self) -> dict: 

37 ... 

38 

39 @classmethod 

40 def decode(cls, data: dict) -> Optional[Message]: 

41 data = dict(data) 

42 op = data.pop('op', '') 

43 if op not in cls.types: 43 ↛ 44line 43 didn't jump to line 44, because the condition on line 43 was never true

44 return None 

45 

46 return cls.types[op](**data) 

47 

48 

49def message(cls: Type[Message]) -> Type[Message]: 

50 assert issubclass(cls, ServerToClient) or issubclass(cls, ClientToServer) 

51 cls.op = cls.__name__ 

52 assert cls.op not in Message.types, cls.op 

53 Message.types[cls.op] = cls 

54 

55 if cls.encode is Message.encode: 55 ↛ 68line 55 didn't jump to line 68, because the condition on line 55 was never false

56 env = {} 

57 fields = [f" '{i.name}': self.{i.name}," for i in dataclasses.fields(cls)] 

58 code = ( 

59 "def encode(self) -> dict:" 

60 " return {" 

61 " 'op': self.op," 

62 " %s" 

63 " }" 

64 ) % '\n'.join(fields) 

65 exec(code, env) 

66 cls.encode = env['encode'] 

67 

68 return cls 

69 

70 

71T = TypeVar('T', bound=Message) 

72 

73 

74def cast(typ: Type[T], msg: Message) -> Optional[T]: 

75 if msg.op == typ.op: 

76 return msg # type: ignore 

77 

78 return None 

79 

80 

81# ---------------------------- 

82@message 

83@dataclass 

84class Info(Message, ServerToClient): 

85 msg: str 

86 

87 

88@message 

89@dataclass 

90class Error(Message, ServerToClient): 

91 msg: str 

92 

93 

94@message 

95@dataclass 

96class SystemMsg(Message, ServerToClient): 

97 msg: str 

98 

99 

100@message 

101@dataclass 

102class CurrentGames(Message, ServerToClient): 

103 games: List[model.Game] 

104 

105 

106@message 

107@dataclass 

108class CurrentUsers(Message, ServerToClient): 

109 users: List[model.User] 

110 

111 

112@message 

113@dataclass 

114class RoomUsers(Message, ServerToClient): 

115 gid: int 

116 users: List[model.User] 

117 

118 

119@message 

120@dataclass 

121class GameJoined(Message, ServerToClient): 

122 game: model.GameDetail 

123 

124 

125@message 

126@dataclass 

127class GameStarted(Message, ServerToClient): 

128 game: model.GameDetail 

129 

130 

131@message 

132@dataclass 

133class PlayerPresence(Message, ServerToClient): 

134 ''' 

135 Indicates if player is still in the game 

136 ''' 

137 gid: int 

138 presence: Dict[int, bool] 

139 

140 

141@message 

142@dataclass 

143class GameEnded(Message, ServerToClient): 

144 gid: int 

145 

146 

147@message 

148@dataclass 

149class GameParams(Message, ServerToClient): 

150 gid: int 

151 params: Dict[str, Any] 

152 

153 

154@message 

155@dataclass 

156class SetGameParam(Message, BiDirectional): 

157 gid: int 

158 key: str 

159 value: Any 

160 

161 

162@message 

163@dataclass 

164class GameData(Message, BiDirectional): 

165 gid: int 

166 tag: str 

167 data: Any 

168 

169 

170@message 

171@dataclass 

172class InviteRequest(Message, ServerToClient): 

173 uid: int 

174 name: str 

175 gid: int 

176 type: str 

177 

178 

179@message 

180@dataclass 

181class ObserveRequest(Message, ServerToClient): 

182 uid: int 

183 

184 

185@message 

186@dataclass 

187class KickRequest(Message, ServerToClient): 

188 uid: int 

189 victim: int 

190 votes: int 

191 

192 

193@message 

194@dataclass 

195class ObserveStarted(Message, ServerToClient): 

196 game: model.GameDetail 

197 observee: int 

198 

199 

200@message 

201@dataclass 

202class GameLeft(Message, ServerToClient): 

203 gid: int 

204 

205 

206@message 

207@dataclass 

208class Greeting(Message, ServerToClient): 

209 node: str 

210 version: str 

211 

212 

213@message 

214@dataclass 

215class AuthError(Message, ServerToClient): 

216 reason: str 

217 

218 

219@message 

220@dataclass 

221class AuthSuccess(Message, ServerToClient): 

222 uid: int 

223 

224 

225@message 

226@dataclass 

227class Ping(Message, ServerToClient): 

228 pass 

229 

230 

231# -------------------------------- 

232# ----- system ----- 

233@message 

234@dataclass 

235class Beat(Message, ClientToServer): 

236 pass 

237 

238 

239@message 

240@dataclass 

241class Pong(Message, ClientToServer): 

242 pass 

243 

244 

245@message 

246@dataclass 

247class Auth(Message, ClientToServer): 

248 token: str 

249 

250 

251# ----- room ----- 

252class CreateRoomFlags(TypedDict): 

253 contest: bool 

254 invite: bool 

255 

256 

257@message 

258@dataclass 

259class CreateRoom(Message, ClientToServer): 

260 name: str 

261 mode: str 

262 flags: CreateRoomFlags 

263 

264 

265@message 

266@dataclass 

267class JoinRoom(Message, ClientToServer): 

268 gid: int 

269 slot: Optional[int] 

270 

271 

272@message 

273@dataclass 

274class LeaveRoom(Message, ClientToServer): 

275 pass 

276 

277 

278@message 

279@dataclass 

280class GetRoomUsers(Message, ClientToServer): 

281 gid: int 

282 

283 

284@message 

285@dataclass 

286class GetReady(Message, ClientToServer): 

287 pass 

288 

289 

290@message 

291@dataclass 

292class CancelReady(Message, ClientToServer): 

293 pass 

294 

295 

296@message 

297@dataclass 

298class ChangeLocation(Message, ClientToServer): 

299 loc: int 

300 

301 

302# ----- observe ----- 

303@message 

304@dataclass 

305class Observe(Message, ClientToServer): 

306 uid: int 

307 

308 

309@message 

310@dataclass 

311class GrantObserve(Message, ClientToServer): 

312 uid: int 

313 grant: bool 

314 

315 

316@message 

317@dataclass 

318class KickObserver(Message, ClientToServer): 

319 uid: int 

320 

321 

322@message 

323@dataclass 

324class ObserverEnter(Message, ServerToClient): 

325 observer: int 

326 observee: int 

327 

328 

329@message 

330@dataclass 

331class ObserverLeave(Message, ServerToClient): 

332 observer: int 

333 observee: int 

334 

335 

336# ----- invite ----- 

337@message 

338@dataclass 

339class Invite(Message, ClientToServer): 

340 uid: int 

341 

342 

343@message 

344@dataclass 

345class Kick(Message, ClientToServer): 

346 uid: int 

347 

348 

349# ----- item ----- 

350@message 

351@dataclass 

352class UseItem(Message, ClientToServer): 

353 sku: str 

354 

355 

356# ----- admin ----- 

357@message 

358@dataclass 

359class AdminStacktrace(Message, ClientToServer): 

360 pass 

361 

362 

363@message 

364@dataclass 

365class AdminClearZombies(Message, ClientToServer): 

366 pass 

367 

368 

369@message 

370@dataclass 

371class AdminMigrate(Message, ClientToServer): 

372 pass 

373 

374 

375@message 

376@dataclass 

377class AdminKick(Message, ClientToServer): 

378 uid: int 

379 

380 

381@message 

382@dataclass 

383class AdminKillGame(Message, ClientToServer): 

384 gid: int 

385 

386 

387@message 

388@dataclass 

389class AdminAdd(Message, ClientToServer): 

390 uid: int 

391 

392 

393@message 

394@dataclass 

395class AdminRemove(Message, ClientToServer): 

396 uid: int 

397 

398 

399@message 

400@dataclass 

401class AdminAddBigbrother(Message, ClientToServer): 

402 uid: int 

403 

404 

405@message 

406@dataclass 

407class AdminRemoveBigbrother(Message, ClientToServer): 

408 uid: int 

409 

410 

411# ----- contest ----- 

412@message 

413@dataclass 

414class SetupContest(Message, ClientToServer): 

415 name: str 

416 mode: str 

417 uids: List[int]