gameServer/Actions.hs
branchsdl2transition
changeset 9798 f2b18754742f
parent 9786 e33ee5ef5d9d
child 9868 53d1b92db6ce
equal deleted inserted replaced
9711:7d0329f37181 9798:f2b18754742f
    19 import Control.Arrow
    19 import Control.Arrow
    20 import Control.Exception as E
    20 import Control.Exception as E
    21 import System.Process
    21 import System.Process
    22 import Network.Socket
    22 import Network.Socket
    23 import System.Random
    23 import System.Random
       
    24 import qualified Data.Traversable as DT
    24 -----------------------------
    25 -----------------------------
    25 #if defined(OFFICIAL_SERVER)
    26 #if defined(OFFICIAL_SERVER)
    26 import OfficialServer.GameReplayStore
    27 import OfficialServer.GameReplayStore
    27 #endif
    28 #endif
    28 import CoreTypes
    29 import CoreTypes
   185 processAction (MoveToLobby msg) = do
   186 processAction (MoveToLobby msg) = do
   186     (Just ci) <- gets clientIndex
   187     (Just ci) <- gets clientIndex
   187     ri <- clientRoomA
   188     ri <- clientRoomA
   188     rnc <- gets roomsClients
   189     rnc <- gets roomsClients
   189     playersNum <- io $ room'sM rnc playersIn ri
   190     playersNum <- io $ room'sM rnc playersIn ri
       
   191     specialRoom <- io $ room'sM rnc isSpecial ri
   190     master <- client's isMaster
   192     master <- client's isMaster
   191 --    client <- client's id
   193 --    client <- client's id
   192     clNick <- client's nick
   194     clNick <- client's nick
   193     chans <- othersChans
   195     chans <- othersChans
   194 
   196 
   195     if master then
   197     if master then
   196         if playersNum > 1 then
   198         if (playersNum > 1) || specialRoom then
   197             mapM_ processAction [ChangeMaster Nothing, NoticeMessage AdminLeft, RemoveClientTeams, AnswerClients chans ["LEFT", clNick, msg]]
   199             mapM_ processAction [ChangeMaster Nothing, NoticeMessage AdminLeft, RemoveClientTeams, AnswerClients chans ["LEFT", clNick, msg]]
   198             else
   200             else
   199             processAction RemoveRoom
   201             processAction RemoveRoom
   200         else
   202         else
   201         mapM_ processAction [RemoveClientTeams, AnswerClients chans ["LEFT", clNick, msg]]
   203         mapM_ processAction [RemoveClientTeams, AnswerClients chans ["LEFT", clNick, msg]]
   203     allClientsChans <- liftM (Prelude.map sendChan . Prelude.filter isVisible) $! allClientsS
   205     allClientsChans <- liftM (Prelude.map sendChan . Prelude.filter isVisible) $! allClientsS
   204     processAction $ AnswerClients allClientsChans ["CLIENT_FLAGS", "-i", clNick]
   206     processAction $ AnswerClients allClientsChans ["CLIENT_FLAGS", "-i", clNick]
   205 
   207 
   206     -- when not removing room
   208     -- when not removing room
   207     ready <- client's isReady
   209     ready <- client's isReady
   208     when (not master || playersNum > 1) . io $ do
   210     when (not master || playersNum > 1 || specialRoom) . io $ do
   209         modifyRoom rnc (\r -> r{
   211         modifyRoom rnc (\r -> r{
   210                 playersIn = playersIn r - 1,
   212                 playersIn = playersIn r - 1,
   211                 readyPlayers = if ready then readyPlayers r - 1 else readyPlayers r
   213                 readyPlayers = if ready then readyPlayers r - 1 else readyPlayers r
   212                 }) ri
   214                 }) ri
   213         moveClientToLobby rnc ci
   215         moveClientToLobby rnc ci
   216 processAction (ChangeMaster delegateId)= do
   218 processAction (ChangeMaster delegateId)= do
   217     (Just ci) <- gets clientIndex
   219     (Just ci) <- gets clientIndex
   218     proto <- client's clientProto
   220     proto <- client's clientProto
   219     ri <- clientRoomA
   221     ri <- clientRoomA
   220     rnc <- gets roomsClients
   222     rnc <- gets roomsClients
   221     newMasterId <- liftM (\ids -> fromMaybe (last . filter (/= ci) $ ids) delegateId) . io $ roomClientsIndicesM rnc ri
   223     specialRoom <- io $ room'sM rnc isSpecial ri
   222     newMaster <- io $ client'sM rnc id newMasterId
   224     newMasterId <- liftM (\ids -> fromMaybe (listToMaybe . reverse . filter (/= ci) $ ids) $ liftM Just delegateId) . io $ roomClientsIndicesM rnc ri
       
   225     newMaster <- io $ client'sM rnc id `DT.mapM` newMasterId
   223     oldMasterId <- io $ room'sM rnc masterID ri
   226     oldMasterId <- io $ room'sM rnc masterID ri
   224     oldMaster <- io $ client'sM rnc id oldMasterId
       
   225     oldRoomName <- io $ room'sM rnc name ri
   227     oldRoomName <- io $ room'sM rnc name ri
   226     kicked <- client's isKickedFromServer
   228     kicked <- client's isKickedFromServer
   227     thisRoomChans <- liftM (map sendChan) $ roomClientsS ri
   229     thisRoomChans <- liftM (map sendChan) $ roomClientsS ri
   228     let newRoomName = if (proto < 42) || kicked then nick newMaster else oldRoomName
   230     let newRoomName = if ((proto < 42) || kicked) && (not specialRoom) then maybeNick newMaster else oldRoomName
   229     mapM_ processAction [
   231 
       
   232     when (isJust oldMasterId) $ do
       
   233         oldMasterNick <- io $ client'sM rnc nick (fromJust oldMasterId)
       
   234         mapM_ processAction [
       
   235             ModifyClient2 (fromJust oldMasterId) (\c -> c{isMaster = False})
       
   236             , AnswerClients thisRoomChans ["CLIENT_FLAGS", "-h", oldMasterNick]
       
   237             ]
       
   238 
       
   239     when (isJust newMasterId) $
       
   240         mapM_ processAction [
       
   241           ModifyClient2 (fromJust newMasterId) (\c -> c{isMaster = True})
       
   242         , AnswerClients [sendChan $ fromJust newMaster] ["ROOM_CONTROL_ACCESS", "1"]
       
   243         , AnswerClients thisRoomChans ["CLIENT_FLAGS", "+h", nick $ fromJust newMaster]
       
   244         ]
       
   245 
       
   246     processAction $
   230         ModifyRoom (\r -> r{masterID = newMasterId
   247         ModifyRoom (\r -> r{masterID = newMasterId
   231                 , name = newRoomName
   248                 , name = newRoomName
   232                 , isRestrictedJoins = False
   249                 , isRestrictedJoins = False
   233                 , isRestrictedTeams = False
   250                 , isRestrictedTeams = False
   234                 , isRegisteredOnly = False}
   251                 , isRegisteredOnly = isSpecial r}
   235                 )
   252                 )
   236         , ModifyClient2 newMasterId (\c -> c{isMaster = True})
       
   237         , ModifyClient2 oldMasterId (\c -> c{isMaster = False})
       
   238         , AnswerClients [sendChan newMaster] ["ROOM_CONTROL_ACCESS", "1"]
       
   239         , AnswerClients thisRoomChans ["CLIENT_FLAGS", "-h", nick oldMaster]
       
   240         , AnswerClients thisRoomChans ["CLIENT_FLAGS", "+h", nick newMaster]
       
   241         ]
       
   242 
   253 
   243     newRoom' <- io $ room'sM rnc id ri
   254     newRoom' <- io $ room'sM rnc id ri
   244     chans <- liftM (map sendChan) $! sameProtoClientsS proto
   255     chans <- liftM (map sendChan) $! sameProtoClientsS proto
   245     processAction $ AnswerClients chans ("ROOM" : "UPD" : oldRoomName : roomInfo (nick newMaster) newRoom')
   256     processAction $ AnswerClients chans ("ROOM" : "UPD" : oldRoomName : roomInfo proto (maybeNick newMaster) newRoom')
   246 
   257 
   247 
   258 
   248 processAction (AddRoom roomName roomPassword) = do
   259 processAction (AddRoom roomName roomPassword) = do
   249     Just clId <- gets clientIndex
   260     Just clId <- gets clientIndex
   250     rnc <- gets roomsClients
   261     rnc <- gets roomsClients
   251     proto <- client's clientProto
   262     proto <- client's clientProto
   252     n <- client's nick
   263     n <- client's nick
   253 
   264 
   254     let rm = newRoom{
   265     let rm = newRoom{
   255             masterID = clId,
   266             masterID = Just clId,
   256             name = roomName,
   267             name = roomName,
   257             password = roomPassword,
   268             password = roomPassword,
   258             roomProto = proto
   269             roomProto = proto
   259             }
   270             }
   260 
   271 
   263     processAction $ MoveToRoom rId
   274     processAction $ MoveToRoom rId
   264 
   275 
   265     chans <- liftM (map sendChan) $! sameProtoClientsS proto
   276     chans <- liftM (map sendChan) $! sameProtoClientsS proto
   266 
   277 
   267     mapM_ processAction [
   278     mapM_ processAction [
   268       AnswerClients chans ("ROOM" : "ADD" : roomInfo n rm{playersIn = 1})
   279       AnswerClients chans ("ROOM" : "ADD" : roomInfo proto n rm{playersIn = 1})
   269         ]
   280         ]
   270 
   281 
   271 
   282 
   272 processAction RemoveRoom = do
   283 processAction RemoveRoom = do
   273     Just clId <- gets clientIndex
   284     Just clId <- gets clientIndex
   290     Just clId <- gets clientIndex
   301     Just clId <- gets clientIndex
   291     proto <- client's clientProto
   302     proto <- client's clientProto
   292     rnc <- gets roomsClients
   303     rnc <- gets roomsClients
   293     ri <- io $ clientRoomM rnc clId
   304     ri <- io $ clientRoomM rnc clId
   294     rm <- io $ room'sM rnc id ri
   305     rm <- io $ room'sM rnc id ri
   295     n <- io $ client'sM rnc nick (masterID rm)
   306     masterCl <- io $ client'sM rnc id `DT.mapM` (masterID rm)
   296     chans <- liftM (map sendChan) $! sameProtoClientsS proto
   307     chans <- liftM (map sendChan) $! sameProtoClientsS proto
   297     processAction $ AnswerClients chans ("ROOM" : "UPD" : name rm : roomInfo n rm)
   308     processAction $ AnswerClients chans ("ROOM" : "UPD" : name rm : roomInfo proto (maybeNick masterCl) rm)
   298 
   309 
   299 
   310 
   300 processAction UnreadyRoomClients = do
   311 processAction UnreadyRoomClients = do
   301     ri <- clientRoomA
   312     ri <- clientRoomA
   302     roomPlayers <- roomClientsS ri
   313     roomPlayers <- roomClientsS ri
   431             when (not b) $
   442             when (not b) $
   432                 if c then
   443                 if c then
   433                     checkerLogin "" False False
   444                     checkerLogin "" False False
   434                     else
   445                     else
   435                     processAction JoinLobby
   446                     processAction JoinLobby
   436         Admin -> do
   447         Admin ->
   437             mapM_ processAction [ModifyClient (\cl -> cl{isAdministrator = True}), JoinLobby]
   448             mapM_ processAction [ModifyClient (\cl -> cl{isAdministrator = True}), JoinLobby]
   438             chan <- client's sendChan
       
   439             processAction $ AnswerClients [chan] ["ADMIN_ACCESS"]
       
   440         ReplayName fn -> processAction $ ShowReplay fn
   449         ReplayName fn -> processAction $ ShowReplay fn
   441     where
   450     where
   442     isBanned = do
   451     isBanned = do
   443         processAction $ CheckBanned False
   452         processAction $ CheckBanned False
   444         liftM B.null $ client's nick
   453         liftM B.null $ client's nick
   712     io $ writeChan (dbQueries si) $ StoreAchievements (B.pack fileName) (map toPair teams) info
   721     io $ writeChan (dbQueries si) $ StoreAchievements (B.pack fileName) (map toPair teams) info
   713     io $ moveCheckedRecord fileName
   722     io $ moveCheckedRecord fileName
   714     where
   723     where
   715         toPair t = (teamname t, teamowner t)
   724         toPair t = (teamname t, teamowner t)
   716 
   725 
   717 processAction (QueryReplay name) = do
   726 processAction (QueryReplay rname) = do
   718     (Just ci) <- gets clientIndex
   727     (Just ci) <- gets clientIndex
   719     si <- gets serverInfo
   728     si <- gets serverInfo
   720     uid <- client's clUID
   729     uid <- client's clUID
   721     io $ writeChan (dbQueries si) $ GetReplayName ci (hashUnique uid) name
   730     io $ writeChan (dbQueries si) $ GetReplayName ci (hashUnique uid) rname
   722 
   731 
   723 #else
   732 #else
   724 processAction SaveReplay = return ()
   733 processAction SaveReplay = return ()
   725 processAction CheckRecord = return ()
   734 processAction CheckRecord = return ()
   726 processAction (CheckFailed _) = return ()
   735 processAction (CheckFailed _) = return ()
   727 processAction (CheckSuccess _) = return ()
   736 processAction (CheckSuccess _) = return ()
   728 processAction (QueryReplay _) = return ()
   737 processAction (QueryReplay _) = return ()
   729 #endif
   738 #endif
   730 
   739 
   731 processAction (ShowReplay name) = do
   740 processAction (ShowReplay rname) = do
   732     c <- client's sendChan
   741     c <- client's sendChan
   733     cl <- client's id
   742     cl <- client's id
   734 
   743 
   735     let fileName = B.concat ["checked/", if B.isPrefixOf "replays/" name then B.drop 8 name else name]
   744     let fileName = B.concat ["checked/", if B.isPrefixOf "replays/" rname then B.drop 8 rname else rname]
   736 
   745 
   737     checkInfo <- liftIO $ E.handle (\(e :: SomeException) ->
   746     cInfo <- liftIO $ E.handle (\(e :: SomeException) ->
   738                     warningM "REPLAYS" (B.unpack $ B.concat ["Problems reading ", fileName, ": ", B.pack $ show e]) >> return Nothing) $ do
   747                     warningM "REPLAYS" (B.unpack $ B.concat ["Problems reading ", fileName, ": ", B.pack $ show e]) >> return Nothing) $ do
   739             (t, p1, p2, msgs) <- liftM read $ readFile (B.unpack fileName)
   748             (t, p1, p2, msgs) <- liftM read $ readFile (B.unpack fileName)
   740             return $ Just (t, Map.fromList p1, Map.fromList p2, reverse msgs)
   749             return $ Just (t, Map.fromList p1, Map.fromList p2, reverse msgs)
   741 
   750 
   742     let (teams, params1, params2, roundMsgs) = fromJust checkInfo
   751     let (teams', params1, params2, roundMsgs') = fromJust cInfo
   743 
   752 
   744     when (isJust checkInfo) $ do
   753     when (isJust cInfo) $ do
   745         mapM_ processAction $ concat [
   754         mapM_ processAction $ concat [
   746             [AnswerClients [c] ["JOINED", nick cl]]
   755             [AnswerClients [c] ["JOINED", nick cl]]
   747             , answerFullConfigParams cl params1 params2
   756             , answerFullConfigParams cl params1 params2
   748             , answerAllTeams cl teams
   757             , answerAllTeams cl teams'
   749             , [AnswerClients [c]  ["RUN_GAME"]]
   758             , [AnswerClients [c]  ["RUN_GAME"]]
   750             , [AnswerClients [c] $ "EM" : roundMsgs]
   759             , [AnswerClients [c] $ "EM" : roundMsgs']
   751             , [AnswerClients [c] ["KICKED"]]
   760             , [AnswerClients [c] ["KICKED"]]
   752             ]
   761             ]