private void PortalStatusCheck(uint PlayerObjectId, GameServer Server)
{
DelayCommand(1.0f, delegate()
{
//
// Bail out if the portal attempt is aborted, e.g. if we have
// timed out.
//
if ((GetDatabase().ACR_GetPCLocalFlags(PlayerObjectId) & ALFA.Database.ACR_PC_LOCAL_FLAG_PORTAL_IN_PROGRESS) == 0)
return;
//
// If the character is no longer spooled, then complete the
// portal sequence.
//
if (!IsCharacterSpooled(PlayerObjectId))
{
//
// Force pending database writes relating to the player to
// complete.
//
GetDatabase().ACR_FlushQueryQueue(PlayerObjectId);
//
// Disable the next internal character save for this player
// object. This prevents the autosave on logout from
// contending with the remote server's initial character
// read.
//
// N.B. Normally, this is not a problem, as the server
// vault subsystem uses file locking internally. But
// ALFA uses SSHFS, which does not support any sort
// of file locking at all (all requestors are let on
// through).
//
// Thus, to avoid the remote server getting into a
// state where it reads a character being transferred
// from the final autosave on logout, we suppress the
// final autosave.
//
// Script-initiated saves are already suppressed by
// the ACR_PC_LOCAL_FLAG_PORTAL_IN_PROGRESS PC local
// flag bit, which just leaves the server's internal
// save.
//
if (!DisableCharacterSave(PlayerObjectId))
{
SendMessageToPC(PlayerObjectId, "Unable to setup for server character transfer - internal error. Please notify the tech team.");
SendMessageToPC(PlayerObjectId, "Aborting portal attempt due to error...");
GetDatabase().ACR_SetPCLocalFlags(
PlayerObjectId,
GetDatabase().ACR_GetPCLocalFlags(PlayerObjectId) & ~(ALFA.Database.ACR_PC_LOCAL_FLAG_PORTAL_IN_PROGRESS));
return;
}
//
// Now retrieve the portal configuration information from
// the data system and transfer the player.
//
// Note that there is no going back from this point. If
// the client does not disconnect on its own, we will boot
// the client later on (because we can never know if the
// client would try and log on to the remote server or if
// it has given up after having sent the request).
//
SendMessageToPC(PlayerObjectId, "Transferring to server " + Server.Name + "...");
GetDatabase().ACR_SetPCLocalFlags(
PlayerObjectId,
GetDatabase().ACR_GetPCLocalFlags(PlayerObjectId) | ALFA.Database.ACR_PC_LOCAL_FLAG_PORTAL_COMMITTED);
//
// Transfer any GUI state needed over to the remote server,
// because the local GUI state is kept (mostly) across the
// portal, but the remote server is ordinarily none-the-
// wiser about this.
//
PlayerState State = TryGetPlayerState(PlayerObjectId);
if (State != null)
{
GUIResynchronizer.SendGUIStateToServer(State, Server, this);
}
lock (WorldManager)
{
ActivatePortal(
PlayerObjectId,
String.Format("{0}:{1}", Server.ServerHostname, Server.ServerPort),
WorldManager.Configuration.PlayerPassword,
"",
TRUE);
}
return;
}
//
// Otherwise, send a notification to the player and start the
// next continuation.
//
SendMessageToPC(PlayerObjectId, "Character transfer in progress...");
PortalStatusCheck(PlayerObjectId, Server);
});
}