server.cs 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. function initServer()
  23. {
  24. echo("\n--------- Initializing " @ $appName @ ": Server Scripts ---------");
  25. //load prefs
  26. %prefPath = getPrefpath();
  27. if ( isFile( %prefPath @ "/serverPrefs.cs" ) )
  28. exec( %prefPath @ "/serverPrefs.cs" );
  29. else
  30. exec( "data/clientServer/scripts/server/defaults.cs" );
  31. exec( "data/clientServer/scripts/server/audio.cs" );
  32. exec( "data/clientServer/scripts/server/commands.cs" );
  33. exec( "data/clientServer/scripts/server/kickban.cs" );
  34. exec( "data/clientServer/scripts/server/message.cs" );
  35. exec( "data/clientServer/scripts/server/levelDownload.cs" );
  36. exec( "data/clientServer/scripts/server/levelLoad.cs" );
  37. exec( "data/clientServer/scripts/server/levelInfo.cs" );
  38. exec( "data/clientServer/scripts/server/connectionToClient.cs" );
  39. // Server::Status is returned in the Game Info Query and represents the
  40. // current status of the server. This string sould be very short.
  41. $Server::Status = "Unknown";
  42. // Turn on testing/debug script functions
  43. $Server::TestCheats = false;
  44. // Specify where the mission files are.
  45. $Server::MissionFileSpec = "data/levels/*.mis";
  46. }
  47. //-----------------------------------------------------------------------------
  48. function initDedicated()
  49. {
  50. enableWinConsole(true);
  51. echo("\n--------- Starting Dedicated Server ---------");
  52. // Make sure this variable reflects the correct state.
  53. $Server::Dedicated = true;
  54. // The server isn't started unless a mission has been specified.
  55. if ($missionArg !$= "") {
  56. createServer("MultiPlayer", $missionArg);
  57. }
  58. else
  59. echo("No mission specified (use -mission filename)");
  60. }
  61. /// Attempt to find an open port to initialize the server with
  62. function portInit(%port)
  63. {
  64. %failCount = 0;
  65. while(%failCount < 10 && !setNetPort(%port))
  66. {
  67. echo("Port init failed on port " @ %port @ " trying next port.");
  68. %port++; %failCount++;
  69. }
  70. }
  71. /// Create a server of the given type, load the given level, and then
  72. /// create a local client connection to the server.
  73. //
  74. /// @return true if successful.
  75. function createAndConnectToLocalServer( %serverType, %level )
  76. {
  77. if( !createServer( %serverType, %level ) )
  78. return false;
  79. %conn = new GameConnection( ServerConnection );
  80. RootGroup.add( ServerConnection );
  81. %conn.setConnectArgs( $pref::Player::Name );
  82. %conn.setJoinPassword( $Client::Password );
  83. %result = %conn.connectLocal();
  84. if( %result !$= "" )
  85. {
  86. %conn.delete();
  87. destroyServer();
  88. return false;
  89. }
  90. return true;
  91. }
  92. /// Create a server with either a "SinglePlayer" or "MultiPlayer" type
  93. /// Specify the level to load on the server
  94. function createServer(%serverType, %level)
  95. {
  96. // Increase the server session number. This is used to make sure we're
  97. // working with the server session we think we are.
  98. $Server::Session++;
  99. if (%level $= "")
  100. {
  101. error("createServer(): level name unspecified");
  102. return false;
  103. }
  104. // Make sure our level name is relative so that it can send
  105. // across the network correctly
  106. %level = makeRelativePath(%level, getWorkingDirectory());
  107. destroyServer();
  108. $missionSequence = 0;
  109. $Server::PlayerCount = 0;
  110. $Server::ServerType = %serverType;
  111. $Server::LoadFailMsg = "";
  112. $Physics::isSinglePlayer = true;
  113. // Setup for multi-player, the network must have been
  114. // initialized before now.
  115. if (%serverType $= "MultiPlayer")
  116. {
  117. $Physics::isSinglePlayer = false;
  118. echo("Starting multiplayer mode");
  119. // Make sure the network port is set to the correct pref.
  120. portInit($Pref::Server::Port);
  121. allowConnections(true);
  122. if ($pref::Net::DisplayOnMaster !$= "Never" )
  123. schedule(0,0,startHeartbeat);
  124. }
  125. // Let the game initialize some things now that the
  126. // the server has been created
  127. onServerCreated();
  128. loadMission(%level, true);
  129. $Game::running = true;
  130. return true;
  131. }
  132. function onServerCreated()
  133. {
  134. // Server::GameType is sent to the master server.
  135. // This variable should uniquely identify your game and/or mod.
  136. $Server::GameType = $appName;
  137. // Server::MissionType sent to the master server. Clients can
  138. // filter servers based on mission type.
  139. // $Server::MissionType = "Deathmatch";
  140. // GameStartTime is the sim time the game started. Used to calculated
  141. // game elapsed time.
  142. $Game::StartTime = 0;
  143. // Create the server physics world.
  144. physicsInitWorld( "server" );
  145. physicsStartSimulation("server");
  146. %cnt = DatablockFilesList.count();
  147. loadDatablockFiles( DatablockFilesList, true );
  148. %cnt = DatablockFilesList.count();
  149. // Keep track of when the game started
  150. $Game::StartTime = $Sim::Time;
  151. }
  152. /// Shut down the server
  153. function destroyServer()
  154. {
  155. $Server::ServerType = "";
  156. $Server::Running = false;
  157. allowConnections(false);
  158. stopHeartbeat();
  159. $missionRunning = false;
  160. // End any running levels and shut down the physics sim
  161. onServerDestroyed();
  162. physicsDestroy();
  163. // Delete all the server objects
  164. if (isObject(ServerGroup))
  165. ServerGroup.delete();
  166. // Delete all the connections:
  167. while (ClientGroup.getCount())
  168. {
  169. %client = ClientGroup.getObject(0);
  170. %client.delete();
  171. }
  172. $Server::GuidList = "";
  173. // Delete all the data blocks...
  174. deleteDataBlocks();
  175. // Save any server settings
  176. %prefPath = getPrefpath();
  177. echo( "Exporting server prefs..." );
  178. export( "$Pref::Server::*", %prefPath@"/serverPrefs.cs", false );
  179. BanList::Export(%prefPath@"/banlist.cs");
  180. // Increase the server session number. This is used to make sure we're
  181. // working with the server session we think we are.
  182. $Server::Session++;
  183. }
  184. function onServerDestroyed()
  185. {
  186. physicsStopSimulation("server");
  187. if (!isObject( MissionGroup ))
  188. return;
  189. echo("*** ENDING MISSION");
  190. // Inform the game code we're done.
  191. if(TheLevelInfo.isMethod("onMissionEnded"))
  192. TheLevelInfo.onMissionEnded();
  193. // Inform the clients
  194. for( %clientIndex = 0; %clientIndex < ClientGroup.getCount(); %clientIndex++ ) {
  195. // clear ghosts and paths from all clients
  196. %cl = ClientGroup.getObject( %clientIndex );
  197. %cl.endMission();
  198. %cl.resetGhosting();
  199. %cl.clearPaths();
  200. }
  201. // Delete everything
  202. MissionGroup.delete();
  203. MissionCleanup.delete();
  204. clearServerPaths();
  205. }
  206. /// Guid list maintenance functions
  207. function addToServerGuidList( %guid )
  208. {
  209. %count = getFieldCount( $Server::GuidList );
  210. for ( %i = 0; %i < %count; %i++ )
  211. {
  212. if ( getField( $Server::GuidList, %i ) == %guid )
  213. return;
  214. }
  215. $Server::GuidList = $Server::GuidList $= "" ? %guid : $Server::GuidList TAB %guid;
  216. }
  217. function removeFromServerGuidList( %guid )
  218. {
  219. %count = getFieldCount( $Server::GuidList );
  220. for ( %i = 0; %i < %count; %i++ )
  221. {
  222. if ( getField( $Server::GuidList, %i ) == %guid )
  223. {
  224. $Server::GuidList = removeField( $Server::GuidList, %i );
  225. return;
  226. }
  227. }
  228. }
  229. /// When the server is queried for information, the value of this function is
  230. /// returned as the status field of the query packet. This information is
  231. /// accessible as the ServerInfo::State variable.
  232. function onServerInfoQuery()
  233. {
  234. return "Doing Ok";
  235. }