Initial commit
This commit is contained in:
23
example/common/server/audio.cs
Executable file
23
example/common/server/audio.cs
Executable file
@ -0,0 +1,23 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function ServerPlay2D(%profile)
|
||||
{
|
||||
// Play the given sound profile on every client.
|
||||
// The sounds will be transmitted as an event, not attached to any object.
|
||||
for(%idx = 0; %idx < ClientGroup.getCount(); %idx++)
|
||||
ClientGroup.getObject(%idx).play2D(%profile);
|
||||
}
|
||||
|
||||
function ServerPlay3D(%profile,%transform)
|
||||
{
|
||||
// Play the given sound profile at the given position on every client
|
||||
// The sound will be transmitted as an event, not attached to any object.
|
||||
for(%idx = 0; %idx < ClientGroup.getCount(); %idx++)
|
||||
ClientGroup.getObject(%idx).play3D(%profile,%transform);
|
||||
}
|
||||
|
0
example/common/server/banlist.cs
Executable file
0
example/common/server/banlist.cs
Executable file
205
example/common/server/clientConnection.cs
Executable file
205
example/common/server/clientConnection.cs
Executable file
@ -0,0 +1,205 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// This script function is called before a client connection
|
||||
// is accepted. Returning "" will accept the connection,
|
||||
// anything else will be sent back as an error to the client.
|
||||
// All the connect args are passed also to onConnectRequest
|
||||
//
|
||||
function GameConnection::onConnectRequest( %client, %netAddress, %name )
|
||||
{
|
||||
echo("Connect request from: " @ %netAddress);
|
||||
if($Server::PlayerCount >= $pref::Server::MaxPlayers)
|
||||
return "CR_SERVERFULL";
|
||||
return "";
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// This script function is the first called on a client accept
|
||||
//
|
||||
function GameConnection::onConnect( %client, %name )
|
||||
{
|
||||
// Send down the connection error info, the client is
|
||||
// responsible for displaying this message if a connection
|
||||
// error occures.
|
||||
messageClient(%client,'MsgConnectionError',"",$Pref::Server::ConnectionError);
|
||||
|
||||
// Send mission information to the client
|
||||
sendLoadInfoToClient( %client );
|
||||
|
||||
// Simulated client lag for testing...
|
||||
// %client.setSimulatedNetParams(0.1, 30);
|
||||
|
||||
// Get the client's unique id:
|
||||
// %authInfo = %client.getAuthInfo();
|
||||
// %client.guid = getField( %authInfo, 3 );
|
||||
%client.guid = 0;
|
||||
addToServerGuidList( %client.guid );
|
||||
|
||||
// Set admin status
|
||||
if (%client.getAddress() $= "local") {
|
||||
%client.isAdmin = true;
|
||||
%client.isSuperAdmin = true;
|
||||
}
|
||||
else {
|
||||
%client.isAdmin = false;
|
||||
%client.isSuperAdmin = false;
|
||||
}
|
||||
|
||||
// Save client preferences on the connection object for later use.
|
||||
%client.gender = "Male";
|
||||
%client.armor = "Light";
|
||||
%client.race = "Human";
|
||||
%client.skin = addTaggedString( "base" );
|
||||
%client.setPlayerName(%name);
|
||||
%client.score = 0;
|
||||
|
||||
//
|
||||
$instantGroup = ServerGroup;
|
||||
$instantGroup = MissionCleanup;
|
||||
echo("CADD: " @ %client @ " " @ %client.getAddress());
|
||||
|
||||
// Inform the client of all the other clients
|
||||
%count = ClientGroup.getCount();
|
||||
for (%cl = 0; %cl < %count; %cl++) {
|
||||
%other = ClientGroup.getObject(%cl);
|
||||
if ((%other != %client)) {
|
||||
// These should be "silent" versions of these messages...
|
||||
messageClient(%client, 'MsgClientJoin', "",
|
||||
%other.name,
|
||||
%other,
|
||||
%other.sendGuid,
|
||||
%other.score,
|
||||
%other.isAIControlled(),
|
||||
%other.isAdmin,
|
||||
%other.isSuperAdmin);
|
||||
}
|
||||
}
|
||||
|
||||
// Inform the client we've joined up
|
||||
messageClient(%client,
|
||||
'MsgClientJoin', '\c2Welcome to the Torque demo app %1.',
|
||||
%client.name,
|
||||
%client,
|
||||
%client.sendGuid,
|
||||
%client.score,
|
||||
%client.isAiControlled(),
|
||||
%client.isAdmin,
|
||||
%client.isSuperAdmin);
|
||||
|
||||
// Inform all the other clients of the new guy
|
||||
messageAllExcept(%client, -1, 'MsgClientJoin', '\c1%1 joined the game.',
|
||||
%client.name,
|
||||
%client,
|
||||
%client.sendGuid,
|
||||
%client.score,
|
||||
%client.isAiControlled(),
|
||||
%client.isAdmin,
|
||||
%client.isSuperAdmin);
|
||||
|
||||
// If the mission is running, go ahead download it to the client
|
||||
if ($missionRunning)
|
||||
%client.loadMission();
|
||||
$Server::PlayerCount++;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// A player's name could be obtained from the auth server, but for
|
||||
// now we use the one passed from the client.
|
||||
// %realName = getField( %authInfo, 0 );
|
||||
//
|
||||
function GameConnection::setPlayerName(%client,%name)
|
||||
{
|
||||
%client.sendGuid = 0;
|
||||
|
||||
// Minimum length requirements
|
||||
%name = stripTrailingSpaces( strToPlayerName( %name ) );
|
||||
if ( strlen( %name ) < 3 )
|
||||
%name = "Poser";
|
||||
|
||||
// Make sure the alias is unique, we'll hit something eventually
|
||||
if (!isNameUnique(%name))
|
||||
{
|
||||
%isUnique = false;
|
||||
for (%suffix = 1; !%isUnique; %suffix++) {
|
||||
%nameTry = %name @ "." @ %suffix;
|
||||
%isUnique = isNameUnique(%nameTry);
|
||||
}
|
||||
%name = %nameTry;
|
||||
}
|
||||
|
||||
// Tag the name with the "smurf" color:
|
||||
%client.nameBase = %name;
|
||||
%client.name = addTaggedString("\cp\c8" @ %name @ "\co");
|
||||
}
|
||||
|
||||
function isNameUnique(%name)
|
||||
{
|
||||
%count = ClientGroup.getCount();
|
||||
for ( %i = 0; %i < %count; %i++ )
|
||||
{
|
||||
%test = ClientGroup.getObject( %i );
|
||||
%rawName = stripChars( detag( getTaggedString( %test.name ) ), "\cp\co\c6\c7\c8\c9" );
|
||||
if ( strcmp( %name, %rawName ) == 0 )
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// This function is called when a client drops for any reason
|
||||
//
|
||||
function GameConnection::onDrop(%client, %reason)
|
||||
{
|
||||
%client.onClientLeaveGame();
|
||||
|
||||
removeFromServerGuidList( %client.guid );
|
||||
messageAllExcept(%client, -1, 'MsgClientDrop', '\c1%1 has left the game.', %client.name, %client);
|
||||
|
||||
removeTaggedString(%client.name);
|
||||
echo("CDROP: " @ %client @ " " @ %client.getAddress());
|
||||
$Server::PlayerCount--;
|
||||
|
||||
// Reset the server if everyone has left the game
|
||||
if( $Server::PlayerCount == 0 && $Server::Dedicated)
|
||||
schedule(0, 0, "resetServerDefaults");
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function GameConnection::startMission(%this)
|
||||
{
|
||||
// Inform the client the mission starting
|
||||
commandToClient(%this, 'MissionStart', $missionSequence);
|
||||
}
|
||||
|
||||
|
||||
function GameConnection::endMission(%this)
|
||||
{
|
||||
// Inform the client the mission is done
|
||||
commandToClient(%this, 'MissionEnd', $missionSequence);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Sync the clock on the client.
|
||||
|
||||
function GameConnection::syncClock(%client, %time)
|
||||
{
|
||||
commandToClient(%client, 'syncClock', %time);
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Update all the clients with the new score
|
||||
|
||||
function GameConnection::incScore(%this,%delta)
|
||||
{
|
||||
%this.score += %delta;
|
||||
messageAll('MsgClientScoreChanged', "", %this.score, %this);
|
||||
}
|
46
example/common/server/commands.cs
Executable file
46
example/common/server/commands.cs
Executable file
@ -0,0 +1,46 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Misc. server commands avialable to clients
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function serverCmdSAD( %client, %password )
|
||||
{
|
||||
if( %password !$= "" && %password $= $Pref::Server::AdminPassword)
|
||||
{
|
||||
%client.isAdmin = true;
|
||||
%client.isSuperAdmin = true;
|
||||
%name = getTaggedString( %client.name );
|
||||
MessageAll( 'MsgAdminForce', "\c2" @ %name @ " has become Admin by force.", %client );
|
||||
}
|
||||
}
|
||||
|
||||
function serverCmdSADSetPassword(%client, %password)
|
||||
{
|
||||
if(%client.isSuperAdmin)
|
||||
$Pref::Server::AdminPassword = %password;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Server chat message handlers
|
||||
|
||||
function serverCmdTeamMessageSent(%client, %text)
|
||||
{
|
||||
if(strlen(%text) >= $Pref::Server::MaxChatLen)
|
||||
%text = getSubStr(%text, 0, $Pref::Server::MaxChatLen);
|
||||
chatMessageTeam(%client, %client.team, '\c3%1: %2', %client.name, %text);
|
||||
}
|
||||
|
||||
function serverCmdMessageSent(%client, %text)
|
||||
{
|
||||
if(strlen(%text) >= $Pref::Server::MaxChatLen)
|
||||
%text = getSubStr(%text, 0, $Pref::Server::MaxChatLen);
|
||||
chatMessageAll(%client, '\c4%1: %2', %client.name, %text);
|
||||
}
|
||||
|
106
example/common/server/game.cs
Executable file
106
example/common/server/game.cs
Executable file
@ -0,0 +1,106 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Invoked from the common server & mission loading functions
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function onServerCreated()
|
||||
{
|
||||
// Invoked by createServer(), when server is created and ready to go
|
||||
|
||||
// Server::GameType is sent to the master server.
|
||||
// This variable should uniquely identify your game and/or mod.
|
||||
$Server::GameType = "Test App";
|
||||
|
||||
// Server::MissionType sent to the master server. Clients can
|
||||
// filter servers based on mission type.
|
||||
$Server::MissionType = "Deathmatch";
|
||||
|
||||
// Load up all datablocks, objects etc. This function is called when
|
||||
// a server is constructed.
|
||||
// exec("./foo.cs");
|
||||
|
||||
// For backwards compatibility...
|
||||
createGame();
|
||||
}
|
||||
|
||||
function onServerDestroyed()
|
||||
{
|
||||
// Invoked by destroyServer(), right before the server is destroyed
|
||||
destroyGame();
|
||||
}
|
||||
|
||||
function onMissionLoaded()
|
||||
{
|
||||
// Called by loadMission() once the mission is finished loading
|
||||
startGame();
|
||||
}
|
||||
|
||||
function onMissionEnded()
|
||||
{
|
||||
// Called by endMission(), right before the mission is destroyed
|
||||
endGame();
|
||||
}
|
||||
|
||||
function onMissionReset()
|
||||
{
|
||||
// Called by resetMission(), after all the temporary mission objects
|
||||
// have been deleted.
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// These methods are extensions to the GameConnection class. Extending
|
||||
// GameConnection make is easier to deal with some of this functionality,
|
||||
// but these could also be implemented as stand-alone functions.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function GameConnection::onClientEnterGame(%this)
|
||||
{
|
||||
// Called for each client after it's finished downloading the
|
||||
// mission and is ready to start playing.
|
||||
// Tg: Should think about renaming this onClientEnterMission
|
||||
}
|
||||
|
||||
function GameConnection::onClientLeaveGame(%this)
|
||||
{
|
||||
// Call for each client that drops
|
||||
// Tg: Should think about renaming this onClientLeaveMission
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Functions that implement game-play
|
||||
// These are here for backwards compatibilty only, games and/or mods should
|
||||
// really be overloading the server and mission functions listed ubove.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function createGame()
|
||||
{
|
||||
// This function is called by onServerCreated (ubove)
|
||||
}
|
||||
|
||||
function destroyGame()
|
||||
{
|
||||
// This function is called by onServerDestroyed (ubove)
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function startGame()
|
||||
{
|
||||
// This is where the game play should start
|
||||
// The default onMissionLoaded function starts the game.
|
||||
}
|
||||
|
||||
function endGame()
|
||||
{
|
||||
// This is where the game play should end
|
||||
// The default onMissionEnded function shuts down the game.
|
||||
}
|
24
example/common/server/kickban.cs
Executable file
24
example/common/server/kickban.cs
Executable file
@ -0,0 +1,24 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function kick(%client)
|
||||
{
|
||||
messageAll( 'MsgAdminForce', '\c2The Admin has kicked %1.', %client.name);
|
||||
|
||||
if (!%client.isAIControlled())
|
||||
BanList::add(%client.guid, %client.getAddress(), $Pref::Server::KickBanTime);
|
||||
%client.delete("You have been kicked from this server");
|
||||
}
|
||||
|
||||
function ban(%client)
|
||||
{
|
||||
messageAll('MsgAdminForce', '\c2The Admin has banned %1.', %client.name);
|
||||
|
||||
if (!%client.isAIControlled())
|
||||
BanList::add(%client.guid, %client.getAddress(), $Pref::Server::BanTime);
|
||||
%client.delete("You have been banned from this server");
|
||||
}
|
154
example/common/server/message.cs
Executable file
154
example/common/server/message.cs
Executable file
@ -0,0 +1,154 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Server side message commands
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function messageClient(%client, %msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10, %a11, %a12, %a13)
|
||||
{
|
||||
commandToClient(%client, 'ServerMessage', %msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10, %a11, %a12, %a13);
|
||||
}
|
||||
|
||||
function messageTeam(%team, %msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10, %a11, %a12, %a13)
|
||||
{
|
||||
%count = ClientGroup.getCount();
|
||||
for(%cl= 0; %cl < %count; %cl++)
|
||||
{
|
||||
%recipient = ClientGroup.getObject(%cl);
|
||||
if(%recipient.team == %team)
|
||||
messageClient(%recipient, %msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10, %a11, %a12, %a13);
|
||||
}
|
||||
}
|
||||
|
||||
function messageTeamExcept(%client, %msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10, %a11, %a12, %a13)
|
||||
{
|
||||
%team = %client.team;
|
||||
%count = ClientGroup.getCount();
|
||||
for(%cl= 0; %cl < %count; %cl++)
|
||||
{
|
||||
%recipient = ClientGroup.getObject(%cl);
|
||||
if((%recipient.team == %team) && (%recipient != %client))
|
||||
messageClient(%recipient, %msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10, %a11, %a12, %a13);
|
||||
}
|
||||
}
|
||||
|
||||
function messageAll(%msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10, %a11, %a12, %a13)
|
||||
{
|
||||
%count = ClientGroup.getCount();
|
||||
for(%cl = 0; %cl < %count; %cl++)
|
||||
{
|
||||
%client = ClientGroup.getObject(%cl);
|
||||
messageClient(%client, %msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10, %a11, %a12, %a13);
|
||||
}
|
||||
}
|
||||
|
||||
function messageAllExcept(%client, %team, %msgtype, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10, %a11, %a12, %a13)
|
||||
{
|
||||
//can exclude a client, a team or both. A -1 value in either field will ignore that exclusion, so
|
||||
//messageAllExcept(-1, -1, $Mesblah, 'Blah!'); will message everyone (since there shouldn't be a client -1 or client on team -1).
|
||||
%count = ClientGroup.getCount();
|
||||
for(%cl= 0; %cl < %count; %cl++)
|
||||
{
|
||||
%recipient = ClientGroup.getObject(%cl);
|
||||
if((%recipient != %client) && (%recipient.team != %team))
|
||||
messageClient(%recipient, %msgType, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10, %a11, %a12, %a13);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Server side client chat'n
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// silly spam protection...
|
||||
$SPAM_PROTECTION_PERIOD = 10000;
|
||||
$SPAM_MESSAGE_THRESHOLD = 4;
|
||||
$SPAM_PENALTY_PERIOD = 10000;
|
||||
$SPAM_MESSAGE = '\c3FLOOD PROTECTION:\cr You must wait another %1 seconds.';
|
||||
|
||||
function GameConnection::spamMessageTimeout(%this)
|
||||
{
|
||||
if(%this.spamMessageCount > 0)
|
||||
%this.spamMessageCount--;
|
||||
}
|
||||
|
||||
function GameConnection::spamReset(%this)
|
||||
{
|
||||
%this.isSpamming = false;
|
||||
}
|
||||
|
||||
function spamAlert(%client)
|
||||
{
|
||||
if($Pref::Server::FloodProtectionEnabled != true)
|
||||
return(false);
|
||||
|
||||
if(!%client.isSpamming && (%client.spamMessageCount >= $SPAM_MESSAGE_THRESHOLD))
|
||||
{
|
||||
%client.spamProtectStart = getSimTime();
|
||||
%client.isSpamming = true;
|
||||
%client.schedule($SPAM_PENALTY_PERIOD, spamReset);
|
||||
}
|
||||
|
||||
if(%client.isSpamming)
|
||||
{
|
||||
%wait = mFloor(($SPAM_PENALTY_PERIOD - (getSimTime() - %client.spamProtectStart)) / 1000);
|
||||
messageClient(%client, "", $SPAM_MESSAGE, %wait);
|
||||
return(true);
|
||||
}
|
||||
|
||||
%client.spamMessageCount++;
|
||||
%client.schedule($SPAM_PROTECTION_PERIOD, spamMessageTimeout);
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
|
||||
function chatMessageClient( %client, %sender, %voiceTag, %voicePitch, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10 )
|
||||
{
|
||||
//see if the client has muted the sender
|
||||
if ( !%client.muted[%sender] )
|
||||
commandToClient( %client, 'ChatMessage', %sender, %voiceTag, %voicePitch, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10 );
|
||||
}
|
||||
|
||||
function chatMessageTeam( %sender, %team, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10 )
|
||||
{
|
||||
if ( ( %msgString $= "" ) || spamAlert( %sender ) )
|
||||
return;
|
||||
|
||||
%count = ClientGroup.getCount();
|
||||
|
||||
for ( %i = 0; %i < %count; %i++ )
|
||||
{
|
||||
%obj = ClientGroup.getObject( %i );
|
||||
if ( %obj.team == %sender.team )
|
||||
chatMessageClient( %obj, %sender, %sender.voiceTag, %sender.voicePitch, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10 );
|
||||
}
|
||||
}
|
||||
|
||||
function chatMessageAll( %sender, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10 )
|
||||
{
|
||||
if ( ( %msgString $= "" ) || spamAlert( %sender ) )
|
||||
return;
|
||||
|
||||
%count = ClientGroup.getCount();
|
||||
|
||||
for ( %i = 0; %i < %count; %i++ )
|
||||
{
|
||||
%obj = ClientGroup.getObject( %i );
|
||||
|
||||
if(%sender.team != 0)
|
||||
chatMessageClient( %obj, %sender, %sender.voiceTag, %sender.voicePitch, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10 );
|
||||
else
|
||||
{
|
||||
// message sender is an observer -- only send message to other observers
|
||||
if(%obj.team == %sender.team)
|
||||
chatMessageClient( %obj, %sender, %sender.voiceTag, %sender.voicePitch, %msgString, %a1, %a2, %a3, %a4, %a5, %a6, %a7, %a8, %a9, %a10 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
117
example/common/server/missionDownload.cs
Executable file
117
example/common/server/missionDownload.cs
Executable file
@ -0,0 +1,117 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Mission Loading
|
||||
// The server portion of the client/server mission loading process
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// Loading Phases:
|
||||
// Phase 1: Transmit Datablocks
|
||||
// Transmit targets
|
||||
// Phase 2: Transmit Ghost Objects
|
||||
// Phase 3: Start Game
|
||||
//
|
||||
// The server invokes the client MissionStartPhase[1-3] function to request
|
||||
// permission to start each phase. When a client is ready for a phase,
|
||||
// it responds with MissionStartPhase[1-3]Ack.
|
||||
|
||||
function GameConnection::loadMission(%this)
|
||||
{
|
||||
// Send over the information that will display the server info
|
||||
// when we learn it got there, we'll send the data blocks
|
||||
%this.currentPhase = 0;
|
||||
if (%this.isAIControlled())
|
||||
{
|
||||
// Cut to the chase...
|
||||
%this.onClientEnterGame();
|
||||
}
|
||||
else
|
||||
{
|
||||
commandToClient(%this, 'MissionStartPhase1', $missionSequence,
|
||||
$Server::MissionFile, MissionGroup.musicTrack);
|
||||
echo("*** Sending mission load to client: " @ $Server::MissionFile);
|
||||
}
|
||||
}
|
||||
|
||||
function serverCmdMissionStartPhase1Ack(%client, %seq)
|
||||
{
|
||||
// Make sure to ignore calls from a previous mission load
|
||||
if (%seq != $missionSequence || !$MissionRunning)
|
||||
return;
|
||||
if (%client.currentPhase != 0)
|
||||
return;
|
||||
%client.currentPhase = 1;
|
||||
|
||||
// Start with the CRC
|
||||
%client.setMissionCRC( $missionCRC );
|
||||
|
||||
// Send over the datablocks...
|
||||
// OnDataBlocksDone will get called when have confirmation
|
||||
// that they've all been received.
|
||||
%client.transmitDataBlocks($missionSequence);
|
||||
}
|
||||
|
||||
function GameConnection::onDataBlocksDone( %this, %missionSequence )
|
||||
{
|
||||
// Make sure to ignore calls from a previous mission load
|
||||
if (%missionSequence != $missionSequence)
|
||||
return;
|
||||
if (%this.currentPhase != 1)
|
||||
return;
|
||||
%this.currentPhase = 1.5;
|
||||
|
||||
// On to the next phase
|
||||
commandToClient(%this, 'MissionStartPhase2', $missionSequence, $Server::MissionFile);
|
||||
}
|
||||
|
||||
function serverCmdMissionStartPhase2Ack(%client, %seq)
|
||||
{
|
||||
// Make sure to ignore calls from a previous mission load
|
||||
if (%seq != $missionSequence || !$MissionRunning)
|
||||
return;
|
||||
if (%client.currentPhase != 1.5)
|
||||
return;
|
||||
%client.currentPhase = 2;
|
||||
|
||||
// Update mod paths, this needs to get there before the objects.
|
||||
%client.transmitPaths();
|
||||
|
||||
// Start ghosting objects to the client
|
||||
%client.activateGhosting();
|
||||
|
||||
}
|
||||
|
||||
function GameConnection::clientWantsGhostAlwaysRetry(%client)
|
||||
{
|
||||
if($MissionRunning)
|
||||
%client.activateGhosting();
|
||||
}
|
||||
|
||||
function GameConnection::onGhostAlwaysFailed(%client)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
function GameConnection::onGhostAlwaysObjectsReceived(%client)
|
||||
{
|
||||
// Ready for next phase.
|
||||
commandToClient(%client, 'MissionStartPhase3', $missionSequence, $Server::MissionFile);
|
||||
}
|
||||
|
||||
function serverCmdMissionStartPhase3Ack(%client, %seq)
|
||||
{
|
||||
// Make sure to ignore calls from a previous mission load
|
||||
if(%seq != $missionSequence || !$MissionRunning)
|
||||
return;
|
||||
if(%client.currentPhase != 2)
|
||||
return;
|
||||
%client.currentPhase = 3;
|
||||
|
||||
// Server is ready to drop into the game
|
||||
%client.startMission();
|
||||
%client.onClientEnterGame();
|
||||
}
|
88
example/common/server/missionInfo.cs
Executable file
88
example/common/server/missionInfo.cs
Executable file
@ -0,0 +1,88 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// Loading info is text displayed on the client side while the mission
|
||||
// is being loaded. This information is extracted from the mission file
|
||||
// and sent to each the client as it joins.
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// clearLoadInfo
|
||||
//
|
||||
// Clears the mission info stored
|
||||
//------------------------------------------------------------------------------
|
||||
function clearLoadInfo() {
|
||||
if (isObject(MissionInfo))
|
||||
MissionInfo.delete();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// buildLoadInfo
|
||||
//
|
||||
// Extract the map description from the .mis file
|
||||
//------------------------------------------------------------------------------
|
||||
function buildLoadInfo( %mission ) {
|
||||
clearLoadInfo();
|
||||
|
||||
%infoObject = "";
|
||||
%file = new FileObject();
|
||||
|
||||
if ( %file.openForRead( %mission ) ) {
|
||||
%inInfoBlock = false;
|
||||
|
||||
while ( !%file.isEOF() ) {
|
||||
%line = %file.readLine();
|
||||
%line = trim( %line );
|
||||
|
||||
if( %line $= "new ScriptObject(MissionInfo) {" )
|
||||
%inInfoBlock = true;
|
||||
else if( %inInfoBlock && %line $= "};" ) {
|
||||
%inInfoBlock = false;
|
||||
%infoObject = %infoObject @ %line;
|
||||
break;
|
||||
}
|
||||
|
||||
if( %inInfoBlock )
|
||||
%infoObject = %infoObject @ %line @ " ";
|
||||
}
|
||||
|
||||
%file.close();
|
||||
}
|
||||
|
||||
// Will create the object "MissionInfo"
|
||||
eval( %infoObject );
|
||||
%file.delete();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// dumpLoadInfo
|
||||
//
|
||||
// Echo the mission information to the console
|
||||
//------------------------------------------------------------------------------
|
||||
function dumpLoadInfo()
|
||||
{
|
||||
echo( "Mission Name: " @ MissionInfo.name );
|
||||
echo( "Mission Description:" );
|
||||
|
||||
for( %i = 0; MissionInfo.desc[%i] !$= ""; %i++ )
|
||||
echo (" " @ MissionInfo.desc[%i]);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// sendLoadInfoToClient
|
||||
//
|
||||
// Sends mission description to the client
|
||||
//------------------------------------------------------------------------------
|
||||
function sendLoadInfoToClient( %client )
|
||||
{
|
||||
messageClient( %client, 'MsgLoadInfo', "", MissionInfo.name );
|
||||
|
||||
// Send Mission Description a line at a time
|
||||
for( %i = 0; MissionInfo.desc[%i] !$= ""; %i++ )
|
||||
messageClient( %client, 'MsgLoadDescripition', "", MissionInfo.desc[%i] );
|
||||
|
||||
messageClient( %client, 'MsgLoadInfoDone' );
|
||||
}
|
147
example/common/server/missionLoad.cs
Executable file
147
example/common/server/missionLoad.cs
Executable file
@ -0,0 +1,147 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// Server mission loading
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
// On every mission load except the first, there is a pause after
|
||||
// the initial mission info is downloaded to the client.
|
||||
$MissionLoadPause = 5000;
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function loadMission( %missionName, %isFirstMission )
|
||||
{
|
||||
endMission();
|
||||
echo("*** LOADING MISSION: " @ %missionName);
|
||||
echo("*** Stage 1 load");
|
||||
|
||||
// Reset all of these
|
||||
clearCenterPrintAll();
|
||||
clearBottomPrintAll();
|
||||
|
||||
// increment the mission sequence (used for ghost sequencing)
|
||||
$missionSequence++;
|
||||
$missionRunning = false;
|
||||
$Server::MissionFile = %missionName;
|
||||
|
||||
// Extract mission info from the mission file,
|
||||
// including the display name and stuff to send
|
||||
// to the client.
|
||||
buildLoadInfo( %missionName );
|
||||
|
||||
// Download mission info to the clients
|
||||
%count = ClientGroup.getCount();
|
||||
for( %cl = 0; %cl < %count; %cl++ ) {
|
||||
%client = ClientGroup.getObject( %cl );
|
||||
if (!%client.isAIControlled())
|
||||
sendLoadInfoToClient(%client);
|
||||
}
|
||||
|
||||
// if this isn't the first mission, allow some time for the server
|
||||
// to transmit information to the clients:
|
||||
if( %isFirstMission || $Server::ServerType $= "SinglePlayer" )
|
||||
loadMissionStage2();
|
||||
else
|
||||
schedule( $MissionLoadPause, ServerGroup, loadMissionStage2 );
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function loadMissionStage2()
|
||||
{
|
||||
// Create the mission group off the ServerGroup
|
||||
echo("*** Stage 2 load");
|
||||
$instantGroup = ServerGroup;
|
||||
|
||||
// Make sure the mission exists
|
||||
%file = $Server::MissionFile;
|
||||
|
||||
if( !isFile( %file ) ) {
|
||||
error( "Could not find mission " @ %file );
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate the mission CRC. The CRC is used by the clients
|
||||
// to caching mission lighting.
|
||||
$missionCRC = getFileCRC( %file );
|
||||
|
||||
// Exec the mission, objects are added to the ServerGroup
|
||||
exec(%file);
|
||||
|
||||
// If there was a problem with the load, let's try another mission
|
||||
if( !isObject(MissionGroup) ) {
|
||||
error( "No 'MissionGroup' found in mission \"" @ $missionName @ "\"." );
|
||||
schedule( 3000, ServerGroup, CycleMissions );
|
||||
return;
|
||||
}
|
||||
|
||||
// Mission cleanup group
|
||||
new SimGroup( MissionCleanup );
|
||||
$instantGroup = MissionCleanup;
|
||||
|
||||
// Construct MOD paths
|
||||
pathOnMissionLoadDone();
|
||||
|
||||
// Mission loading done...
|
||||
echo("*** Mission loaded");
|
||||
|
||||
// Start all the clients in the mission
|
||||
$missionRunning = true;
|
||||
for( %clientIndex = 0; %clientIndex < ClientGroup.getCount(); %clientIndex++ )
|
||||
ClientGroup.getObject(%clientIndex).loadMission();
|
||||
|
||||
// Go ahead and launch the game
|
||||
onMissionLoaded();
|
||||
purgeResources();
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function endMission()
|
||||
{
|
||||
if (!isObject( MissionGroup ))
|
||||
return;
|
||||
|
||||
echo("*** ENDING MISSION");
|
||||
|
||||
// Inform the game code we're done.
|
||||
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();
|
||||
|
||||
$ServerGroup.delete();
|
||||
$ServerGroup = new SimGroup(ServerGroup);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function resetMission()
|
||||
{
|
||||
echo("*** MISSION RESET");
|
||||
|
||||
// Remove any temporary mission objects
|
||||
MissionCleanup.delete();
|
||||
$instantGroup = ServerGroup;
|
||||
new SimGroup( MissionCleanup );
|
||||
$instantGroup = MissionCleanup;
|
||||
|
||||
//
|
||||
onMissionReset();
|
||||
}
|
148
example/common/server/server.cs
Executable file
148
example/common/server/server.cs
Executable file
@ -0,0 +1,148 @@
|
||||
//-----------------------------------------------------------------------------
|
||||
// Torque Game Engine
|
||||
// Copyright (C) GarageGames.com, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function portInit(%port)
|
||||
{
|
||||
%failCount = 0;
|
||||
while(%failCount < 10 && !setNetPort(%port)) {
|
||||
echo("Port init failed on port " @ %port @ " trying next port.");
|
||||
%port++; %failCount++;
|
||||
}
|
||||
}
|
||||
|
||||
function createServer(%serverType, %mission)
|
||||
{
|
||||
if (%mission $= "") {
|
||||
error("createServer: mission name unspecified");
|
||||
return;
|
||||
}
|
||||
|
||||
destroyServer();
|
||||
|
||||
//
|
||||
$missionSequence = 0;
|
||||
$Server::PlayerCount = 0;
|
||||
$Server::ServerType = %serverType;
|
||||
|
||||
// Setup for multi-player, the network must have been
|
||||
// initialized before now.
|
||||
if (%serverType $= "MultiPlayer") {
|
||||
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);
|
||||
}
|
||||
|
||||
// Load the mission
|
||||
$ServerGroup = new SimGroup(ServerGroup);
|
||||
onServerCreated();
|
||||
loadMission(%mission, true);
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function destroyServer()
|
||||
{
|
||||
$Server::ServerType = "";
|
||||
allowConnections(false);
|
||||
stopHeartbeat();
|
||||
$missionRunning = false;
|
||||
|
||||
// End any running mission
|
||||
endMission();
|
||||
onServerDestroyed();
|
||||
|
||||
// Delete all the server objects
|
||||
if (isObject(MissionGroup))
|
||||
MissionGroup.delete();
|
||||
if (isObject(MissionCleanup))
|
||||
MissionCleanup.delete();
|
||||
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
|
||||
echo( "Exporting server prefs..." );
|
||||
export( "$Pref::Server::*", "~/prefs.cs", false );
|
||||
|
||||
// Dump anything we're not using
|
||||
purgeResources();
|
||||
}
|
||||
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
function resetServerDefaults()
|
||||
{
|
||||
echo( "Resetting server defaults..." );
|
||||
|
||||
// Override server defaults with prefs:
|
||||
exec( "~/defaults.cs" );
|
||||
exec( "~/prefs.cs" );
|
||||
|
||||
loadMission( $Server::MissionFile );
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
// Huh, didn't find it.
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
function onServerInfoQuery()
|
||||
{
|
||||
// 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.
|
||||
return "Doing Ok";
|
||||
}
|
||||
|
Reference in New Issue
Block a user