Merge branch 'master' of ssh://3dhosting.de/var/git/careminster
commit
8bc43ea773
|
@ -561,16 +561,15 @@ namespace OpenSim.Framework
|
||||||
if (attachpoint == 0)
|
if (attachpoint == 0)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (item == UUID.Zero)
|
|
||||||
{
|
|
||||||
lock (m_attachments)
|
lock (m_attachments)
|
||||||
|
{
|
||||||
|
if (item == UUID.Zero)
|
||||||
{
|
{
|
||||||
if (m_attachments.ContainsKey(attachpoint))
|
if (m_attachments.ContainsKey(attachpoint))
|
||||||
{
|
{
|
||||||
m_attachments.Remove(attachpoint);
|
m_attachments.Remove(attachpoint);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -582,13 +581,27 @@ namespace OpenSim.Framework
|
||||||
//
|
//
|
||||||
// Therefore, we will carry on with the set if the existing attachment has no asset id.
|
// Therefore, we will carry on with the set if the existing attachment has no asset id.
|
||||||
AvatarAttachment existingAttachment = GetAttachmentForItem(item);
|
AvatarAttachment existingAttachment = GetAttachmentForItem(item);
|
||||||
if (existingAttachment != null
|
if (existingAttachment != null)
|
||||||
&& existingAttachment.AssetID != UUID.Zero
|
|
||||||
&& existingAttachment.AttachPoint == (attachpoint & 0x7F))
|
|
||||||
{
|
{
|
||||||
// m_log.DebugFormat("[AVATAR APPEARANCE] attempt to attach an already attached item {0}",item);
|
// m_log.DebugFormat(
|
||||||
|
// "[AVATAR APPEARANCE]: Found existing attachment for {0}, asset {1} at point {2}",
|
||||||
|
// existingAttachment.ItemID, existingAttachment.AssetID, existingAttachment.AttachPoint);
|
||||||
|
|
||||||
|
if (existingAttachment.AssetID != UUID.Zero && existingAttachment.AttachPoint == (attachpoint & 0x7F))
|
||||||
|
{
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[AVATAR APPEARANCE]: Ignoring attempt to attach an already attached item {0} at point {1}",
|
||||||
|
item, attachpoint);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Remove it here so that the later append does not add a second attachment but we still update
|
||||||
|
// the assetID
|
||||||
|
DetachAttachment(existingAttachment.ItemID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// check if this is an append or a replace, 0x80 marks it as an append
|
// check if this is an append or a replace, 0x80 marks it as an append
|
||||||
if ((attachpoint & 0x80) > 0)
|
if ((attachpoint & 0x80) > 0)
|
||||||
|
@ -601,6 +614,7 @@ namespace OpenSim.Framework
|
||||||
{
|
{
|
||||||
ReplaceAttachment(new AvatarAttachment(attachpoint,item, asset));
|
ReplaceAttachment(new AvatarAttachment(attachpoint,item, asset));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -648,6 +662,10 @@ namespace OpenSim.Framework
|
||||||
int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; });
|
int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; });
|
||||||
if (index >= 0)
|
if (index >= 0)
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[AVATAR APPEARANCE]: Detaching attachment {0}, index {1}, point {2}",
|
||||||
|
// m_attachments[kvp.Key][index].ItemID, index, m_attachments[kvp.Key][index].AttachPoint);
|
||||||
|
|
||||||
// Remove it from the list of attachments at that attach point
|
// Remove it from the list of attachments at that attach point
|
||||||
m_attachments[kvp.Key].RemoveAt(index);
|
m_attachments[kvp.Key].RemoveAt(index);
|
||||||
|
|
||||||
|
|
|
@ -359,8 +359,9 @@ Asset service request failures: {3}" + Environment.NewLine,
|
||||||
inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime,
|
inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime,
|
||||||
netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime));
|
netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime));
|
||||||
|
|
||||||
|
/* 20130319 RA: For the moment, disable the dump of 'scene' catagory as they are mostly output by
|
||||||
|
* the two formatted printouts above.
|
||||||
SortedDictionary<string, SortedDictionary<string, Stat>> sceneStats;
|
SortedDictionary<string, SortedDictionary<string, Stat>> sceneStats;
|
||||||
|
|
||||||
if (StatsManager.TryGetStats("scene", out sceneStats))
|
if (StatsManager.TryGetStats("scene", out sceneStats))
|
||||||
{
|
{
|
||||||
foreach (KeyValuePair<string, SortedDictionary<string, Stat>> kvp in sceneStats)
|
foreach (KeyValuePair<string, SortedDictionary<string, Stat>> kvp in sceneStats)
|
||||||
|
@ -374,6 +375,7 @@ Asset service request failures: {3}" + Environment.NewLine,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
sb.Append(Environment.NewLine);
|
sb.Append(Environment.NewLine);
|
||||||
|
|
|
@ -369,8 +369,7 @@ namespace OpenSim.Region.CoreModules.Asset
|
||||||
AssetBase asset = null;
|
AssetBase asset = null;
|
||||||
|
|
||||||
string filename = GetFileName(id);
|
string filename = GetFileName(id);
|
||||||
|
while (File.Exists(filename))
|
||||||
if (File.Exists(filename))
|
|
||||||
{
|
{
|
||||||
FileStream stream = null;
|
FileStream stream = null;
|
||||||
try
|
try
|
||||||
|
@ -381,6 +380,8 @@ namespace OpenSim.Region.CoreModules.Asset
|
||||||
asset = (AssetBase)bformatter.Deserialize(stream);
|
asset = (AssetBase)bformatter.Deserialize(stream);
|
||||||
|
|
||||||
m_DiskHits++;
|
m_DiskHits++;
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
catch (System.Runtime.Serialization.SerializationException e)
|
catch (System.Runtime.Serialization.SerializationException e)
|
||||||
{
|
{
|
||||||
|
@ -393,12 +394,24 @@ namespace OpenSim.Region.CoreModules.Asset
|
||||||
// {different version of AssetBase} -- we should attempt to
|
// {different version of AssetBase} -- we should attempt to
|
||||||
// delete it and re-cache
|
// delete it and re-cache
|
||||||
File.Delete(filename);
|
File.Delete(filename);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch (IOException e)
|
||||||
|
{
|
||||||
|
// This is a sharing violation: File exists but can't be opened because it's
|
||||||
|
// being written
|
||||||
|
Thread.Sleep(100);
|
||||||
|
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
m_log.WarnFormat(
|
m_log.WarnFormat(
|
||||||
"[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}",
|
"[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}",
|
||||||
filename, id, e.Message, e.StackTrace);
|
filename, id, e.Message, e.StackTrace);
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
|
|
|
@ -573,8 +573,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
}
|
}
|
||||||
|
|
||||||
// m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
// "[ATTACHMENTS MODULE]: Detaching object {0} {1} for {2} in {3}",
|
// "[ATTACHMENTS MODULE]: Detaching object {0} {1} (FromItemID {2}) for {3} in {4}",
|
||||||
// so.Name, so.LocalId, sp.Name, m_scene.Name);
|
// so.Name, so.LocalId, so.FromItemID, sp.Name, m_scene.Name);
|
||||||
|
|
||||||
// Scripts MUST be snapshotted before the object is
|
// Scripts MUST be snapshotted before the object is
|
||||||
// removed from the scene because doing otherwise will
|
// removed from the scene because doing otherwise will
|
||||||
|
|
|
@ -829,7 +829,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||||
sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule());
|
sceneB, config, new CapabilitiesModule(), etmB, attModB, new BasicInventoryAccessModule());
|
||||||
|
|
||||||
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1);
|
UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(sceneA, 0x1);
|
||||||
ScenePresence beforeTeleportSp = SceneHelpers.AddScenePresence(sceneA, ua1.PrincipalID, sh.SceneManager);
|
|
||||||
|
AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID);
|
||||||
|
TestClient tc = new TestClient(acd, sceneA, sh.SceneManager);
|
||||||
|
List<TestClient> destinationTestClients = new List<TestClient>();
|
||||||
|
EntityTransferHelpers.SetUpInformClientOfNeighbour(tc, destinationTestClients);
|
||||||
|
|
||||||
|
ScenePresence beforeTeleportSp = SceneHelpers.AddScenePresence(sceneA, tc, acd, sh.SceneManager);
|
||||||
beforeTeleportSp.AbsolutePosition = new Vector3(30, 31, 32);
|
beforeTeleportSp.AbsolutePosition = new Vector3(30, 31, 32);
|
||||||
|
|
||||||
InventoryItemBase attItem = CreateAttachmentItem(sceneA, ua1.PrincipalID, "att", 0x10, 0x20);
|
InventoryItemBase attItem = CreateAttachmentItem(sceneA, ua1.PrincipalID, "att", 0x10, 0x20);
|
||||||
|
@ -848,7 +854,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
|
||||||
teleportLookAt,
|
teleportLookAt,
|
||||||
(uint)TeleportFlags.ViaLocation);
|
(uint)TeleportFlags.ViaLocation);
|
||||||
|
|
||||||
((TestClient)beforeTeleportSp.ControllingClient).CompleteTeleportClientSide();
|
destinationTestClients[0].CompleteMovement();
|
||||||
|
|
||||||
// Check attachments have made it into sceneB
|
// Check attachments have made it into sceneB
|
||||||
ScenePresence afterTeleportSceneBSp = sceneB.GetScenePresence(ua1.PrincipalID);
|
ScenePresence afterTeleportSceneBSp = sceneB.GetScenePresence(ua1.PrincipalID);
|
||||||
|
|
|
@ -361,7 +361,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
|
|
||||||
public void QueueAppearanceSave(UUID agentid)
|
public void QueueAppearanceSave(UUID agentid)
|
||||||
{
|
{
|
||||||
// m_log.WarnFormat("[AVFACTORY]: Queue appearance save for {0}", agentid);
|
// m_log.DebugFormat("[AVFACTORY]: Queueing appearance save for {0}", agentid);
|
||||||
|
|
||||||
// 10000 ticks per millisecond, 1000 milliseconds per second
|
// 10000 ticks per millisecond, 1000 milliseconds per second
|
||||||
long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000);
|
long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000);
|
||||||
|
@ -658,7 +658,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// m_log.WarnFormat("[AVFACTORY] avatar {0} save appearance",agentid);
|
// m_log.DebugFormat("[AVFACTORY]: Saving appearance for avatar {0}", agentid);
|
||||||
|
|
||||||
// This could take awhile since it needs to pull inventory
|
// This could take awhile since it needs to pull inventory
|
||||||
// We need to do it at the point of save so that there is a sufficient delay for any upload of new body part/shape
|
// We need to do it at the point of save so that there is a sufficient delay for any upload of new body part/shape
|
||||||
|
@ -667,6 +667,14 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory
|
||||||
// multiple save requests.
|
// multiple save requests.
|
||||||
SetAppearanceAssets(sp.UUID, sp.Appearance);
|
SetAppearanceAssets(sp.UUID, sp.Appearance);
|
||||||
|
|
||||||
|
// List<AvatarAttachment> attachments = sp.Appearance.GetAttachments();
|
||||||
|
// foreach (AvatarAttachment att in attachments)
|
||||||
|
// {
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[AVFACTORY]: For {0} saving attachment {1} at point {2}",
|
||||||
|
// sp.Name, att.ItemID, att.AttachPoint);
|
||||||
|
// }
|
||||||
|
|
||||||
m_scene.AvatarService.SetAppearance(agentid, sp.Appearance);
|
m_scene.AvatarService.SetAppearance(agentid, sp.Appearance);
|
||||||
|
|
||||||
// Trigger this here because it's the final step in the set/queue/save process for appearance setting.
|
// Trigger this here because it's the final step in the set/queue/save process for appearance setting.
|
||||||
|
|
|
@ -256,7 +256,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
|
||||||
// If camera is moved into client, then camera position can be used
|
// If camera is moved into client, then camera position can be used
|
||||||
// MT: No, it can't, as chat is heard from the avatar position, not
|
// MT: No, it can't, as chat is heard from the avatar position, not
|
||||||
// the camera position.
|
// the camera position.
|
||||||
s.ForEachRootScenePresence(
|
s.ForEachScenePresence(
|
||||||
delegate(ScenePresence presence)
|
delegate(ScenePresence presence)
|
||||||
{
|
{
|
||||||
if (destination != UUID.Zero && presence.UUID != destination)
|
if (destination != UUID.Zero && presence.UUID != destination)
|
||||||
|
|
|
@ -167,6 +167,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
|
|
||||||
if (!DisableInterRegionTeleportCancellation)
|
if (!DisableInterRegionTeleportCancellation)
|
||||||
client.OnTeleportCancel += OnClientCancelTeleport;
|
client.OnTeleportCancel += OnClientCancelTeleport;
|
||||||
|
|
||||||
|
client.OnConnectionClosed += OnConnectionClosed;
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void Close() {}
|
public virtual void Close() {}
|
||||||
|
@ -185,6 +187,18 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
|
|
||||||
#region Agent Teleports
|
#region Agent Teleports
|
||||||
|
|
||||||
|
private void OnConnectionClosed(IClientAPI client)
|
||||||
|
{
|
||||||
|
if (client.IsLoggingOut)
|
||||||
|
{
|
||||||
|
m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Aborting);
|
||||||
|
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[ENTITY TRANSFER MODULE]: Aborted teleport request from {0} in {1} due to simultaneous logout",
|
||||||
|
client.Name, Scene.Name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void OnClientCancelTeleport(IClientAPI client)
|
private void OnClientCancelTeleport(IClientAPI client)
|
||||||
{
|
{
|
||||||
m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Cancelling);
|
m_entityTransferStateMachine.UpdateInTransit(client.AgentId, AgentTransferState.Cancelling);
|
||||||
|
@ -520,12 +534,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
"[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.",
|
"[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.",
|
||||||
sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName);
|
sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName);
|
||||||
|
|
||||||
// if (!sp.ValidateAttachments())
|
|
||||||
// {
|
|
||||||
// sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state");
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
|
|
||||||
string reason;
|
string reason;
|
||||||
string version;
|
string version;
|
||||||
if (!Scene.SimulationService.QueryAccess(
|
if (!Scene.SimulationService.QueryAccess(
|
||||||
|
@ -588,6 +596,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's create an agent there if one doesn't exist yet.
|
// Let's create an agent there if one doesn't exist yet.
|
||||||
|
// NOTE: logout will always be false for a non-HG teleport.
|
||||||
bool logout = false;
|
bool logout = false;
|
||||||
if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout))
|
if (!CreateAgent(sp, reg, finalDestination, agentCircuit, teleportFlags, out reason, out logout))
|
||||||
{
|
{
|
||||||
|
@ -608,6 +617,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
else if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after CreateAgent due to previous client close.",
|
||||||
|
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Past this point we have to attempt clean up if the teleport fails, so update transfer state.
|
// Past this point we have to attempt clean up if the teleport fails, so update transfer state.
|
||||||
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
|
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring);
|
||||||
|
@ -630,11 +647,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
|
|
||||||
if (m_eqModule != null)
|
if (m_eqModule != null)
|
||||||
{
|
{
|
||||||
|
// The EnableSimulator message makes the client establish a connection with the destination
|
||||||
|
// simulator by sending the initial UseCircuitCode UDP packet to the destination containing the
|
||||||
|
// correct circuit code.
|
||||||
m_eqModule.EnableSimulator(destinationHandle, endPoint, sp.UUID);
|
m_eqModule.EnableSimulator(destinationHandle, endPoint, sp.UUID);
|
||||||
|
|
||||||
// ES makes the client send a UseCircuitCode message to the destination,
|
// XXX: Is this wait necessary? We will always end up waiting on UpdateAgent for the destination
|
||||||
// which triggers a bunch of things there.
|
// simulator to confirm that it has established communication with the viewer.
|
||||||
// So let's wait
|
|
||||||
Thread.Sleep(200);
|
Thread.Sleep(200);
|
||||||
|
|
||||||
// At least on LL 3.3.4 for teleports between different regions on the same simulator this appears
|
// At least on LL 3.3.4 for teleports between different regions on the same simulator this appears
|
||||||
|
@ -645,6 +664,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// XXX: This is a little misleading since we're information the client of its avatar destination,
|
||||||
|
// which may or may not be a neighbour region of the source region. This path is probably little
|
||||||
|
// used anyway (with EQ being the one used). But it is currently being used for test code.
|
||||||
sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint);
|
sp.ControllingClient.InformClientOfNeighbour(destinationHandle, endPoint);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -662,14 +684,37 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
|
|
||||||
//sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent...");
|
//sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent...");
|
||||||
|
|
||||||
|
// We will check for an abort before UpdateAgent since UpdateAgent will require an active viewer to
|
||||||
|
// establish th econnection to the destination which makes it return true.
|
||||||
|
if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} before UpdateAgent",
|
||||||
|
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// A common teleport failure occurs when we can send CreateAgent to the
|
||||||
|
// destination region but the viewer cannot establish the connection (e.g. due to network issues between
|
||||||
|
// the viewer and the destination). In this case, UpdateAgent timesout after 10 seconds, although then
|
||||||
|
// there's a further 10 second wait whilst we attempt to tell the destination to delete the agent in Fail().
|
||||||
if (!UpdateAgent(reg, finalDestination, agent, sp))
|
if (!UpdateAgent(reg, finalDestination, agent, sp))
|
||||||
{
|
{
|
||||||
// Region doesn't take it
|
if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after UpdateAgent due to previous client close.",
|
||||||
|
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_log.WarnFormat(
|
m_log.WarnFormat(
|
||||||
"[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Returning avatar to source region.",
|
"[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1} from {2}. Keeping avatar in source region.",
|
||||||
sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
|
sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
|
||||||
|
|
||||||
Fail(sp, finalDestination, logout);
|
Fail(sp, finalDestination, logout, "Connection between viewer and destination region could not be established.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -679,7 +724,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
"[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request",
|
"[ENTITY TRANSFER MODULE]: Cancelled teleport of {0} to {1} from {2} after UpdateAgent on client request",
|
||||||
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
||||||
|
|
||||||
CleanupAbortedInterRegionTeleport(sp, finalDestination);
|
CleanupFailedInterRegionTeleport(sp, finalDestination);
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -688,6 +733,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
"[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}",
|
"[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} from {1} to {2}",
|
||||||
capsPath, sp.Scene.RegionInfo.RegionName, sp.Name);
|
capsPath, sp.Scene.RegionInfo.RegionName, sp.Name);
|
||||||
|
|
||||||
|
// We need to set this here to avoid an unlikely race condition when teleporting to a neighbour simulator,
|
||||||
|
// where that neighbour simulator could otherwise request a child agent create on the source which then
|
||||||
|
// closes our existing agent which is still signalled as root.
|
||||||
|
sp.IsChildAgent = true;
|
||||||
|
|
||||||
if (m_eqModule != null)
|
if (m_eqModule != null)
|
||||||
{
|
{
|
||||||
m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID);
|
m_eqModule.TeleportFinishEvent(destinationHandle, 13, endPoint, 0, teleportFlags, capsPath, sp.UUID);
|
||||||
|
@ -698,19 +748,25 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
teleportFlags, capsPath);
|
teleportFlags, capsPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Let's set this to true tentatively. This does not trigger OnChildAgent
|
|
||||||
sp.IsChildAgent = true;
|
|
||||||
|
|
||||||
// TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
|
// TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which
|
||||||
// trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
|
// trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation
|
||||||
// that the client contacted the destination before we close things here.
|
// that the client contacted the destination before we close things here.
|
||||||
if (!m_entityTransferStateMachine.WaitForAgentArrivedAtDestination(sp.UUID))
|
if (!m_entityTransferStateMachine.WaitForAgentArrivedAtDestination(sp.UUID))
|
||||||
{
|
{
|
||||||
|
if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting)
|
||||||
|
{
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[ENTITY TRANSFER MODULE]: Aborted teleport of {0} to {1} from {2} after WaitForAgentArrivedAtDestination due to previous client close.",
|
||||||
|
sp.Name, finalDestination.RegionName, sp.Scene.Name);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
m_log.WarnFormat(
|
m_log.WarnFormat(
|
||||||
"[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.",
|
"[ENTITY TRANSFER MODULE]: Teleport of {0} to {1} from {2} failed due to no callback from destination region. Returning avatar to source region.",
|
||||||
sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
|
sp.Name, finalDestination.RegionName, sp.Scene.RegionInfo.RegionName);
|
||||||
|
|
||||||
Fail(sp, finalDestination, logout);
|
Fail(sp, finalDestination, logout, "Destination region did not signal teleport completion.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -733,8 +789,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
// Now let's make it officially a child agent
|
// Now let's make it officially a child agent
|
||||||
sp.MakeChildAgent();
|
sp.MakeChildAgent();
|
||||||
|
|
||||||
// sp.Scene.CleanDroppedAttachments();
|
|
||||||
|
|
||||||
// Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
|
// Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone
|
||||||
|
|
||||||
if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
|
if (NeedsClosing(sp.DrawDistance, oldRegionX, newRegionX, oldRegionY, newRegionY, reg))
|
||||||
|
@ -774,7 +828,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// <param name='sp'> </param>
|
/// <param name='sp'> </param>
|
||||||
/// <param name='finalDestination'></param>
|
/// <param name='finalDestination'></param>
|
||||||
protected virtual void CleanupAbortedInterRegionTeleport(ScenePresence sp, GridRegion finalDestination)
|
protected virtual void CleanupFailedInterRegionTeleport(ScenePresence sp, GridRegion finalDestination)
|
||||||
{
|
{
|
||||||
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
|
m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp);
|
||||||
|
|
||||||
|
@ -793,12 +847,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
/// <param name='sp'></param>
|
/// <param name='sp'></param>
|
||||||
/// <param name='finalDestination'></param>
|
/// <param name='finalDestination'></param>
|
||||||
/// <param name='logout'></param>
|
/// <param name='logout'></param>
|
||||||
protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout)
|
/// <param name='reason'>Human readable reason for teleport failure. Will be sent to client.</param>
|
||||||
|
protected virtual void Fail(ScenePresence sp, GridRegion finalDestination, bool logout, string reason)
|
||||||
{
|
{
|
||||||
CleanupAbortedInterRegionTeleport(sp, finalDestination);
|
CleanupFailedInterRegionTeleport(sp, finalDestination);
|
||||||
|
|
||||||
sp.ControllingClient.SendTeleportFailed(
|
sp.ControllingClient.SendTeleportFailed(
|
||||||
string.Format("Problems connecting to destination {0}", finalDestination.RegionName));
|
string.Format(
|
||||||
|
"Problems connecting to destination {0}, reason: {1}", finalDestination.RegionName, reason));
|
||||||
|
|
||||||
sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout);
|
sp.Scene.EventManager.TriggerTeleportFail(sp.ControllingClient, logout);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,11 +51,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
/// This is a state machine.
|
/// This is a state machine.
|
||||||
///
|
///
|
||||||
/// [Entry] => Preparing
|
/// [Entry] => Preparing
|
||||||
/// Preparing => { Transferring || Cancelling || CleaningUp || [Exit] }
|
/// Preparing => { Transferring || Cancelling || CleaningUp || Aborting || [Exit] }
|
||||||
/// Transferring => { ReceivedAtDestination || Cancelling || CleaningUp }
|
/// Transferring => { ReceivedAtDestination || Cancelling || CleaningUp || Aborting }
|
||||||
/// Cancelling => CleaningUp
|
/// Cancelling => CleaningUp || Aborting
|
||||||
/// ReceivedAtDestination => CleaningUp
|
/// ReceivedAtDestination => CleaningUp || Aborting
|
||||||
/// CleaningUp => [Exit]
|
/// CleaningUp => [Exit]
|
||||||
|
/// Aborting => [Exit]
|
||||||
///
|
///
|
||||||
/// In other words, agents normally travel throwing Preparing => Transferring => ReceivedAtDestination => CleaningUp
|
/// In other words, agents normally travel throwing Preparing => Transferring => ReceivedAtDestination => CleaningUp
|
||||||
/// However, any state can transition to CleaningUp if the teleport has failed.
|
/// However, any state can transition to CleaningUp if the teleport has failed.
|
||||||
|
@ -66,7 +67,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
Transferring, // The agent is in the process of being transferred to a destination
|
Transferring, // The agent is in the process of being transferred to a destination
|
||||||
ReceivedAtDestination, // The destination has notified us that the agent has been successfully received
|
ReceivedAtDestination, // The destination has notified us that the agent has been successfully received
|
||||||
CleaningUp, // The agent is being changed to child/removed after a transfer
|
CleaningUp, // The agent is being changed to child/removed after a transfer
|
||||||
Cancelling // The user has cancelled the teleport but we have yet to act upon this.
|
Cancelling, // The user has cancelled the teleport but we have yet to act upon this.
|
||||||
|
Aborting // The transfer is aborting. Unlike Cancelling, no compensating actions should be performed
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -134,7 +136,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
// Illegal to try and update an agent that's not actually in transit.
|
// Illegal to try and update an agent that's not actually in transit.
|
||||||
if (!m_agentsInTransit.ContainsKey(id))
|
if (!m_agentsInTransit.ContainsKey(id))
|
||||||
{
|
{
|
||||||
if (newState != AgentTransferState.Cancelling)
|
if (newState != AgentTransferState.Cancelling && newState != AgentTransferState.Aborting)
|
||||||
failureMessage = string.Format(
|
failureMessage = string.Format(
|
||||||
"Agent with ID {0} is not registered as in transit in {1}",
|
"Agent with ID {0} is not registered as in transit in {1}",
|
||||||
id, m_mod.Scene.RegionInfo.RegionName);
|
id, m_mod.Scene.RegionInfo.RegionName);
|
||||||
|
@ -145,7 +147,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
{
|
{
|
||||||
oldState = m_agentsInTransit[id];
|
oldState = m_agentsInTransit[id];
|
||||||
|
|
||||||
if (newState == AgentTransferState.CleaningUp && oldState != AgentTransferState.CleaningUp)
|
if (newState == AgentTransferState.Aborting)
|
||||||
|
{
|
||||||
|
transitionOkay = true;
|
||||||
|
}
|
||||||
|
else if (newState == AgentTransferState.CleaningUp && oldState != AgentTransferState.CleaningUp)
|
||||||
{
|
{
|
||||||
transitionOkay = true;
|
transitionOkay = true;
|
||||||
}
|
}
|
||||||
|
@ -292,8 +298,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
|
||||||
|
|
||||||
// There should be no race condition here since no other code should be removing the agent transfer or
|
// There should be no race condition here since no other code should be removing the agent transfer or
|
||||||
// changing the state to another other than Transferring => ReceivedAtDestination.
|
// changing the state to another other than Transferring => ReceivedAtDestination.
|
||||||
while (m_agentsInTransit[id] != AgentTransferState.ReceivedAtDestination && count-- > 0)
|
|
||||||
|
while (count-- > 0)
|
||||||
{
|
{
|
||||||
|
lock (m_agentsInTransit)
|
||||||
|
{
|
||||||
|
if (m_agentsInTransit[id] == AgentTransferState.ReceivedAtDestination)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
// m_log.Debug(" >>> Waiting... " + count);
|
// m_log.Debug(" >>> Waiting... " + count);
|
||||||
Thread.Sleep(100);
|
Thread.Sleep(100);
|
||||||
}
|
}
|
||||||
|
|
|
@ -136,7 +136,7 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
|
||||||
{
|
{
|
||||||
lock (m_logFileWriteLock)
|
lock (m_logFileWriteLock)
|
||||||
{
|
{
|
||||||
DateTime now = DateTime.Now;
|
DateTime now = DateTime.UtcNow;
|
||||||
if (m_logFile == null || now > m_logFileEndTime)
|
if (m_logFile == null || now > m_logFileEndTime)
|
||||||
{
|
{
|
||||||
if (m_logFile != null)
|
if (m_logFile != null)
|
||||||
|
|
|
@ -2990,8 +2990,22 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
sp.IsChildAgent = false;
|
sp.IsChildAgent = false;
|
||||||
sp.IsLoggingIn = true;
|
sp.IsLoggingIn = true;
|
||||||
|
|
||||||
|
// We leave a 5 second pause before attempting to rez attachments to avoid a clash with
|
||||||
|
// version 3 viewers that maybe doing their own attachment rezzing related to their current
|
||||||
|
// outfit folder on startup. If these operations do clash, then the symptoms are invisible
|
||||||
|
// attachments until one zooms in on the avatar.
|
||||||
|
//
|
||||||
|
// We do not pause if we are launching on the same thread anyway in order to avoid pointlessly
|
||||||
|
// delaying any attachment related regression tests.
|
||||||
if (AttachmentsModule != null)
|
if (AttachmentsModule != null)
|
||||||
Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); });
|
Util.FireAndForget(
|
||||||
|
o =>
|
||||||
|
{
|
||||||
|
if (Util.FireAndForgetMethod != FireAndForgetMethod.None)
|
||||||
|
Thread.Sleep(5000);
|
||||||
|
|
||||||
|
AttachmentsModule.RezAttachments(sp);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -1529,6 +1529,15 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXX: If we force an update here, then multiple attachments do appear correctly on a destination region
|
||||||
|
// If we do it a little bit earlier (e.g. when converting the child to a root agent) then this does not work.
|
||||||
|
// This may be due to viewer code or it may be something we're not doing properly simulator side.
|
||||||
|
lock (m_attachments)
|
||||||
|
{
|
||||||
|
foreach (SceneObjectGroup sog in m_attachments)
|
||||||
|
sog.ScheduleGroupForFullUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
// m_log.DebugFormat(
|
// m_log.DebugFormat(
|
||||||
// "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms",
|
// "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms",
|
||||||
// client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds);
|
// client.Name, Scene.RegionInfo.RegionName, (DateTime.Now - startTime).Milliseconds);
|
||||||
|
|
|
@ -94,7 +94,12 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
// SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA, eqmA);
|
// SceneHelpers.SetupSceneModules(sceneA, config, new CapabilitiesModule(), etmA, eqmA);
|
||||||
SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB);
|
SceneHelpers.SetupSceneModules(sceneB, config, new CapabilitiesModule(), etmB);
|
||||||
|
|
||||||
ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager);
|
AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
|
||||||
|
TestClient tc = new TestClient(acd, sceneA, sh.SceneManager);
|
||||||
|
List<TestClient> destinationTestClients = new List<TestClient>();
|
||||||
|
EntityTransferHelpers.SetUpInformClientOfNeighbour(tc, destinationTestClients);
|
||||||
|
|
||||||
|
ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, tc, acd, sh.SceneManager);
|
||||||
originalSp.AbsolutePosition = new Vector3(128, 32, 10);
|
originalSp.AbsolutePosition = new Vector3(128, 32, 10);
|
||||||
|
|
||||||
// originalSp.Flying = true;
|
// originalSp.Flying = true;
|
||||||
|
|
|
@ -26,7 +26,10 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Reflection;
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Text;
|
||||||
using Nini.Config;
|
using Nini.Config;
|
||||||
using NUnit.Framework;
|
using NUnit.Framework;
|
||||||
using OpenMetaverse;
|
using OpenMetaverse;
|
||||||
|
@ -40,8 +43,6 @@ using OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation;
|
||||||
using OpenSim.Region.CoreModules.World.Permissions;
|
using OpenSim.Region.CoreModules.World.Permissions;
|
||||||
using OpenSim.Tests.Common;
|
using OpenSim.Tests.Common;
|
||||||
using OpenSim.Tests.Common.Mock;
|
using OpenSim.Tests.Common.Mock;
|
||||||
using System.IO;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace OpenSim.Region.Framework.Scenes.Tests
|
namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
{
|
{
|
||||||
|
@ -68,7 +69,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestSameRegionTeleport()
|
public void TestSameRegion()
|
||||||
{
|
{
|
||||||
TestHelpers.InMethod();
|
TestHelpers.InMethod();
|
||||||
// log4net.Config.XmlConfigurator.Configure();
|
// log4net.Config.XmlConfigurator.Configure();
|
||||||
|
@ -106,10 +107,10 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void TestSameSimulatorSeparatedRegionsTeleport()
|
public void TestSameSimulatorIsolatedRegions()
|
||||||
{
|
{
|
||||||
TestHelpers.InMethod();
|
TestHelpers.InMethod();
|
||||||
// log4net.Config.XmlConfigurator.Configure();
|
// TestHelpers.EnableLogging();
|
||||||
|
|
||||||
UUID userId = TestHelpers.ParseTail(0x1);
|
UUID userId = TestHelpers.ParseTail(0x1);
|
||||||
|
|
||||||
|
@ -141,9 +142,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager);
|
ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager);
|
||||||
sp.AbsolutePosition = new Vector3(30, 31, 32);
|
sp.AbsolutePosition = new Vector3(30, 31, 32);
|
||||||
|
|
||||||
// XXX: A very nasty hack to tell the client about the destination scene without having to crank the whole
|
List<TestClient> destinationTestClients = new List<TestClient>();
|
||||||
// UDP stack (?)
|
EntityTransferHelpers.SetUpInformClientOfNeighbour((TestClient)sp.ControllingClient, destinationTestClients);
|
||||||
// ((TestClient)sp.ControllingClient).TeleportTargetScene = sceneB;
|
|
||||||
|
|
||||||
sceneA.RequestTeleportLocation(
|
sceneA.RequestTeleportLocation(
|
||||||
sp.ControllingClient,
|
sp.ControllingClient,
|
||||||
|
@ -152,7 +152,10 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
teleportLookAt,
|
teleportLookAt,
|
||||||
(uint)TeleportFlags.ViaLocation);
|
(uint)TeleportFlags.ViaLocation);
|
||||||
|
|
||||||
((TestClient)sp.ControllingClient).CompleteTeleportClientSide();
|
// SetupInformClientOfNeighbour() will have handled the callback into the target scene to setup the child
|
||||||
|
// agent. This call will now complete the movement of the user into the destination and upgrade the agent
|
||||||
|
// from child to root.
|
||||||
|
destinationTestClients[0].CompleteMovement();
|
||||||
|
|
||||||
Assert.That(sceneA.GetScenePresence(userId), Is.Null);
|
Assert.That(sceneA.GetScenePresence(userId), Is.Null);
|
||||||
|
|
||||||
|
@ -177,7 +180,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
/// Test teleport procedures when the target simulator returns false when queried about access.
|
/// Test teleport procedures when the target simulator returns false when queried about access.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Test]
|
[Test]
|
||||||
public void TestSameSimulatorSeparatedRegionsQueryAccessFails()
|
public void TestSameSimulatorIsolatedRegions_DeniedOnQueryAccess()
|
||||||
{
|
{
|
||||||
TestHelpers.InMethod();
|
TestHelpers.InMethod();
|
||||||
// TestHelpers.EnableLogging();
|
// TestHelpers.EnableLogging();
|
||||||
|
@ -261,7 +264,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
/// Test teleport procedures when the target simulator create agent step is refused.
|
/// Test teleport procedures when the target simulator create agent step is refused.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Test]
|
[Test]
|
||||||
public void TestSameSimulatorSeparatedRegionsCreateAgentFails()
|
public void TestSameSimulatorIsolatedRegions_DeniedOnCreateAgent()
|
||||||
{
|
{
|
||||||
TestHelpers.InMethod();
|
TestHelpers.InMethod();
|
||||||
// TestHelpers.EnableLogging();
|
// TestHelpers.EnableLogging();
|
||||||
|
@ -333,12 +336,100 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
// TestHelpers.DisableLogging();
|
// TestHelpers.DisableLogging();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Test teleport when the destination region does not process (or does not receive) the connection attempt
|
||||||
|
/// from the viewer.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This could be quite a common case where the source region can connect to a remove destination region
|
||||||
|
/// (for CreateAgent) but the viewer cannot reach the destination region due to network issues.
|
||||||
|
/// </remarks>
|
||||||
[Test]
|
[Test]
|
||||||
public void TestSameSimulatorNeighbouringRegionsTeleport()
|
public void TestSameSimulatorIsolatedRegions_DestinationDidNotProcessViewerConnection()
|
||||||
{
|
{
|
||||||
TestHelpers.InMethod();
|
TestHelpers.InMethod();
|
||||||
// TestHelpers.EnableLogging();
|
// TestHelpers.EnableLogging();
|
||||||
|
|
||||||
|
UUID userId = TestHelpers.ParseTail(0x1);
|
||||||
|
Vector3 preTeleportPosition = new Vector3(30, 31, 32);
|
||||||
|
|
||||||
|
EntityTransferModule etmA = new EntityTransferModule();
|
||||||
|
EntityTransferModule etmB = new EntityTransferModule();
|
||||||
|
|
||||||
|
LocalSimulationConnectorModule lscm = new LocalSimulationConnectorModule();
|
||||||
|
|
||||||
|
IConfigSource config = new IniConfigSource();
|
||||||
|
config.AddConfig("Modules");
|
||||||
|
config.Configs["Modules"].Set("EntityTransferModule", etmA.Name);
|
||||||
|
config.Configs["Modules"].Set("SimulationServices", lscm.Name);
|
||||||
|
|
||||||
|
config.AddConfig("EntityTransfer");
|
||||||
|
|
||||||
|
// In order to run a single threaded regression test we do not want the entity transfer module waiting
|
||||||
|
// for a callback from the destination scene before removing its avatar data.
|
||||||
|
config.Configs["EntityTransfer"].Set("wait_for_callback", false);
|
||||||
|
|
||||||
|
// config.AddConfig("Startup");
|
||||||
|
// config.Configs["Startup"].Set("serverside_object_permissions", true);
|
||||||
|
|
||||||
|
SceneHelpers sh = new SceneHelpers();
|
||||||
|
TestScene sceneA = sh.SetupScene("sceneA", TestHelpers.ParseTail(0x100), 1000, 1000);
|
||||||
|
TestScene sceneB = sh.SetupScene("sceneB", TestHelpers.ParseTail(0x200), 1002, 1000);
|
||||||
|
|
||||||
|
SceneHelpers.SetupSceneModules(sceneA, config, etmA );
|
||||||
|
|
||||||
|
// We need to set up the permisions module on scene B so that our later use of agent limit to deny
|
||||||
|
// QueryAccess won't succeed anyway because administrators are always allowed in and the default
|
||||||
|
// IsAdministrator if no permissions module is present is true.
|
||||||
|
SceneHelpers.SetupSceneModules(sceneB, config, new object[] { new PermissionsModule(), etmB });
|
||||||
|
|
||||||
|
// Shared scene modules
|
||||||
|
SceneHelpers.SetupSceneModules(new Scene[] { sceneA, sceneB }, config, lscm);
|
||||||
|
|
||||||
|
Vector3 teleportPosition = new Vector3(10, 11, 12);
|
||||||
|
Vector3 teleportLookAt = new Vector3(20, 21, 22);
|
||||||
|
|
||||||
|
ScenePresence sp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager);
|
||||||
|
sp.AbsolutePosition = preTeleportPosition;
|
||||||
|
|
||||||
|
sceneA.RequestTeleportLocation(
|
||||||
|
sp.ControllingClient,
|
||||||
|
sceneB.RegionInfo.RegionHandle,
|
||||||
|
teleportPosition,
|
||||||
|
teleportLookAt,
|
||||||
|
(uint)TeleportFlags.ViaLocation);
|
||||||
|
|
||||||
|
// FIXME: Not setting up InformClientOfNeighbour on the TestClient means that it does not initiate
|
||||||
|
// communication with the destination region. But this is a very non-obvious way of doing it - really we
|
||||||
|
// should be forced to expicitly set this up.
|
||||||
|
|
||||||
|
Assert.That(sceneB.GetScenePresence(userId), Is.Null);
|
||||||
|
|
||||||
|
ScenePresence sceneASp = sceneA.GetScenePresence(userId);
|
||||||
|
Assert.That(sceneASp, Is.Not.Null);
|
||||||
|
Assert.That(sceneASp.Scene.RegionInfo.RegionName, Is.EqualTo(sceneA.RegionInfo.RegionName));
|
||||||
|
Assert.That(sceneASp.AbsolutePosition, Is.EqualTo(preTeleportPosition));
|
||||||
|
|
||||||
|
Assert.That(sceneA.GetRootAgentCount(), Is.EqualTo(1));
|
||||||
|
Assert.That(sceneA.GetChildAgentCount(), Is.EqualTo(0));
|
||||||
|
Assert.That(sceneB.GetRootAgentCount(), Is.EqualTo(0));
|
||||||
|
Assert.That(sceneB.GetChildAgentCount(), Is.EqualTo(0));
|
||||||
|
|
||||||
|
// TODO: Add assertions to check correct circuit details in both scenes.
|
||||||
|
|
||||||
|
// Lookat is sent to the client only - sp.Lookat does not yield the same thing (calculation from camera
|
||||||
|
// position instead).
|
||||||
|
// Assert.That(sp.Lookat, Is.EqualTo(teleportLookAt));
|
||||||
|
|
||||||
|
// TestHelpers.DisableLogging();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Test]
|
||||||
|
public void TestSameSimulatorNeighbouringRegions()
|
||||||
|
{
|
||||||
|
TestHelpers.InMethod();
|
||||||
|
TestHelpers.EnableLogging();
|
||||||
|
|
||||||
UUID userId = TestHelpers.ParseTail(0x1);
|
UUID userId = TestHelpers.ParseTail(0x1);
|
||||||
|
|
||||||
EntityTransferModule etmA = new EntityTransferModule();
|
EntityTransferModule etmA = new EntityTransferModule();
|
||||||
|
@ -366,10 +457,14 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
Vector3 teleportPosition = new Vector3(10, 11, 12);
|
Vector3 teleportPosition = new Vector3(10, 11, 12);
|
||||||
Vector3 teleportLookAt = new Vector3(20, 21, 22);
|
Vector3 teleportLookAt = new Vector3(20, 21, 22);
|
||||||
|
|
||||||
ScenePresence originalSp = SceneHelpers.AddScenePresence(sceneA, userId, sh.SceneManager);
|
AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
|
||||||
originalSp.AbsolutePosition = new Vector3(30, 31, 32);
|
TestClient tc = new TestClient(acd, sceneA, sh.SceneManager);
|
||||||
|
List<TestClient> destinationTestClients = new List<TestClient>();
|
||||||
|
EntityTransferHelpers.SetUpInformClientOfNeighbour(tc, destinationTestClients);
|
||||||
|
|
||||||
|
ScenePresence beforeSceneASp = SceneHelpers.AddScenePresence(sceneA, tc, acd, sh.SceneManager);
|
||||||
|
beforeSceneASp.AbsolutePosition = new Vector3(30, 31, 32);
|
||||||
|
|
||||||
ScenePresence beforeSceneASp = sceneA.GetScenePresence(userId);
|
|
||||||
Assert.That(beforeSceneASp, Is.Not.Null);
|
Assert.That(beforeSceneASp, Is.Not.Null);
|
||||||
Assert.That(beforeSceneASp.IsChildAgent, Is.False);
|
Assert.That(beforeSceneASp.IsChildAgent, Is.False);
|
||||||
|
|
||||||
|
@ -377,10 +472,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
Assert.That(beforeSceneBSp, Is.Not.Null);
|
Assert.That(beforeSceneBSp, Is.Not.Null);
|
||||||
Assert.That(beforeSceneBSp.IsChildAgent, Is.True);
|
Assert.That(beforeSceneBSp.IsChildAgent, Is.True);
|
||||||
|
|
||||||
// XXX: A very nasty hack to tell the client about the destination scene without having to crank the whole
|
// In this case, we will not receieve a second InformClientOfNeighbour since the viewer already knows
|
||||||
// UDP stack (?)
|
// about the neighbour region it is teleporting to.
|
||||||
// ((TestClient)beforeSceneASp.ControllingClient).TeleportTargetScene = sceneB;
|
|
||||||
|
|
||||||
sceneA.RequestTeleportLocation(
|
sceneA.RequestTeleportLocation(
|
||||||
beforeSceneASp.ControllingClient,
|
beforeSceneASp.ControllingClient,
|
||||||
sceneB.RegionInfo.RegionHandle,
|
sceneB.RegionInfo.RegionHandle,
|
||||||
|
@ -388,7 +481,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests
|
||||||
teleportLookAt,
|
teleportLookAt,
|
||||||
(uint)TeleportFlags.ViaLocation);
|
(uint)TeleportFlags.ViaLocation);
|
||||||
|
|
||||||
((TestClient)beforeSceneASp.ControllingClient).CompleteTeleportClientSide();
|
destinationTestClients[0].CompleteMovement();
|
||||||
|
|
||||||
ScenePresence afterSceneASp = sceneA.GetScenePresence(userId);
|
ScenePresence afterSceneASp = sceneA.GetScenePresence(userId);
|
||||||
Assert.That(afterSceneASp, Is.Not.Null);
|
Assert.That(afterSceneASp, Is.Not.Null);
|
||||||
|
|
|
@ -176,16 +176,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
|
||||||
// " {0,-36} {1,-10} {2,-36} {3,-14} {4,-15}\n",
|
// " {0,-36} {1,-10} {2,-36} {3,-14} {4,-15}\n",
|
||||||
// attachmentObject.Name, attachmentObject.LocalId, attachmentObject.FromItemID,
|
// attachmentObject.Name, attachmentObject.LocalId, attachmentObject.FromItemID,
|
||||||
// (AttachmentPoint)attachmentObject.AttachmentPoint, attachmentObject.RootPart.AttachedPos);
|
// (AttachmentPoint)attachmentObject.AttachmentPoint, attachmentObject.RootPart.AttachedPos);
|
||||||
ct.Rows.Add(
|
|
||||||
new ConsoleDisplayTableRow(
|
ct.AddRow(
|
||||||
new List<string>()
|
|
||||||
{
|
|
||||||
attachmentObject.Name,
|
attachmentObject.Name,
|
||||||
attachmentObject.LocalId.ToString(),
|
attachmentObject.LocalId,
|
||||||
attachmentObject.FromItemID.ToString(),
|
attachmentObject.FromItemID,
|
||||||
((AttachmentPoint)attachmentObject.AttachmentPoint).ToString(),
|
((AttachmentPoint)attachmentObject.AttachmentPoint),
|
||||||
attachmentObject.RootPart.AttachedPos.ToString()
|
attachmentObject.RootPart.AttachedPos);
|
||||||
}));
|
|
||||||
// }
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -286,7 +286,7 @@ public override void SetShapeCollisionMargin(BulletShape shape, float margin)
|
||||||
{
|
{
|
||||||
BulletShapeUnman shapeu = shape as BulletShapeUnman;
|
BulletShapeUnman shapeu = shape as BulletShapeUnman;
|
||||||
if (shapeu != null && shapeu.HasPhysicalShape)
|
if (shapeu != null && shapeu.HasPhysicalShape)
|
||||||
BSAPICPP.SetShapeCollisionMargin2(shapeu.ptr, margin);
|
BSAPICPP.SetShapeCollisionMargin(shapeu.ptr, margin);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override BulletShape BuildCapsuleShape(BulletWorld world, float radius, float height, Vector3 scale)
|
public override BulletShape BuildCapsuleShape(BulletWorld world, float radius, float height, Vector3 scale)
|
||||||
|
@ -1420,7 +1420,7 @@ public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData)
|
||||||
public static extern bool IsNativeShape2(IntPtr shape);
|
public static extern bool IsNativeShape2(IntPtr shape);
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern void SetShapeCollisionMargin2(IntPtr shape, float margin);
|
public static extern void SetShapeCollisionMargin(IntPtr shape, float margin);
|
||||||
|
|
||||||
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity]
|
||||||
public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float height, Vector3 scale);
|
public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float height, Vector3 scale);
|
||||||
|
|
|
@ -1201,8 +1201,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
|
||||||
|
|
||||||
VehicleAddForce(appliedGravity);
|
VehicleAddForce(appliedGravity);
|
||||||
|
|
||||||
VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},collid={2},appliedForce={3}",
|
VDetailLog("{0}, MoveLinear,applyGravity,vehGrav={1},collid={2},fudge={3},mass={4},appliedForce={3}",
|
||||||
Prim.LocalID, m_VehicleGravity, Prim.IsColliding, appliedGravity);
|
Prim.LocalID, m_VehicleGravity,
|
||||||
|
Prim.IsColliding, BSParam.VehicleGroundGravityFudge, m_vehicleMass, appliedGravity);
|
||||||
}
|
}
|
||||||
|
|
||||||
// =======================================================================
|
// =======================================================================
|
||||||
|
|
|
@ -39,6 +39,20 @@ public static class BSParam
|
||||||
{
|
{
|
||||||
private static string LogHeader = "[BULLETSIM PARAMETERS]";
|
private static string LogHeader = "[BULLETSIM PARAMETERS]";
|
||||||
|
|
||||||
|
// Tuning notes:
|
||||||
|
// From: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=6575
|
||||||
|
// Contact points can be added even if the distance is positive. The constraint solver can deal with
|
||||||
|
// contacts with positive distances as well as negative (penetration). Contact points are discarded
|
||||||
|
// if the distance exceeds a certain threshold.
|
||||||
|
// Bullet has a contact processing threshold and a contact breaking threshold.
|
||||||
|
// If the distance is larger than the contact breaking threshold, it will be removed after one frame.
|
||||||
|
// If the distance is larger than the contact processing threshold, the constraint solver will ignore it.
|
||||||
|
|
||||||
|
// This is separate/independent from the collision margin. The collision margin increases the object a bit
|
||||||
|
// to improve collision detection performance and accuracy.
|
||||||
|
// ===================
|
||||||
|
// From:
|
||||||
|
|
||||||
// Level of Detail values kept as float because that's what the Meshmerizer wants
|
// Level of Detail values kept as float because that's what the Meshmerizer wants
|
||||||
public static float MeshLOD { get; private set; }
|
public static float MeshLOD { get; private set; }
|
||||||
public static float MeshCircularLOD { get; private set; }
|
public static float MeshCircularLOD { get; private set; }
|
||||||
|
@ -74,9 +88,11 @@ public static class BSParam
|
||||||
public static bool ShouldRemoveZeroWidthTriangles { get; private set; }
|
public static bool ShouldRemoveZeroWidthTriangles { get; private set; }
|
||||||
|
|
||||||
public static float TerrainImplementation { get; private set; }
|
public static float TerrainImplementation { get; private set; }
|
||||||
|
public static int TerrainMeshMagnification { get; private set; }
|
||||||
public static float TerrainFriction { get; private set; }
|
public static float TerrainFriction { get; private set; }
|
||||||
public static float TerrainHitFraction { get; private set; }
|
public static float TerrainHitFraction { get; private set; }
|
||||||
public static float TerrainRestitution { get; private set; }
|
public static float TerrainRestitution { get; private set; }
|
||||||
|
public static float TerrainContactProcessingThreshold { get; private set; }
|
||||||
public static float TerrainCollisionMargin { get; private set; }
|
public static float TerrainCollisionMargin { get; private set; }
|
||||||
|
|
||||||
public static float DefaultFriction { get; private set; }
|
public static float DefaultFriction { get; private set; }
|
||||||
|
@ -446,6 +462,10 @@ public static class BSParam
|
||||||
(float)BSTerrainPhys.TerrainImplementation.Mesh,
|
(float)BSTerrainPhys.TerrainImplementation.Mesh,
|
||||||
(s) => { return TerrainImplementation; },
|
(s) => { return TerrainImplementation; },
|
||||||
(s,v) => { TerrainImplementation = v; } ),
|
(s,v) => { TerrainImplementation = v; } ),
|
||||||
|
new ParameterDefn<int>("TerrainMeshMagnification", "Number of times the 256x256 heightmap is multiplied to create the terrain mesh" ,
|
||||||
|
3,
|
||||||
|
(s) => { return TerrainMeshMagnification; },
|
||||||
|
(s,v) => { TerrainMeshMagnification = v; } ),
|
||||||
new ParameterDefn<float>("TerrainFriction", "Factor to reduce movement against terrain surface" ,
|
new ParameterDefn<float>("TerrainFriction", "Factor to reduce movement against terrain surface" ,
|
||||||
0.3f,
|
0.3f,
|
||||||
(s) => { return TerrainFriction; },
|
(s) => { return TerrainFriction; },
|
||||||
|
@ -458,6 +478,10 @@ public static class BSParam
|
||||||
0f,
|
0f,
|
||||||
(s) => { return TerrainRestitution; },
|
(s) => { return TerrainRestitution; },
|
||||||
(s,v) => { TerrainRestitution = v; /* TODO: set on real terrain */ } ),
|
(s,v) => { TerrainRestitution = v; /* TODO: set on real terrain */ } ),
|
||||||
|
new ParameterDefn<float>("TerrainContactProcessingThreshold", "Distance from terrain to stop processing collisions" ,
|
||||||
|
0.0f,
|
||||||
|
(s) => { return TerrainContactProcessingThreshold; },
|
||||||
|
(s,v) => { TerrainContactProcessingThreshold = v; /* TODO: set on real terrain */ } ),
|
||||||
new ParameterDefn<float>("TerrainCollisionMargin", "Margin where collision checking starts" ,
|
new ParameterDefn<float>("TerrainCollisionMargin", "Margin where collision checking starts" ,
|
||||||
0.08f,
|
0.08f,
|
||||||
(s) => { return TerrainCollisionMargin; },
|
(s) => { return TerrainCollisionMargin; },
|
||||||
|
|
|
@ -947,9 +947,9 @@ public class BSPrim : BSPhysObject
|
||||||
ZeroMotion(true);
|
ZeroMotion(true);
|
||||||
|
|
||||||
// Set various physical properties so other object interact properly
|
// Set various physical properties so other object interact properly
|
||||||
MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false);
|
|
||||||
PhysicsScene.PE.SetFriction(PhysBody, Friction);
|
PhysicsScene.PE.SetFriction(PhysBody, Friction);
|
||||||
PhysicsScene.PE.SetRestitution(PhysBody, Restitution);
|
PhysicsScene.PE.SetRestitution(PhysBody, Restitution);
|
||||||
|
PhysicsScene.PE.SetContactProcessingThreshold(PhysBody, BSParam.ContactProcessingThreshold);
|
||||||
|
|
||||||
// Mass is zero which disables a bunch of physics stuff in Bullet
|
// Mass is zero which disables a bunch of physics stuff in Bullet
|
||||||
UpdatePhysicalMassProperties(0f, false);
|
UpdatePhysicalMassProperties(0f, false);
|
||||||
|
|
|
@ -687,7 +687,7 @@ public sealed class BSShapeCollection : IDisposable
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
PhysicsScene.Logger.ErrorFormat("{0} All mesh triangles degenerate. Prim {1} at {2} in {3}",
|
PhysicsScene.Logger.DebugFormat("{0} All mesh triangles degenerate. Prim {1} at {2} in {3}",
|
||||||
LogHeader, prim.PhysObjectName, prim.RawPosition, PhysicsScene.Name);
|
LogHeader, prim.PhysObjectName, prim.RawPosition, PhysicsScene.Name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -263,6 +263,7 @@ public sealed class BSTerrainManager : IDisposable
|
||||||
|
|
||||||
if (MegaRegionParentPhysicsScene == null)
|
if (MegaRegionParentPhysicsScene == null)
|
||||||
{
|
{
|
||||||
|
// This terrain is not part of the mega-region scheme. Create vanilla terrain.
|
||||||
BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords);
|
BSTerrainPhys newTerrainPhys = BuildPhysicalTerrain(terrainRegionBase, id, heightMap, minCoords, maxCoords);
|
||||||
m_terrains.Add(terrainRegionBase, newTerrainPhys);
|
m_terrains.Add(terrainRegionBase, newTerrainPhys);
|
||||||
|
|
||||||
|
|
|
@ -76,11 +76,26 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
||||||
m_sizeX = (int)(maxCoords.X - minCoords.X);
|
m_sizeX = (int)(maxCoords.X - minCoords.X);
|
||||||
m_sizeY = (int)(maxCoords.Y - minCoords.Y);
|
m_sizeY = (int)(maxCoords.Y - minCoords.Y);
|
||||||
|
|
||||||
if (!BSTerrainMesh.ConvertHeightmapToMesh(PhysicsScene, initialMap,
|
bool meshCreationSuccess = false;
|
||||||
m_sizeX, m_sizeY,
|
if (BSParam.TerrainMeshMagnification == 1)
|
||||||
(float)m_sizeX, (float)m_sizeY,
|
{
|
||||||
Vector3.Zero, 1.0f,
|
// If a magnification of one, use the old routine that is tried and true.
|
||||||
out indicesCount, out indices, out verticesCount, out vertices))
|
meshCreationSuccess = BSTerrainMesh.ConvertHeightmapToMesh(PhysicsScene,
|
||||||
|
initialMap, m_sizeX, m_sizeY, // input size
|
||||||
|
Vector3.Zero, // base for mesh
|
||||||
|
out indicesCount, out indices, out verticesCount, out vertices);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Other magnifications use the newer routine
|
||||||
|
meshCreationSuccess = BSTerrainMesh.ConvertHeightmapToMesh2(PhysicsScene,
|
||||||
|
initialMap, m_sizeX, m_sizeY, // input size
|
||||||
|
BSParam.TerrainMeshMagnification,
|
||||||
|
physicsScene.TerrainManager.DefaultRegionSize,
|
||||||
|
Vector3.Zero, // base for mesh
|
||||||
|
out indicesCount, out indices, out verticesCount, out vertices);
|
||||||
|
}
|
||||||
|
if (!meshCreationSuccess)
|
||||||
{
|
{
|
||||||
// DISASTER!!
|
// DISASTER!!
|
||||||
PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap", ID);
|
PhysicsScene.DetailLog("{0},BSTerrainMesh.create,failedConversionOfHeightmap", ID);
|
||||||
|
@ -88,6 +103,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
||||||
// Something is very messed up and a crash is in our future.
|
// Something is very messed up and a crash is in our future.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicsScene.DetailLog("{0},BSTerrainMesh.create,meshed,indices={1},indSz={2},vertices={3},vertSz={4}",
|
PhysicsScene.DetailLog("{0},BSTerrainMesh.create,meshed,indices={1},indSz={2},vertices={3},vertSz={4}",
|
||||||
ID, indicesCount, indices.Length, verticesCount, vertices.Length);
|
ID, indicesCount, indices.Length, verticesCount, vertices.Length);
|
||||||
|
|
||||||
|
@ -112,11 +128,13 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
||||||
// Something is very messed up and a crash is in our future.
|
// Something is very messed up and a crash is in our future.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
physicsScene.PE.SetShapeCollisionMargin(m_terrainShape, BSParam.TerrainCollisionMargin);
|
||||||
|
|
||||||
// Set current terrain attributes
|
// Set current terrain attributes
|
||||||
PhysicsScene.PE.SetFriction(m_terrainBody, BSParam.TerrainFriction);
|
PhysicsScene.PE.SetFriction(m_terrainBody, BSParam.TerrainFriction);
|
||||||
PhysicsScene.PE.SetHitFraction(m_terrainBody, BSParam.TerrainHitFraction);
|
PhysicsScene.PE.SetHitFraction(m_terrainBody, BSParam.TerrainHitFraction);
|
||||||
PhysicsScene.PE.SetRestitution(m_terrainBody, BSParam.TerrainRestitution);
|
PhysicsScene.PE.SetRestitution(m_terrainBody, BSParam.TerrainRestitution);
|
||||||
|
PhysicsScene.PE.SetContactProcessingThreshold(m_terrainBody, BSParam.TerrainContactProcessingThreshold);
|
||||||
PhysicsScene.PE.SetCollisionFlags(m_terrainBody, CollisionFlags.CF_STATIC_OBJECT);
|
PhysicsScene.PE.SetCollisionFlags(m_terrainBody, CollisionFlags.CF_STATIC_OBJECT);
|
||||||
|
|
||||||
// Static objects are not very massive.
|
// Static objects are not very massive.
|
||||||
|
@ -184,9 +202,7 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
||||||
// Return 'true' if successfully created.
|
// Return 'true' if successfully created.
|
||||||
public static bool ConvertHeightmapToMesh( BSScene physicsScene,
|
public static bool ConvertHeightmapToMesh( BSScene physicsScene,
|
||||||
float[] heightMap, int sizeX, int sizeY, // parameters of incoming heightmap
|
float[] heightMap, int sizeX, int sizeY, // parameters of incoming heightmap
|
||||||
float extentX, float extentY, // zero based range for output vertices
|
|
||||||
Vector3 extentBase, // base to be added to all vertices
|
Vector3 extentBase, // base to be added to all vertices
|
||||||
float magnification, // number of vertices to create between heightMap coords
|
|
||||||
out int indicesCountO, out int[] indicesO,
|
out int indicesCountO, out int[] indicesO,
|
||||||
out int verticesCountO, out float[] verticesO)
|
out int verticesCountO, out float[] verticesO)
|
||||||
{
|
{
|
||||||
|
@ -207,17 +223,15 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
||||||
// of the heightmap.
|
// of the heightmap.
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// One vertice per heightmap value plus the vertices off the top and bottom edge.
|
// One vertice per heightmap value plus the vertices off the side and bottom edge.
|
||||||
int totalVertices = (sizeX + 1) * (sizeY + 1);
|
int totalVertices = (sizeX + 1) * (sizeY + 1);
|
||||||
vertices = new float[totalVertices * 3];
|
vertices = new float[totalVertices * 3];
|
||||||
int totalIndices = sizeX * sizeY * 6;
|
int totalIndices = sizeX * sizeY * 6;
|
||||||
indices = new int[totalIndices];
|
indices = new int[totalIndices];
|
||||||
|
|
||||||
float magX = (float)sizeX / extentX;
|
|
||||||
float magY = (float)sizeY / extentY;
|
|
||||||
if (physicsScene != null)
|
if (physicsScene != null)
|
||||||
physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2},extentBase={3},magX={4},magY={5}",
|
physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh,totVert={1},totInd={2},extentBase={3}",
|
||||||
BSScene.DetailLogZero, totalVertices, totalIndices, extentBase, magX, magY);
|
BSScene.DetailLogZero, totalVertices, totalIndices, extentBase);
|
||||||
float minHeight = float.MaxValue;
|
float minHeight = float.MaxValue;
|
||||||
// Note that sizeX+1 vertices are created since there is land between this and the next region.
|
// Note that sizeX+1 vertices are created since there is land between this and the next region.
|
||||||
for (int yy = 0; yy <= sizeY; yy++)
|
for (int yy = 0; yy <= sizeY; yy++)
|
||||||
|
@ -230,8 +244,8 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
||||||
if (xx == sizeX) offset -= 1;
|
if (xx == sizeX) offset -= 1;
|
||||||
float height = heightMap[offset];
|
float height = heightMap[offset];
|
||||||
minHeight = Math.Min(minHeight, height);
|
minHeight = Math.Min(minHeight, height);
|
||||||
vertices[verticesCount + 0] = (float)xx * magX + extentBase.X;
|
vertices[verticesCount + 0] = (float)xx + extentBase.X;
|
||||||
vertices[verticesCount + 1] = (float)yy * magY + extentBase.Y;
|
vertices[verticesCount + 1] = (float)yy + extentBase.Y;
|
||||||
vertices[verticesCount + 2] = height + extentBase.Z;
|
vertices[verticesCount + 2] = height + extentBase.Z;
|
||||||
verticesCount += 3;
|
verticesCount += 3;
|
||||||
}
|
}
|
||||||
|
@ -270,5 +284,158 @@ public sealed class BSTerrainMesh : BSTerrainPhys
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class HeightMapGetter
|
||||||
|
{
|
||||||
|
private float[] m_heightMap;
|
||||||
|
private int m_sizeX;
|
||||||
|
private int m_sizeY;
|
||||||
|
public HeightMapGetter(float[] pHeightMap, int pSizeX, int pSizeY)
|
||||||
|
{
|
||||||
|
m_heightMap = pHeightMap;
|
||||||
|
m_sizeX = pSizeX;
|
||||||
|
m_sizeY = pSizeY;
|
||||||
|
}
|
||||||
|
// The heightmap is extended as an infinite plane at the last height
|
||||||
|
public float GetHeight(int xx, int yy)
|
||||||
|
{
|
||||||
|
int offset = 0;
|
||||||
|
// Extend the height with the height from the last row or column
|
||||||
|
if (yy >= m_sizeY)
|
||||||
|
if (xx >= m_sizeX)
|
||||||
|
offset = (m_sizeY - 1) * m_sizeX + (m_sizeX - 1);
|
||||||
|
else
|
||||||
|
offset = (m_sizeY - 1) * m_sizeX + xx;
|
||||||
|
else
|
||||||
|
if (xx >= m_sizeX)
|
||||||
|
offset = yy * m_sizeX + (m_sizeX - 1);
|
||||||
|
else
|
||||||
|
offset = yy * m_sizeX + xx;
|
||||||
|
|
||||||
|
return m_heightMap[offset];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convert the passed heightmap to mesh information suitable for CreateMeshShape2().
|
||||||
|
// Version that handles magnification.
|
||||||
|
// Return 'true' if successfully created.
|
||||||
|
public static bool ConvertHeightmapToMesh2( BSScene physicsScene,
|
||||||
|
float[] heightMap, int sizeX, int sizeY, // parameters of incoming heightmap
|
||||||
|
int magnification, // number of vertices per heighmap step
|
||||||
|
Vector3 extent, // dimensions of the output mesh
|
||||||
|
Vector3 extentBase, // base to be added to all vertices
|
||||||
|
out int indicesCountO, out int[] indicesO,
|
||||||
|
out int verticesCountO, out float[] verticesO)
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
int indicesCount = 0;
|
||||||
|
int verticesCount = 0;
|
||||||
|
int[] indices = new int[0];
|
||||||
|
float[] vertices = new float[0];
|
||||||
|
|
||||||
|
HeightMapGetter hmap = new HeightMapGetter(heightMap, sizeX, sizeY);
|
||||||
|
|
||||||
|
// The vertices dimension of the output mesh
|
||||||
|
int meshX = sizeX * magnification;
|
||||||
|
int meshY = sizeY * magnification;
|
||||||
|
// The output size of one mesh step
|
||||||
|
float meshXStep = extent.X / meshX;
|
||||||
|
float meshYStep = extent.Y / meshY;
|
||||||
|
|
||||||
|
// Create an array of vertices that is meshX+1 by meshY+1 (note the loop
|
||||||
|
// from zero to <= meshX). The triangle indices are then generated as two triangles
|
||||||
|
// per heightmap point. There are meshX by meshY of these squares. The extra row and
|
||||||
|
// column of vertices are used to complete the triangles of the last row and column
|
||||||
|
// of the heightmap.
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Vertices for the output heightmap plus one on the side and bottom to complete triangles
|
||||||
|
int totalVertices = (meshX + 1) * (meshY + 1);
|
||||||
|
vertices = new float[totalVertices * 3];
|
||||||
|
int totalIndices = meshX * meshY * 6;
|
||||||
|
indices = new int[totalIndices];
|
||||||
|
|
||||||
|
if (physicsScene != null)
|
||||||
|
physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh2,inSize={1},outSize={2},totVert={3},totInd={4},extentBase={5}",
|
||||||
|
BSScene.DetailLogZero, new Vector2(sizeX, sizeY), new Vector2(meshX, meshY),
|
||||||
|
totalVertices, totalIndices, extentBase);
|
||||||
|
|
||||||
|
float minHeight = float.MaxValue;
|
||||||
|
// Note that sizeX+1 vertices are created since there is land between this and the next region.
|
||||||
|
// Loop through the output vertices and compute the mediun height in between the input vertices
|
||||||
|
for (int yy = 0; yy <= meshY; yy++)
|
||||||
|
{
|
||||||
|
for (int xx = 0; xx <= meshX; xx++) // Hint: the "<=" means we go around sizeX + 1 times
|
||||||
|
{
|
||||||
|
float offsetY = (float)yy * (float)sizeY / (float)meshY; // The Y that is closest to the mesh point
|
||||||
|
int stepY = (int)offsetY;
|
||||||
|
float fractionalY = offsetY - (float)stepY;
|
||||||
|
float offsetX = (float)xx * (float)sizeX / (float)meshX; // The X that is closest to the mesh point
|
||||||
|
int stepX = (int)offsetX;
|
||||||
|
float fractionalX = offsetX - (float)stepX;
|
||||||
|
|
||||||
|
// physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh2,xx={1},yy={2},offX={3},stepX={4},fractX={5},offY={6},stepY={7},fractY={8}",
|
||||||
|
// BSScene.DetailLogZero, xx, yy, offsetX, stepX, fractionalX, offsetY, stepY, fractionalY);
|
||||||
|
|
||||||
|
// get the four corners of the heightmap square the mesh point is in
|
||||||
|
float heightUL = hmap.GetHeight(stepX , stepY );
|
||||||
|
float heightUR = hmap.GetHeight(stepX + 1, stepY );
|
||||||
|
float heightLL = hmap.GetHeight(stepX , stepY + 1);
|
||||||
|
float heightLR = hmap.GetHeight(stepX + 1, stepY + 1);
|
||||||
|
|
||||||
|
// bilinear interplolation
|
||||||
|
float height = heightUL * (1 - fractionalX) * (1 - fractionalY)
|
||||||
|
+ heightUR * fractionalX * (1 - fractionalY)
|
||||||
|
+ heightLL * (1 - fractionalX) * fractionalY
|
||||||
|
+ heightLR * fractionalX * fractionalY;
|
||||||
|
|
||||||
|
// physicsScene.DetailLog("{0},BSTerrainMesh.ConvertHeightMapToMesh2,heightUL={1},heightUR={2},heightLL={3},heightLR={4},heightMap={5}",
|
||||||
|
// BSScene.DetailLogZero, heightUL, heightUR, heightLL, heightLR, height);
|
||||||
|
|
||||||
|
minHeight = Math.Min(minHeight, height);
|
||||||
|
|
||||||
|
vertices[verticesCount + 0] = (float)xx * meshXStep + extentBase.X;
|
||||||
|
vertices[verticesCount + 1] = (float)yy * meshYStep + extentBase.Y;
|
||||||
|
vertices[verticesCount + 2] = height + extentBase.Z;
|
||||||
|
verticesCount += 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// The number of vertices generated
|
||||||
|
verticesCount /= 3;
|
||||||
|
|
||||||
|
// Loop through all the heightmap squares and create indices for the two triangles for that square
|
||||||
|
for (int yy = 0; yy < meshY; yy++)
|
||||||
|
{
|
||||||
|
for (int xx = 0; xx < meshX; xx++)
|
||||||
|
{
|
||||||
|
int offset = yy * (meshX + 1) + xx;
|
||||||
|
// Each vertices is presumed to be the upper left corner of a box of two triangles
|
||||||
|
indices[indicesCount + 0] = offset;
|
||||||
|
indices[indicesCount + 1] = offset + 1;
|
||||||
|
indices[indicesCount + 2] = offset + meshX + 1; // accounting for the extra column
|
||||||
|
indices[indicesCount + 3] = offset + 1;
|
||||||
|
indices[indicesCount + 4] = offset + meshX + 2;
|
||||||
|
indices[indicesCount + 5] = offset + meshX + 1;
|
||||||
|
indicesCount += 6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
if (physicsScene != null)
|
||||||
|
physicsScene.Logger.ErrorFormat("{0} Failed conversion of heightmap to mesh. For={1}/{2}, e={3}",
|
||||||
|
LogHeader, physicsScene.RegionName, extentBase, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
indicesCountO = indicesCount;
|
||||||
|
indicesO = indices;
|
||||||
|
verticesCountO = verticesCount;
|
||||||
|
verticesO = vertices;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,91 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) Contributors, http://opensimulator.org/
|
||||||
|
* See CONTRIBUTORS.TXT for a full list of copyright holders.
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions are met:
|
||||||
|
* * Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* * Redistributions in binary form must reproduce the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer in the
|
||||||
|
* documentation and/or other materials provided with the distribution.
|
||||||
|
* * Neither the name of the OpenSimulator Project nor the
|
||||||
|
* names of its contributors may be used to endorse or promote products
|
||||||
|
* derived from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
|
||||||
|
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
|
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
|
||||||
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
|
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
|
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
|
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
|
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Text;
|
||||||
|
using log4net;
|
||||||
|
using Nini.Config;
|
||||||
|
using NUnit.Framework;
|
||||||
|
using OpenMetaverse;
|
||||||
|
using OpenSim.Framework;
|
||||||
|
using OpenSim.Framework.Communications;
|
||||||
|
using OpenSim.Framework.Servers;
|
||||||
|
using OpenSim.Region.Framework.Interfaces;
|
||||||
|
using OpenSim.Region.Framework.Scenes;
|
||||||
|
using OpenSim.Region.CoreModules.Framework;
|
||||||
|
using OpenSim.Tests.Common;
|
||||||
|
using OpenSim.Tests.Common.Mock;
|
||||||
|
|
||||||
|
namespace OpenSim.Tests.Common
|
||||||
|
{
|
||||||
|
public static class EntityTransferHelpers
|
||||||
|
{
|
||||||
|
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set up correct handling of the InformClientOfNeighbour call from the source region that triggers the
|
||||||
|
/// viewer to setup a connection with the destination region.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name='tc'></param>
|
||||||
|
/// <param name='neighbourTcs'>
|
||||||
|
/// A list that will be populated with any TestClients set up in response to
|
||||||
|
/// being informed about a destination region.
|
||||||
|
/// </param>
|
||||||
|
public static void SetUpInformClientOfNeighbour(TestClient tc, List<TestClient> neighbourTcs)
|
||||||
|
{
|
||||||
|
// XXX: Confusingly, this is also used for non-neighbour notification (as in teleports that do not use the
|
||||||
|
// event queue).
|
||||||
|
|
||||||
|
tc.OnTestClientInformClientOfNeighbour += (neighbourHandle, neighbourExternalEndPoint) =>
|
||||||
|
{
|
||||||
|
uint x, y;
|
||||||
|
Utils.LongToUInts(neighbourHandle, out x, out y);
|
||||||
|
x /= Constants.RegionSize;
|
||||||
|
y /= Constants.RegionSize;
|
||||||
|
|
||||||
|
m_log.DebugFormat(
|
||||||
|
"[TEST CLIENT]: Processing inform client of neighbour located at {0},{1} at {2}",
|
||||||
|
x, y, neighbourExternalEndPoint);
|
||||||
|
|
||||||
|
// In response to this message, we are going to make a teleport to the scene we've previous been told
|
||||||
|
// about by test code (this needs to be improved).
|
||||||
|
AgentCircuitData newAgent = tc.RequestClientInfo();
|
||||||
|
|
||||||
|
Scene neighbourScene;
|
||||||
|
SceneManager.Instance.TryGetScene(x, y, out neighbourScene);
|
||||||
|
|
||||||
|
TestClient neighbourTc = new TestClient(newAgent, neighbourScene, SceneManager.Instance);
|
||||||
|
neighbourTcs.Add(neighbourTc);
|
||||||
|
neighbourScene.AddNewClient(neighbourTc, PresenceType.User);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -531,6 +531,31 @@ namespace OpenSim.Tests.Common
|
||||||
/// <param name="sceneManager"></param>
|
/// <param name="sceneManager"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static ScenePresence AddScenePresence(Scene scene, AgentCircuitData agentData, SceneManager sceneManager)
|
public static ScenePresence AddScenePresence(Scene scene, AgentCircuitData agentData, SceneManager sceneManager)
|
||||||
|
{
|
||||||
|
return AddScenePresence(scene, new TestClient(agentData, scene, sceneManager), agentData, sceneManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a root agent.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// This function
|
||||||
|
///
|
||||||
|
/// 1) Tells the scene that an agent is coming. Normally, the login service (local if standalone, from the
|
||||||
|
/// userserver if grid) would give initial login data back to the client and separately tell the scene that the
|
||||||
|
/// agent was coming.
|
||||||
|
///
|
||||||
|
/// 2) Connects the agent with the scene
|
||||||
|
///
|
||||||
|
/// This function performs actions equivalent with notifying the scene that an agent is
|
||||||
|
/// coming and then actually connecting the agent to the scene. The one step missed out is the very first
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="scene"></param>
|
||||||
|
/// <param name="agentData"></param>
|
||||||
|
/// <param name="sceneManager"></param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static ScenePresence AddScenePresence(
|
||||||
|
Scene scene, IClientAPI client, AgentCircuitData agentData, SceneManager sceneManager)
|
||||||
{
|
{
|
||||||
// We emulate the proper login sequence here by doing things in four stages
|
// We emulate the proper login sequence here by doing things in four stages
|
||||||
|
|
||||||
|
@ -541,7 +566,7 @@ namespace OpenSim.Tests.Common
|
||||||
lpsc.m_PresenceService.LoginAgent(agentData.AgentID.ToString(), agentData.SessionID, agentData.SecureSessionID);
|
lpsc.m_PresenceService.LoginAgent(agentData.AgentID.ToString(), agentData.SessionID, agentData.SecureSessionID);
|
||||||
|
|
||||||
// Stages 1 & 2
|
// Stages 1 & 2
|
||||||
ScenePresence sp = IntroduceClientToScene(scene, sceneManager, agentData, TeleportFlags.ViaLogin);
|
ScenePresence sp = IntroduceClientToScene(scene, client, agentData, TeleportFlags.ViaLogin);
|
||||||
|
|
||||||
// Stage 3: Complete the entrance into the region. This converts the child agent into a root agent.
|
// Stage 3: Complete the entrance into the region. This converts the child agent into a root agent.
|
||||||
sp.CompleteMovement(sp.ControllingClient, true);
|
sp.CompleteMovement(sp.ControllingClient, true);
|
||||||
|
@ -558,11 +583,11 @@ namespace OpenSim.Tests.Common
|
||||||
/// neighbours and where no teleporting takes place.
|
/// neighbours and where no teleporting takes place.
|
||||||
/// </param>
|
/// </param>
|
||||||
/// <param name='scene'></param>
|
/// <param name='scene'></param>
|
||||||
/// <param name='sceneManager></param>
|
/// <param name='testClient'></param>
|
||||||
/// <param name='agentData'></param>
|
/// <param name='agentData'></param>
|
||||||
/// <param name='tf'></param>
|
/// <param name='tf'></param>
|
||||||
private static ScenePresence IntroduceClientToScene(
|
private static ScenePresence IntroduceClientToScene(
|
||||||
Scene scene, SceneManager sceneManager, AgentCircuitData agentData, TeleportFlags tf)
|
Scene scene, IClientAPI client, AgentCircuitData agentData, TeleportFlags tf)
|
||||||
{
|
{
|
||||||
string reason;
|
string reason;
|
||||||
|
|
||||||
|
@ -571,10 +596,9 @@ namespace OpenSim.Tests.Common
|
||||||
Console.WriteLine("NewUserConnection failed: " + reason);
|
Console.WriteLine("NewUserConnection failed: " + reason);
|
||||||
|
|
||||||
// Stage 2: add the new client as a child agent to the scene
|
// Stage 2: add the new client as a child agent to the scene
|
||||||
TestClient client = new TestClient(agentData, scene, sceneManager);
|
|
||||||
scene.AddNewClient(client, PresenceType.User);
|
scene.AddNewClient(client, PresenceType.User);
|
||||||
|
|
||||||
return scene.GetScenePresence(agentData.AgentID);
|
return scene.GetScenePresence(client.AgentId);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ScenePresence AddChildScenePresence(Scene scene, UUID agentId)
|
public static ScenePresence AddChildScenePresence(Scene scene, UUID agentId)
|
||||||
|
@ -583,7 +607,8 @@ namespace OpenSim.Tests.Common
|
||||||
acd.child = true;
|
acd.child = true;
|
||||||
|
|
||||||
// XXX: ViaLogin may not be correct for child agents
|
// XXX: ViaLogin may not be correct for child agents
|
||||||
return IntroduceClientToScene(scene, null, acd, TeleportFlags.ViaLogin);
|
TestClient client = new TestClient(acd, scene, null);
|
||||||
|
return IntroduceClientToScene(scene, client, acd, TeleportFlags.ViaLogin);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -46,8 +46,6 @@ namespace OpenSim.Tests.Common.Mock
|
||||||
|
|
||||||
EventWaitHandle wh = new EventWaitHandle (false, EventResetMode.AutoReset, "Crossing");
|
EventWaitHandle wh = new EventWaitHandle (false, EventResetMode.AutoReset, "Crossing");
|
||||||
|
|
||||||
private TestClient TeleportSceneClient;
|
|
||||||
|
|
||||||
private Scene m_scene;
|
private Scene m_scene;
|
||||||
private SceneManager m_sceneManager;
|
private SceneManager m_sceneManager;
|
||||||
|
|
||||||
|
@ -60,7 +58,9 @@ namespace OpenSim.Tests.Common.Mock
|
||||||
public List<ImagePacketPacket> SentImagePacketPackets { get; private set; }
|
public List<ImagePacketPacket> SentImagePacketPackets { get; private set; }
|
||||||
public List<ImageNotInDatabasePacket> SentImageNotInDatabasePackets { get; private set; }
|
public List<ImageNotInDatabasePacket> SentImageNotInDatabasePackets { get; private set; }
|
||||||
|
|
||||||
|
// Test client specific events - for use by tests to implement some IClientAPI behaviour.
|
||||||
public event Action<RegionInfo, Vector3, Vector3> OnReceivedMoveAgentIntoRegion;
|
public event Action<RegionInfo, Vector3, Vector3> OnReceivedMoveAgentIntoRegion;
|
||||||
|
public event Action<ulong, IPEndPoint> OnTestClientInformClientOfNeighbour;
|
||||||
|
|
||||||
// disable warning: public events, part of the public API
|
// disable warning: public events, part of the public API
|
||||||
#pragma warning disable 67
|
#pragma warning disable 67
|
||||||
|
@ -604,23 +604,8 @@ namespace OpenSim.Tests.Common.Mock
|
||||||
|
|
||||||
public virtual void InformClientOfNeighbour(ulong neighbourHandle, IPEndPoint neighbourExternalEndPoint)
|
public virtual void InformClientOfNeighbour(ulong neighbourHandle, IPEndPoint neighbourExternalEndPoint)
|
||||||
{
|
{
|
||||||
m_log.DebugFormat("[TEST CLIENT]: Processing inform client of neighbour");
|
if (OnTestClientInformClientOfNeighbour != null)
|
||||||
|
OnTestClientInformClientOfNeighbour(neighbourHandle, neighbourExternalEndPoint);
|
||||||
// In response to this message, we are going to make a teleport to the scene we've previous been told
|
|
||||||
// about by test code (this needs to be improved).
|
|
||||||
AgentCircuitData newAgent = RequestClientInfo();
|
|
||||||
|
|
||||||
// Stage 2: add the new client as a child agent to the scene
|
|
||||||
uint x, y;
|
|
||||||
Utils.LongToUInts(neighbourHandle, out x, out y);
|
|
||||||
x /= Constants.RegionSize;
|
|
||||||
y /= Constants.RegionSize;
|
|
||||||
|
|
||||||
Scene neighbourScene;
|
|
||||||
m_sceneManager.TryGetScene(x, y, out neighbourScene);
|
|
||||||
|
|
||||||
TeleportSceneClient = new TestClient(newAgent, neighbourScene, m_sceneManager);
|
|
||||||
neighbourScene.AddNewClient(TeleportSceneClient, PresenceType.User);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual void SendRegionTeleport(ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint,
|
public virtual void SendRegionTeleport(ulong regionHandle, byte simAccess, IPEndPoint regionExternalEndPoint,
|
||||||
|
@ -635,12 +620,6 @@ namespace OpenSim.Tests.Common.Mock
|
||||||
// CompleteTeleportClientSide();
|
// CompleteTeleportClientSide();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void CompleteTeleportClientSide()
|
|
||||||
{
|
|
||||||
TeleportSceneClient.CompleteMovement();
|
|
||||||
//TeleportTargetScene.AgentCrossing(newAgent.AgentID, new Vector3(90, 90, 90), false);
|
|
||||||
}
|
|
||||||
|
|
||||||
public virtual void SendTeleportFailed(string reason)
|
public virtual void SendTeleportFailed(string reason)
|
||||||
{
|
{
|
||||||
m_log.DebugFormat("[TEST CLIENT]: Teleport failed with reason {0}", reason);
|
m_log.DebugFormat("[TEST CLIENT]: Teleport failed with reason {0}", reason);
|
||||||
|
|
Loading…
Reference in New Issue