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, Dict, Tuple, Type, TypeVar 

6 

7# -- third party -- 

8# -- own -- 

9from . import parts 

10from .base import Game 

11from .endpoint import Client 

12from game.base import Packet 

13from utils.events import EventHub 

14import core 

15import wire 

16 

17 

18# -- code -- 

19class Options(object): 

20 def __init__(self, options: Dict[str, Any]): 

21 self.node = options.get('node', 'localhost') # Current node name 

22 self.listen = options.get('listen', '') # Listen 

23 self.backend = options.get('backend', '') # Backend URI 

24 self.interconnect = options.get('interconnect', '') # URI of chat server 

25 self.archive_path = options.get('archive_path', '') # file:// URI of dir for storing game archives 

26 self.disables = options.get('disables', []) # disabled core components, will assign a None value 

27 self.testing = options.get('testing', False) # In testing? 

28 

29 

30T = TypeVar('T', bound=wire.Message) 

31 

32 

33class _ClientCommandMapping(dict): 

34 __slots__ = ('core',) 

35 

36 def __init__(self, core: Core): 

37 self.core = core 

38 super().__init__() 

39 

40 def __getitem__(self, k: Type[T]) -> EventHub[Tuple[Client, T]]: 

41 if k in self: 

42 return dict.__getitem__(self, k) 

43 

44 hub = EventHub() 

45 hub.name = f'{self.core}::client_command' 

46 self[k] = hub 

47 return hub 

48 

49 

50class Events(object): 

51 def __init__(self, core: Core) -> None: 

52 self.core = core 

53 

54 # ev = (core: Core) 

55 self.core_initialized = EventHub[Core]() 

56 

57 # Fires when user state changes, 

58 # ev = (c: Client, from: str, to: str) 

59 self.user_state_transition = EventHub[Tuple[Client, str, str]]() 

60 

61 # Client connected 

62 self.client_connected = EventHub[Client]() 

63 

64 # Client dropped(connection lost) 

65 self.client_dropped = EventHub[Client]() 

66 

67 # Client logged in when previous login still online, or still in active game 

68 # ev = c: Client # old client obj with new connection `pivot_to`ed to it 

69 self.client_pivot = EventHub[Client]() 

70 

71 # Client send some command 

72 # ev = (c: Client, args: (...)) 

73 self.client_command = _ClientCommandMapping(core) 

74 

75 # Game is created 

76 # ev = g: Game 

77 self.game_created = EventHub[Game]() 

78 

79 # Sent client game data 

80 self.game_data_send = EventHub[Tuple[Game, Client, Packet]]() 

81 

82 # Received client game data 

83 self.game_data_recv = EventHub[Tuple[Game, Client, Packet]]() 

84 

85 # Fires after old game ended and new game created. 

86 # Actors should copy settings from old to new 

87 # ev = (old: Game, g: Game) 

88 self.game_successive_create = EventHub[Tuple[Game, Game]]() 

89 

90 # Game started running 

91 # ev = (g: Game) 

92 self.game_started = EventHub[Game]() 

93 

94 # Client joined a game 

95 # ev = (g: Game, c: Client) 

96 self.game_joined = EventHub[Tuple[Game, Client]]() 

97 

98 # Client left a game 

99 # ev = (g: Game, c: Client) 

100 self.game_left = EventHub[Tuple[Game, Client]]() 

101 

102 # Game was ended, successfully or not. 

103 # ev = (g: Game) 

104 self.game_ended = EventHub[Game]() 

105 

106 # Game ended in half way. 

107 # This fires before GAME_ENDED 

108 # ev = (g: Game) 

109 self.game_aborted = EventHub[Game]() 

110 

111 # Game crashed 

112 # ev = (g: Game) 

113 self.game_crashed = EventHub[Game]() 

114 

115 def __setattr__(self, name, v): 

116 if hasattr(v, 'name'): 

