server.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  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. //Force-load the defaults just so we don't have any mistakes
  27. exec( "data/clientServer/scripts/server/defaults.cs" );
  28. //Then, if the user has saved preferences, we load those over-top the defaults
  29. %prefPath = getPrefpath();
  30. if ( isFile( %prefPath @ "/serverPrefs.cs" ) )
  31. exec( %prefPath @ "/serverPrefs.cs" );
  32. exec( "data/clientServer/scripts/server/audio.cs" );
  33. exec( "data/clientServer/scripts/server/commands.cs" );
  34. exec( "data/clientServer/scripts/server/kickban.cs" );
  35. exec( "data/clientServer/scripts/server/message.cs" );
  36. exec( "data/clientServer/scripts/server/levelDownload.cs" );
  37. exec( "data/clientServer/scripts/server/levelLoad.cs" );
  38. exec( "data/clientServer/scripts/server/levelInfo.cs" );
  39. exec( "data/clientServer/scripts/server/connectionToClient.cs" );
  40. // Server::Status is returned in the Game Info Query and represents the
  41. // current status of the server. This string sould be very short.
  42. $Server::Status = "Unknown";
  43. // Turn on testing/debug script functions
  44. $Server::TestCheats = false;
  45. // Specify where the mission files are.
  46. $Server::MissionFileSpec = "data/levels/*.mis";
  47. }
  48. //-----------------------------------------------------------------------------
  49. function initDedicated()
  50. {
  51. enableWinConsole(true);
  52. echo("\n--------- Starting Dedicated Server ---------");
  53. // Make sure this variable reflects the correct state.
  54. $Server::Dedicated = true;
  55. // The server isn't started unless a mission has been specified.
  56. if ($missionArg !$= "") {
  57. createServer("MultiPlayer", $missionArg);
  58. }
  59. else
  60. echo("No mission specified (use -mission filename)");
  61. }
  62. /// Attempt to find an open port to initialize the server with
  63. function portInit(%port)
  64. {
  65. %failCount = 0;
  66. while(%failCount < 10 && !setNetPort(%port))
  67. {
  68. echo("Port init failed on port " @ %port @ " trying next port.");
  69. %port++; %failCount++;
  70. }
  71. }
  72. /// Create a server of the given type, load the given level, and then
  73. /// create a local client connection to the server.
  74. //
  75. /// @return true if successful.
  76. function createAndConnectToLocalServer( %serverType, %level )
  77. {
  78. if( !createServer( %serverType, %level ) )
  79. return false;
  80. %conn = new GameConnection( ServerConnection );
  81. RootGroup.add( ServerConnection );
  82. %conn.setConnectArgs( $pref::Player::Name );
  83. %conn.setJoinPassword( $Client::Password );
  84. %result = %conn.connectLocal();
  85. if( %result !$= "" )
  86. {
  87. %conn.delete();
  88. destroyServer();
  89. MessageBoxOK("Error starting local server!", "There was an error when trying to connect to the local server.");
  90. if(isObject(MainMenuGui))
  91. Canvas.setContent(MainMenuGui);
  92. return false;
  93. }
  94. return true;
  95. }
  96. /// Create a server with either a "SinglePlayer" or "MultiPlayer" type
  97. /// Specify the level to load on the server
  98. function createServer(%serverType, %level)
  99. {
  100. // Increase the server session number. This is used to make sure we're
  101. // working with the server session we think we are.
  102. $Server::Session++;
  103. if (%level $= "")
  104. {
  105. error("createServer(): level name unspecified");
  106. return false;
  107. }
  108. // Make sure our level name is relative so that it can send
  109. // across the network correctly
  110. %level = makeRelativePath(%level, getWorkingDirectory());
  111. destroyServer();
  112. $missionSequence = 0;
  113. $Server::PlayerCount = 0;
  114. $Server::ServerType = %serverType;
  115. $Server::LoadFailMsg = "";
  116. $Physics::isSinglePlayer = true;
  117. // Setup for multi-player, the network must have been
  118. // initialized before now.
  119. if (%serverType $= "MultiPlayer")
  120. {
  121. $Physics::isSinglePlayer = false;
  122. echo("Starting multiplayer mode");
  123. // Make sure the network port is set to the correct pref.
  124. portInit($Pref::Server::Port);
  125. allowConnections(true);
  126. if ($pref::Net::DisplayOnMaster !$= "Never" )
  127. schedule(0,0,startHeartbeat);
  128. }
  129. // Let the game initialize some things now that the
  130. // the server has been created
  131. onServerCreated();
  132. loadMission(%level, true);
  133. $Game::running = true;
  134. return true;
  135. }
  136. function onServerCreated()
  137. {
  138. // Server::GameType is sent to the master server.
  139. // This variable should uniquely identify your game and/or mod.
  140. $Server::GameType = $appName;
  141. // Server::MissionType sent to the master server. Clients can
  142. // filter servers based on mission type.
  143. // $Server::MissionType = "Deathmatch";
  144. // GameStartTime is the sim time the game started. Used to calculated
  145. // game elapsed time.
  146. $Game::StartTime = 0;
  147. // Create the server physics world.
  148. physicsInitWorld( "server" );
  149. physicsStartSimulation("server");
  150. %cnt = DatablockFilesList.count();
  151. loadDatablockFiles( DatablockFilesList, true );
  152. %cnt = DatablockFilesList.count();
  153. // Keep track of when the game started
  154. $Game::StartTime = $Sim::Time;
  155. }
  156. /// Shut down the server
  157. function destroyServer()
  158. {
  159. $Server::ServerType = "";
  160. $Server::Running = false;
  161. allowConnections(false);
  162. stopHeartbeat();
  163. $missionRunning = false;
  164. // End any running levels and shut down the physics sim
  165. onServerDestroyed();
  166. //physicsDestroy();
  167. // Delete all the server objects
  168. if (isObject(ServerGroup))
  169. ServerGroup.delete();
  170. // Delete all the connections:
  171. while (ClientGroup.getCount())
  172. {
  173. %client = ClientGroup.getObject(0);
  174. %client.delete();
  175. }
  176. $Server::GuidList = "";
  177. // Delete all the data blocks...
  178. deleteDataBlocks();
  179. // Save any server settings
  180. %prefPath = getPrefpath();
  181. echo( "Exporting server prefs..." );
  182. export( "$Pref::Server::*", %prefPath@"/serverPrefs.cs", false );
  183. BanList::Export(%prefPath@"/banlist.cs");
  184. // Increase the server session number. This is used to make sure we're
  185. // working with the server session we think we are.
  186. $Server::Session++;
  187. }
  188. function onServerDestroyed()
  189. {
  190. physicsStopSimulation("server");
  191. if (!isObject( MissionGroup ))
  192. return;
  193. echo("*** ENDING MISSION");
  194. // Inform the game code we're done.
  195. if(TheLevelInfo.isMethod("onMissionEnded"))
  196. TheLevelInfo.onMissionEnded();
  197. // Inform the clients
  198. for( %clientIndex = 0; %clientIndex < ClientGroup.getCount(); %clientIndex++ ) {
  199. // clear ghosts and paths from all clients
  200. %cl = ClientGroup.getObject( %clientIndex );
  201. %cl.endMission();
  202. %cl.resetGhosting();
  203. %cl.clearPaths();
  204. }
  205. // Delete everything
  206. MissionGroup.delete();
  207. MissionCleanup.delete();
  208. clearServerPaths();
  209. }
  210. /// Guid list maintenance functions
  211. function addToServerGuidList( %guid )
  212. {
  213. %count = getFieldCount( $Server::GuidList );
  214. for ( %i = 0; %i < %count; %i++ )
  215. {
  216. if ( getField( $Server::GuidList, %i ) == %guid )
  217. return;
  218. }
  219. $Server::GuidList = $Server::GuidList $= "" ? %guid : $Server::GuidList TAB %guid;
  220. }
  221. function removeFromServerGuidList( %guid )
  222. {
  223. %count = getFieldCount( $Server::GuidList );
  224. for ( %i = 0; %i < %count; %i++ )
  225. {
  226. if ( getField( $Server::GuidList, %i ) == %guid )
  227. {
  228. $Server::GuidList = removeField( $Server::GuidList, %i );
  229. return;
  230. }
  231. }
  232. }
  233. /// When the server is queried for information, the value of this function is
  234. /// returned as the status field of the query packet. This information is
  235. /// accessible as the ServerInfo::State variable.
  236. function onServerInfoQuery()
  237. {
  238. return "Doing Ok";
  239. }