--- 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> команда 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> команда team вылетела в сетевой игре
+ 'o' stop syncing, game over!
Клиент фронтенду:
- 'C' запрос текущего конфига игры
- 'q' выход по причине окончания демки
- 'i' статистика
+ 'C' запрос текущего конфига игры
+ 'q' выход по причине окончания демки
+ 'i' статистика
+ 'K' вывести сообщение из KB
+ 'Q' выход через команду /quit
+ 'q' выход по причине окончания игры
--- 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
--- 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 (,)
--- 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
--- 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] =
--- 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
)
--- 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;