117 v.name = f'{repr(self.core)}::{name}' 

118 object.__setattr__(self, name, v) 

119 

120 

121class Core(core.Core): 

122 core_type = 'S' 

123 

124 def __init__(self, **options: Dict[str, Any]) -> None: 

125 super().__init__() 

126 

127 self.options = Options(options) 

128 self.events = Events(self) 

129 disables = self.options.disables 

130 

131 if 'serve' not in disables: 131 ↛ 134line 131 didn't jump to line 134, because the condition on line 131 was never false

132 self.serve = parts.serve.Serve(self) 

133 

134 if 'auth' not in disables: 134 ↛ 137line 134 didn't jump to line 137, because the condition on line 134 was never false

135 self.auth = parts.auth.Auth(self) 

136 

137 if 'lobby' not in disables: 137 ↛ 140line 137 didn't jump to line 140, because the condition on line 137 was never false

138 self.lobby = parts.lobby.Lobby(self) 

139 

140 if 'room' not in disables: 140 ↛ 143line 140 didn't jump to line 143, because the condition on line 140 was never false

141 self.room = parts.room.Room(self) 

142 

143 if 'game' not in disables: 143 ↛ 146line 143 didn't jump to line 146, because the condition on line 143 was never false

144 self.game = parts.game.GamePart(self) 

145 

146 if 'observe' not in disables: 146 ↛ 149line 146 didn't jump to line 149, because the condition on line 146 was never false

147 self.observe = parts.observe.Observe(self) 

148 

149 if 'invite' not in disables: 149 ↛ 152line 149 didn't jump to line 152, because the condition on line 149 was never false

150 self.invite = parts.invite.Invite(self) 

151 

152 if 'item' not in disables: 152 ↛ 155line 152 didn't jump to line 155, because the condition on line 152 was never false

153 self.item = parts.item.Item(self) 

154 

155 if 'reward' not in disables: 155 ↛ 158line 155 didn't jump to line 158, because the condition on line 155 was never false

156 self.reward = parts.reward.Reward(self) 

157 

158 if 'contest' not in disables: 158 ↛ 161line 158 didn't jump to line 161, because the condition on line 158 was never false

159 self.contest = parts.contest.Contest(self) 

160 

161 if 'admin' not in disables: 161 ↛ 164line 161 didn't jump to line 164, because the condition on line 161 was never false

162 self.admin = parts.admin.Admin(self) 

163 

164 if 'kedama' not in disables: 164 ↛ 167line 164 didn't jump to line 167, because the condition on line 164 was never false

165 self.kedama = parts.kedama.Kedama(self) 

166 

167 if 'archive' not in disables: 167 ↛ 170line 167 didn't jump to line 170, because the condition on line 167 was never false

168 self.archive = parts.archive.Archive(self) 

169 

170 if 'hooks' not in disables: 170 ↛ 173line 170 didn't jump to line 173, because the condition on line 170 was never false

171 self.hooks = parts.hooks.Hooks(self) 

172 

173 if 'connect' not in disables: 173 ↛ 174line 173 didn't jump to line 174, because the condition on line 173 was never true

174 self.connect = parts.connect.Connect(self) 

175 

176 if 'backend' not in disables: 176 ↛ 177line 176 didn't jump to line 177, because the condition on line 176 was never true

177 self.backend = parts.backend.Backend(self) 

178 

179 if 'log' not in disables: 179 ↛ 182line 179 didn't jump to line 182, because the condition on line 179 was never false

180 self.log = parts.log.Log(self) 

181 

182 if 'stats' not in disables: 182 ↛ 183line 182 didn't jump to line 183, because the condition on line 182 was never true

183 self.stats = parts.stats.Stats(self) 

184 

185 if 'view' not in disables: 185 ↛ 188line 185 didn't jump to line 188, because the condition on line 185 was never false

186 self.view = parts.view.View(self) 

187 

188 self.events.core_initialized.emit(self)