# HG changeset patch # User Mitchell Kember # Date 1354746348 18000 # Node ID 9ffb156902f60e787d780fd68ff6d067bca14c5d # Parent d2207f22c5f21016497e100502c6711d9c4f563e# Parent d7cf4a9ce685d04ffba65b5d217b2007052d25ae Merge diff -r d2207f22c5f2 -r 9ffb156902f6 doc/protocol.txt --- a/doc/protocol.txt Wed Dec 05 13:45:18 2012 -0500 +++ b/doc/protocol.txt Wed Dec 05 17:25:48 2012 -0500 @@ -1,34 +1,35 @@ - '?' ping? - '!' pong! - 'l','L' срабатывание команд -left, +left - 'r','R' -right, +right - 'u','U' -up, +up - 'd','D' -down, +down - 'z', 'Z' -precise, +precise - 'N' срабатывание команды /nextturn - 'S' /switch - 's' + <текст> /say - '+' пустой пакет для постоянности лага - '1'..'5' /timer 1..5 - chr(128+№) /slot № - 'w' /setweap - 'p' /put - 'j' /ljump - 'J' /hjump - 'E' + <текст> сообщение об ошибке - ',' /skip - 'K' вывести сообщение из KB - 'Q' выход через команду /quit - 'q' выход по причине окончания игры - 't' + № /taunt № - 'F' + команда team вылетела в сетевой игре + '?' ping? + '!' pong! + 'l','L' срабатывание команд -left, +left + 'r','R' -right, +right + 'u','U' -up, +up + 'd','D' -down, +down + 'z', 'Z' -precise, +precise + 'N' срабатывание команды /nextturn + 'S' /switch + 's' + <текст> /say + '+' пустой пакет для постоянности лага + '1'..'5' /timer 1..5 + chr(128+№) /slot № + 'w' /setweap + 'p' /put + 'j' /ljump + 'J' /hjump + 'E' + <текст> сообщение об ошибке + ',' /skip + 't' + № /taunt № фронтенд клиенту: - 'e' + <команда> выполнить "/<команда>" - 'T' + {L,N,D} тип игры (локальная, сетевая, просмотр демо) - 'W' + <текст> сообщение о нефатальной ошибке + 'e' + <команда> выполнить "/<команда>" + 'T' + {L,N,D} тип игры (локальная, сетевая, просмотр демо) + 'W' + <текст> сообщение о нефатальной ошибке + 'F' + команда team вылетела в сетевой игре + 'o' stop syncing, game over! Клиент фронтенду: - 'C' запрос текущего конфига игры - 'q' выход по причине окончания демки - 'i' статистика + 'C' запрос текущего конфига игры + 'q' выход по причине окончания демки + 'i' статистика + 'K' вывести сообщение из KB + 'Q' выход через команду /quit + 'q' выход по причине окончания игры diff -r d2207f22c5f2 -r 9ffb156902f6 gameServer/Actions.hs --- a/gameServer/Actions.hs Wed Dec 05 13:45:18 2012 -0500 +++ b/gameServer/Actions.hs Wed Dec 05 17:25:48 2012 -0500 @@ -55,7 +55,7 @@ | BanNick B.ByteString NominalDiffTime B.ByteString | BanList | Unban B.ByteString - | ChangeMaster + | ChangeMaster (Maybe ClientIndex) | RemoveClientTeams ClientIndex | ModifyClient (ClientInfo -> ClientInfo) | ModifyClient2 ClientIndex (ClientInfo -> ClientInfo) @@ -74,7 +74,7 @@ | RestartServer | AddNick2Bans B.ByteString B.ByteString UTCTime | AddIP2Bans B.ByteString B.ByteString UTCTime - | CheckBanned + | CheckBanned Bool | SaveReplay @@ -235,7 +235,7 @@ if master then if playersNum > 1 then - mapM_ processAction [ChangeMaster, NoticeMessage AdminLeft, RemoveClientTeams ci, AnswerClients chans ["LEFT", clNick, msg]] + mapM_ processAction [ChangeMaster Nothing, NoticeMessage AdminLeft, RemoveClientTeams ci, AnswerClients chans ["LEFT", clNick, msg]] else processAction RemoveRoom else @@ -251,26 +251,27 @@ moveClientToLobby rnc ci -processAction ChangeMaster = do +processAction (ChangeMaster delegateId)= do (Just ci) <- gets clientIndex proto <- client's clientProto ri <- clientRoomA rnc <- gets roomsClients - newMasterId <- liftM (last . filter (/= ci)) . io $ roomClientsIndicesM rnc ri + newMasterId <- liftM (\ids -> fromMaybe (last . filter (/= ci) $ ids) delegateId) . io $ roomClientsIndicesM rnc ri newMaster <- io $ client'sM rnc id newMasterId oldRoomName <- io $ room'sM rnc name ri oldMaster <- client's nick + kicked <- client's isKickedFromServer thisRoomChans <- liftM (map sendChan) $ roomClientsS ri - let newRoomName = if proto < 42 then nick newMaster else oldRoomName + let newRoomName = if (proto < 42) || kicked then nick newMaster else oldRoomName mapM_ processAction [ ModifyRoom (\r -> r{masterID = newMasterId , name = newRoomName , isRestrictedJoins = False , isRestrictedTeams = False + , isRegisteredOnly = False , readyPlayers = if isReady newMaster then readyPlayers r else readyPlayers r + 1}) , ModifyClient2 newMasterId (\c -> c{isMaster = True, isReady = True}) , AnswerClients [sendChan newMaster] ["ROOM_CONTROL_ACCESS", "1"] - , AnswerClients thisRoomChans ["WARNING", "New room admin is " `B.append` nick newMaster] , AnswerClients thisRoomChans ["CLIENT_FLAGS", "-h", oldMaster] , AnswerClients thisRoomChans ["CLIENT_FLAGS", "+hr", nick newMaster] ] @@ -362,6 +363,7 @@ ) : UnreadyRoomClients : SendUpdateOnThisRoom + : AnswerClients thisRoomChans ["ROUND_FINISHED"] : answerRemovedTeams @@ -423,17 +425,14 @@ haveSameNick <- liftM (not . null . tail . filter (\c -> caseInsensitiveCompare (nick c) n)) allClientsS if haveSameNick then if p < 38 then - mapM_ processAction [ByeClient "Nickname is already in use", removeNick] + processAction $ ByeClient "Nickname is already in use" else - mapM_ processAction [NoticeMessage NickAlreadyInUse, removeNick] + processAction $ NoticeMessage NickAlreadyInUse else do db <- gets (dbQueries . serverInfo) io $ writeChan db $ CheckAccount ci (hashUnique uid) n h return () - where - removeNick = ModifyClient (\c -> c{nick = ""}) - processAction ClearAccountsCache = do dbq <- gets (dbQueries . serverInfo) @@ -458,7 +457,7 @@ processAction $ AnswerClients [chan] ["ADMIN_ACCESS"] where isBanned = do - processAction CheckBanned + processAction $ CheckBanned False liftM B.null $ client's nick @@ -488,8 +487,9 @@ clHost <- client's host currentTime <- io getCurrentTime mapM_ processAction [ - AddIP2Bans clHost "60 seconds cooldown after kick" (addUTCTime 60 currentTime), - ByeClient "Kicked" + AddIP2Bans clHost "60 seconds cooldown after kick" (addUTCTime 60 currentTime) + , ModifyClient (\c -> c{isKickedFromServer = True}) + , ByeClient "Kicked" ] @@ -503,12 +503,14 @@ , KickClient banId ] + processAction (BanIP ip seconds reason) = do currentTime <- io getCurrentTime let msg = B.concat ["Ban for ", B.pack . show $ seconds, " (", reason, ")"] processAction $ AddIP2Bans ip msg (addUTCTime seconds currentTime) + processAction (BanNick n seconds reason) = do currentTime <- io getCurrentTime let msg = @@ -519,6 +521,7 @@ processAction $ AddNick2Bans n msg (addUTCTime seconds currentTime) + processAction BanList = do time <- io $ getCurrentTime ch <- client's sendChan @@ -529,12 +532,14 @@ ban2Str time (BanByIP b r t) = ["I", b, r, B.pack . show $ t `diffUTCTime` time] ban2Str time (BanByNick b r t) = ["N", b, r, B.pack . show $ t `diffUTCTime` time] + processAction (Unban entry) = do processAction $ ModifyServerInfo (\s -> s{bans = filter (not . f) $ bans s}) where f (BanByIP bip _ _) = bip == entry f (BanByNick bn _ _) = bn == entry + processAction (KickRoomClient kickId) = do modify (\s -> s{clientIndex = Just kickId}) ch <- client's sendChan @@ -556,7 +561,7 @@ mapM_ processAction [ AnswerClients [sendChan cl] ["CONNECTED", "Hedgewars server http://www.hedgewars.org/", serverVersion] - , CheckBanned + , CheckBanned True , AddIP2Bans (host cl) "Reconnected too fast" (addUTCTime 10 $ connectTime cl) ] @@ -570,21 +575,22 @@ when (not $ ci `Set.member` rc) $ processAction $ ModifyServerInfo (\s -> s{bans = BanByIP ip reason expiring : bans s}) -processAction CheckBanned = do +processAction (CheckBanned byIP) = do clTime <- client's connectTime clNick <- client's nick clHost <- client's host si <- gets serverInfo let validBans = filter (checkNotExpired clTime) $ bans si - let ban = L.find (checkBan clHost clNick) $ validBans + let ban = L.find (checkBan byIP clHost clNick) $ validBans mapM_ processAction $ ModifyServerInfo (\s -> s{bans = validBans}) : [ByeClient (getBanReason $ fromJust ban) | isJust ban] where checkNotExpired testTime (BanByIP _ _ time) = testTime `diffUTCTime` time <= 0 checkNotExpired testTime (BanByNick _ _ time) = testTime `diffUTCTime` time <= 0 - checkBan ip _ (BanByIP bip _ _) = bip `B.isPrefixOf` ip - checkBan _ n (BanByNick bn _ _) = caseInsensitiveCompare bn n + checkBan True ip _ (BanByIP bip _ _) = bip `B.isPrefixOf` ip + checkBan False _ n (BanByNick bn _ _) = caseInsensitiveCompare bn n + checkBan _ _ _ _ = False getBanReason (BanByIP _ msg _) = msg getBanReason (BanByNick _ msg _) = msg diff -r d2207f22c5f2 -r 9ffb156902f6 gameServer/CoreTypes.hs --- a/gameServer/CoreTypes.hs Wed Dec 05 13:45:18 2012 -0500 +++ b/gameServer/CoreTypes.hs Wed Dec 05 17:25:48 2012 -0500 @@ -36,6 +36,7 @@ isReady :: !Bool, isInGame :: Bool, isAdministrator :: Bool, + isKickedFromServer :: Bool, clientClan :: Maybe B.ByteString, teamsInGame :: Word } @@ -100,6 +101,7 @@ readyPlayers :: !Int, isRestrictedJoins :: Bool, isRestrictedTeams :: Bool, + isRegisteredOnly :: Bool, roomBansList :: ![B.ByteString], mapParams :: Map.Map B.ByteString B.ByteString, params :: Map.Map B.ByteString [B.ByteString] @@ -118,6 +120,7 @@ 0 False False + False [] ( Map.fromList $ Prelude.zipWith (,) diff -r d2207f22c5f2 -r 9ffb156902f6 gameServer/HWProtoInRoomState.hs --- a/gameServer/HWProtoInRoomState.hs Wed Dec 05 13:45:18 2012 -0500 +++ b/gameServer/HWProtoInRoomState.hs Wed Dec 05 17:25:48 2012 -0500 @@ -264,6 +264,14 @@ [ModifyRoom (\r -> r{isRestrictedTeams = not $ isRestrictedTeams r})] +handleCmd_inRoom ["TOGGLE_REGISTERED_ONLY"] = do + cl <- thisClient + return $ + if not $ isMaster cl then + [ProtocolError "Not room master"] + else + [ModifyRoom (\r -> r{isRegisteredOnly = not $ isRegisteredOnly r})] + handleCmd_inRoom ["ROOM_NAME", newName] = do cl <- thisClient rs <- allRoomInfos @@ -293,6 +301,16 @@ [KickRoomClient kickId | master && isJust maybeClientId && (kickId /= thisClientId) && sameRoom] +handleCmd_inRoom ["DELEGATE", newAdmin] = do + (thisClientId, rnc) <- ask + maybeClientId <- clientByNick newAdmin + master <- liftM isMaster thisClient + let newAdminId = fromJust maybeClientId + let sameRoom = clientRoom rnc thisClientId == clientRoom rnc newAdminId + return + [ChangeMaster (Just newAdminId) | master && isJust maybeClientId && (newAdminId /= thisClientId) && sameRoom] + + handleCmd_inRoom ["TEAMCHAT", msg] = do cl <- thisClient chans <- roomSameClanChans diff -r d2207f22c5f2 -r 9ffb156902f6 gameServer/HWProtoLobbyState.hs --- a/gameServer/HWProtoLobbyState.hs Wed Dec 05 13:45:18 2012 -0500 +++ b/gameServer/HWProtoLobbyState.hs Wed Dec 05 17:25:48 2012 -0500 @@ -80,6 +80,8 @@ [Warning "No such room"] else if isRestrictedJoins jRoom then [Warning "Joining restricted"] + else if isRegisteredOnly jRoom then + [Warning "Registered users only"] else if isBanned then [Warning "You are banned in this room"] else if roomPassword /= password jRoom then @@ -89,20 +91,21 @@ MoveToRoom jRI , AnswerClients [sendChan cl] $ "JOINED" : nicks , AnswerClients chans ["CLIENT_FLAGS", "-r", nick cl] - , AnswerClients [sendChan cl] $ ["WARNING", "Room admin is " `B.append` ownerNick] , AnswerClients [sendChan cl] $ ["CLIENT_FLAGS", "+h", ownerNick] ] - ++ map (readynessMessage cl) jRoomClients + ++ (if clientProto cl < 38 then map (readynessMessage cl) jRoomClients else [sendStateFlags cl jRoomClients]) ++ answerFullConfig cl (mapParams jRoom) (params jRoom) ++ answerTeams cl jRoom - ++ watchRound cl jRoom + ++ watchRound cl jRoom chans where - readynessMessage cl c = AnswerClients [sendChan cl] $ - if clientProto cl < 38 then - [if isReady c then "READY" else "NOT_READY", nick c] - else - ["CLIENT_FLAGS", if isReady c then "+r" else "-r", nick c] + readynessMessage cl c = AnswerClients [sendChan cl] [if isReady c then "READY" else "NOT_READY", nick c] + sendStateFlags cl clients = AnswerClients [sendChan cl] . concat . intersperse [""] . filter (not . null) . concat $ + [f "+r" ready, f "-r" unready, f "+g" ingame, f "-g" inroomlobby] + where + (ready, unready) = partition isReady clients + (ingame, inroomlobby) = partition isInGame clients + f fl lst = ["CLIENT_FLAGS" : fl : map nick lst | not $ null lst] toAnswer cl (paramName, paramStrs) = AnswerClients [sendChan cl] $ "CFG" : paramName : paramStrs @@ -119,11 +122,13 @@ answerTeams cl jRoom = let f = if isJust $ gameInfo jRoom then teamsAtStart . fromJust . gameInfo else teams in answerAllTeams cl $ f jRoom - watchRound cl jRoom = if isNothing $ gameInfo jRoom then + watchRound cl jRoom chans = if isNothing $ gameInfo jRoom then [] else - [AnswerClients [sendChan cl] ["RUN_GAME"], - AnswerClients [sendChan cl] $ "EM" : toEngineMsg "e$spectate 1" : Foldable.toList (roundMsgs . fromJust . gameInfo $ jRoom)] + [AnswerClients [sendChan cl] ["RUN_GAME"] + , AnswerClients chans ["CLIENT_FLAGS", "+g", nick cl] + , ModifyClient (\c -> c{isInGame = True}) + , AnswerClients [sendChan cl] $ "EM" : toEngineMsg "e$spectate 1" : Foldable.toList (roundMsgs . fromJust . gameInfo $ jRoom)] handleCmd_lobby ["JOIN_ROOM", roomName] = diff -r d2207f22c5f2 -r 9ffb156902f6 gameServer/NetRoutines.hs --- a/gameServer/NetRoutines.hs Wed Dec 05 13:45:18 2012 -0500 +++ b/gameServer/NetRoutines.hs Wed Dec 05 17:25:48 2012 -0500 @@ -41,6 +41,7 @@ False False False + False Nothing 0 ) diff -r d2207f22c5f2 -r 9ffb156902f6 hedgewars/uIO.pas --- a/hedgewars/uIO.pas Wed Dec 05 13:45:18 2012 -0500 +++ b/hedgewars/uIO.pas Wed Dec 05 17:25:48 2012 -0500 @@ -124,6 +124,7 @@ 'E': OutError(copy(s, 2, Length(s) - 1), true); 'W': OutError(copy(s, 2, Length(s) - 1), false); 'M': ParseCommand('landcheck ' + s, true); + 'o': if fastUntilLag then ParseCommand('forcequit', true); 'T': case s[2] of 'L': GameType:= gmtLocal; 'D': GameType:= gmtDemo;