| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2012 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- function initServer()
- {
- echo("\n--------- Initializing " @ $appName @ ": Server Scripts ---------");
-
- //load prefs
- //Force-load the defaults just so we don't have any mistakes
- exec( "data/clientServer/scripts/server/defaults.cs" );
-
- //Then, if the user has saved preferences, we load those over-top the defaults
- %prefPath = getPrefpath();
- if ( isFile( %prefPath @ "/serverPrefs.cs" ) )
- exec( %prefPath @ "/serverPrefs.cs" );
-
- exec( "data/clientServer/scripts/server/audio.cs" );
- exec( "data/clientServer/scripts/server/commands.cs" );
- exec( "data/clientServer/scripts/server/kickban.cs" );
- exec( "data/clientServer/scripts/server/message.cs" );
- exec( "data/clientServer/scripts/server/levelDownload.cs" );
- exec( "data/clientServer/scripts/server/levelLoad.cs" );
- exec( "data/clientServer/scripts/server/levelInfo.cs" );
- exec( "data/clientServer/scripts/server/connectionToClient.cs" );
- // Server::Status is returned in the Game Info Query and represents the
- // current status of the server. This string sould be very short.
- $Server::Status = "Unknown";
- // Turn on testing/debug script functions
- $Server::TestCheats = false;
- // Specify where the mission files are.
- $Server::MissionFileSpec = "data/levels/*.mis";
- }
- //-----------------------------------------------------------------------------
- function initDedicated()
- {
- enableWinConsole(true);
- echo("\n--------- Starting Dedicated Server ---------");
- // Make sure this variable reflects the correct state.
- $Server::Dedicated = true;
- // The server isn't started unless a mission has been specified.
- if ($missionArg !$= "") {
- createServer("MultiPlayer", $missionArg);
- }
- else
- echo("No mission specified (use -mission filename)");
- }
- /// Attempt to find an open port to initialize the server with
- function portInit(%port)
- {
- %failCount = 0;
- while(%failCount < 10 && !setNetPort(%port))
- {
- echo("Port init failed on port " @ %port @ " trying next port.");
- %port++; %failCount++;
- }
- }
- /// Create a server of the given type, load the given level, and then
- /// create a local client connection to the server.
- //
- /// @return true if successful.
- function createAndConnectToLocalServer( %serverType, %level )
- {
- if( !createServer( %serverType, %level ) )
- return false;
-
- %conn = new GameConnection( ServerConnection );
- RootGroup.add( ServerConnection );
-
- %conn.setConnectArgs( $pref::Player::Name );
- %conn.setJoinPassword( $Client::Password );
-
- %result = %conn.connectLocal();
- if( %result !$= "" )
- {
- %conn.delete();
- destroyServer();
-
- MessageBoxOK("Error starting local server!", "There was an error when trying to connect to the local server.");
-
- if(isObject(MainMenuGui))
- Canvas.setContent(MainMenuGui);
-
- return false;
- }
-
- return true;
- }
- /// Create a server with either a "SinglePlayer" or "MultiPlayer" type
- /// Specify the level to load on the server
- function createServer(%serverType, %level)
- {
- // Increase the server session number. This is used to make sure we're
- // working with the server session we think we are.
- $Server::Session++;
-
- if (%level $= "")
- {
- error("createServer(): level name unspecified");
- return false;
- }
-
- // Make sure our level name is relative so that it can send
- // across the network correctly
- %level = makeRelativePath(%level, getWorkingDirectory());
- destroyServer();
- $missionSequence = 0;
- $Server::PlayerCount = 0;
- $Server::ServerType = %serverType;
- $Server::LoadFailMsg = "";
- $Physics::isSinglePlayer = true;
-
- // Setup for multi-player, the network must have been
- // initialized before now.
- if (%serverType $= "MultiPlayer")
- {
- $Physics::isSinglePlayer = false;
-
- echo("Starting multiplayer mode");
- // Make sure the network port is set to the correct pref.
- portInit($Pref::Server::Port);
- allowConnections(true);
- if ($pref::Net::DisplayOnMaster !$= "Never" )
- schedule(0,0,startHeartbeat);
- }
- // Let the game initialize some things now that the
- // the server has been created
- onServerCreated();
- loadMission(%level, true);
-
- $Game::running = true;
-
- return true;
- }
- function onServerCreated()
- {
- // Server::GameType is sent to the master server.
- // This variable should uniquely identify your game and/or mod.
- $Server::GameType = $appName;
- // Server::MissionType sent to the master server. Clients can
- // filter servers based on mission type.
- // $Server::MissionType = "Deathmatch";
- // GameStartTime is the sim time the game started. Used to calculated
- // game elapsed time.
- $Game::StartTime = 0;
- // Create the server physics world.
- physicsInitWorld( "server" );
- physicsStartSimulation("server");
-
- %cnt = DatablockFilesList.count();
- loadDatablockFiles( DatablockFilesList, true );
-
- %cnt = DatablockFilesList.count();
-
- // Keep track of when the game started
- $Game::StartTime = $Sim::Time;
- }
- /// Shut down the server
- function destroyServer()
- {
- $Server::ServerType = "";
- $Server::Running = false;
-
- allowConnections(false);
- stopHeartbeat();
- $missionRunning = false;
-
- // End any running levels and shut down the physics sim
- onServerDestroyed();
- //physicsDestroy();
- // Delete all the server objects
- if (isObject(ServerGroup))
- ServerGroup.delete();
- // Delete all the connections:
- while (ClientGroup.getCount())
- {
- %client = ClientGroup.getObject(0);
- %client.delete();
- }
- $Server::GuidList = "";
- // Delete all the data blocks...
- deleteDataBlocks();
-
- // Save any server settings
- %prefPath = getPrefpath();
- echo( "Exporting server prefs..." );
- export( "$Pref::Server::*", %prefPath@"/serverPrefs.cs", false );
-
- BanList::Export(%prefPath@"/banlist.cs");
- // Increase the server session number. This is used to make sure we're
- // working with the server session we think we are.
- $Server::Session++;
- }
- function onServerDestroyed()
- {
- physicsStopSimulation("server");
-
- if (!isObject( MissionGroup ))
- return;
- echo("*** ENDING MISSION");
-
- // Inform the game code we're done.
- if(TheLevelInfo.isMethod("onMissionEnded"))
- TheLevelInfo.onMissionEnded();
- // Inform the clients
- for( %clientIndex = 0; %clientIndex < ClientGroup.getCount(); %clientIndex++ ) {
- // clear ghosts and paths from all clients
- %cl = ClientGroup.getObject( %clientIndex );
- %cl.endMission();
- %cl.resetGhosting();
- %cl.clearPaths();
- }
-
- // Delete everything
- MissionGroup.delete();
- MissionCleanup.delete();
-
- clearServerPaths();
- }
- /// Guid list maintenance functions
- function addToServerGuidList( %guid )
- {
- %count = getFieldCount( $Server::GuidList );
- for ( %i = 0; %i < %count; %i++ )
- {
- if ( getField( $Server::GuidList, %i ) == %guid )
- return;
- }
- $Server::GuidList = $Server::GuidList $= "" ? %guid : $Server::GuidList TAB %guid;
- }
- function removeFromServerGuidList( %guid )
- {
- %count = getFieldCount( $Server::GuidList );
- for ( %i = 0; %i < %count; %i++ )
- {
- if ( getField( $Server::GuidList, %i ) == %guid )
- {
- $Server::GuidList = removeField( $Server::GuidList, %i );
- return;
- }
- }
- }
- /// When the server is queried for information, the value of this function is
- /// returned as the status field of the query packet. This information is
- /// accessible as the ServerInfo::State variable.
- function onServerInfoQuery()
- {
- return "Doing Ok";
- }
|