====== Clientside/serverside detection ====== ===== Introduction ===== You can check if a script is running serverside, clientside or in singleplayer using functions provided by ACSUtils. ===== Terminology ===== * **Server** -- an engine instance that runs the gameplay code. * **Client** -- an engine instance that runs the rendering code and controls a player on the server. In singleplayer, the same engine instance is **both a server and a client**. Both ''IsServer()'' and ''IsClient()'' return true in singleplayer. In ZDoom and GZDoom multiplayer (but not Zandronum's), all players are both servers and clients, just like in singleplayer. Zandronum multiplayer emulation is singleplayer. Just like in singleplayer, the same engine instance is both a server and a client. In real Zandronum multiplayer, the server is only a server and clients are only clients, obviously. Yet, if Zandronum were to allow hosting non-dedicated servers, where a player allows others to connect to their singleplayer game without launching a separate engine instance, the hosting player would be both a server and a client, while other players in the game would be only clients. ===== Functions ===== * ''bool IsServer()'' -- returns true if the script is running on a **server**. * ''bool IsClient()'' -- returns true if the script is running on a **client**. * ''bool IsServerOnly()'' -- returns true if the script is running on a **server that is not also client**. * ''bool IsClientOnly()'' -- returns true if the script is running on a **client that is not also server**. ===== Writing robust multiplayer code ===== The definitions above enable writing ACS code that functions correctly in both singleplayer and multiplayer without singleplayer being a special case. Using ''IsClient'' and ''IsServer'' correctly ensures that your mod runs correctly in both singleplayer and multiplayer: if (IsServer()) { // Run serverside gameplay code. } if (IsClient()) { // Draw hud, spawn effects. } You can also make sure that a serverside-only function is not called on the client, and a clientside-only function is not called on the server. function ServersideOnlyFunction(void) { // writing if (IsClient()) would incorrectly display the warning in singleplayer. if (!IsServer()) printbold(s:"Error: ServersideOnlyFunction was called clientside"); ... } function ClientsideOnlyFunction(void) { // writing if (IsServer()) would incorrectly display the warning in singleplayer. if (!IsClient()) printbold(s:"Error: ClientsideOnlyFunction was called serverside"); ... } ===== How it works ===== All detection of clients and servers is founded on two functions: [[zdoom>ConsolePlayerNumber]] and [[zan>IsNetworkGame]] (formerly known as ''IsMultiplayer''). ''IsClient()'' simply checks if [[zdoom>ConsolePlayerNumber]] is not negative. ''IsServer()'' is more complicated. It returns true if [[zdoom>ConsolePlayerNumber]] is negative. But if it's not negative, it needs to distinguish between multiplayer emulation and real multiplayer. It checks if the multiplayer is real using [[zan>IsNetworkGame]]. But calling this function in ZDoom/GZDoom crashes the engine. Therefore, before calling ''IsNetworkGame'', it checks if the engine is Zandronum using [[source_port_detection|IsZandronum]]. If the engine is not Zandronum, the function returns true, because in ZDoom/GZDoom multiplayer all players run gameplay code. If the engine is Zandronum, the function returns false if it's real multiplayer, true if it's multiplayer emulation. ''IsServerOnly'' and ''IsClientOnly'' simply return ''IsServer() && !IsClient()'' and ''IsClient() && !IsServer()'', respectively.