gameServer/ServerCore.hs
changeset 4904 0eab727d4717
parent 4568 f85243bf890e
parent 4612 e82758d6f924
child 4918 c6d3aec73f93
--- a/gameServer/ServerCore.hs	Wed Feb 02 09:05:48 2011 +0100
+++ b/gameServer/ServerCore.hs	Wed Feb 02 11:28:38 2011 +0300
@@ -2,86 +2,92 @@
 
 import Network
 import Control.Concurrent
-import Control.Concurrent.STM
-import Control.Concurrent.Chan
 import Control.Monad
-import qualified Data.IntMap as IntMap
 import System.Log.Logger
+import Control.Monad.Reader
+import Control.Monad.State.Strict
+import Data.Set as Set
+import qualified Data.ByteString.Char8 as B
+import Control.DeepSeq
 --------------------------------------
 import CoreTypes
 import NetRoutines
-import Utils
 import HWProtoCore
 import Actions
 import OfficialServer.DBInteraction
+import ServerState
+
+
+timerLoop :: Int -> Chan CoreMessage -> IO ()
+timerLoop tick messagesChan = threadDelay 30000000 >> writeChan messagesChan (TimerAction tick) >> timerLoop (tick + 1) messagesChan
 
 
-timerLoop :: Int -> Chan CoreMessage -> IO()
-timerLoop tick messagesChan = threadDelay (30 * 10^6) >> writeChan messagesChan (TimerAction tick) >> timerLoop (tick + 1) messagesChan
-
-firstAway (_, a, b, c) = (a, b, c)
-
-reactCmd :: ServerInfo -> Int -> [String] -> Clients -> Rooms -> IO (ServerInfo, Clients, Rooms)
-reactCmd serverInfo clID cmd clients rooms =
-    liftM firstAway $ foldM processAction (clID, serverInfo, clients, rooms) $ handleCmd clID clients rooms cmd
+reactCmd :: [B.ByteString] -> StateT ServerState IO ()
+reactCmd cmd = do
+    (Just ci) <- gets clientIndex
+    rnc <- gets roomsClients
+    actions <- liftIO $ withRoomsAndClients rnc (\irnc -> runReader (handleCmd cmd) (ci, irnc))
+    forM_ (actions `deepseq` actions) processAction
 
-mainLoop :: ServerInfo -> Clients -> Rooms -> IO ()
-mainLoop serverInfo clients rooms = do
-    r <- readChan $ coreChan serverInfo
-    
-    (newServerInfo, mClients, mRooms) <-
-        case r of
-            Accept ci ->
-                liftM firstAway $ processAction
-                    (clientUID ci, serverInfo, clients, rooms) (AddClient ci)
+mainLoop :: StateT ServerState IO ()
+mainLoop = forever $ do
+    get >>= \s -> put $! s
+
+    si <- gets serverInfo
+    r <- liftIO $ readChan $ coreChan si
+
+    case r of
+        Accept ci -> processAction (AddClient ci)
+
+        ClientMessage (ci, cmd) -> do
+            liftIO $ debugM "Clients" $ (show ci) ++ ": " ++ (show cmd)
 
-            ClientMessage (clID, cmd) -> do
-                debugM "Clients" $ (show clID) ++ ": " ++ (show cmd)
-                if clID `IntMap.member` clients then
-                    reactCmd serverInfo clID cmd clients rooms
-                    else
-                    do
-                    debugM "Clients" "Message from dead client"
-                    return (serverInfo, clients, rooms)
+            removed <- gets removedClients
+            when (not $ ci `Set.member` removed) $ do
+                as <- get
+                put $! as{clientIndex = Just ci}
+                reactCmd cmd
+
+        Remove ci -> do
+            liftIO $ debugM "Clients"  $ "DeleteClient: " ++ show ci
+            processAction (DeleteClient ci)
 
-            ClientAccountInfo (clID, info) ->
-                if clID `IntMap.member` clients then
-                    liftM firstAway $ processAction
-                        (clID, serverInfo, clients, rooms)
-                        (ProcessAccountInfo info)
-                    else
-                    do
-                    debugM "Clients" "Got info for dead client"
-                    return (serverInfo, clients, rooms)
+                --else
+                --do
+                --debugM "Clients" "Message from dead client"
+                --return (serverInfo, rnc)
 
-            TimerAction tick ->
-                liftM firstAway $
-                    foldM processAction (0, serverInfo, clients, rooms) $
-                        PingAll : [StatsAction | even tick]
+        ClientAccountInfo (ci, info) -> do
+            rnc <- gets roomsClients
+            exists <- liftIO $ clientExists rnc ci
+            when (exists) $ do
+                as <- get
+                put $! as{clientIndex = Just ci}
+                processAction (ProcessAccountInfo info)
+                return ()
+
+        TimerAction tick ->
+                mapM_ processAction $
+                    PingAll : [StatsAction | even tick]
 
 
-    {-          let hadRooms = (not $ null rooms) && (null mrooms)
-                    in unless ((not $ isDedicated serverInfo) && ((null clientsIn) || hadRooms)) $
-                        mainLoop serverInfo acceptChan messagesChan clientsIn mrooms -}
-
-    mainLoop newServerInfo mClients mRooms
-
 startServer :: ServerInfo -> Socket -> IO ()
-startServer serverInfo serverSocket = do
-    putStrLn $ "Listening on port " ++ show (listenPort serverInfo)
+startServer si serverSocket = do
+    putStrLn $ "Listening on port " ++ show (listenPort si)
 
     forkIO $
         acceptLoop
             serverSocket
-            (coreChan serverInfo)
-            0
+            (coreChan si)
 
     return ()
-    
-    forkIO $ timerLoop 0 $ coreChan serverInfo
+
+    forkIO $ timerLoop 0 $ coreChan si
+
+    startDBConnection si
 
-    startDBConnection serverInfo
+    rnc <- newRoomsAndClients newRoom
 
-    forkIO $ mainLoop serverInfo IntMap.empty (IntMap.singleton 0 newRoom)
+    forkIO $ evalStateT mainLoop (ServerState Nothing si Set.empty rnc)
 
-    forever $ threadDelay (60 * 60 * 10^6) >> putStrLn "***"
\ No newline at end of file
+    forever $ threadDelay 3600000000 -- one hour