Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SpawnObject Override Overhaul #1342

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Engine/source/module/moduleDefinition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@ mModuleId(StringTable->EmptyString()),
mLoadCount( 0 ),
mScopeSet( 0 ),
mLocked( false ),
mpModuleManager( NULL )
mpModuleManager( NULL ),
mPriority(0.0f)
{
// Set Vector Associations.
VECTOR_SET_ASSOCIATION( mDependencies );
Expand Down Expand Up @@ -111,6 +112,8 @@ void ModuleDefinition::initPersistFields()

/// Misc.
addProtectedField( "Signature", TypeString, 0, &defaultProtectedNotSetFn, &getSignature, &defaultProtectedNotWriteFn, "A unique signature of the module definition based upon its Id, version and build. This is read-only and is available only after the module has been registered by a module manager." );
addProtectedField( "Priority", TypeF32, 0, &setPriority, &defaultProtectedGetFn, &defaultProtectedNotWriteFn, "A numeric value indicating execution priority for certain callback commands. 0 has the highest priority and is then sorted from there ascending in value. This is read-only and is available only after the module has been registered by a module manager.");

}

//-----------------------------------------------------------------------------
Expand Down
6 changes: 6 additions & 0 deletions Engine/source/module/moduleDefinition.h
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ class ModuleDefinition : public SimSet
SimObjectId mScopeSet;
bool mLocked;
ModuleManager* mpModuleManager;
F32 mPriority;

private:
inline bool checkUnlocked( void ) const { if ( mLocked ) { Con::warnf("Ignoring changes for locked module definition."); } return !mLocked; }
Expand Down Expand Up @@ -195,6 +196,9 @@ class ModuleDefinition : public SimSet
inline bool getModuleLocked( void ) const { return mLocked; }
inline ModuleManager* getModuleManager( void ) const { return mpModuleManager; }

inline void setPriority(const F32 pPriority) { if (checkUnlocked()) { mPriority = pPriority; } }
inline F32 getPriority(void) const { return mPriority; }

using Parent::save;
bool save( void );

Expand Down Expand Up @@ -332,6 +336,8 @@ class ModuleDefinition : public SimSet
}
static bool writeDependencies( void* obj, StringTableEntry pFieldName ) { return static_cast<ModuleDefinition*>(obj)->getDependencies().size() > 0; }
static const char* getSignature(void* obj, const char* data) { return static_cast<ModuleDefinition*>(obj)->getSignature(); }

static bool setPriority(void* obj, const char* index, const char* data) { static_cast<ModuleDefinition*>(obj)->setPriority((F32)dAtof(data)); return false; }
};

