module Game.LambdaHack.Server.LoopM
( loopSer
#ifdef EXPOSE_INTERNAL
, factionArena, arenasForLoop, handleFidUpd, loopUpd, endClip
, manageCalmAndDomination, applyPeriodicLevel
, handleTrajectories, hTrajectories, advanceTrajectory
, handleActors, hActors, handleUIunderAI, dieSer, restartGame
#endif
) where
import Prelude ()
import Game.LambdaHack.Core.Prelude
import qualified Data.EnumMap.Strict as EM
import qualified Data.EnumSet as ES
import Game.LambdaHack.Atomic
import Game.LambdaHack.Client (ReqUI (..), Response (..))
import Game.LambdaHack.Common.Actor
import Game.LambdaHack.Common.ActorState
import Game.LambdaHack.Common.Analytics
import Game.LambdaHack.Common.Faction
import Game.LambdaHack.Common.Item
import qualified Game.LambdaHack.Common.ItemAspect as IA
import Game.LambdaHack.Common.Kind
import Game.LambdaHack.Common.Level
import Game.LambdaHack.Common.Misc
import Game.LambdaHack.Common.MonadStateRead
import Game.LambdaHack.Common.Perception
import Game.LambdaHack.Common.State
import qualified Game.LambdaHack.Common.Tile as Tile
import Game.LambdaHack.Common.Time
import Game.LambdaHack.Common.Types
import Game.LambdaHack.Common.Vector
import Game.LambdaHack.Content.FactionKind
import qualified Game.LambdaHack.Content.ItemKind as IK
import Game.LambdaHack.Content.ModeKind
import Game.LambdaHack.Content.RuleKind
import qualified Game.LambdaHack.Definition.Ability as Ability
import Game.LambdaHack.Definition.Defs
import Game.LambdaHack.Server.CommonM
import Game.LambdaHack.Server.HandleEffectM
import Game.LambdaHack.Server.HandleRequestM
import Game.LambdaHack.Server.MonadServer
import Game.LambdaHack.Server.PeriodicM
import Game.LambdaHack.Server.ProtocolM
import Game.LambdaHack.Server.ServerOptions
import Game.LambdaHack.Server.StartM
import Game.LambdaHack.Server.State
loopSer :: (MonadServerAtomic m, MonadServerComm m)
=> ServerOptions
-> (Bool -> FactionId -> ChanServer -> IO ())
-> m ()
loopSer :: forall (m :: * -> *).
(MonadServerAtomic m, MonadServerComm m) =>
ServerOptions -> (Bool -> FactionId -> ChanServer -> IO ()) -> m ()
loopSer ServerOptions
serverOptions Bool -> FactionId -> ChanServer -> IO ()
executorClient = do
(StateServer -> StateServer) -> m ()
forall (m :: * -> *).
MonadServer m =>
(StateServer -> StateServer) -> m ()
modifyServer ((StateServer -> StateServer) -> m ())
-> (StateServer -> StateServer) -> m ()
forall a b. (a -> b) -> a -> b
$ \StateServer
ser -> StateServer
ser { soptionsNxt = serverOptions
, soptions = serverOptions }
cops <- (State -> COps) -> m COps
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState State -> COps
scops
let updConn Bool
startsNewGame = (FactionId -> ChanServer -> IO ()) -> m ()
forall (m :: * -> *).
(MonadServerAtomic m, MonadServerComm m) =>
(FactionId -> ChanServer -> IO ()) -> m ()
updateConn ((FactionId -> ChanServer -> IO ()) -> m ())
-> (FactionId -> ChanServer -> IO ()) -> m ()
forall a b. (a -> b) -> a -> b
$ Bool -> FactionId -> ChanServer -> IO ()
executorClient Bool
startsNewGame
restored <- tryRestore
case restored of
Just (State
sRaw, StateServer
ser) | Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ ServerOptions -> Bool
snewGameSer ServerOptions
serverOptions -> do
UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ State -> UpdAtomic
UpdResumeServer
(State -> UpdAtomic) -> State -> UpdAtomic
forall a b. (a -> b) -> a -> b
$ (COps -> COps) -> State -> State
updateCOpsAndCachedData (COps -> COps -> COps
forall a b. a -> b -> a
const COps
cops) State
sRaw
StateServer -> m ()
forall (m :: * -> *). MonadServer m => StateServer -> m ()
putServer StateServer
ser {soptionsNxt = serverOptions}
m ()
forall (m :: * -> *). MonadServer m => m ()
applyDebug
factionD <- (State -> FactionDict) -> m FactionDict
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState State -> FactionDict
sfactionD
let f FactionId
fid = let cmd :: UpdAtomic
cmd = State -> UpdAtomic
UpdResumeServer
(State -> UpdAtomic) -> State -> UpdAtomic
forall a b. (a -> b) -> a -> b
$ (COps -> COps) -> State -> State
updateCOpsAndCachedData (COps -> COps -> COps
forall a b. a -> b -> a
const COps
cops)
(State -> State) -> State -> State
forall a b. (a -> b) -> a -> b
$ StateServer -> EnumMap FactionId State
sclientStates StateServer
ser EnumMap FactionId State -> FactionId -> State
forall k a. Enum k => EnumMap k a -> k -> a
EM.! FactionId
fid
in FactionId -> UpdAtomic -> m Bool
forall (m :: * -> *).
MonadServerAtomic m =>
FactionId -> UpdAtomic -> m Bool
execUpdAtomicFidCatch FactionId
fid UpdAtomic
cmd
mapM_ (void <$> f) $ EM.keys factionD
updConn False
initPer
pers <- getsServer sperFid
let clear = Perception -> b -> Perception
forall a b. a -> b -> a
const Perception
emptyPer
persFid FactionId
fid | ServerOptions -> Bool
sknowEvents ServerOptions
serverOptions = (Perception -> Perception)
-> EnumMap LevelId Perception -> EnumMap LevelId Perception
forall a b k. (a -> b) -> EnumMap k a -> EnumMap k b
EM.map Perception -> Perception
forall {b}. b -> Perception
clear (PerFid
pers PerFid -> FactionId -> EnumMap LevelId Perception
forall k a. Enum k => EnumMap k a -> k -> a
EM.! FactionId
fid)
| Bool
otherwise = PerFid
pers PerFid -> FactionId -> EnumMap LevelId Perception
forall k a. Enum k => EnumMap k a -> k -> a
EM.! FactionId
fid
mapM_ (\FactionId
fid -> FactionId -> UpdAtomic -> m ()
forall (m :: * -> *).
(MonadServerAtomic m, MonadServerComm m) =>
FactionId -> UpdAtomic -> m ()
sendUpdate FactionId
fid (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ FactionId -> EnumMap LevelId Perception -> UpdAtomic
UpdResume FactionId
fid (FactionId -> EnumMap LevelId Perception
persFid FactionId
fid))
(EM.keys factionD)
arenasNew <- arenasForLoop
modifyServer $ \StateServer
ser2 -> StateServer
ser2 {sarenas = arenasNew, svalidArenas = True}
rngs <- getsServer srngs
when (sdumpInitRngs serverOptions) $ dumpRngs rngs
Maybe (State, StateServer)
_ -> do
factionDold <- (State -> FactionDict) -> m FactionDict
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState State -> FactionDict
sfactionD
s <- gameReset serverOptions Nothing Nothing
let optionsBarRngs =
ServerOptions
serverOptions {sdungeonRng = Nothing, smainRng = Nothing}
modifyServer $ \StateServer
ser -> StateServer
ser { soptionsNxt = optionsBarRngs
, soptions = optionsBarRngs }
execUpdAtomic $ UpdRestartServer s
updConn True
initPer
reinitGame factionDold
writeSaveAll False False
loopUpd $ updConn True
factionArena :: MonadStateRead m => Faction -> m (Maybe LevelId)
factionArena :: forall (m :: * -> *).
MonadStateRead m =>
Faction -> m (Maybe LevelId)
factionArena Faction
fact = case Faction -> Maybe ActorId
gleader Faction
fact of
Just ActorId
leader -> do
b <- (State -> Actor) -> m Actor
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> Actor) -> m Actor) -> (State -> Actor) -> m Actor
forall a b. (a -> b) -> a -> b
$ ActorId -> State -> Actor
getActorBody ActorId
leader
return $ Just $ blid b
Maybe ActorId
Nothing -> Maybe LevelId -> m (Maybe LevelId)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe LevelId
forall a. Maybe a
Nothing
arenasForLoop :: MonadStateRead m => m (ES.EnumSet LevelId)
{-# INLINE arenasForLoop #-}
arenasForLoop :: forall (m :: * -> *). MonadStateRead m => m (EnumSet LevelId)
arenasForLoop = do
factionD <- (State -> FactionDict) -> m FactionDict
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState State -> FactionDict
sfactionD
marenas <- mapM factionArena $ EM.elems factionD
let arenas = [LevelId] -> EnumSet LevelId
forall k. Enum k => [k] -> EnumSet k
ES.fromList ([LevelId] -> EnumSet LevelId) -> [LevelId] -> EnumSet LevelId
forall a b. (a -> b) -> a -> b
$ [Maybe LevelId] -> [LevelId]
forall a. [Maybe a] -> [a]
catMaybes [Maybe LevelId]
marenas
!_A = Bool -> () -> ()
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Bool -> Bool
not (EnumSet LevelId -> Bool
forall k. EnumSet k -> Bool
ES.null EnumSet LevelId
arenas)
Bool -> (String, FactionDict) -> Bool
forall v. Show v => Bool -> v -> Bool
`blame` String
"game over not caught earlier"
String -> FactionDict -> (String, FactionDict)
forall v. String -> v -> (String, v)
`swith` FactionDict
factionD) ()
return $! arenas
handleFidUpd :: forall m. (MonadServerAtomic m, MonadServerComm m)
=> (FactionId -> m ()) -> FactionId -> Faction -> m ()
{-# INLINE handleFidUpd #-}
handleFidUpd :: forall (m :: * -> *).
(MonadServerAtomic m, MonadServerComm m) =>
(FactionId -> m ()) -> FactionId -> Faction -> m ()
handleFidUpd FactionId -> m ()
updatePerFid FactionId
fid Faction
fact = do
FactionId -> m ()
updatePerFid FactionId
fid
let handle :: [LevelId] -> m Bool
handle :: [LevelId] -> m Bool
handle [] = Bool -> m Bool
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
handle (LevelId
lid : [LevelId]
rest) = do
breakASAP <- (StateServer -> Bool) -> m Bool
forall a. (StateServer -> a) -> m a
forall (m :: * -> *) a. MonadServer m => (StateServer -> a) -> m a
getsServer StateServer -> Bool
sbreakASAP
if breakASAP
then return False
else do
nonWaitMove <- handleActors lid fid
if nonWaitMove
then return True
else handle rest
killDying :: [LevelId] -> m ()
killDying :: [LevelId] -> m ()
killDying = (LevelId -> m ()) -> [LevelId] -> m ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
(a -> m ()) -> t a -> m ()
mapM_ LevelId -> m ()
killDyingLid
killDyingLid :: LevelId -> m ()
killDyingLid :: LevelId -> m ()
killDyingLid LevelId
lid = do
localTime <- (State -> Time) -> m Time
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> Time) -> m Time) -> (State -> Time) -> m Time
forall a b. (a -> b) -> a -> b
$ LevelId -> State -> Time
getLocalTime LevelId
lid
levelTime <- getsServer $ (EM.! lid) . (EM.! fid) . sactorTime
let l = ((ActorId, Time) -> Bool) -> [(ActorId, Time)] -> [(ActorId, Time)]
forall a. (a -> Bool) -> [a] -> [a]
filter (\(ActorId
_, Time
atime) -> Time
atime Time -> Time -> Bool
forall a. Ord a => a -> a -> Bool
<= Time
localTime) ([(ActorId, Time)] -> [(ActorId, Time)])
-> [(ActorId, Time)] -> [(ActorId, Time)]
forall a b. (a -> b) -> a -> b
$ EnumMap ActorId Time -> [(ActorId, Time)]
forall k a. Enum k => EnumMap k a -> [(k, a)]
EM.assocs EnumMap ActorId Time
levelTime
killAid (ActorId
aid, b
_) = do
b1 <- (State -> Actor) -> m Actor
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> Actor) -> m Actor) -> (State -> Actor) -> m Actor
forall a b. (a -> b) -> a -> b
$ ActorId -> State -> Actor
getActorBody ActorId
aid
when (bhp b1 <= 0) $ dieSer aid b1
mapM_ killAid l
fa <- Faction -> m (Maybe LevelId)
forall (m :: * -> *).
MonadStateRead m =>
Faction -> m (Maybe LevelId)
factionArena Faction
fact
arenas <- getsServer sarenas
let myArenas = case Maybe LevelId
fa of
Just LevelId
myArena -> LevelId
myArena LevelId -> [LevelId] -> [LevelId]
forall a. a -> [a] -> [a]
: LevelId -> [LevelId] -> [LevelId]
forall a. Eq a => a -> [a] -> [a]
delete LevelId
myArena (EnumSet LevelId -> [LevelId]
forall k. Enum k => EnumSet k -> [k]
ES.elems EnumSet LevelId
arenas)
Maybe LevelId
Nothing -> EnumSet LevelId -> [LevelId]
forall k. Enum k => EnumSet k -> [k]
ES.elems EnumSet LevelId
arenas
nonWaitMove <- handle myArenas
breakASAP <- getsServer sbreakASAP
unless breakASAP $ killDying myArenas
when nonWaitMove $ updatePerFid fid
loopUpd :: forall m. (MonadServerAtomic m, MonadServerComm m)
=> m () -> m ()
loopUpd :: forall (m :: * -> *).
(MonadServerAtomic m, MonadServerComm m) =>
m () -> m ()
loopUpd m ()
updConn = do
let updatePerFid :: FactionId -> m ()
{-# NOINLINE updatePerFid #-}
updatePerFid :: FactionId -> m ()
updatePerFid FactionId
fid = do
perValid <- (StateServer -> EnumMap LevelId Bool) -> m (EnumMap LevelId Bool)
forall a. (StateServer -> a) -> m a
forall (m :: * -> *) a. MonadServer m => (StateServer -> a) -> m a
getsServer ((StateServer -> EnumMap LevelId Bool) -> m (EnumMap LevelId Bool))
-> (StateServer -> EnumMap LevelId Bool)
-> m (EnumMap LevelId Bool)
forall a b. (a -> b) -> a -> b
$ (EnumMap FactionId (EnumMap LevelId Bool)
-> FactionId -> EnumMap LevelId Bool
forall k a. Enum k => EnumMap k a -> k -> a
EM.! FactionId
fid) (EnumMap FactionId (EnumMap LevelId Bool) -> EnumMap LevelId Bool)
-> (StateServer -> EnumMap FactionId (EnumMap LevelId Bool))
-> StateServer
-> EnumMap LevelId Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StateServer -> EnumMap FactionId (EnumMap LevelId Bool)
sperValidFid
mapM_ (\(LevelId
lid, Bool
valid) -> Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless Bool
valid (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ FactionId -> LevelId -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
FactionId -> LevelId -> m ()
updatePer FactionId
fid LevelId
lid)
(EM.assocs perValid)
handleFid :: (FactionId, Faction) -> m ()
{-# NOINLINE handleFid #-}
handleFid :: (FactionId, Faction) -> m ()
handleFid (FactionId
fid, Faction
fact) = do
breakASAP <- (StateServer -> Bool) -> m Bool
forall a. (StateServer -> a) -> m a
forall (m :: * -> *) a. MonadServer m => (StateServer -> a) -> m a
getsServer StateServer -> Bool
sbreakASAP
unless breakASAP $ handleFidUpd updatePerFid fid fact
loopConditionally :: m ()
loopConditionally = do
factionD <- (State -> FactionDict) -> m FactionDict
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState State -> FactionDict
sfactionD
mapM_ updatePerFid (EM.keys factionD)
modifyServer $ \StateServer
ser -> StateServer
ser { sbreakLoop = False
, sbreakASAP = False }
endOrLoop loopUpdConn (restartGame updConn loopUpdConn)
loopUpdConn :: m ()
loopUpdConn = do
factionD <- (State -> FactionDict) -> m FactionDict
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState State -> FactionDict
sfactionD
let hasUI (a
_, Faction
fact) = FactionKind -> Bool
fhasUI (Faction -> FactionKind
gkind Faction
fact)
(factionUI, factionsRest) = case break hasUI $ EM.assocs factionD of
([(FactionId, Faction)]
noUI1, (FactionId, Faction)
ui : [(FactionId, Faction)]
noUI2) -> ((FactionId, Faction)
ui, [(FactionId, Faction)]
noUI1 [(FactionId, Faction)]
-> [(FactionId, Faction)] -> [(FactionId, Faction)]
forall a. [a] -> [a] -> [a]
++ [(FactionId, Faction)]
noUI2)
([(FactionId, Faction)], [(FactionId, Faction)])
_ -> String -> ((FactionId, Faction), [(FactionId, Faction)])
forall a. (?callStack::CallStack) => String -> a
error String
"no UI faction in the game"
mapM_ handleFid $ factionUI : factionsRest
breakASAP <- getsServer sbreakASAP
breakLoop <- getsServer sbreakLoop
if breakASAP || breakLoop
then loopConditionally
else do
arenas <- getsServer sarenas
mapM_ (\FactionId
fid -> (LevelId -> m ()) -> [LevelId] -> m ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
(a -> m ()) -> t a -> m ()
mapM_ (LevelId -> FactionId -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
LevelId -> FactionId -> m ()
`handleTrajectories` FactionId
fid) ([LevelId] -> m ()) -> [LevelId] -> m ()
forall a b. (a -> b) -> a -> b
$ EnumSet LevelId -> [LevelId]
forall k. Enum k => EnumSet k -> [k]
ES.elems EnumSet LevelId
arenas)
(EM.keys factionD)
endClip updatePerFid
breakLoop2 <- getsServer sbreakLoop
if breakLoop2
then loopConditionally
else loopUpdConn
m ()
loopUpdConn
endClip :: forall m. MonadServerAtomic m => (FactionId -> m ()) -> m ()
{-# INLINE endClip #-}
endClip :: forall (m :: * -> *).
MonadServerAtomic m =>
(FactionId -> m ()) -> m ()
endClip FactionId -> m ()
updatePerFid = do
COps{corule} <- (State -> COps) -> m COps
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState State -> COps
scops
time <- getsState stime
let clipN = Time
time Time -> Time -> Int
`timeFit` Time
timeClip
breakLoop <- getsServer sbreakLoop
unless breakLoop $ do
arenas <- getsServer sarenas
execUpdAtomic $ UpdAgeGame arenas
when (clipN `mod` rleadLevelClips corule == 0) leadLevelSwitch
case clipN `mod` clipsInTurn of
Int
0 ->
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Int
clipN Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` (Int
3 Int -> Int -> Int
forall a. Num a => a -> a -> a
* Int
clipsInTurn) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0)
m ()
forall (m :: * -> *). MonadServerAtomic m => m ()
spawnMonster
Int
4 ->
m ()
forall (m :: * -> *). MonadServerAtomic m => m ()
applyPeriodicLevel
Int
_ -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
breakLoop2 <- getsServer sbreakLoop
unless breakLoop2 $ do
validArenas <- getsServer svalidArenas
unless validArenas $ do
arenasNew <- arenasForLoop
modifyServer $ \StateServer
ser -> StateServer
ser {sarenas = arenasNew, svalidArenas = True}
factionD <- getsState sfactionD
mapM_ updatePerFid (EM.keys factionD)
#ifndef USE_JSFILE
unless breakLoop2 $
when (succ clipN `mod` rwriteSaveClips corule == 0) $
writeSaveAll False False
#endif
manageCalmAndDomination :: MonadServerAtomic m => ActorId -> Actor -> m ()
manageCalmAndDomination :: forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> Actor -> m ()
manageCalmAndDomination ActorId
aid Actor
b = do
performedDomination <-
if Actor -> Int64
bcalm Actor
b Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
> Int64
0 then Bool -> m Bool
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False else do
hiImpression <- Actor -> m (Maybe (FactionId, Int))
forall (m :: * -> *).
MonadServerAtomic m =>
Actor -> m (Maybe (FactionId, Int))
highestImpression Actor
b
case hiImpression of
Maybe (FactionId, Int)
Nothing -> Bool -> m Bool
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
Just (FactionId
hiImpressionFid, Int
hiImpressionK) -> do
fact <- (State -> Faction) -> m Faction
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> Faction) -> m Faction)
-> (State -> Faction) -> m Faction
forall a b. (a -> b) -> a -> b
$ (FactionDict -> FactionId -> Faction
forall k a. Enum k => EnumMap k a -> k -> a
EM.! Actor -> FactionId
bfid Actor
b) (FactionDict -> Faction)
-> (State -> FactionDict) -> State -> Faction
forall b c a. (b -> c) -> (a -> b) -> a -> c
. State -> FactionDict
sfactionD
if fhasPointman (gkind fact)
|| hiImpressionK >= 10
then dominateFidSfx aid aid (btrunk b) hiImpressionFid
else return False
unless performedDomination $ do
newCalmDelta <- getsState $ regenCalmDelta aid b
unless (newCalmDelta == 0) $
updateCalm aid newCalmDelta
applyPeriodicLevel :: MonadServerAtomic m => m ()
applyPeriodicLevel :: forall (m :: * -> *). MonadServerAtomic m => m ()
applyPeriodicLevel = do
arenas <- (StateServer -> EnumSet LevelId) -> m (EnumSet LevelId)
forall a. (StateServer -> a) -> m a
forall (m :: * -> *) a. MonadServer m => (StateServer -> a) -> m a
getsServer StateServer -> EnumSet LevelId
sarenas
let applyPeriodicItem ActorId
_ CStore
_ (ItemId
_, (a
_, [])) = () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
applyPeriodicItem ActorId
aid CStore
cstore (ItemId
iid, (a, [a])
_) = do
itemFull <- (State -> ItemFull) -> m ItemFull
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> ItemFull) -> m ItemFull)
-> (State -> ItemFull) -> m ItemFull
forall a b. (a -> b) -> a -> b
$ ItemId -> State -> ItemFull
itemToFull ItemId
iid
let arItem = ItemFull -> AspectRecord
aspectRecordFull ItemFull
itemFull
when (IA.checkFlag Ability.Periodic arItem) $ do
b2 <- getsState $ getActorBody aid
bag <- getsState $ getBodyStoreBag b2 cstore
case iid `EM.lookup` bag of
Maybe ItemQuant
Nothing -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
Just (Int
k, ItemTimers
_) -> do
let effApplyFlags :: EffApplyFlags
effApplyFlags = EffApplyFlags
{ effToUse :: EffToUse
effToUse = EffToUse
EffBare
, effVoluntary :: Bool
effVoluntary = Bool
True
, effUseAllCopies :: Bool
effUseAllCopies = Int
k Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
1
, effKineticPerformed :: Bool
effKineticPerformed = Bool
False
, effActivation :: ActivationFlag
effActivation = ActivationFlag
Ability.ActivationPeriodic
, effMayDestroy :: Bool
effMayDestroy = Bool
True
}
m UseResult -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m UseResult -> m ()) -> m UseResult -> m ()
forall a b. (a -> b) -> a -> b
$ EffApplyFlags
-> ActorId
-> ActorId
-> ActorId
-> ItemId
-> Container
-> ItemFull
-> m UseResult
forall (m :: * -> *).
MonadServerAtomic m =>
EffApplyFlags
-> ActorId
-> ActorId
-> ActorId
-> ItemId
-> Container
-> ItemFull
-> m UseResult
effectAndDestroyAndAddKill
EffApplyFlags
effApplyFlags
ActorId
aid ActorId
aid ActorId
aid ItemId
iid (ActorId -> CStore -> Container
CActor ActorId
aid CStore
cstore) ItemFull
itemFull
applyPeriodicActor (ActorId
aid, Actor
b) =
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Bool -> Bool
not (Actor -> Bool
bproj Actor
b) Bool -> Bool -> Bool
&& Actor -> Int64
bhp Actor
b Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
> Int64
0 Bool -> Bool -> Bool
&& Actor -> LevelId
blid Actor
b LevelId -> EnumSet LevelId -> Bool
forall k. Enum k => k -> EnumSet k -> Bool
`ES.member` EnumSet LevelId
arenas) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ do
((ItemId, ItemQuant) -> m ()) -> [(ItemId, ItemQuant)] -> m ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
(a -> m ()) -> t a -> m ()
mapM_ (ActorId -> CStore -> (ItemId, ItemQuant) -> m ()
forall {m :: * -> *} {a} {a}.
MonadServerAtomic m =>
ActorId -> CStore -> (ItemId, (a, [a])) -> m ()
applyPeriodicItem ActorId
aid CStore
CEqp) ([(ItemId, ItemQuant)] -> m ()) -> [(ItemId, ItemQuant)] -> m ()
forall a b. (a -> b) -> a -> b
$ ItemBag -> [(ItemId, ItemQuant)]
forall k a. Enum k => EnumMap k a -> [(k, a)]
EM.assocs (ItemBag -> [(ItemId, ItemQuant)])
-> ItemBag -> [(ItemId, ItemQuant)]
forall a b. (a -> b) -> a -> b
$ Actor -> ItemBag
beqp Actor
b
((ItemId, ItemQuant) -> m ()) -> [(ItemId, ItemQuant)] -> m ()
forall (t :: * -> *) (m :: * -> *) a.
(Foldable t, Monad m) =>
(a -> m ()) -> t a -> m ()
mapM_ (ActorId -> CStore -> (ItemId, ItemQuant) -> m ()
forall {m :: * -> *} {a} {a}.
MonadServerAtomic m =>
ActorId -> CStore -> (ItemId, (a, [a])) -> m ()
applyPeriodicItem ActorId
aid CStore
COrgan) ([(ItemId, ItemQuant)] -> m ()) -> [(ItemId, ItemQuant)] -> m ()
forall a b. (a -> b) -> a -> b
$ ItemBag -> [(ItemId, ItemQuant)]
forall k a. Enum k => EnumMap k a -> [(k, a)]
EM.assocs (ItemBag -> [(ItemId, ItemQuant)])
-> ItemBag -> [(ItemId, ItemQuant)]
forall a b. (a -> b) -> a -> b
$ Actor -> ItemBag
borgan Actor
b
ActorId -> Actor -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> Actor -> m ()
manageCalmAndDomination ActorId
aid Actor
b
allActors <- getsState sactorD
mapM_ applyPeriodicActor $ EM.assocs allActors
handleTrajectories :: MonadServerAtomic m => LevelId -> FactionId -> m ()
handleTrajectories :: forall (m :: * -> *).
MonadServerAtomic m =>
LevelId -> FactionId -> m ()
handleTrajectories LevelId
lid FactionId
fid = do
localTime <- (State -> Time) -> m Time
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> Time) -> m Time) -> (State -> Time) -> m Time
forall a b. (a -> b) -> a -> b
$ LevelId -> State -> Time
getLocalTime LevelId
lid
levelTime <- getsServer $ (EM.! lid) . (EM.! fid) . strajTime
let l = [ActorId] -> [ActorId]
forall a. Ord a => [a] -> [a]
sort ([ActorId] -> [ActorId]) -> [ActorId] -> [ActorId]
forall a b. (a -> b) -> a -> b
$ ((ActorId, Time) -> ActorId) -> [(ActorId, Time)] -> [ActorId]
forall a b. (a -> b) -> [a] -> [b]
map (ActorId, Time) -> ActorId
forall a b. (a, b) -> a
fst
([(ActorId, Time)] -> [ActorId]) -> [(ActorId, Time)] -> [ActorId]
forall a b. (a -> b) -> a -> b
$ ((ActorId, Time) -> Bool) -> [(ActorId, Time)] -> [(ActorId, Time)]
forall a. (a -> Bool) -> [a] -> [a]
filter (\(ActorId
_, Time
atime) -> Time
atime Time -> Time -> Bool
forall a. Ord a => a -> a -> Bool
<= Time
localTime) ([(ActorId, Time)] -> [(ActorId, Time)])
-> [(ActorId, Time)] -> [(ActorId, Time)]
forall a b. (a -> b) -> a -> b
$ EnumMap ActorId Time -> [(ActorId, Time)]
forall k a. Enum k => EnumMap k a -> [(k, a)]
EM.assocs EnumMap ActorId Time
levelTime
mapM_ hTrajectories l
breakLoop <- getsServer sbreakLoop
unless (null l || breakLoop) $
handleTrajectories lid fid
hTrajectories :: MonadServerAtomic m => ActorId -> m ()
{-# INLINE hTrajectories #-}
hTrajectories :: forall (m :: * -> *). MonadServerAtomic m => ActorId -> m ()
hTrajectories ActorId
aid = do
b1 <- (State -> Actor) -> m Actor
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> Actor) -> m Actor) -> (State -> Actor) -> m Actor
forall a b. (a -> b) -> a -> b
$ ActorId -> State -> Actor
getActorBody ActorId
aid
let removePushed Actor
b =
(StateServer -> StateServer) -> m ()
forall (m :: * -> *).
MonadServer m =>
(StateServer -> StateServer) -> m ()
modifyServer ((StateServer -> StateServer) -> m ())
-> (StateServer -> StateServer) -> m ()
forall a b. (a -> b) -> a -> b
$ \StateServer
ser ->
StateServer
ser { strajTime =
EM.adjust (EM.adjust (EM.delete aid) (blid b)) (bfid b)
(strajTime ser)
, strajPushedBy = EM.delete aid (strajPushedBy ser) }
removeTrajectory Actor
b =
Bool -> m () -> m ()
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Actor -> Bool
bproj Actor
b)
(m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ ActorId
-> Maybe ([Vector], Speed) -> Maybe ([Vector], Speed) -> UpdAtomic
UpdTrajectory ActorId
aid (Actor -> Maybe ([Vector], Speed)
btrajectory Actor
b) Maybe ([Vector], Speed)
forall a. Maybe a
Nothing
breakLoop <- getsServer sbreakLoop
if breakLoop then return ()
else if actorDying b1 then dieSer aid b1
else case btrajectory b1 of
Maybe ([Vector], Speed)
Nothing -> Actor -> m ()
removePushed Actor
b1
Just ([], Speed
_) -> Actor -> m ()
removeTrajectory Actor
b1 m () -> m () -> m ()
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Actor -> m ()
removePushed Actor
b1
Just{} -> do
ActorId -> Actor -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> Actor -> m ()
advanceTrajectory ActorId
aid Actor
b1
b2 <- (State -> Actor) -> m Actor
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> Actor) -> m Actor) -> (State -> Actor) -> m Actor
forall a b. (a -> b) -> a -> b
$ ActorId -> State -> Actor
getActorBody ActorId
aid
if actorDying b2
then dieSer aid b2
else case btrajectory b2 of
Maybe ([Vector], Speed)
Nothing -> Actor -> m ()
removePushed Actor
b2
Just ([], Speed
_) -> Actor -> m ()
removeTrajectory Actor
b2 m () -> m () -> m ()
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Actor -> m ()
removePushed Actor
b2
Just{} ->
ActorId -> m ()
forall (m :: * -> *). MonadServerAtomic m => ActorId -> m ()
advanceTimeTraj ActorId
aid
advanceTrajectory :: MonadServerAtomic m => ActorId -> Actor -> m ()
advanceTrajectory :: forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> Actor -> m ()
advanceTrajectory ActorId
aid Actor
b1 = do
COps{coTileSpeedup} <- (State -> COps) -> m COps
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState State -> COps
scops
lvl <- getLevel $ blid b1
arTrunk <- getsState $ (EM.! btrunk b1) . sdiscoAspect
let registerKill KillHow
killHow =
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Actor -> Bool
bproj Actor
b1
Bool -> Bool -> Bool
&& Bool -> Bool
not (Flag -> AspectRecord -> Bool
IA.checkFlag Flag
Ability.Blast AspectRecord
arTrunk)) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ do
killer <- (StateServer -> ActorId) -> m ActorId
forall a. (StateServer -> a) -> m a
forall (m :: * -> *) a. MonadServer m => (StateServer -> a) -> m a
getsServer ((StateServer -> ActorId) -> m ActorId)
-> (StateServer -> ActorId) -> m ActorId
forall a b. (a -> b) -> a -> b
$ ActorId -> ActorId -> EnumMap ActorId ActorId -> ActorId
forall k a. Enum k => a -> k -> EnumMap k a -> a
EM.findWithDefault ActorId
aid ActorId
aid (EnumMap ActorId ActorId -> ActorId)
-> (StateServer -> EnumMap ActorId ActorId)
-> StateServer
-> ActorId
forall b c a. (b -> c) -> (a -> b) -> a -> c
. StateServer -> EnumMap ActorId ActorId
strajPushedBy
addKillToAnalytics killer killHow (bfid b1) (btrunk b1)
case btrajectory b1 of
Just (Vector
d : [Vector]
lv, Speed
speed) -> do
let tpos :: Point
tpos = Actor -> Point
bpos Actor
b1 Point -> Vector -> Point
`shift` Vector
d
if TileSpeedup -> ContentId TileKind -> Bool
Tile.isWalkable TileSpeedup
coTileSpeedup (ContentId TileKind -> Bool) -> ContentId TileKind -> Bool
forall a b. (a -> b) -> a -> b
$ Level
lvl Level -> Point -> ContentId TileKind
`at` Point
tpos then do
UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ ActorId
-> Maybe ([Vector], Speed) -> Maybe ([Vector], Speed) -> UpdAtomic
UpdTrajectory ActorId
aid (Actor -> Maybe ([Vector], Speed)
btrajectory Actor
b1) (([Vector], Speed) -> Maybe ([Vector], Speed)
forall a. a -> Maybe a
Just ([Vector]
lv, Speed
speed))
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when ([Vector] -> Bool
forall a. [a] -> Bool
null [Vector]
lv) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ KillHow -> m ()
registerKill KillHow
KillDropLaunch
let occupied :: Bool
occupied = Point -> Level -> Bool
occupiedBigLvl Point
tpos Level
lvl Bool -> Bool -> Bool
|| Point -> Level -> Bool
occupiedProjLvl Point
tpos Level
lvl
reqMoveHit :: m ()
reqMoveHit = Bool -> Bool -> ActorId -> Vector -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
Bool -> Bool -> ActorId -> Vector -> m ()
reqMoveGeneric Bool
False Bool
True ActorId
aid Vector
d
reqDisp :: ActorId -> m ()
reqDisp = Bool -> ActorId -> ActorId -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
Bool -> ActorId -> ActorId -> m ()
reqDisplaceGeneric Bool
False ActorId
aid
if | Actor -> Bool
bproj Actor
b1 -> m ()
reqMoveHit
| Bool
occupied ->
case (Point -> Level -> Maybe ActorId
posToBigLvl Point
tpos Level
lvl, Point -> Level -> [ActorId]
posToProjsLvl Point
tpos Level
lvl) of
(Maybe ActorId
Nothing, []) -> String -> m ()
forall a. (?callStack::CallStack) => String -> a
error String
"advanceTrajectory: not occupied"
(Maybe ActorId
Nothing, [ActorId
target]) -> ActorId -> m ()
reqDisp ActorId
target
(Maybe ActorId
Nothing, [ActorId]
_) -> m ()
reqMoveHit
(Just ActorId
target, []) ->
if [Vector] -> Bool
forall a. [a] -> Bool
null [Vector]
lv then ActorId -> m ()
reqDisp ActorId
target else m ()
reqMoveHit
(Just ActorId
_, [ActorId]
_) -> m ()
reqMoveHit
| Bool
otherwise -> m ()
reqMoveHit
else do
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (Actor -> Bool
bproj Actor
b1) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
SfxAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => SfxAtomic -> m ()
execSfxAtomic (SfxAtomic -> m ()) -> SfxAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ ActorId -> Point -> SfxAtomic
SfxCollideTile ActorId
aid Point
tpos
embedsPre <- (State -> ItemBag) -> m ItemBag
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> ItemBag) -> m ItemBag)
-> (State -> ItemBag) -> m ItemBag
forall a b. (a -> b) -> a -> b
$ LevelId -> Point -> State -> ItemBag
getEmbedBag (Actor -> LevelId
blid Actor
b1) Point
tpos
mfail <- reqAlterFail (not $ bproj b1) EffBare False aid tpos
embedsPost <- getsState $ getEmbedBag (blid b1) tpos
b2 <- getsState $ getActorBody aid
let tpos2 = Actor -> Point
bpos Actor
b2 Point -> Vector -> Point
`shift` Vector
d
lvl2 <- getLevel $ blid b2
case mfail of
Maybe ReqFailure
Nothing | TileSpeedup -> ContentId TileKind -> Bool
Tile.isWalkable TileSpeedup
coTileSpeedup (ContentId TileKind -> Bool) -> ContentId TileKind -> Bool
forall a b. (a -> b) -> a -> b
$ Level
lvl2 Level -> Point -> ContentId TileKind
`at` Point
tpos2 ->
if ItemBag
embedsPre ItemBag -> ItemBag -> Bool
forall a. Eq a => a -> a -> Bool
/= ItemBag
embedsPost Bool -> Bool -> Bool
&& Bool -> Bool
not (ItemBag -> Bool
forall k a. EnumMap k a -> Bool
EM.null ItemBag
embedsPre) then
if Actor -> Int64
bhp Actor
b2 Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
> Int64
oneM then do
UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ ActorId -> Int64 -> UpdAtomic
UpdRefillHP ActorId
aid Int64
minusM
b3 <- (State -> Actor) -> m Actor
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> Actor) -> m Actor) -> (State -> Actor) -> m Actor
forall a b. (a -> b) -> a -> b
$ ActorId -> State -> Actor
getActorBody ActorId
aid
advanceTrajectory aid b3
else do
UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ ActorId
-> Maybe ([Vector], Speed) -> Maybe ([Vector], Speed) -> UpdAtomic
UpdTrajectory ActorId
aid (Actor -> Maybe ([Vector], Speed)
btrajectory Actor
b2)
(Maybe ([Vector], Speed) -> UpdAtomic)
-> Maybe ([Vector], Speed) -> UpdAtomic
forall a b. (a -> b) -> a -> b
$ ([Vector], Speed) -> Maybe ([Vector], Speed)
forall a. a -> Maybe a
Just ([], Speed
speed)
KillHow -> m ()
registerKill KillHow
KillTileLaunch
else
ActorId -> Actor -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> Actor -> m ()
advanceTrajectory ActorId
aid Actor
b2
Maybe ReqFailure
_ -> do
UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ ActorId
-> Maybe ([Vector], Speed) -> Maybe ([Vector], Speed) -> UpdAtomic
UpdTrajectory ActorId
aid (Actor -> Maybe ([Vector], Speed)
btrajectory Actor
b2) Maybe ([Vector], Speed)
forall a. Maybe a
Nothing
if Actor -> Bool
bproj Actor
b2
then KillHow -> m ()
registerKill KillHow
KillTileLaunch
else Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Actor -> Int64
bhp Actor
b2 Int64 -> Int64 -> Bool
forall a. Ord a => a -> a -> Bool
> Int64
oneM) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$ do
UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ ActorId -> Int64 -> UpdAtomic
UpdRefillHP ActorId
aid Int64
minusM
let effect :: Effect
effect = Int -> Effect
IK.RefillHP (-Int
2)
SfxAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => SfxAtomic -> m ()
execSfxAtomic (SfxAtomic -> m ()) -> SfxAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ FactionId -> ActorId -> ItemId -> Effect -> Int64 -> SfxAtomic
SfxEffect (Actor -> FactionId
bfid Actor
b2) ActorId
aid (Actor -> ItemId
btrunk Actor
b2) Effect
effect (-Int64
1)
Maybe ([Vector], Speed)
_ -> String -> m ()
forall a. (?callStack::CallStack) => String -> a
error (String -> m ()) -> String -> m ()
forall a b. (a -> b) -> a -> b
$ String
"Nothing or empty trajectory" String -> (ActorId, Actor) -> String
forall v. Show v => String -> v -> String
`showFailure` (ActorId
aid, Actor
b1)
handleActors :: (MonadServerAtomic m, MonadServerComm m)
=> LevelId -> FactionId -> m Bool
handleActors :: forall (m :: * -> *).
(MonadServerAtomic m, MonadServerComm m) =>
LevelId -> FactionId -> m Bool
handleActors LevelId
lid FactionId
fid = do
localTime <- (State -> Time) -> m Time
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> Time) -> m Time) -> (State -> Time) -> m Time
forall a b. (a -> b) -> a -> b
$ LevelId -> State -> Time
getLocalTime LevelId
lid
levelTime <- getsServer $ (EM.! lid) . (EM.! fid) . sactorTime
let l = [ActorId] -> [ActorId]
forall a. Ord a => [a] -> [a]
sort ([ActorId] -> [ActorId]) -> [ActorId] -> [ActorId]
forall a b. (a -> b) -> a -> b
$ ((ActorId, Time) -> ActorId) -> [(ActorId, Time)] -> [ActorId]
forall a b. (a -> b) -> [a] -> [b]
map (ActorId, Time) -> ActorId
forall a b. (a, b) -> a
fst
([(ActorId, Time)] -> [ActorId]) -> [(ActorId, Time)] -> [ActorId]
forall a b. (a -> b) -> a -> b
$ ((ActorId, Time) -> Bool) -> [(ActorId, Time)] -> [(ActorId, Time)]
forall a. (a -> Bool) -> [a] -> [a]
filter (\(ActorId
_, Time
atime) -> Time
atime Time -> Time -> Bool
forall a. Ord a => a -> a -> Bool
<= Time
localTime) ([(ActorId, Time)] -> [(ActorId, Time)])
-> [(ActorId, Time)] -> [(ActorId, Time)]
forall a b. (a -> b) -> a -> b
$ EnumMap ActorId Time -> [(ActorId, Time)]
forall k a. Enum k => EnumMap k a -> [(k, a)]
EM.assocs EnumMap ActorId Time
levelTime
mleader <- getsState $ gleader . (EM.! fid) . sfactionD
hActors $ case mleader of
Just ActorId
aid | ActorId
aid ActorId -> [ActorId] -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [ActorId]
l -> ActorId
aid ActorId -> [ActorId] -> [ActorId]
forall a. a -> [a] -> [a]
: ActorId -> [ActorId] -> [ActorId]
forall a. Eq a => a -> [a] -> [a]
delete ActorId
aid [ActorId]
l
Maybe ActorId
_ -> [ActorId]
l
hActors :: forall m. (MonadServerAtomic m, MonadServerComm m)
=> [ActorId] -> m Bool
hActors :: forall (m :: * -> *).
(MonadServerAtomic m, MonadServerComm m) =>
[ActorId] -> m Bool
hActors [] = Bool -> m Bool
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return Bool
False
hActors as :: [ActorId]
as@(ActorId
aid : [ActorId]
rest) = do
b1 <- (State -> Actor) -> m Actor
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> Actor) -> m Actor) -> (State -> Actor) -> m Actor
forall a b. (a -> b) -> a -> b
$ ActorId -> State -> Actor
getActorBody ActorId
aid
let !_A = Bool -> () -> ()
forall a. (?callStack::CallStack) => Bool -> a -> a
assert (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ Actor -> Bool
bproj Actor
b1) ()
if bhp b1 <= 0 then
hActors rest
else do
let side = Actor -> FactionId
bfid Actor
b1
fact <- getsState $ (EM.! side) . sfactionD
breakLoop <- getsServer sbreakLoop
let mleader = Faction -> Maybe ActorId
gleader Faction
fact
aidIsLeader = Maybe ActorId
mleader Maybe ActorId -> Maybe ActorId -> Bool
forall a. Eq a => a -> a -> Bool
== ActorId -> Maybe ActorId
forall a. a -> Maybe a
Just ActorId
aid
mainUIactor = FactionKind -> Bool
fhasUI (Faction -> FactionKind
gkind Faction
fact)
Bool -> Bool -> Bool
&& (Bool
aidIsLeader Bool -> Bool -> Bool
|| Bool -> Bool
not (FactionKind -> Bool
fhasPointman (Faction -> FactionKind
gkind Faction
fact)))
mainUIunderAI = Bool
mainUIactor Bool -> Bool -> Bool
&& Faction -> Bool
gunderAI Faction
fact Bool -> Bool -> Bool
&& Bool -> Bool
not Bool
breakLoop
when mainUIunderAI $
handleUIunderAI side aid
factNew <- getsState $ (EM.! side) . sfactionD
let doQueryAI = Bool -> Bool
not Bool
mainUIactor Bool -> Bool -> Bool
|| Faction -> Bool
gunderAI Faction
factNew
breakASAP <- getsServer sbreakASAP
if breakASAP then return True else do
let mswitchLeader :: Maybe ActorId -> m ActorId
{-# NOINLINE mswitchLeader #-}
mswitchLeader (Just ActorId
aidNew) = FactionId -> ActorId -> m ()
forall (m :: * -> *).
MonadServerAtomic m =>
FactionId -> ActorId -> m ()
switchLeader FactionId
side ActorId
aidNew m () -> m ActorId -> m ActorId
forall a b. m a -> m b -> m b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ActorId -> m ActorId
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ActorId
aidNew
mswitchLeader Maybe ActorId
Nothing = ActorId -> m ActorId
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ActorId
aid
(aidNew, mtimed) <-
if doQueryAI then do
(cmd, maid) <- sendQueryAI side aid
aidNew <- mswitchLeader maid
mtimed <- handleRequestAI cmd
return (aidNew, mtimed)
else do
(cmd, maid) <- sendQueryUI RespQueryUI side aid
aidNew <- mswitchLeader maid
mtimed <- handleRequestUI side aidNew cmd
return (aidNew, mtimed)
case mtimed of
Just RequestTimed
timed -> do
nonWaitMove <- FactionId -> ActorId -> RequestTimed -> m Bool
forall (m :: * -> *).
MonadServerAtomic m =>
FactionId -> ActorId -> RequestTimed -> m Bool
handleRequestTimed FactionId
side ActorId
aidNew RequestTimed
timed
if nonWaitMove then return True else hActors rest
Maybe RequestTimed
Nothing -> do
breakASAP2 <- (StateServer -> Bool) -> m Bool
forall a. (StateServer -> a) -> m a
forall (m :: * -> *) a. MonadServer m => (StateServer -> a) -> m a
getsServer StateServer -> Bool
sbreakASAP
if breakASAP2 then return True else hActors as
handleUIunderAI :: (MonadServerAtomic m, MonadServerComm m)
=> FactionId -> ActorId -> m ()
handleUIunderAI :: forall (m :: * -> *).
(MonadServerAtomic m, MonadServerComm m) =>
FactionId -> ActorId -> m ()
handleUIunderAI FactionId
side ActorId
aid = do
cmdS <- Response -> FactionId -> ActorId -> m (ReqUI, Maybe ActorId)
forall (m :: * -> *).
(MonadServerAtomic m, MonadServerComm m) =>
Response -> FactionId -> ActorId -> m (ReqUI, Maybe ActorId)
sendQueryUI Response
RespQueryUIunderAI FactionId
side ActorId
aid
case fst cmdS of
ReqUI
ReqUINop -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()
ReqUI
ReqUIAutomate -> UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ FactionId -> Bool -> UpdAtomic
UpdAutoFaction FactionId
side Bool
False
ReqUI
ReqUIGameDropAndExit -> ActorId -> m ()
forall (m :: * -> *). MonadServerAtomic m => ActorId -> m ()
reqGameDropAndExit ActorId
aid
ReqUI
ReqUIGameSaveAndExit -> ActorId -> m ()
forall (m :: * -> *). MonadServerAtomic m => ActorId -> m ()
reqGameSaveAndExit ActorId
aid
ReqUI
_ -> String -> m ()
forall a. (?callStack::CallStack) => String -> a
error (String -> m ()) -> String -> m ()
forall a b. (a -> b) -> a -> b
$ String
"" String -> (ReqUI, Maybe ActorId) -> String
forall v. Show v => String -> v -> String
`showFailure` (ReqUI, Maybe ActorId)
cmdS
dieSer :: MonadServerAtomic m => ActorId -> Actor -> m ()
dieSer :: forall (m :: * -> *).
MonadServerAtomic m =>
ActorId -> Actor -> m ()
dieSer ActorId
aid Actor
b2 = do
if Actor -> Bool
bproj Actor
b2 then
Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Maybe ([Vector], Speed) -> Bool
forall a. Maybe a -> Bool
isJust (Maybe ([Vector], Speed) -> Bool)
-> Maybe ([Vector], Speed) -> Bool
forall a b. (a -> b) -> a -> b
$ Actor -> Maybe ([Vector], Speed)
btrajectory Actor
b2) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
UpdAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => UpdAtomic -> m ()
execUpdAtomic (UpdAtomic -> m ()) -> UpdAtomic -> m ()
forall a b. (a -> b) -> a -> b
$ ActorId
-> Maybe ([Vector], Speed) -> Maybe ([Vector], Speed) -> UpdAtomic
UpdTrajectory ActorId
aid (Actor -> Maybe ([Vector], Speed)
btrajectory Actor
b2) Maybe ([Vector], Speed)
forall a. Maybe a
Nothing
else do
kindId <- (State -> ContentId ItemKind) -> m (ContentId ItemKind)
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> ContentId ItemKind) -> m (ContentId ItemKind))
-> (State -> ContentId ItemKind) -> m (ContentId ItemKind)
forall a b. (a -> b) -> a -> b
$ ItemId -> State -> ContentId ItemKind
getIidKindIdServer (ItemId -> State -> ContentId ItemKind)
-> ItemId -> State -> ContentId ItemKind
forall a b. (a -> b) -> a -> b
$ Actor -> ItemId
btrunk Actor
b2
execUpdAtomic $ UpdRecordKill aid kindId 1
deduceKilled aid
electLeader (bfid b2) (blid b2) aid
arTrunk <- (State -> AspectRecord) -> m AspectRecord
forall a. (State -> a) -> m a
forall (m :: * -> *) a. MonadStateRead m => (State -> a) -> m a
getsState ((State -> AspectRecord) -> m AspectRecord)
-> (State -> AspectRecord) -> m AspectRecord
forall a b. (a -> b) -> a -> b
$ (EnumMap ItemId AspectRecord -> ItemId -> AspectRecord
forall k a. Enum k => EnumMap k a -> k -> a
EM.! Actor -> ItemId
btrunk Actor
b2) (EnumMap ItemId AspectRecord -> AspectRecord)
-> (State -> EnumMap ItemId AspectRecord) -> State -> AspectRecord
forall b c a. (b -> c) -> (a -> b) -> a -> c
. State -> EnumMap ItemId AspectRecord
sdiscoAspect
let spentProj = Actor -> Bool
bproj Actor
b2 Bool -> Bool -> Bool
&& ItemBag -> Bool
forall k a. EnumMap k a -> Bool
EM.null (Actor -> ItemBag
beqp Actor
b2)
isBlast = Flag -> AspectRecord -> Bool
IA.checkFlag Flag
Ability.Blast AspectRecord
arTrunk
(effScope, bumping) = if bproj b2
then (EffBareAndOnCombine, False)
else (EffBare, True)
when (not spentProj && isBlast) $
void $ reqAlterFail bumping effScope False aid (bpos b2)
b3 <- getsState $ getActorBody aid
dropAllEquippedItems aid b3
bag <- getsState $ getBodyStoreBag b3 COrgan
discoAspect <- getsState sdiscoAspect
let f = m UseResult -> m ()
forall (f :: * -> *) a. Functor f => f a -> f ()
void (m UseResult -> m ())
-> (ItemId -> ItemQuant -> m UseResult)
-> ItemId
-> ItemQuant
-> m ()
forall (f :: * -> *) (g :: * -> *) a b.
(Functor f, Functor g) =>
(a -> b) -> f (g a) -> f (g b)
<$$> Bool
-> Bool
-> CStore
-> ActorId
-> Actor
-> Int
-> ItemId
-> ItemQuant
-> m UseResult
forall (m :: * -> *).
MonadServerAtomic m =>
Bool
-> Bool
-> CStore
-> ActorId
-> Actor
-> Int
-> ItemId
-> ItemQuant
-> m UseResult
dropCStoreItem Bool
False Bool
True CStore
COrgan ActorId
aid Actor
b3 Int
forall a. Bounded a => a
maxBound
isCondition = Flag -> AspectRecord -> Bool
IA.checkFlag Flag
Ability.Condition (AspectRecord -> Bool)
-> (ItemId -> AspectRecord) -> ItemId -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (EnumMap ItemId AspectRecord
discoAspect EnumMap ItemId AspectRecord -> ItemId -> AspectRecord
forall k a. Enum k => EnumMap k a -> k -> a
EM.!)
mapM_ (uncurry f) $ filter (not . isCondition . fst) $ EM.assocs bag
when (not spentProj && not isBlast) $
void $ reqAlterFail bumping effScope False aid (bpos b2)
b4 <- getsState $ getActorBody aid
execUpdAtomic $ UpdDestroyActor aid b4 []
restartGame :: MonadServerAtomic m
=> m () -> m () -> Maybe (GroupName ModeKind) -> m ()
restartGame :: forall (m :: * -> *).
MonadServerAtomic m =>
m () -> m () -> Maybe (GroupName ModeKind) -> m ()
restartGame m ()
updConn m ()
loop Maybe (GroupName ModeKind)
mgameMode = do
SfxAtomic -> m ()
forall (m :: * -> *). MonadServerAtomic m => SfxAtomic -> m ()
execSfxAtomic SfxAtomic
SfxRestart
soptionsNxt <- (StateServer -> ServerOptions) -> m ServerOptions
forall a. (StateServer -> a) -> m a
forall (m :: * -> *) a. MonadServer m => (StateServer -> a) -> m a
getsServer StateServer -> ServerOptions
soptionsNxt
srandom <- getsServer srandom
factionDold <- getsState sfactionD
s <- gameReset soptionsNxt mgameMode (Just srandom)
let optionsBarRngs = ServerOptions
soptionsNxt { sdungeonRng = Nothing
, smainRng = Nothing
, sassertExplored = Nothing }
modifyServer $ \StateServer
ser -> StateServer
ser { soptionsNxt = optionsBarRngs
, soptions = optionsBarRngs }
execUpdAtomic $ UpdRestartServer s
updConn
initPer
reinitGame factionDold
writeSaveAll False True
loop