1 {-# LANGUAGE OverloadedStrings #-} |
1 {-# LANGUAGE OverloadedStrings #-} |
2 module HWProtoInRoomState where |
2 module HWProtoInRoomState where |
3 |
3 |
4 import qualified Data.Map as Map |
4 import qualified Data.Map as Map |
5 import Data.Sequence((|>)) |
|
6 import Data.List as L |
5 import Data.List as L |
7 import Data.Maybe |
6 import Data.Maybe |
8 import qualified Data.ByteString.Char8 as B |
7 import qualified Data.ByteString.Char8 as B |
9 import Control.Monad |
8 import Control.Monad |
10 import Control.Monad.Reader |
9 import Control.Monad.Reader |
11 import Control.DeepSeq |
|
12 -------------------------------------- |
10 -------------------------------------- |
13 import CoreTypes |
11 import CoreTypes |
14 import Actions |
12 import Actions |
15 import Utils |
13 import Utils |
16 import HandlerUtils |
14 import HandlerUtils |
27 handleCmd_inRoom ["PART"] = return [MoveToLobby "part"] |
25 handleCmd_inRoom ["PART"] = return [MoveToLobby "part"] |
28 handleCmd_inRoom ["PART", msg] = return [MoveToLobby $ "part: " `B.append` msg] |
26 handleCmd_inRoom ["PART", msg] = return [MoveToLobby $ "part: " `B.append` msg] |
29 |
27 |
30 |
28 |
31 handleCmd_inRoom ("CFG" : paramName : paramStrs) |
29 handleCmd_inRoom ("CFG" : paramName : paramStrs) |
32 | null paramStrs = return [ProtocolError "Empty config entry"] |
30 | null paramStrs = return [ProtocolError $ loc "Empty config entry"] |
33 | otherwise = do |
31 | otherwise = do |
34 chans <- roomOthersChans |
32 chans <- roomOthersChans |
35 cl <- thisClient |
33 cl <- thisClient |
36 if isMaster cl then |
34 if isMaster cl then |
37 return [ |
35 return [ |
38 ModifyRoom f, |
36 ModifyRoom f, |
39 AnswerClients chans ("CFG" : paramName : paramStrs)] |
37 AnswerClients chans ("CFG" : paramName : paramStrs)] |
40 else |
38 else |
41 return [ProtocolError "Not room master"] |
39 return [ProtocolError $ loc "Not room master"] |
42 where |
40 where |
43 f r = if paramName `Map.member` (mapParams r) then |
41 f r = if paramName `Map.member` (mapParams r) then |
44 r{mapParams = Map.insert paramName (head paramStrs) (mapParams r)} |
42 r{mapParams = Map.insert paramName (head paramStrs) (mapParams r)} |
45 else |
43 else |
46 r{params = Map.insert paramName paramStrs (params r)} |
44 r{params = Map.insert paramName paramStrs (params r)} |
47 |
45 |
48 handleCmd_inRoom ("ADD_TEAM" : tName : color : grave : fort : voicepack : flag : difStr : hhsInfo) |
46 handleCmd_inRoom ("ADD_TEAM" : tName : color : grave : fort : voicepack : flag : difStr : hhsInfo) |
49 | length hhsInfo /= 16 = return [ProtocolError "Corrupted hedgehogs info"] |
47 | length hhsInfo /= 16 = return [ProtocolError $ loc "Corrupted hedgehogs info"] |
50 | otherwise = do |
48 | otherwise = do |
51 (ci, _) <- ask |
49 (ci, _) <- ask |
52 rm <- thisRoom |
50 rm <- thisRoom |
53 clNick <- clientNick |
51 clNick <- clientNick |
54 clChan <- thisClientChans |
52 clChan <- thisClientChans |
58 teamColor <- |
56 teamColor <- |
59 if clientProto cl < 42 then |
57 if clientProto cl < 42 then |
60 return color |
58 return color |
61 else |
59 else |
62 liftM (head . (L.\\) (map B.singleton ['0'..]) . map teamcolor . teams) thisRoom |
60 liftM (head . (L.\\) (map B.singleton ['0'..]) . map teamcolor . teams) thisRoom |
63 let newTeam = clNick `seq` TeamInfo ci clNick tName teamColor grave fort voicepack flag dif (newTeamHHNum rm) (hhsList hhsInfo) |
61 let roomTeams = teams rm |
|
62 let hhNum = let p = if not $ null roomTeams then hhnum $ head roomTeams else 4 in newTeamHHNum roomTeams p |
|
63 let newTeam = clNick `seq` TeamInfo ci clNick tName teamColor grave fort voicepack flag dif hhNum (hhsList hhsInfo) |
64 return $ |
64 return $ |
65 if not . null . drop (maxTeams rm - 1) $ teams rm then |
65 if not . null . drop (maxTeams rm - 1) $ roomTeams then |
66 [Warning "too many teams"] |
66 [Warning $ loc "too many teams"] |
67 else if canAddNumber rm <= 0 then |
67 else if canAddNumber roomTeams <= 0 then |
68 [Warning "too many hedgehogs"] |
68 [Warning $ loc "too many hedgehogs"] |
69 else if isJust $ findTeam rm then |
69 else if isJust $ findTeam rm then |
70 [Warning "There's already a team with same name in the list"] |
70 [Warning $ loc "There's already a team with same name in the list"] |
71 else if isJust $ gameInfo rm then |
71 else if isJust $ gameInfo rm then |
72 [Warning "round in progress"] |
72 [Warning $ loc "round in progress"] |
73 else if isRestrictedTeams rm then |
73 else if isRestrictedTeams rm then |
74 [Warning "restricted"] |
74 [Warning $ loc "restricted"] |
75 else |
75 else |
76 [ModifyRoom (\r -> r{teams = teams r ++ [newTeam]}), |
76 [ModifyRoom (\r -> r{teams = teams r ++ [newTeam]}), |
77 SendUpdateOnThisRoom, |
77 SendUpdateOnThisRoom, |
78 ModifyClient (\c -> c{teamsInGame = teamsInGame c + 1, clientClan = Just teamColor}), |
78 ModifyClient (\c -> c{teamsInGame = teamsInGame c + 1, clientClan = Just teamColor}), |
79 AnswerClients clChan ["TEAM_ACCEPTED", tName], |
79 AnswerClients clChan ["TEAM_ACCEPTED", tName], |
|
80 AnswerClients clChan ["HH_NUM", tName, showB $ hhnum newTeam], |
80 AnswerClients othChans $ teamToNet $ newTeam, |
81 AnswerClients othChans $ teamToNet $ newTeam, |
81 AnswerClients roomChans ["TEAM_COLOR", tName, teamColor] |
82 AnswerClients roomChans ["TEAM_COLOR", tName, teamColor] |
82 ] |
83 ] |
83 where |
84 where |
84 canAddNumber r = 48 - (sum . map hhnum $ teams r) |
85 canAddNumber rt = (48::Int) - (sum $ map hhnum rt) |
85 findTeam = find (\t -> tName == teamname t) . teams |
86 findTeam = find (\t -> tName == teamname t) . teams |
86 dif = readInt_ difStr |
87 dif = readInt_ difStr |
87 hhsList [] = [] |
88 hhsList [] = [] |
88 hhsList [_] = error "Hedgehogs list with odd elements number" |
89 hhsList [_] = error "Hedgehogs list with odd elements number" |
89 hhsList (n:h:hhs) = HedgehogInfo n h : hhsList hhs |
90 hhsList (n:h:hhs) = HedgehogInfo n h : hhsList hhs |
90 newTeamHHNum r = min 4 (canAddNumber r) |
91 newTeamHHNum rt p = min p (canAddNumber rt) |
91 maxTeams r |
92 maxTeams r |
92 | roomProto r < 38 = 6 |
93 | roomProto r < 38 = 6 |
93 | otherwise = 8 |
94 | otherwise = 8 |
94 |
95 |
95 |
96 |
100 |
101 |
101 let maybeTeam = findTeam r |
102 let maybeTeam = findTeam r |
102 let team = fromJust maybeTeam |
103 let team = fromJust maybeTeam |
103 |
104 |
104 return $ |
105 return $ |
105 if isNothing $ findTeam r then |
106 if isNothing $ maybeTeam then |
106 [Warning "REMOVE_TEAM: no such team"] |
107 [Warning $ loc "REMOVE_TEAM: no such team"] |
107 else if clNick /= teamowner team then |
108 else if clNick /= teamowner team then |
108 [ProtocolError "Not team owner!"] |
109 [ProtocolError $ loc "Not team owner!"] |
109 else |
110 else |
110 [RemoveTeam tName, |
111 [RemoveTeam tName, |
111 ModifyClient |
112 ModifyClient |
112 (\c -> c{ |
113 (\c -> c{ |
113 teamsInGame = teamsInGame c - 1, |
114 teamsInGame = teamsInGame c - 1, |
119 findTeam = find (\t -> tName == teamname t) . teams |
120 findTeam = find (\t -> tName == teamname t) . teams |
120 |
121 |
121 |
122 |
122 handleCmd_inRoom ["HH_NUM", teamName, numberStr] = do |
123 handleCmd_inRoom ["HH_NUM", teamName, numberStr] = do |
123 cl <- thisClient |
124 cl <- thisClient |
124 others <- roomOthersChans |
|
125 r <- thisRoom |
125 r <- thisRoom |
|
126 clChan <- thisClientChans |
|
127 roomChans <- roomClientsChans |
126 |
128 |
127 let maybeTeam = findTeam r |
129 let maybeTeam = findTeam r |
128 let team = fromJust maybeTeam |
130 let team = fromJust maybeTeam |
129 |
131 |
130 return $ |
132 return $ |
131 if not $ isMaster cl then |
133 if not $ isMaster cl then |
132 [ProtocolError "Not room master"] |
134 [ProtocolError $ loc "Not room master"] |
133 else if hhNumber < 1 || hhNumber > 8 || isNothing maybeTeam || hhNumber > canAddNumber r + hhnum team then |
135 else if isNothing maybeTeam then |
134 [] |
136 [] |
|
137 else if hhNumber < 1 || hhNumber > 8 || hhNumber > canAddNumber r + hhnum team then |
|
138 [AnswerClients clChan ["HH_NUM", teamName, showB $ hhnum team]] |
135 else |
139 else |
136 [ModifyRoom $ modifyTeam team{hhnum = hhNumber}, |
140 [ModifyRoom $ modifyTeam team{hhnum = hhNumber}, |
137 AnswerClients others ["HH_NUM", teamName, showB hhNumber]] |
141 AnswerClients roomChans ["HH_NUM", teamName, showB hhNumber]] |
138 where |
142 where |
139 hhNumber = readInt_ numberStr |
143 hhNumber = readInt_ numberStr |
140 findTeam = find (\t -> teamName == teamname t) . teams |
144 findTeam = find (\t -> teamName == teamname t) . teams |
141 canAddNumber = (-) 48 . sum . map hhnum . teams |
145 canAddNumber = (-) 48 . sum . map hhnum . teams |
142 |
146 |
150 let maybeTeam = findTeam r |
154 let maybeTeam = findTeam r |
151 let team = fromJust maybeTeam |
155 let team = fromJust maybeTeam |
152 |
156 |
153 return $ |
157 return $ |
154 if not $ isMaster cl then |
158 if not $ isMaster cl then |
155 [ProtocolError "Not room master"] |
159 [ProtocolError $ loc "Not room master"] |
156 else if isNothing maybeTeam then |
160 else if isNothing maybeTeam then |
157 [] |
161 [] |
158 else |
162 else |
159 [ModifyRoom $ modifyTeam team{teamcolor = newColor}, |
163 [ModifyRoom $ modifyTeam team{teamcolor = newColor}, |
160 AnswerClients others ["TEAM_COLOR", teamName, newColor], |
164 AnswerClients others ["TEAM_COLOR", teamName, newColor], |
185 chans <- roomClientsChans |
189 chans <- roomClientsChans |
186 |
190 |
187 let nicks = map (nick . client rnc) . roomClients rnc $ clientRoom rnc ci |
191 let nicks = map (nick . client rnc) . roomClients rnc $ clientRoom rnc ci |
188 let allPlayersRegistered = all ((<) 0 . B.length . webPassword . client rnc . teamownerId) $ teams rm |
192 let allPlayersRegistered = all ((<) 0 . B.length . webPassword . client rnc . teamownerId) $ teams rm |
189 |
193 |
190 if isMaster cl && playersIn rm == readyPlayers rm && not (isJust $ gameInfo rm) then |
194 if isMaster cl && (playersIn rm == readyPlayers rm || clientProto cl > 43) && not (isJust $ gameInfo rm) then |
191 if enoughClans rm then |
195 if enoughClans rm then |
192 return [ |
196 return [ |
193 ModifyRoom |
197 ModifyRoom |
194 (\r -> r{ |
198 (\r -> r{ |
195 gameInfo = Just $ newGameInfo (teams rm) (length $ teams rm) allPlayersRegistered (mapParams rm) (params rm) |
199 gameInfo = Just $ newGameInfo (teams rm) (length $ teams rm) allPlayersRegistered (mapParams rm) (params rm) |
229 let clTeams = map teamname . filter (\t -> teamowner t == nick cl) . teams $ rm |
234 let clTeams = map teamname . filter (\t -> teamowner t == nick cl) . teams $ rm |
230 let unsetInGameState = [AnswerClients chans ["CLIENT_FLAGS", "-g", nick cl], ModifyClient (\c -> c{isInGame = False})] |
235 let unsetInGameState = [AnswerClients chans ["CLIENT_FLAGS", "-g", nick cl], ModifyClient (\c -> c{isInGame = False})] |
231 |
236 |
232 if isInGame cl then |
237 if isInGame cl then |
233 if isJust $ gameInfo rm then |
238 if isJust $ gameInfo rm then |
234 if (isMaster cl && isCorrect) then |
239 return $ unsetInGameState ++ map SendTeamRemovalMessage clTeams |
235 return $ FinishGame : unsetInGameState |
|
236 else |
|
237 return $ unsetInGameState ++ map SendTeamRemovalMessage clTeams |
|
238 else |
240 else |
239 return unsetInGameState |
241 return unsetInGameState |
240 else |
242 else |
241 return [] -- don't accept this message twice |
243 return [] -- don't accept this message twice |
242 where |
244 where |
248 |
250 |
249 handleCmd_inRoom ["TOGGLE_RESTRICT_JOINS"] = do |
251 handleCmd_inRoom ["TOGGLE_RESTRICT_JOINS"] = do |
250 cl <- thisClient |
252 cl <- thisClient |
251 return $ |
253 return $ |
252 if not $ isMaster cl then |
254 if not $ isMaster cl then |
253 [ProtocolError "Not room master"] |
255 [ProtocolError $ loc "Not room master"] |
254 else |
256 else |
255 [ModifyRoom (\r -> r{isRestrictedJoins = not $ isRestrictedJoins r})] |
257 [ModifyRoom (\r -> r{isRestrictedJoins = not $ isRestrictedJoins r})] |
256 |
258 |
257 |
259 |
258 handleCmd_inRoom ["TOGGLE_RESTRICT_TEAMS"] = do |
260 handleCmd_inRoom ["TOGGLE_RESTRICT_TEAMS"] = do |
259 cl <- thisClient |
261 cl <- thisClient |
260 return $ |
262 return $ |
261 if not $ isMaster cl then |
263 if not $ isMaster cl then |
262 [ProtocolError "Not room master"] |
264 [ProtocolError $ loc "Not room master"] |
263 else |
265 else |
264 [ModifyRoom (\r -> r{isRestrictedTeams = not $ isRestrictedTeams r})] |
266 [ModifyRoom (\r -> r{isRestrictedTeams = not $ isRestrictedTeams r})] |
265 |
267 |
266 |
268 |
267 handleCmd_inRoom ["TOGGLE_REGISTERED_ONLY"] = do |
269 handleCmd_inRoom ["TOGGLE_REGISTERED_ONLY"] = do |
268 cl <- thisClient |
270 cl <- thisClient |
269 return $ |
271 return $ |
270 if not $ isMaster cl then |
272 if not $ isMaster cl then |
271 [ProtocolError "Not room master"] |
273 [ProtocolError $ loc "Not room master"] |
272 else |
274 else |
273 [ModifyRoom (\r -> r{isRegisteredOnly = not $ isRegisteredOnly r})] |
275 [ModifyRoom (\r -> r{isRegisteredOnly = not $ isRegisteredOnly r})] |
274 |
276 |
275 handleCmd_inRoom ["ROOM_NAME", newName] = do |
277 handleCmd_inRoom ["ROOM_NAME", newName] = do |
276 cl <- thisClient |
278 cl <- thisClient |
278 rm <- thisRoom |
280 rm <- thisRoom |
279 chans <- sameProtoChans |
281 chans <- sameProtoChans |
280 |
282 |
281 return $ |
283 return $ |
282 if not $ isMaster cl then |
284 if not $ isMaster cl then |
283 [ProtocolError "Not room master"] |
285 [ProtocolError $ loc "Not room master"] |
284 else |
286 else |
285 if isJust $ find (\r -> newName == name r) rs then |
287 if isJust $ find (\r -> newName == name r) rs then |
286 [Warning "Room with such name already exists"] |
288 [Warning $ loc "Room with such name already exists"] |
287 else |
289 else |
288 [ModifyRoom roomUpdate, |
290 [ModifyRoom roomUpdate, |
289 AnswerClients chans ("ROOM" : "UPD" : name rm : roomInfo (nick cl) (roomUpdate rm))] |
291 AnswerClients chans ("ROOM" : "UPD" : name rm : roomInfo (nick cl) (roomUpdate rm))] |
290 where |
292 where |
291 roomUpdate r = r{name = newName} |
293 roomUpdate r = r{name = newName} |
303 |
305 |
304 handleCmd_inRoom ["DELEGATE", newAdmin] = do |
306 handleCmd_inRoom ["DELEGATE", newAdmin] = do |
305 (thisClientId, rnc) <- ask |
307 (thisClientId, rnc) <- ask |
306 maybeClientId <- clientByNick newAdmin |
308 maybeClientId <- clientByNick newAdmin |
307 master <- liftM isMaster thisClient |
309 master <- liftM isMaster thisClient |
|
310 serverAdmin <- liftM isAdministrator thisClient |
308 let newAdminId = fromJust maybeClientId |
311 let newAdminId = fromJust maybeClientId |
309 let sameRoom = clientRoom rnc thisClientId == clientRoom rnc newAdminId |
312 let sameRoom = clientRoom rnc thisClientId == clientRoom rnc newAdminId |
310 return |
313 return |
311 [ChangeMaster (Just newAdminId) | master && isJust maybeClientId && (newAdminId /= thisClientId) && sameRoom] |
314 [ChangeMaster (Just newAdminId) | |
|
315 (master || serverAdmin) |
|
316 && isJust maybeClientId |
|
317 && ((newAdminId /= thisClientId) || (serverAdmin && not master)) |
|
318 && sameRoom] |
312 |
319 |
313 |
320 |
314 handleCmd_inRoom ["TEAMCHAT", msg] = do |
321 handleCmd_inRoom ["TEAMCHAT", msg] = do |
315 cl <- thisClient |
322 cl <- thisClient |
316 chans <- roomSameClanChans |
323 chans <- roomSameClanChans |