#endif // _MODULE_DEFINITION_H
Expand Down
19 changes: 18 additions & 1 deletion Engine/source/module/moduleManager_ScriptBinding.h
Original file line number Diff line number Diff line change
Expand Up @@ -150,8 +150,14 @@ DefineEngineMethod(ModuleManager, findModuleByFilePath, String, (const char* fil
}

//-----------------------------------------------------------------------------
static S32 QSORT_CALLBACK _findModulesSortByPriority(ModuleDefinition* const* a, ModuleDefinition* const* b)
{
F32 diff = (*a)->getPriority() - (*b)->getPriority();
return diff > 0 ? 1 : diff < 0 ? -1 : 0;
}

DefineEngineMethod(ModuleManager, findModules, String, (bool loadedOnly), (true),

DefineEngineMethod(ModuleManager, findModules, String, (bool loadedOnly, bool sortByPriority, const char* moduleGroup), (true, false, ""),
"Find all the modules registered with the specified loaded state.\n"
"@param loadedOnly Whether to return only modules that are loaded or not.\n"
"@return A list of space - separated module definition object Ids.\n")
Expand All @@ -174,12 +180,23 @@ DefineEngineMethod(ModuleManager, findModules, String, (bool loadedOnly), (true)
char* pReturnBuffer = Con::getReturnBuffer( bufferSize );
char* pBufferWrite = pReturnBuffer;

if (sortByPriority)
moduleDefinitions.sort(_findModulesSortByPriority);

StringTableEntry moduleGroupStr = StringTable->insert(moduleGroup);

// Iterate module definitions.
for ( ModuleManager::typeConstModuleDefinitionVector::const_iterator moduleDefinitionItr = moduleDefinitions.begin(); moduleDefinitionItr != moduleDefinitions.end(); ++moduleDefinitionItr )
{
// Fetch module definition.
const ModuleDefinition* pModuleDefinition = *moduleDefinitionItr;

if(moduleGroupStr != StringTable->EmptyString())
{
if (pModuleDefinition->getModuleGroup() != moduleGroupStr)
continue;
}

// Format module definition.
const U32 offset = dSprintf( pBufferWrite, bufferSize, "%d ", pModuleDefinition->getId() );
pBufferWrite += offset;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ function Core_ClientServer::finishMapLoad(%this)
Core_ClientServer.GetEventManager().postEvent( "mapLoadComplete" );
}

function Core_ClientServer::FailMapLoad(%this, %moduleName, %isFine)
function Core_ClientServer::FailMapLoad(%this, %moduleName, %canContinueOnFail)
{
Core_ClientServer.failedModuleName = %moduleName;
Core_ClientServer.GetEventManager().postEvent( "mapLoadFail", %isFine );
Core_ClientServer.GetEventManager().postEvent( "mapLoadFail", %canContinueOnFail );
}

function Core_ClientServerListener::onMapLoadComplete(%this)
Expand All @@ -50,9 +50,9 @@ function Core_ClientServerListener::onMapLoadComplete(%this)
}
}

function Core_ClientServerListener::onmapLoadFail(%this, %isFine)
function Core_ClientServerListener::onMapLoadFail(%this, %canContinueOnFail)
{
if (%isFine)
if (%canContinueOnFail)
{
%this.onMapLoadComplete();
return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
// 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 )
function GameConnection::onConnectRequest( %this, %netAddress, %name )
{
echo("Connect request from: " @ %netAddress);
if($Server::PlayerCount >= $pref::Server::MaxPlayers)
Expand All @@ -47,11 +47,11 @@ function GameConnection::onConnect( %this, %clientData )
sendLoadInfoToClient(%this);

// Simulated client lag for testing...
// %client.setSimulatedNetParams(0.1, 30);
// %this.setSimulatedNetParams(0.1, 30);

// Get the client's unique id:
// %authInfo = %client.getAuthInfo();
// %client.guid = getField(%authInfo, 3);
// %authInfo = %this.getAuthInfo();
// %this.guid = getField(%authInfo, 3);
%this.guid = 0;
addToServerGuidList(%this.guid);

Expand Down Expand Up @@ -81,19 +81,194 @@ function GameConnection::onConnect( %this, %clientData )

%this.connectData = %clientData;

//Signal and listener logic for the spawn config/processing here
%this.GetEventManager().registerEvent("setSpawnObjectTypeComplete");
%this.GetEventManager().registerEvent("setSpawnObjectTypeFailed");
%this.GetEventManager().registerEvent("setSpawnPointComplete");
%this.GetEventManager().registerEvent("setSpawnPointFailed");
%this.GetEventManager().registerEvent("postSpawnComplete");

%this.listener = new ScriptMsgListener() {
class = GameConnectionListener;
};
%this.GetEventManager().subscribe( %this.listener, "setSpawnObjectTypeComplete" );
%this.GetEventManager().subscribe( %this.listener, "setSpawnObjectTypeFailed" );
%this.GetEventManager().subscribe( %this.listener, "setSpawnPointComplete" );
%this.GetEventManager().subscribe( %this.listener, "setSpawnPointFailed" );
%this.GetEventManager().subscribe( %this.listener, "postSpawnComplete" );

callGamemodeFunction("onClientConnect", %this);

$Server::PlayerCount++;
}

function GameConnection::GetEventManager(%this)
{
if( !isObject( %this.eventManager ) )
%this.eventManager = new EventManager() {
queue = "GameConnectionEventManager";
};

return %this.eventManager;
}

function GameConnection::spawnControlObject( %this )
{
//baseline controlObject spawn type with extention points
%this.spawnClass = "Camera";
%this.spawnDBType = "CameraData";
%this.spawnDataBlock = "Observer";

%this.numModsNeedingLoaded = 0;
%this.moduleLoadedDone = 0;
%modulesIDList = getModulesAndGameModesList(true, "Game");

%this.numModsNeedingLoaded = getNumCanCallOnObjectList("setSpawnObjectType", %modulesIDList);

if (%this.numModsNeedingLoaded)
callOnObjectList("setSpawnObjectType", %modulesIdList, %this);
else
%this.GetEventManager().onSetSpawnObjectTypeComplete(); //just jump to progress
}

function GameConnectionListener::onSetSpawnObjectTypeComplete( %this, %client )
{
%client.moduleLoadedDone++;

if (%client.moduleLoadedDone < %client.numModsNeedingLoaded)
return; //continue to wait

if (isObject(%client.player))
{
// The client should not already have a player. Assigning
// a new one could result in an uncontrolled player object.
error("Attempting to create a player for a client that already has one!");
}

// Spawn with the engine's Sim::spawnObject() function
%client.player = spawnObject(%client.spawnClass, %client.spawnDataBlock);

if (!%client.player.isMemberOfClass(%client.spawnClass))
warn("Trying to spawn a class that does not derive from "@ %client.spawnClass);

// Add the player object to MissionCleanup so that it
// won't get saved into the level files and will get
// cleaned up properly
MissionCleanup.add(%client.player);

// Store the client object on the player object for
// future reference
%client.player.client = %client;

%client.setSpawnPoint();

// Give the client control of the camera if in the editor
if( $startWorldEditor )
{
%control = %client.camera;
%control.mode = "Fly";
EditorGui.syncCameraGui();
}
else
%control = %client.player;

// Allow the player/camera to receive move data from the GameConnection. Without this
// the user is unable to control the player/camera.
if (!isDefined("%noControl"))
%client.setControlObject(%control);
}

function GameConnectionListener::onSetSpawnObjectTypeFailed( %this, %client, %canContinueOnFail )
{
errorf("Failed to properly set Spawn Object Type for client: " @ %client);
}

function GameConnection::setSpawnPoint( %this )
{
//baseline spawn point config rules with extention points
%this.playerSpawnGroups = "PlayerSpawnPoints PlayerDropPoints";
%this.spawnPoint = "";
%this.spawnLocation = "0 0 0";

%this.numModsNeedingLoaded = 0;
%this.moduleLoadedDone = 0;
%modulesIDList = getModulesAndGameModesList(true, "Game");

%this.numModsNeedingLoaded = getNumCanCallOnObjectList("setSpawnPoint", %modulesIDList);

if (%this.numModsNeedingLoaded)
callOnObjectList("setSpawnPoint", %modulesIdList, %this);
else
%this.GetEventManager().onSetSpawnPointComplete();
}

function GameConnectionListener::onSetSpawnPointComplete( %this, %client )
{
%client.moduleLoadedDone++;
if (%client.moduleLoadedDone < %client.numModsNeedingLoaded)
return; //continue to wait

if (isObject(%client.player))
%client.player.setTransform(%client.spawnLocation);
else
{
// If we weren't able to create the player object then warn the user
// When the player clicks OK in one of these message boxes, we will fall through
// to the "if (!isObject(%player))" check below.
if (isDefined("%this.spawnDataBlock"))
{
MessageBoxOK("Spawn Failed",
"Unable to create a player with class " @ %client.spawnClass @
" and datablock " @ %client.spawnDataBlock @ ".\n\nStarting as an Observer instead.",
"");
}
else
{
MessageBoxOK("Spawn Failed",
"Unable to create a player with class " @ %client.spawnClass @
".\n\nStarting as an Observer instead.",
"");
}
}
%client.onPostSpawn();
}

function GameConnectionListener::onSetSpawnPointFailed( %this, %client, %canContinueOnFail )
{
errorf("Failed to properly set Spawn Object Type for client: " @ %client);
}

function GameConnection::onPostSpawn( %this )
{
%this.numModsNeedingLoaded = 0;
%this.moduleLoadedDone = 0;
%modulesIDList = getModulesAndGameModesList(true, "Game");

%this.numModsNeedingLoaded = getNumCanCallOnObjectList("onPostSpawn", %modulesIDList);

if (%this.numModsNeedingLoaded)
callOnObjectList("onPostSpawn", %modulesIdList, %this);
else
%this.GetEventManager().onPostSpawnComplete();
}

function GameConnectionListener::onPostSpawnComplete(%this, %client)
{
%client.moduleLoadedDone++;
if (%client.moduleLoadedDone < %client.numModsNeedingLoaded)
return; //continue to wait

//Continue on. Room for special handling here if needbe but not expressly required
}

//-----------------------------------------------------------------------------
// 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)
function GameConnection::setPlayerName(%this,%name)
{
%client.sendGuid = 0;
%this.sendGuid = 0;

// Minimum length requirements
%name = trim( strToPlayerName( %name ) );
Expand All @@ -112,8 +287,8 @@ function GameConnection::setPlayerName(%client,%name)
}

// Tag the name with the "smurf" color:
%client.nameBase = %name;
%client.playerName = addTaggedString("\cp\c8" @ %name @ "\co");
%this.nameBase = %name;
%this.playerName = addTaggedString("\cp\c8" @ %name @ "\co");
}

function isNameUnique(%name)
Expand All @@ -132,7 +307,7 @@ function isNameUnique(%name)
//-----------------------------------------------------------------------------
// This function is called when a client drops for any reason
//
function GameConnection::onDrop(%client, %reason)
function GameConnection::onDrop(%this, %reason)
{
%entityIds = parseMissionGroupForIds("Entity", "");
%entityCount = getWordCount(%entityIds);
Expand All @@ -148,15 +323,15 @@ function GameConnection::onDrop(%client, %reason)
%entityIds = %entityIds SPC %child.getID();
}

%entity.notify("onClientDisconnect", %client);
%entity.notify("onClientDisconnect", %this);
}

if($missionRunning)
{
%hasGameMode = callGamemodeFunction("onClientLeaveGame", %client);
%hasGameMode = callGamemodeFunction("onClientLeaveGame", %this);
}

removeFromServerGuidList( %client.guid );
removeFromServerGuidList( %this.guid );

$Server::PlayerCount--;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ function serverCmdMissionStartPhase3Ack(%client, %seq)
%client.currentPhase = 3;

%hasGameMode = callGamemodeFunction("onClientEnterGame", %client);

%client.spawnControlObject();

//if that also failed, just spawn a camera
if(%hasGameMode == 0)
Expand Down
Loading
Loading