mirror of
https://github.com/RaindropViewer/RaindropViewer.git
synced 2026-07-27 22:11:39 +00:00
Manual migrate LMV to LMV_1.9.18.429
- added dlls: OggVorbisEncoder.dll, OpenJpegDotNet.dll
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* Copyright (c) 2019-2022, Sjofn LLC
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
@@ -1047,7 +1048,7 @@ namespace OpenMetaverse
|
||||
remove { lock (m_GroupChatJoinedLock) { m_GroupChatJoined -= value; } }
|
||||
}
|
||||
|
||||
/// <summary>The event subscribers. null if no subcribers</summary>
|
||||
/// <summary>The event subscribers. null if no subscribers</summary>
|
||||
private EventHandler<AlertMessageEventArgs> m_AlertMessage;
|
||||
|
||||
/// <summary>Raises the AlertMessage event</summary>
|
||||
@@ -1270,24 +1271,24 @@ namespace OpenMetaverse
|
||||
|
||||
/// <summary>Your (client) avatars <see cref="UUID"/></summary>
|
||||
/// <remarks>"client", "agent", and "avatar" all represent the same thing</remarks>
|
||||
public UUID AgentID => id;
|
||||
public UUID AgentID { get; private set; }
|
||||
|
||||
/// <summary>Temporary <seealso cref="UUID"/> assigned to this session, used for
|
||||
/// verifying our identity in packets</summary>
|
||||
public UUID SessionID => sessionID;
|
||||
public UUID SessionID { get; private set; }
|
||||
|
||||
/// <summary>Shared secret <seealso cref="UUID"/> that is never sent over the wire</summary>
|
||||
public UUID SecureSessionID => secureSessionID;
|
||||
public UUID SecureSessionID { get; private set; }
|
||||
|
||||
/// <summary>Your (client) avatar ID, local to the current region/sim</summary>
|
||||
public uint LocalID => localID;
|
||||
|
||||
/// <summary>Where the avatar started at login. Can be "last", "home"
|
||||
/// or a login <seealso cref="T:OpenMetaverse.URI"/></summary>
|
||||
public string StartLocation => startLocation;
|
||||
public string StartLocation { get; private set; } = string.Empty;
|
||||
|
||||
/// <summary>The access level of this agent, usually M, PG or A</summary>
|
||||
public string AgentAccess => agentAccess;
|
||||
public string AgentAccess { get; private set; } = string.Empty;
|
||||
|
||||
/// <summary>The CollisionPlane of Agent</summary>
|
||||
public Vector4 CollisionPlane => collisionPlane;
|
||||
@@ -1301,21 +1302,24 @@ namespace OpenMetaverse
|
||||
/// <summary>A <seealso cref="Vector3"/> which specifies the angular speed, and axis about which an Avatar is rotating.</summary>
|
||||
public Vector3 AngularVelocity => angularVelocity;
|
||||
|
||||
/// <summary>Region handle for 'home' region</summary>
|
||||
public ulong HomeRegionHandle => home.RegionHandle;
|
||||
|
||||
/// <summary>Position avatar client will goto when login to 'home' or during
|
||||
/// teleport request to 'home' region.</summary>
|
||||
public Vector3 HomePosition => homePosition;
|
||||
public Vector3 HomePosition => home.Position;
|
||||
|
||||
/// <summary>LookAt point saved/restored with HomePosition</summary>
|
||||
public Vector3 HomeLookAt => homeLookAt;
|
||||
public Vector3 HomeLookAt => home.LookAt;
|
||||
|
||||
/// <summary>Avatar First Name (i.e. Philip)</summary>
|
||||
public string FirstName => firstName;
|
||||
public string FirstName { get; private set; } = string.Empty;
|
||||
|
||||
/// <summary>Avatar Last Name (i.e. Linden)</summary>
|
||||
public string LastName => lastName;
|
||||
public string LastName { get; private set; } = string.Empty;
|
||||
|
||||
/// <summary>LookAt point received with the login response message</summary>
|
||||
public Vector3 LookAt => lookAt;
|
||||
public Vector3 LookAt { get; private set; }
|
||||
|
||||
/// <summary>Avatar Full Name (i.e. Philip Linden)</summary>
|
||||
public string Name
|
||||
@@ -1325,28 +1329,28 @@ namespace OpenMetaverse
|
||||
// This is a fairly common request, so assume the name doesn't
|
||||
// change mid-session and cache the result
|
||||
if (fullName == null || fullName.Length < 2)
|
||||
fullName = $"{firstName} {lastName}";
|
||||
fullName = $"{FirstName} {LastName}";
|
||||
return fullName;
|
||||
}
|
||||
}
|
||||
/// <summary>Gets the health of the agent</summary>
|
||||
public float Health => health;
|
||||
public float Health { get; private set; }
|
||||
|
||||
/// <summary>Gets the current balance of the agent</summary>
|
||||
public int Balance => balance;
|
||||
public int Balance { get; private set; }
|
||||
|
||||
/// <summary>Gets the local ID of the prim the agent is sitting on,
|
||||
/// zero if the avatar is not currently sitting</summary>
|
||||
public uint SittingOn => sittingOn;
|
||||
|
||||
/// <summary>Gets the <seealso cref="UUID"/> of the agents active group.</summary>
|
||||
public UUID ActiveGroup => activeGroup;
|
||||
public UUID ActiveGroup { get; private set; }
|
||||
|
||||
/// <summary>Gets the Agents powers in the currently active group</summary>
|
||||
public GroupPowers ActiveGroupPowers => activeGroupPowers;
|
||||
public GroupPowers ActiveGroupPowers { get; private set; }
|
||||
|
||||
/// <summary>Current status message for teleporting</summary>
|
||||
public string TeleportMessage => teleportMessage;
|
||||
public string TeleportMessage { get; private set; } = string.Empty;
|
||||
|
||||
/// <summary>Current position of the agent as a relative offset from
|
||||
/// the simulator, or the parent object if we are sitting on something</summary>
|
||||
@@ -1466,25 +1470,11 @@ namespace OpenMetaverse
|
||||
|
||||
#region Private Members
|
||||
|
||||
private UUID id;
|
||||
private UUID sessionID;
|
||||
private UUID secureSessionID;
|
||||
private string startLocation = string.Empty;
|
||||
private string agentAccess = string.Empty;
|
||||
private Vector3 homePosition;
|
||||
private Vector3 homeLookAt;
|
||||
private Vector3 lookAt;
|
||||
private string firstName = string.Empty;
|
||||
private string lastName = string.Empty;
|
||||
private HomeInfo home;
|
||||
private string fullName;
|
||||
private string teleportMessage = string.Empty;
|
||||
private TeleportStatus teleportStat = TeleportStatus.None;
|
||||
private ManualResetEvent teleportEvent = new ManualResetEvent(false);
|
||||
private uint heightWidthGenCounter;
|
||||
private float health;
|
||||
private int balance;
|
||||
private UUID activeGroup;
|
||||
private GroupPowers activeGroupPowers;
|
||||
private Dictionary<UUID, AssetGesture> gestureCache = new Dictionary<UUID, AssetGesture>();
|
||||
#endregion Private Members
|
||||
|
||||
@@ -1549,6 +1539,7 @@ namespace OpenMetaverse
|
||||
Client.Network.RegisterLoginResponseCallback(Network_OnLoginResponse);
|
||||
// Alert Messages
|
||||
Client.Network.RegisterCallback(PacketType.AlertMessage, AlertMessageHandler);
|
||||
Client.Network.RegisterCallback(PacketType.AgentAlertMessage, AgentAlertMessageHandler);
|
||||
// script control change messages, ie: when an in-world LSL script wants to take control of your agent.
|
||||
Client.Network.RegisterCallback(PacketType.ScriptControlChange, ScriptControlChangeHandler);
|
||||
// Camera Constraint (probably needs to move to AgentManagerCamera TODO:
|
||||
@@ -1578,17 +1569,17 @@ namespace OpenMetaverse
|
||||
{
|
||||
int group_id = message_chunk_group_id;
|
||||
message_chunk_group_id++;
|
||||
if (message_chunk_group_id > 500) message_chunk_group_id = 1;
|
||||
if (message_chunk_group_id > 500) { message_chunk_group_id = 1; }
|
||||
string[] chunks = message.SplitBy(900).ToArray();
|
||||
int chunkid = 1;
|
||||
foreach(string C in chunks)
|
||||
foreach(string chunk in chunks)
|
||||
{
|
||||
string chunk_grouping = "";
|
||||
if(hide_chunk_grouping == false)
|
||||
{
|
||||
chunk_grouping = "[" + group_id.ToString() + "|" + chunkid.ToString() + "|"+chunks.Length.ToString()+"]";
|
||||
chunk_grouping = $"[{group_id}|{chunkid}|{chunks.Length}]";
|
||||
}
|
||||
Chat(""+ chunk_grouping+"" + C + "", channel, type, false);
|
||||
Chat($"{chunk_grouping}{chunk}", channel, type, false);
|
||||
chunkid++;
|
||||
}
|
||||
}
|
||||
@@ -1598,7 +1589,7 @@ namespace OpenMetaverse
|
||||
{
|
||||
AgentData =
|
||||
{
|
||||
AgentID = id,
|
||||
AgentID = AgentID,
|
||||
SessionID = Client.Self.SessionID
|
||||
},
|
||||
ChatData =
|
||||
@@ -1616,6 +1607,26 @@ namespace OpenMetaverse
|
||||
/// Request any instant messages sent while the client was offline to be resent.
|
||||
/// </summary>
|
||||
public void RetrieveInstantMessages()
|
||||
{
|
||||
Uri offlineMsgsCap = Client.Network.CurrentSim.Caps.CapabilityURI("ReadOfflineMsgs");
|
||||
if (offlineMsgsCap == null
|
||||
|| Client.Network.CurrentSim.Caps.CapabilityURI("AcceptFriendship") == null
|
||||
|| Client.Network.CurrentSim.Caps.CapabilityURI("AcceptGroupInvite") == null)
|
||||
{
|
||||
// fallback to lludp
|
||||
RetrieveInstantMessagesLegacy();
|
||||
return;
|
||||
}
|
||||
|
||||
var request = new CapsClient(offlineMsgsCap);
|
||||
request.OnComplete += OfflineMessageHandlerCallback;
|
||||
request.GetRequestAsync(Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request offline instant messages via the legacy LLUDP packet
|
||||
/// </summary>
|
||||
private void RetrieveInstantMessagesLegacy()
|
||||
{
|
||||
RetrieveInstantMessagesPacket p = new RetrieveInstantMessagesPacket
|
||||
{
|
||||
@@ -1902,7 +1913,7 @@ namespace OpenMetaverse
|
||||
if (request != null)
|
||||
{
|
||||
ChatSessionAcceptInvitation acceptInvite = new ChatSessionAcceptInvitation {SessionID = session_id};
|
||||
request.BeginGetResponse(acceptInvite.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
request.PostRequestAsync(acceptInvite.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
|
||||
lock (GroupChatSessions.Dictionary)
|
||||
if (!GroupChatSessions.ContainsKey(session_id))
|
||||
@@ -1941,7 +1952,7 @@ namespace OpenMetaverse
|
||||
|
||||
startConference.SessionID = tmp_session_id;
|
||||
|
||||
request.BeginGetResponse(startConference.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
request.PostRequestAsync(startConference.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2490,8 +2501,8 @@ namespace OpenMetaverse
|
||||
/// </summary>
|
||||
/// <param name="objectLocalID">The Objects Simulator Local ID</param>
|
||||
/// <seealso cref="Simulator.ObjectsPrimitives"/>
|
||||
/// <seealso cref="Grab"/>
|
||||
/// <seealso cref="GrabUpdate"/>
|
||||
/// <seealso cref="AgentManager.Grab"/>
|
||||
/// <seealso cref="AgentManager.GrabUpdate"/>
|
||||
public void DeGrab(uint objectLocalID)
|
||||
{
|
||||
DeGrab(objectLocalID, TOUCH_INVALID_TEXCOORD, TOUCH_INVALID_TEXCOORD,
|
||||
@@ -2658,14 +2669,14 @@ namespace OpenMetaverse
|
||||
{
|
||||
AgentData =
|
||||
{
|
||||
AgentID = id,
|
||||
AgentID = AgentID,
|
||||
SessionID = Client.Self.SessionID
|
||||
},
|
||||
MoneyData =
|
||||
{
|
||||
Description = Utils.StringToBytes(description),
|
||||
DestID = target,
|
||||
SourceID = id,
|
||||
SourceID = AgentID,
|
||||
TransactionType = (int) type,
|
||||
AggregatePermInventory = 0,
|
||||
AggregatePermNextOwner = 0,
|
||||
@@ -2957,7 +2968,7 @@ namespace OpenMetaverse
|
||||
teleportStat == TeleportStatus.Start ||
|
||||
teleportStat == TeleportStatus.Progress)
|
||||
{
|
||||
teleportMessage = "Teleport timed out.";
|
||||
TeleportMessage = "Teleport timed out.";
|
||||
teleportStat = TeleportStatus.Failed;
|
||||
}
|
||||
|
||||
@@ -3004,7 +3015,7 @@ namespace OpenMetaverse
|
||||
}
|
||||
else
|
||||
{
|
||||
teleportMessage = "Unable to resolve name: " + simName;
|
||||
TeleportMessage = "Unable to resolve name: " + simName;
|
||||
teleportStat = TeleportStatus.Failed;
|
||||
return false;
|
||||
}
|
||||
@@ -3067,7 +3078,7 @@ namespace OpenMetaverse
|
||||
teleportStat == TeleportStatus.Start ||
|
||||
teleportStat == TeleportStatus.Progress)
|
||||
{
|
||||
teleportMessage = "Teleport timed out.";
|
||||
TeleportMessage = "Teleport timed out.";
|
||||
teleportStat = TeleportStatus.Failed;
|
||||
}
|
||||
|
||||
@@ -3109,7 +3120,7 @@ namespace OpenMetaverse
|
||||
}
|
||||
else
|
||||
{
|
||||
teleportMessage = "CAPS event queue is not running";
|
||||
TeleportMessage = "CAPS event queue is not running";
|
||||
teleportEvent.Set();
|
||||
teleportStat = TeleportStatus.Failed;
|
||||
}
|
||||
@@ -3153,7 +3164,7 @@ namespace OpenMetaverse
|
||||
{
|
||||
AgentData =
|
||||
{
|
||||
AgentID = Client.Self.id,
|
||||
AgentID = Client.Self.AgentID,
|
||||
SessionID = Client.Self.SessionID
|
||||
},
|
||||
Info =
|
||||
@@ -3236,8 +3247,8 @@ namespace OpenMetaverse
|
||||
{
|
||||
AgentData =
|
||||
{
|
||||
AgentID = id,
|
||||
SessionID = sessionID
|
||||
AgentID = AgentID,
|
||||
SessionID = SessionID
|
||||
},
|
||||
PropertiesData =
|
||||
{
|
||||
@@ -3255,7 +3266,7 @@ namespace OpenMetaverse
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update agents profile interests
|
||||
/// Update agent's profile interests
|
||||
/// </summary>
|
||||
/// <param name="interests">selection of interests from <seealso cref="T:OpenMetaverse.Avatar.Interests"/> struct</param>
|
||||
public void UpdateInterests(Avatar.Interests interests)
|
||||
@@ -3264,8 +3275,8 @@ namespace OpenMetaverse
|
||||
{
|
||||
AgentData =
|
||||
{
|
||||
AgentID = id,
|
||||
SessionID = sessionID
|
||||
AgentID = AgentID,
|
||||
SessionID = SessionID
|
||||
},
|
||||
PropertiesData =
|
||||
{
|
||||
@@ -3280,6 +3291,29 @@ namespace OpenMetaverse
|
||||
Client.Network.SendPacket(aiup);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update agent's private notes for target avatar
|
||||
/// </summary>
|
||||
/// <param name="target">target avatar for notes</param>
|
||||
/// <param name="notes">notes to store</param>
|
||||
public void UpdateProfileNotes(UUID target, string notes)
|
||||
{
|
||||
AvatarNotesUpdatePacket anup = new AvatarNotesUpdatePacket
|
||||
{
|
||||
AgentData =
|
||||
{
|
||||
AgentID = AgentID,
|
||||
SessionID = SessionID
|
||||
},
|
||||
Data =
|
||||
{
|
||||
TargetID = target,
|
||||
Notes = Utils.StringToBytes(notes)
|
||||
}
|
||||
};
|
||||
Client.Network.SendPacket(anup);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the height and the width of the client window. This is used
|
||||
/// by the server to build a virtual camera frustum for our avatar
|
||||
@@ -3583,7 +3617,7 @@ namespace OpenMetaverse
|
||||
AgentData =
|
||||
{
|
||||
AgentID = Client.Self.AgentID,
|
||||
SessionID = Client.Self.sessionID
|
||||
SessionID = Client.Self.SessionID
|
||||
},
|
||||
Data = {PickID = pickID}
|
||||
};
|
||||
@@ -3693,7 +3727,7 @@ namespace OpenMetaverse
|
||||
}
|
||||
};
|
||||
|
||||
request.BeginGetResponse(Client.Settings.CAPS_TIMEOUT);
|
||||
request.GetRequestAsync(Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -3731,7 +3765,7 @@ namespace OpenMetaverse
|
||||
NewDisplayName = newName
|
||||
};
|
||||
|
||||
request.BeginGetResponse(msg.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
request.PostRequestAsync(msg.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -3750,7 +3784,7 @@ namespace OpenMetaverse
|
||||
};
|
||||
|
||||
CapsClient request = Client.Network.CurrentSim.Caps.CreateCapsClient("UpdateAgentLanguage");
|
||||
request?.BeginGetResponse(msg.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
request?.PostRequestAsync(msg.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -3785,15 +3819,15 @@ namespace OpenMetaverse
|
||||
{
|
||||
bool success = true;
|
||||
|
||||
if (error == null && result is OSDMap)
|
||||
if (error == null && result is OSDMap osdMap)
|
||||
{
|
||||
var map = ((OSDMap)result)["access_prefs"];
|
||||
agentAccess = ((OSDMap)map)["max"];
|
||||
Logger.Log($"Max maturity access set to {agentAccess}", Helpers.LogLevel.Info, Client );
|
||||
var map = osdMap["access_prefs"];
|
||||
AgentAccess = ((OSDMap)map)["max"];
|
||||
Logger.Log($"Max maturity access set to {AgentAccess}", Helpers.LogLevel.Info, Client );
|
||||
}
|
||||
else if (error == null)
|
||||
{
|
||||
Logger.Log($"Max maturity unchanged at {agentAccess}", Helpers.LogLevel.Info, Client);
|
||||
Logger.Log($"Max maturity unchanged at {AgentAccess}", Helpers.LogLevel.Info, Client);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3803,16 +3837,20 @@ namespace OpenMetaverse
|
||||
|
||||
if (callback != null)
|
||||
{
|
||||
try { callback(new AgentAccessEventArgs(success, agentAccess)); }
|
||||
try { callback(new AgentAccessEventArgs(success, AgentAccess)); }
|
||||
catch { } // *TODO: So gross
|
||||
}
|
||||
|
||||
};
|
||||
OSDMap req = new OSDMap();
|
||||
OSDMap prefs = new OSDMap {["max"] = access};
|
||||
req["access_prefs"] = prefs;
|
||||
OSDMap req = new OSDMap
|
||||
{
|
||||
["access_prefs"] = new OSDMap { ["max"] = access }
|
||||
};
|
||||
//OSDMap req = new OSDMap();
|
||||
//OSDMap prefs = new OSDMap {["max"] = access};
|
||||
//req["access_prefs"] = prefs;
|
||||
|
||||
request.BeginGetResponse(req, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
request.PostRequestAsync(req, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -3851,7 +3889,7 @@ namespace OpenMetaverse
|
||||
var postData = new OSDMap {
|
||||
["hover_height"] = hoverHeight
|
||||
};
|
||||
request.BeginGetResponse(postData, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
request.PostRequestAsync(postData, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
|
||||
#endregion Misc
|
||||
@@ -3894,6 +3932,57 @@ namespace OpenMetaverse
|
||||
}
|
||||
}
|
||||
|
||||
protected void OfflineMessageHandlerCallback(CapsClient client, OSD response, Exception error)
|
||||
{
|
||||
if (error != null) {
|
||||
Logger.Log($"Failed to retrieve offline messages from the simulator: {error.Message}",
|
||||
Helpers.LogLevel.Warning);
|
||||
RetrieveInstantMessagesLegacy();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_InstantMessage == null) return; // don't bother if we don't have any listeners
|
||||
|
||||
if (!(response is OSDMap respMap) || respMap.Count == 0 || respMap.ContainsKey("messages"))
|
||||
{
|
||||
Logger.Log("Failed to retrieve offline messages because the capability returned some goofy shit.",
|
||||
Helpers.LogLevel.Warning);
|
||||
RetrieveInstantMessagesLegacy();
|
||||
return;
|
||||
}
|
||||
|
||||
if (respMap["messages"] is OSDArray msgArray)
|
||||
{
|
||||
foreach (var osd in msgArray)
|
||||
{
|
||||
var msg = (OSDMap)osd;
|
||||
|
||||
InstantMessage message;
|
||||
message.FromAgentID = msg["from_agent_id"].AsUUID();
|
||||
message.FromAgentName = msg["from_agent_name"].AsString();
|
||||
message.ToAgentID = msg["to_agent_id"].AsUUID();
|
||||
message.RegionID = msg["region_id"].AsUUID();
|
||||
message.Dialog = (InstantMessageDialog)msg["dialog"].AsInteger();
|
||||
message.IMSessionID = msg["transaction-id"].AsUUID();
|
||||
message.Timestamp = new DateTime(msg["timestamp"].AsInteger());
|
||||
message.Message = msg["message"].AsString();
|
||||
message.Offline = msg.ContainsKey("offline")
|
||||
? (InstantMessageOnline)msg["offline"].AsInteger()
|
||||
: InstantMessageOnline.Offline;
|
||||
message.ParentEstateID = msg.ContainsKey("parent_estate_id")
|
||||
? msg["parent_estate_id"].AsUInteger() : 1;
|
||||
message.Position = msg.ContainsKey("position")
|
||||
? msg["position"].AsVector3()
|
||||
: new Vector3(msg["local_x"], msg["local_y"], msg["local_z"]);
|
||||
message.BinaryBucket = msg.ContainsKey("binary_bucket")
|
||||
? msg["binary_bucket"].AsBinary() : new byte[] { 0 };
|
||||
message.GroupIM = msg.ContainsKey("from_group") && msg["from_group"].AsBoolean();
|
||||
|
||||
OnInstantMessage(new InstantMessageEventArgs(message, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Take an incoming Chat packet, auto-parse, and if OnChat is defined call
|
||||
/// that with the appropriate arguments.
|
||||
@@ -4036,7 +4125,7 @@ namespace OpenMetaverse
|
||||
protected void HealthHandler(object sender, PacketReceivedEventArgs e)
|
||||
{
|
||||
Packet packet = e.Packet;
|
||||
health = ((HealthMessagePacket)packet).HealthData.Health;
|
||||
Health = ((HealthMessagePacket)packet).HealthData.Health;
|
||||
}
|
||||
|
||||
/// <summary>Process an incoming packet and raise the appropriate events</summary>
|
||||
@@ -4051,17 +4140,17 @@ namespace OpenMetaverse
|
||||
|
||||
if (p.AgentData.AgentID == simulator.Client.Self.AgentID)
|
||||
{
|
||||
firstName = Utils.BytesToString(p.AgentData.FirstName);
|
||||
lastName = Utils.BytesToString(p.AgentData.LastName);
|
||||
activeGroup = p.AgentData.ActiveGroupID;
|
||||
activeGroupPowers = (GroupPowers)p.AgentData.GroupPowers;
|
||||
FirstName = Utils.BytesToString(p.AgentData.FirstName);
|
||||
LastName = Utils.BytesToString(p.AgentData.LastName);
|
||||
ActiveGroup = p.AgentData.ActiveGroupID;
|
||||
ActiveGroupPowers = (GroupPowers)p.AgentData.GroupPowers;
|
||||
|
||||
if (m_AgentData == null) return;
|
||||
|
||||
string groupTitle = Utils.BytesToString(p.AgentData.GroupTitle);
|
||||
string groupName = Utils.BytesToString(p.AgentData.GroupName);
|
||||
|
||||
OnAgentData(new AgentDataReplyEventArgs(firstName, lastName, activeGroup, groupTitle, activeGroupPowers, groupName));
|
||||
OnAgentData(new AgentDataReplyEventArgs(FirstName, LastName, ActiveGroup, groupTitle, ActiveGroupPowers, groupName));
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4080,7 +4169,7 @@ namespace OpenMetaverse
|
||||
if (packet.Type == PacketType.MoneyBalanceReply)
|
||||
{
|
||||
MoneyBalanceReplyPacket reply = (MoneyBalanceReplyPacket)packet;
|
||||
this.balance = reply.MoneyData.MoneyBalance;
|
||||
this.Balance = reply.MoneyData.MoneyBalance;
|
||||
|
||||
if (m_MoneyBalance != null)
|
||||
{
|
||||
@@ -4107,7 +4196,7 @@ namespace OpenMetaverse
|
||||
|
||||
if (m_Balance != null)
|
||||
{
|
||||
OnBalance(new BalanceEventArgs(balance));
|
||||
OnBalance(new BalanceEventArgs(Balance));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4223,7 +4312,7 @@ namespace OpenMetaverse
|
||||
{
|
||||
TeleportStartPacket start = (TeleportStartPacket)packet;
|
||||
|
||||
teleportMessage = "Teleport started";
|
||||
TeleportMessage = "Teleport started";
|
||||
flags = (TeleportFlags)start.Info.TeleportFlags;
|
||||
teleportStat = TeleportStatus.Start;
|
||||
|
||||
@@ -4233,21 +4322,21 @@ namespace OpenMetaverse
|
||||
{
|
||||
TeleportProgressPacket progress = (TeleportProgressPacket)packet;
|
||||
|
||||
teleportMessage = Utils.BytesToString(progress.Info.Message);
|
||||
TeleportMessage = Utils.BytesToString(progress.Info.Message);
|
||||
flags = (TeleportFlags)progress.Info.TeleportFlags;
|
||||
teleportStat = TeleportStatus.Progress;
|
||||
|
||||
Logger.DebugLog($"TeleportProgress received, Message: {teleportMessage}, Flags: {flags}", Client);
|
||||
Logger.DebugLog($"TeleportProgress received, Message: {TeleportMessage}, Flags: {flags}", Client);
|
||||
}
|
||||
else if (packet.Type == PacketType.TeleportFailed)
|
||||
{
|
||||
TeleportFailedPacket failed = (TeleportFailedPacket)packet;
|
||||
|
||||
teleportMessage = Utils.BytesToString(failed.Info.Reason);
|
||||
TeleportMessage = Utils.BytesToString(failed.Info.Reason);
|
||||
teleportStat = TeleportStatus.Failed;
|
||||
finished = true;
|
||||
|
||||
Logger.DebugLog($"TeleportFailed received, Reason: {teleportMessage}", Client);
|
||||
Logger.DebugLog($"TeleportFailed received, Reason: {TeleportMessage}", Client);
|
||||
}
|
||||
else if (packet.Type == PacketType.TeleportFinish)
|
||||
{
|
||||
@@ -4266,25 +4355,25 @@ namespace OpenMetaverse
|
||||
|
||||
if (newSimulator != null)
|
||||
{
|
||||
teleportMessage = "Teleport finished";
|
||||
TeleportMessage = "Teleport finished";
|
||||
teleportStat = TeleportStatus.Finished;
|
||||
|
||||
Logger.Log($"Moved to new sim {newSimulator}", Helpers.LogLevel.Info, Client);
|
||||
}
|
||||
else
|
||||
{
|
||||
teleportMessage = "Failed to connect to the new sim after a teleport";
|
||||
TeleportMessage = "Failed to connect to the new sim after a teleport";
|
||||
teleportStat = TeleportStatus.Failed;
|
||||
|
||||
// We're going to get disconnected now
|
||||
Logger.Log(teleportMessage, Helpers.LogLevel.Error, Client);
|
||||
Logger.Log(TeleportMessage, Helpers.LogLevel.Error, Client);
|
||||
}
|
||||
}
|
||||
else if (packet.Type == PacketType.TeleportCancel)
|
||||
{
|
||||
//TeleportCancelPacket cancel = (TeleportCancelPacket)packet;
|
||||
|
||||
teleportMessage = "Cancelled";
|
||||
TeleportMessage = "Cancelled";
|
||||
teleportStat = TeleportStatus.Cancelled;
|
||||
finished = true;
|
||||
|
||||
@@ -4294,7 +4383,7 @@ namespace OpenMetaverse
|
||||
{
|
||||
TeleportLocalPacket local = (TeleportLocalPacket)packet;
|
||||
|
||||
teleportMessage = "Teleport finished";
|
||||
TeleportMessage = "Teleport finished";
|
||||
flags = (TeleportFlags)local.Info.TeleportFlags;
|
||||
teleportStat = TeleportStatus.Finished;
|
||||
relativePosition = local.Info.Position;
|
||||
@@ -4308,7 +4397,7 @@ namespace OpenMetaverse
|
||||
|
||||
if (m_Teleport != null)
|
||||
{
|
||||
OnTeleport(new TeleportEventArgs(teleportMessage, teleportStat, flags));
|
||||
OnTeleport(new TeleportEventArgs(TeleportMessage, teleportStat, flags));
|
||||
}
|
||||
|
||||
if (finished) teleportEvent.Set();
|
||||
@@ -4394,17 +4483,16 @@ namespace OpenMetaverse
|
||||
private void Network_OnLoginResponse(bool loginSuccess, bool redirect, string message, string reason,
|
||||
LoginResponseData reply)
|
||||
{
|
||||
id = reply.AgentID;
|
||||
sessionID = reply.SessionID;
|
||||
secureSessionID = reply.SecureSessionID;
|
||||
firstName = reply.FirstName;
|
||||
lastName = reply.LastName;
|
||||
startLocation = reply.StartLocation;
|
||||
agentAccess = reply.AgentAccess;
|
||||
AgentID = reply.AgentID;
|
||||
SessionID = reply.SessionID;
|
||||
SecureSessionID = reply.SecureSessionID;
|
||||
FirstName = reply.FirstName;
|
||||
LastName = reply.LastName;
|
||||
StartLocation = reply.StartLocation;
|
||||
AgentAccess = reply.AgentAccess;
|
||||
Movement.Camera.LookDirection(reply.LookAt);
|
||||
homePosition = reply.HomePosition;
|
||||
homeLookAt = reply.HomeLookAt;
|
||||
lookAt = reply.LookAt;
|
||||
home = reply.Home;
|
||||
LookAt = reply.LookAt;
|
||||
|
||||
if (reply.Gestures != null)
|
||||
{
|
||||
@@ -4671,7 +4759,7 @@ namespace OpenMetaverse
|
||||
AgentID = memberID
|
||||
};
|
||||
|
||||
request.BeginGetResponse(req.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
request.PostRequestAsync(req.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4689,7 +4777,31 @@ namespace OpenMetaverse
|
||||
|
||||
AlertMessagePacket alert = (AlertMessagePacket)packet;
|
||||
|
||||
OnAlertMessage(new AlertMessageEventArgs(Utils.BytesToString(alert.AlertData.Message)));
|
||||
string message = Utils.BytesToString(alert.AlertData.Message);
|
||||
|
||||
if (alert.AlertInfo.Length > 0)
|
||||
{
|
||||
string notificationid = Utils.BytesToString(alert.AlertInfo[0].Message);
|
||||
OSDMap extra = (alert.AlertInfo[0].ExtraParams != null && alert.AlertInfo[0].ExtraParams.Length > 0)
|
||||
? OSDParser.Deserialize(alert.AlertInfo[0].ExtraParams) as OSDMap
|
||||
: null;
|
||||
OnAlertMessage(new AlertMessageEventArgs(message, notificationid, extra));
|
||||
}
|
||||
else
|
||||
{
|
||||
OnAlertMessage(new AlertMessageEventArgs(message, null, null));
|
||||
}
|
||||
}
|
||||
|
||||
protected void AgentAlertMessageHandler(object sender, PacketReceivedEventArgs e)
|
||||
{
|
||||
if (m_AlertMessage == null) return;
|
||||
Packet packet = e.Packet;
|
||||
|
||||
AgentAlertMessagePacket alert = (AgentAlertMessagePacket)packet;
|
||||
// HACK: Agent alerts support modal and Generic Alerts do not, but it's all the same for
|
||||
// my simplified ass right now.
|
||||
OnAlertMessage(new AlertMessageEventArgs(Utils.BytesToString(alert.AlertData.Message), null, null));
|
||||
}
|
||||
|
||||
/// <summary>Process an incoming packet and raise the appropriate events</summary>
|
||||
@@ -5309,14 +5421,20 @@ namespace OpenMetaverse
|
||||
{
|
||||
/// <summary>Get the alert message</summary>
|
||||
public string Message { get; }
|
||||
public string NotificationId { get; }
|
||||
public OSDMap ExtraParams { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new instance of the AlertMessageEventArgs class
|
||||
/// </summary>
|
||||
/// <param name="message">The alert message</param>
|
||||
public AlertMessageEventArgs(string message)
|
||||
/// <param name="message">user readable message</param>
|
||||
/// <param name="notificationid">notification id for alert, may be null</param>
|
||||
/// <param name="extraparams">any extra params in OSD format, may be null</param>
|
||||
public AlertMessageEventArgs(string message, string notificationid, OSDMap extraparams)
|
||||
{
|
||||
Message = message;
|
||||
NotificationId = notificationid;
|
||||
ExtraParams = extraparams;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
using System;
|
||||
using System.Threading;
|
||||
using OpenMetaverse.Packets;
|
||||
using UnityEngine;
|
||||
|
||||
namespace OpenMetaverse
|
||||
{
|
||||
@@ -378,10 +377,7 @@ namespace OpenMetaverse
|
||||
}
|
||||
}
|
||||
/// <summary>The current value of the agent control flags</summary>
|
||||
public uint AgentControls
|
||||
{
|
||||
get { return agentControls; }
|
||||
}
|
||||
public uint AgentControls { get; private set; }
|
||||
|
||||
/// <summary>Gets or sets the interval in milliseconds at which
|
||||
/// AgentUpdate packets are sent to the current simulator. Setting
|
||||
@@ -421,11 +417,7 @@ namespace OpenMetaverse
|
||||
}
|
||||
|
||||
/// <summary>Reset movement controls every time we send an update</summary>
|
||||
public bool AutoResetControls
|
||||
{
|
||||
get { return autoResetControls; }
|
||||
set { autoResetControls = value; }
|
||||
}
|
||||
public bool AutoResetControls { get; set; }
|
||||
|
||||
#endregion Properties
|
||||
|
||||
@@ -460,13 +452,11 @@ namespace OpenMetaverse
|
||||
|
||||
private bool alwaysRun;
|
||||
private GridClient Client;
|
||||
private uint agentControls;
|
||||
private int duplicateCount;
|
||||
private AgentState lastState;
|
||||
/// <summary>Timer for sending AgentUpdate packets</summary>
|
||||
private Timer updateTimer;
|
||||
private int updateInterval;
|
||||
private bool autoResetControls;
|
||||
|
||||
/// <summary>Default constructor</summary>
|
||||
public AgentMovement(GridClient client)
|
||||
@@ -599,8 +589,6 @@ namespace OpenMetaverse
|
||||
/// <param name="simulator">Simulator to send the update to</param>
|
||||
public void SendUpdate(bool reliable, Simulator simulator)
|
||||
{
|
||||
Debug.Log("sending movement packet.");
|
||||
|
||||
// Since version 1.40.4 of the Linden simulator, sending this update
|
||||
// causes corruption of the agent position in the simulator
|
||||
if (simulator != null && (!simulator.AgentMovementComplete))
|
||||
@@ -612,7 +600,7 @@ namespace OpenMetaverse
|
||||
Vector3 zAxis = Camera.UpAxis;
|
||||
|
||||
// Attempted to sort these in a rough order of how often they might change
|
||||
if (agentControls == 0 &&
|
||||
if (AgentControls == 0 &&
|
||||
yAxis == LastCameraYAxis &&
|
||||
origin == LastCameraCenter &&
|
||||
State == lastState &&
|
||||
@@ -655,13 +643,13 @@ namespace OpenMetaverse
|
||||
update.AgentData.CameraUpAxis = zAxis;
|
||||
update.AgentData.Far = Camera.Far;
|
||||
update.AgentData.State = (byte)State;
|
||||
update.AgentData.ControlFlags = agentControls;
|
||||
update.AgentData.ControlFlags = AgentControls;
|
||||
update.AgentData.Flags = (byte)Flags;
|
||||
|
||||
Client.Network.SendPacket(update, simulator);
|
||||
Logger.DebugLog("sent packet of agent movement!");
|
||||
Logger.DebugLog("sent out a packet of agent movement!");
|
||||
|
||||
if (autoResetControls) {
|
||||
if (AutoResetControls) {
|
||||
ResetControlFlags();
|
||||
}
|
||||
}
|
||||
@@ -714,20 +702,20 @@ namespace OpenMetaverse
|
||||
|
||||
private bool GetControlFlag(ControlFlags flag)
|
||||
{
|
||||
return (agentControls & (uint)flag) != 0;
|
||||
return (AgentControls & (uint)flag) != 0;
|
||||
}
|
||||
|
||||
private void SetControlFlag(ControlFlags flag, bool value)
|
||||
{
|
||||
if (value) agentControls |= (uint)flag;
|
||||
else agentControls &= ~((uint)flag);
|
||||
if (value) AgentControls |= (uint)flag;
|
||||
else AgentControls &= ~((uint)flag);
|
||||
}
|
||||
|
||||
public void ResetControlFlags()
|
||||
{
|
||||
// Reset all of the flags except for persistent settings like
|
||||
// away, fly, mouselook, and crouching
|
||||
agentControls &=
|
||||
AgentControls &=
|
||||
(uint)(ControlFlags.AGENT_CONTROL_AWAY |
|
||||
ControlFlags.AGENT_CONTROL_FLY |
|
||||
ControlFlags.AGENT_CONTROL_MOUSELOOK |
|
||||
|
||||
@@ -30,7 +30,6 @@ using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using LibreMetaverse;
|
||||
using Microsoft.Collections.Extensions;
|
||||
using OpenMetaverse.Packets;
|
||||
using OpenMetaverse.Imaging;
|
||||
@@ -367,7 +366,7 @@ namespace OpenMetaverse
|
||||
|
||||
/// <summary>Visual parameters last sent to the sim</summary>
|
||||
public byte[] MyVisualParameters;
|
||||
|
||||
|
||||
/// <summary>Textures about this client sent to the sim</summary>
|
||||
public Primitive.TextureEntry MyTextures;
|
||||
|
||||
@@ -414,7 +413,7 @@ namespace OpenMetaverse
|
||||
{
|
||||
MaxDegreeOfParallelism = MAX_CONCURRENT_DOWNLOADS
|
||||
};
|
||||
|
||||
|
||||
#endregion Private Members
|
||||
|
||||
/// <summary>
|
||||
@@ -485,7 +484,7 @@ namespace OpenMetaverse
|
||||
|
||||
// This is the first time setting appearance, run through the entire sequence
|
||||
AppearanceThread = new Thread(
|
||||
delegate()
|
||||
delegate ()
|
||||
{
|
||||
var cancellationToken = CancellationTokenSource.Token;
|
||||
bool success = true;
|
||||
@@ -495,7 +494,7 @@ namespace OpenMetaverse
|
||||
{
|
||||
// Set all of the baked textures to UUID.Zero to force rebaking
|
||||
for (int bakedIndex = 0; bakedIndex < BAKED_TEXTURE_COUNT; bakedIndex++)
|
||||
Textures[(int) BakeTypeToAgentTextureIndex((BakeType) bakedIndex)].TextureID = UUID.Zero;
|
||||
Textures[(int)BakeTypeToAgentTextureIndex((BakeType)bakedIndex)].TextureID = UUID.Zero;
|
||||
}
|
||||
|
||||
// FIXME: we really need to make this better...
|
||||
@@ -700,7 +699,7 @@ namespace OpenMetaverse
|
||||
new AgentCachedTexturePacket.WearableDataBlock
|
||||
{
|
||||
ID = hash,
|
||||
TextureIndex = (byte) bakedIndex
|
||||
TextureIndex = (byte)bakedIndex
|
||||
};
|
||||
hashes.Add(block);
|
||||
|
||||
@@ -737,8 +736,8 @@ namespace OpenMetaverse
|
||||
[Obsolete]
|
||||
public UUID GetWearableAsset(WearableType type)
|
||||
{
|
||||
return Wearables.TryGetValue(type, out var wearableList)
|
||||
? wearableList.First().AssetID
|
||||
return Wearables.TryGetValue(type, out var wearableList)
|
||||
? wearableList.First().AssetID
|
||||
: UUID.Zero;
|
||||
}
|
||||
|
||||
@@ -804,7 +803,8 @@ namespace OpenMetaverse
|
||||
ItemID = wearableItem.UUID,
|
||||
WearableType = wearableItem.WearableType
|
||||
};
|
||||
if (replace || wearableItem.AssetType == AssetType.Bodypart) {
|
||||
if (replace || wearableItem.AssetType == AssetType.Bodypart)
|
||||
{
|
||||
// Dump everything from the key
|
||||
Wearables.Remove(wearableItem.WearableType);
|
||||
}
|
||||
@@ -830,7 +830,7 @@ namespace OpenMetaverse
|
||||
/// <param name="wearableItem">Wearable to be removed from the outfit</param>
|
||||
public void RemoveFromOutfit(InventoryItem wearableItem)
|
||||
{
|
||||
List<InventoryItem> wearableItems = new List<InventoryItem> {wearableItem};
|
||||
List<InventoryItem> wearableItems = new List<InventoryItem> { wearableItem };
|
||||
RemoveFromOutfit(wearableItems);
|
||||
}
|
||||
|
||||
@@ -915,7 +915,7 @@ namespace OpenMetaverse
|
||||
for (int i = 0; i < WEARABLE_COUNT; i++)
|
||||
{
|
||||
WearableType wearableType = (WearableType)i;
|
||||
if (WearableTypeToAssetType(wearableType) == AssetType.Bodypart
|
||||
if (WearableTypeToAssetType(wearableType) == AssetType.Bodypart
|
||||
&& !Wearables.ContainsKey(wearableType))
|
||||
{
|
||||
needsCurrentWearables = true;
|
||||
@@ -998,8 +998,8 @@ namespace OpenMetaverse
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Calls either <seealso cref="ReplaceOutfit"/> or
|
||||
/// <seealso cref="AddToOutfit"/> depending on the value of
|
||||
/// Calls either <seealso cref="AppearanceManager.ReplaceOutfit"/> or
|
||||
/// <seealso cref="AppearanceManager.AddToOutfit"/> depending on the value of
|
||||
/// replaceItems
|
||||
/// </summary>
|
||||
/// <param name="wearables">List of wearable inventory items to add
|
||||
@@ -1060,15 +1060,15 @@ namespace OpenMetaverse
|
||||
{
|
||||
AttachmentPt =
|
||||
replace
|
||||
? (byte) attachment.AttachmentPoint
|
||||
: (byte) (ATTACHMENT_ADD | (byte) attachment.AttachmentPoint),
|
||||
EveryoneMask = (uint) attachment.Permissions.EveryoneMask,
|
||||
GroupMask = (uint) attachment.Permissions.GroupMask,
|
||||
ItemFlags = (uint) attachment.Flags,
|
||||
? (byte)attachment.AttachmentPoint
|
||||
: (byte)(ATTACHMENT_ADD | (byte)attachment.AttachmentPoint),
|
||||
EveryoneMask = (uint)attachment.Permissions.EveryoneMask,
|
||||
GroupMask = (uint)attachment.Permissions.GroupMask,
|
||||
ItemFlags = (uint)attachment.Flags,
|
||||
ItemID = attachment.UUID,
|
||||
Name = Utils.StringToBytes(attachment.Name),
|
||||
Description = Utils.StringToBytes(attachment.Description),
|
||||
NextOwnerMask = (uint) attachment.Permissions.NextOwnerMask,
|
||||
NextOwnerMask = (uint)attachment.Permissions.NextOwnerMask,
|
||||
OwnerID = attachment.OwnerID
|
||||
};
|
||||
|
||||
@@ -1081,14 +1081,14 @@ namespace OpenMetaverse
|
||||
InventoryObject attachment = (InventoryObject)attachments[i];
|
||||
attachmentsPacket.ObjectData[i] = new RezMultipleAttachmentsFromInvPacket.ObjectDataBlock
|
||||
{
|
||||
AttachmentPt = replace ? (byte) 0 : ATTACHMENT_ADD,
|
||||
EveryoneMask = (uint) attachment.Permissions.EveryoneMask,
|
||||
GroupMask = (uint) attachment.Permissions.GroupMask,
|
||||
ItemFlags = (uint) attachment.Flags,
|
||||
AttachmentPt = replace ? (byte)0 : ATTACHMENT_ADD,
|
||||
EveryoneMask = (uint)attachment.Permissions.EveryoneMask,
|
||||
GroupMask = (uint)attachment.Permissions.GroupMask,
|
||||
ItemFlags = (uint)attachment.Flags,
|
||||
ItemID = attachment.UUID,
|
||||
Name = Utils.StringToBytes(attachment.Name),
|
||||
Description = Utils.StringToBytes(attachment.Description),
|
||||
NextOwnerMask = (uint) attachment.Permissions.NextOwnerMask,
|
||||
NextOwnerMask = (uint)attachment.Permissions.NextOwnerMask,
|
||||
OwnerID = attachment.OwnerID
|
||||
};
|
||||
|
||||
@@ -1365,7 +1365,7 @@ namespace OpenMetaverse
|
||||
WearableType type = (WearableType)i;
|
||||
wearing.WearableData[i] = new AgentIsNowWearingPacket.WearableDataBlock
|
||||
{
|
||||
WearableType = (byte) i,
|
||||
WearableType = (byte)i,
|
||||
// This appears to be hacked on SL server side to support multi-layers
|
||||
ItemID = Wearables.ContainsKey(type) ?
|
||||
(Wearables[type].First()?.ItemID ?? UUID.Zero)
|
||||
@@ -1414,9 +1414,12 @@ namespace OpenMetaverse
|
||||
WearableType = wearableItem.WearableType
|
||||
};
|
||||
// Body cannot be layered. Overwrite when multiple are selected.
|
||||
if (wearableItem.AssetType == AssetType.Bodypart) {
|
||||
if (wearableItem.AssetType == AssetType.Bodypart)
|
||||
{
|
||||
bodyparts[wearableItem.WearableType] = wd;
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
newWearables.Add(wearableItem.WearableType, wd);
|
||||
}
|
||||
}
|
||||
@@ -1428,7 +1431,7 @@ namespace OpenMetaverse
|
||||
}
|
||||
|
||||
// heavy handed body part sanity check
|
||||
if (newWearables.ContainsKey(WearableType.Shape) &&
|
||||
if (newWearables.ContainsKey(WearableType.Shape) &&
|
||||
newWearables.ContainsKey(WearableType.Skin) &&
|
||||
newWearables.ContainsKey(WearableType.Eyes) &&
|
||||
newWearables.ContainsKey(WearableType.Hair))
|
||||
@@ -1741,7 +1744,7 @@ namespace OpenMetaverse
|
||||
foreach (var wearable in wearables)
|
||||
{
|
||||
if (wearable.Asset == null) continue;
|
||||
|
||||
|
||||
DecodeWearableParams(wearable, ref Textures);
|
||||
--pendingWearables;
|
||||
}
|
||||
@@ -1750,7 +1753,7 @@ namespace OpenMetaverse
|
||||
return true;
|
||||
|
||||
Logger.DebugLog("Downloading " + pendingWearables + " wearable assets");
|
||||
|
||||
|
||||
Parallel.ForEach(wearables, _parallelOptions,
|
||||
wearable =>
|
||||
{
|
||||
@@ -1759,7 +1762,7 @@ namespace OpenMetaverse
|
||||
|
||||
// Fetch this wearable asset
|
||||
Client.Assets.RequestAsset(wearable.AssetID, wearable.AssetType, true,
|
||||
delegate(AssetDownload transfer, Asset asset)
|
||||
delegate (AssetDownload transfer, Asset asset)
|
||||
{
|
||||
if (transfer.Success && asset is AssetWearable assetWearable)
|
||||
{
|
||||
@@ -1862,7 +1865,7 @@ namespace OpenMetaverse
|
||||
AutoResetEvent downloadEvent = new AutoResetEvent(false);
|
||||
|
||||
Client.Assets.RequestImage(textureId,
|
||||
delegate(TextureRequestState state, AssetTexture assetTexture)
|
||||
delegate (TextureRequestState state, AssetTexture assetTexture)
|
||||
{
|
||||
if (state == TextureRequestState.Finished)
|
||||
{
|
||||
@@ -1889,7 +1892,7 @@ namespace OpenMetaverse
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log(
|
||||
$"Download of texture {textureId} failed with exception {e}",
|
||||
$"Download of texture {textureId} failed with exception {e}",
|
||||
Helpers.LogLevel.Warning, Client);
|
||||
}
|
||||
}
|
||||
@@ -1911,14 +1914,23 @@ namespace OpenMetaverse
|
||||
{
|
||||
AvatarTextureIndex textureIndex = BakeTypeToAgentTextureIndex((BakeType)bakedIndex);
|
||||
|
||||
|
||||
if (Textures[(int)textureIndex].TextureID == UUID.Zero)
|
||||
{
|
||||
|
||||
// If this is the skirt layer and we're not wearing a skirt then skip it
|
||||
if (bakedIndex == (int)BakeType.Skirt && !Wearables.ContainsKey(WearableType.Skirt))
|
||||
{
|
||||
Logger.DebugLog("texture: " + (AvatarTextureIndex)textureIndex + " skipping not attached");
|
||||
continue;
|
||||
|
||||
}
|
||||
Logger.DebugLog("texture: " + (AvatarTextureIndex)textureIndex + " is needed adding to pending Bakes");
|
||||
pendingBakes.Add((BakeType)bakedIndex);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.DebugLog("texture: " + (AvatarTextureIndex)textureIndex + " is ready");
|
||||
}
|
||||
}
|
||||
|
||||
if (pendingBakes.Any())
|
||||
@@ -1939,7 +1951,7 @@ namespace OpenMetaverse
|
||||
{
|
||||
Textures[i].Texture = null;
|
||||
}
|
||||
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
@@ -1975,7 +1987,10 @@ namespace OpenMetaverse
|
||||
--retries;
|
||||
}
|
||||
|
||||
Textures[(int)BakeTypeToAgentTextureIndex(bakeType)].TextureID = newAssetID;
|
||||
int bakeIndex = (int)BakeTypeToAgentTextureIndex(bakeType);
|
||||
Logger.DebugLog("Saving back to " + (AvatarTextureIndex)bakeIndex);
|
||||
|
||||
Textures[bakeIndex].TextureID = newAssetID;
|
||||
|
||||
if (newAssetID == UUID.Zero)
|
||||
{
|
||||
@@ -1997,7 +2012,7 @@ namespace OpenMetaverse
|
||||
var uploadEvent = new AutoResetEvent(false);
|
||||
|
||||
Client.Assets.RequestUploadBakedTexture(textureData,
|
||||
delegate(UUID newAssetID)
|
||||
delegate (UUID newAssetID)
|
||||
{
|
||||
bakeID = newAssetID;
|
||||
uploadEvent.Set();
|
||||
@@ -2082,11 +2097,11 @@ namespace OpenMetaverse
|
||||
// TODO: create Current Outfit Folder
|
||||
}
|
||||
|
||||
OSDMap request = new OSDMap(1) {["cof_version"] = COF.Version};
|
||||
OSDMap request = new OSDMap(1) { ["cof_version"] = COF.Version };
|
||||
|
||||
string msg = "Setting server side baking failed";
|
||||
|
||||
OSD res = capsRequest.GetResponse(request, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT * 2);
|
||||
OSD res = capsRequest.PostRequest(request, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT * 2);
|
||||
|
||||
if (res is OSDMap result)
|
||||
{
|
||||
@@ -2196,16 +2211,16 @@ namespace OpenMetaverse
|
||||
bool found = false;
|
||||
foreach (var wearableList in Wearables)
|
||||
{
|
||||
if(wearableList.Value.Any(wearable => wearable.Asset != null &&
|
||||
wearable.Asset.Params
|
||||
.TryGetValue(vp.ParamID, out paramValue)))
|
||||
if (wearableList.Value.Any(wearable => wearable.Asset != null &&
|
||||
wearable.Asset.Params
|
||||
.TryGetValue(vp.ParamID, out paramValue)))
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// Try and find this value in our collection of downloaded wearables
|
||||
|
||||
@@ -2249,13 +2264,16 @@ namespace OpenMetaverse
|
||||
break;
|
||||
}
|
||||
|
||||
if (vpIndex <= nrParams) break;
|
||||
if (vpIndex >= nrParams) break;
|
||||
}
|
||||
|
||||
MyVisualParameters = new byte[set.VisualParam.Length];
|
||||
for (int i = 0; i < set.VisualParam.Length; i++)
|
||||
{
|
||||
MyVisualParameters[i] = set.VisualParam[i].ParamValue;
|
||||
if (set.VisualParam[i] != null)
|
||||
{
|
||||
MyVisualParameters[i] = set.VisualParam[i].ParamValue;
|
||||
}
|
||||
}
|
||||
|
||||
#endregion VisualParam
|
||||
@@ -2267,8 +2285,15 @@ namespace OpenMetaverse
|
||||
for (uint i = 0; i < Textures.Length; i++)
|
||||
{
|
||||
Primitive.TextureEntryFace face = te.CreateFace(i);
|
||||
face.TextureID = Textures[i].TextureID;
|
||||
Logger.DebugLog("Sending texture entry for " + (AvatarTextureIndex)i + " to " + Textures[i].TextureID, Client);
|
||||
if (Textures[i].TextureID != UUID.Zero)
|
||||
{
|
||||
face.TextureID = Textures[i].TextureID;
|
||||
Logger.DebugLog("Sending texture entry for " + (AvatarTextureIndex)i + " to " + Textures[i].TextureID, Client);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.DebugLog("Skipping texture entry for " + (AvatarTextureIndex)i + " its null", Client);
|
||||
}
|
||||
}
|
||||
|
||||
set.ObjectData.TextureEntry = te.GetBytes();
|
||||
@@ -2562,7 +2587,7 @@ namespace OpenMetaverse
|
||||
CancellationTokenSource.Dispose();
|
||||
CancellationTokenSource = null;
|
||||
}
|
||||
|
||||
|
||||
if (AppearanceThread != null)
|
||||
{
|
||||
AppearanceThread = null;
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Net;
|
||||
using OpenMetaverse.Packets;
|
||||
using OpenMetaverse.Assets;
|
||||
using OpenMetaverse.Http;
|
||||
@@ -163,7 +162,7 @@ namespace OpenMetaverse
|
||||
{
|
||||
public UUID ID;
|
||||
public int Size;
|
||||
public byte[] AssetData = Utils.EmptyBytes;
|
||||
public byte[] AssetData;
|
||||
public int Transferred;
|
||||
public bool Success;
|
||||
public AssetType AssetType;
|
||||
@@ -637,16 +636,6 @@ namespace OpenMetaverse
|
||||
catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); }
|
||||
|
||||
return;
|
||||
} else
|
||||
{
|
||||
//not in asset cache and not connected. big oopsie :o
|
||||
if (Client.Network.Connected == false)
|
||||
{
|
||||
|
||||
Logger.Log("Assetmanager : Cache miss and DISCONNECTED!", Helpers.LogLevel.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// If ViewerAsset capability exists, use that, if not, fallback to UDP (which is obsoleted on Second Life.)
|
||||
@@ -859,8 +848,6 @@ namespace OpenMetaverse
|
||||
/// </summary>
|
||||
/// <param name="assetID">Use UUID.Zero if you do not have the
|
||||
/// asset ID but have all the necessary permissions</param>
|
||||
/// <param name="assetType"></param>
|
||||
/// <param name="priority">Whether to prioritize this asset download or not</param>
|
||||
/// <param name="transfer"></param>
|
||||
/// <param name="callback"></param>
|
||||
private void RequestInventoryAssetHTTP(UUID assetID, AssetDownload transfer, AssetReceivedCallback callback)
|
||||
@@ -1143,7 +1130,7 @@ namespace OpenMetaverse
|
||||
Logger.Log("Bake upload failed during asset upload", Helpers.LogLevel.Warning, Client);
|
||||
callback(UUID.Zero);
|
||||
};
|
||||
upload.BeginGetResponse(textureData, "application/octet-stream", Client.Settings.CAPS_TIMEOUT);
|
||||
upload.PostRequestAsync(textureData, "application/octet-stream", Client.Settings.CAPS_TIMEOUT);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -1152,7 +1139,7 @@ namespace OpenMetaverse
|
||||
Logger.Log("Bake upload failed during uploader retrieval", Helpers.LogLevel.Warning, Client);
|
||||
callback(UUID.Zero);
|
||||
};
|
||||
request.BeginGetResponse(new OSDMap(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
request.PostRequestAsync(new OSDMap(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
*/
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse.Assets
|
||||
{
|
||||
|
||||
@@ -27,9 +27,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Xml;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse.Assets
|
||||
{
|
||||
|
||||
@@ -28,10 +28,8 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.Threading;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse.Assets
|
||||
{
|
||||
@@ -435,7 +433,10 @@ namespace OpenMetaverse.Assets
|
||||
xtw.WriteElementString("SnapshotID", parcel.SnapshotID.ToString());
|
||||
xtw.WriteElementString("UserLocation", parcel.UserLocation.ToString());
|
||||
xtw.WriteElementString("UserLookAt", parcel.UserLookAt.ToString());
|
||||
xtw.WriteElementString("Dwell", "0");
|
||||
xtw.WriteElementString("Dwell", parcel.Dwell.ToString());
|
||||
xtw.WriteElementString("SeeAVs", parcel.SeeAVs.ToString());
|
||||
xtw.WriteElementString("AnyAVSounds", parcel.AnyAVSounds.ToString());
|
||||
xtw.WriteElementString("GroupAVSounds", parcel.GroupAVSounds.ToString());
|
||||
xtw.WriteElementString("OtherCleanTime", Convert.ToString(parcel.OtherCleanTime));
|
||||
|
||||
xtw.WriteEndElement();
|
||||
@@ -534,9 +535,8 @@ namespace OpenMetaverse.Assets
|
||||
|
||||
if (prim.Textures.FaceTextures != null)
|
||||
{
|
||||
for (int i = 0; i < prim.Textures.FaceTextures.Length; i++)
|
||||
foreach (var face in prim.Textures.FaceTextures)
|
||||
{
|
||||
Primitive.TextureEntryFace face = prim.Textures.FaceTextures[i];
|
||||
if (face != null)
|
||||
textureList[face.TextureID] = face.TextureID;
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace OpenMetaverse.Assets
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
|
||||
@@ -24,9 +24,6 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse.Assets
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -24,9 +24,6 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse.Assets
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -24,9 +24,6 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse.Assets
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse.Assets
|
||||
{
|
||||
|
||||
@@ -24,9 +24,6 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse.Assets
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -27,8 +27,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse.Assets
|
||||
{
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse.Assets
|
||||
{
|
||||
|
||||
@@ -24,9 +24,6 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse.Assets
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -28,7 +28,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse.Assets
|
||||
{
|
||||
|
||||
@@ -28,7 +28,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
|
||||
namespace OpenMetaverse.Assets
|
||||
@@ -782,8 +781,9 @@ namespace OpenMetaverse.Assets
|
||||
if (Items != null)
|
||||
{
|
||||
OSDArray array = new OSDArray(Items.Length);
|
||||
for (int i = 0; i < Items.Length; i++)
|
||||
array.Add(Items[i].Serialize());
|
||||
foreach (var i in Items)
|
||||
array.Add(i.Serialize());
|
||||
|
||||
map["items"] = array;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,9 +24,6 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse.Assets
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -24,9 +24,6 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse.Assets
|
||||
{
|
||||
/// <summary>
|
||||
|
||||
@@ -24,8 +24,9 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using OggVorbisEncoder;
|
||||
using System;
|
||||
using OpenMetaverse;
|
||||
using System.IO;
|
||||
|
||||
namespace OpenMetaverse.Assets
|
||||
{
|
||||
@@ -46,17 +47,162 @@ namespace OpenMetaverse.Assets
|
||||
public AssetSound(UUID assetID, byte[] assetData)
|
||||
: base(assetID, assetData)
|
||||
{
|
||||
if ((assetID != UUID.Zero) && (assetData.Length > 0))
|
||||
{
|
||||
encodedAudio = true;
|
||||
}
|
||||
}
|
||||
|
||||
protected bool encodedAudio = false;
|
||||
|
||||
/// <summary>
|
||||
/// Converts a byte data for a wave PCM file @ 44100 to a OGG encoding
|
||||
/// </summary>
|
||||
public override void Encode()
|
||||
{
|
||||
if (encodedAudio == false)
|
||||
{
|
||||
encodedAudio = true;
|
||||
AssetData = ConvertRawPCMFile(44100, 1, AssetData, PcmSample.SixteenBit, 44100, 2);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// TODO: Encodes a sound file
|
||||
/// </summary>
|
||||
public override void Encode() { }
|
||||
|
||||
/// <summary>
|
||||
/// TODO: Decode a sound file
|
||||
/// its already ogg just play it or convert it yourself
|
||||
/// </summary>
|
||||
/// <returns>true</returns>
|
||||
public override bool Decode() { return true; }
|
||||
|
||||
|
||||
private static byte[] ConvertRawPCMFile(int outputSampleRate, int outputChannels, byte[] pcmSamples, PcmSample pcmSampleSize, int pcmSampleRate, int pcmChannels)
|
||||
{
|
||||
int numPcmSamples = (pcmSamples.Length / (int)pcmSampleSize / pcmChannels);
|
||||
float pcmDuraton = numPcmSamples / (float)pcmSampleRate;
|
||||
|
||||
int numOutputSamples = (int)(pcmDuraton * outputSampleRate);
|
||||
//Ensure that samble buffer is aligned to write chunk size
|
||||
numOutputSamples = (numOutputSamples / WriteBufferSize) * WriteBufferSize;
|
||||
|
||||
float[][] outSamples = new float[outputChannels][];
|
||||
|
||||
for (int ch = 0; ch < outputChannels; ch++)
|
||||
{
|
||||
outSamples[ch] = new float[numOutputSamples];
|
||||
}
|
||||
|
||||
for (int sampleNumber = 0; sampleNumber < numOutputSamples; sampleNumber++)
|
||||
{
|
||||
float rawSample = 0.0f;
|
||||
|
||||
for (int ch = 0; ch < outputChannels; ch++)
|
||||
{
|
||||
int sampleIndex = (sampleNumber * pcmChannels) * (int)pcmSampleSize;
|
||||
|
||||
if (ch < pcmChannels) sampleIndex += (ch * (int)pcmSampleSize);
|
||||
|
||||
switch (pcmSampleSize)
|
||||
{
|
||||
case PcmSample.EightBit:
|
||||
rawSample = ByteToSample(pcmSamples[sampleIndex]);
|
||||
break;
|
||||
case PcmSample.SixteenBit:
|
||||
rawSample = ShortToSample((short)(pcmSamples[sampleIndex + 1] << 8 | pcmSamples[sampleIndex]));
|
||||
break;
|
||||
}
|
||||
|
||||
outSamples[ch][sampleNumber] = rawSample;
|
||||
}
|
||||
}
|
||||
|
||||
return GenerateFile(outSamples, outputSampleRate, outputChannels);
|
||||
}
|
||||
|
||||
private static float ByteToSample(short pcmValue)
|
||||
{
|
||||
return pcmValue / 128f;
|
||||
}
|
||||
|
||||
private static float ShortToSample(short pcmValue)
|
||||
{
|
||||
return pcmValue / 32768f;
|
||||
}
|
||||
|
||||
private static readonly int WriteBufferSize = 512;
|
||||
private static byte[] GenerateFile(float[][] floatSamples, int sampleRate, int channels)
|
||||
{
|
||||
MemoryStream outputData = new MemoryStream();
|
||||
|
||||
// Stores all the static vorbis bitstream settings
|
||||
var info = VorbisInfo.InitVariableBitRate(channels, sampleRate, 0.5f);
|
||||
|
||||
// set up our packet->stream encoder
|
||||
var serial = new Random().Next();
|
||||
var oggStream = new OggStream(serial);
|
||||
|
||||
// =========================================================
|
||||
// HEADER
|
||||
// =========================================================
|
||||
// Vorbis streams begin with three headers; the initial header (with
|
||||
// most of the codec setup parameters) which is mandated by the Ogg
|
||||
// bitstream spec. The second header holds any comment fields. The
|
||||
// third header holds the bitstream codebook.
|
||||
|
||||
var comments = new Comments();
|
||||
comments.AddTag("ARTIST", "TEST");
|
||||
|
||||
var infoPacket = HeaderPacketBuilder.BuildInfoPacket(info);
|
||||
var commentsPacket = HeaderPacketBuilder.BuildCommentsPacket(comments);
|
||||
var booksPacket = HeaderPacketBuilder.BuildBooksPacket(info);
|
||||
|
||||
oggStream.PacketIn(infoPacket);
|
||||
oggStream.PacketIn(commentsPacket);
|
||||
oggStream.PacketIn(booksPacket);
|
||||
|
||||
// Flush to force audio data onto its own page per the spec
|
||||
FlushPages(oggStream, outputData, true);
|
||||
|
||||
// =========================================================
|
||||
// BODY (Audio Data)
|
||||
// =========================================================
|
||||
var processingState = ProcessingState.Create(info);
|
||||
|
||||
for (int readIndex = 0; readIndex <= floatSamples[0].Length; readIndex += WriteBufferSize)
|
||||
{
|
||||
if (readIndex == floatSamples[0].Length)
|
||||
{
|
||||
processingState.WriteEndOfStream();
|
||||
}
|
||||
else
|
||||
{
|
||||
processingState.WriteData(floatSamples, WriteBufferSize, readIndex);
|
||||
}
|
||||
|
||||
while (!oggStream.Finished && processingState.PacketOut(out OggPacket packet))
|
||||
{
|
||||
oggStream.PacketIn(packet);
|
||||
|
||||
FlushPages(oggStream, outputData, false);
|
||||
}
|
||||
}
|
||||
|
||||
FlushPages(oggStream, outputData, true);
|
||||
|
||||
return outputData.ToArray();
|
||||
}
|
||||
|
||||
private static void FlushPages(OggStream oggStream, Stream output, bool force)
|
||||
{
|
||||
while (oggStream.PageOut(out OggPage page, force))
|
||||
{
|
||||
output.Write(page.Header, 0, page.Header.Length);
|
||||
output.Write(page.Body, 0, page.Body.Length);
|
||||
}
|
||||
}
|
||||
|
||||
enum PcmSample : int
|
||||
{
|
||||
EightBit = 1,
|
||||
SixteenBit = 2
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* Copyright (c) 2021-2022, Sjofn LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
@@ -24,8 +25,6 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.Imaging;
|
||||
|
||||
namespace OpenMetaverse.Assets
|
||||
@@ -41,9 +40,6 @@ namespace OpenMetaverse.Assets
|
||||
/// <summary>A <seealso cref="ManagedImage"/> object containing image data</summary>
|
||||
public ManagedImage Image;
|
||||
|
||||
/// <summary></summary>
|
||||
public OpenJPEG.J2KLayerInfo[] LayerInfo;
|
||||
|
||||
/// <summary></summary>
|
||||
public int Components;
|
||||
|
||||
@@ -81,7 +77,10 @@ namespace OpenMetaverse.Assets
|
||||
/// </summary>
|
||||
public override void Encode()
|
||||
{
|
||||
AssetData = OpenJPEG.Encode(Image);
|
||||
using (var writer = new OpenJpegDotNet.IO.Writer(Image.ExportTex2D()))
|
||||
{
|
||||
AssetData = writer.Encode();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -91,36 +90,27 @@ namespace OpenMetaverse.Assets
|
||||
/// <returns>True if the decoding was successful, otherwise false</returns>
|
||||
public override bool Decode()
|
||||
{
|
||||
if (AssetData != null && AssetData.Length > 0)
|
||||
if (AssetData == null || AssetData.Length <= 0) { return false; }
|
||||
|
||||
this.Components = 0;
|
||||
|
||||
using (var reader = new OpenJpegDotNet.IO.Reader(AssetData))
|
||||
{
|
||||
this.Components = 0;
|
||||
|
||||
if (OpenJPEG.DecodeToImage(AssetData, out Image))
|
||||
{
|
||||
if ((Image.Channels & ManagedImage.ImageChannels.Color) != 0)
|
||||
Components += 3;
|
||||
if ((Image.Channels & ManagedImage.ImageChannels.Gray) != 0)
|
||||
++Components;
|
||||
if ((Image.Channels & ManagedImage.ImageChannels.Bump) != 0)
|
||||
++Components;
|
||||
if ((Image.Channels & ManagedImage.ImageChannels.Alpha) != 0)
|
||||
++Components;
|
||||
|
||||
return true;
|
||||
}
|
||||
// *hack: decode from ManagedImage directly or better yet, get rid of ManagedImage entirely!
|
||||
if (!reader.ReadHeader()) { return false; }
|
||||
Image = new ManagedImage(reader.DecodeToBitmap());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
if ((Image.Channels & ManagedImage.ImageChannels.Color) != 0)
|
||||
Components += 3;
|
||||
if ((Image.Channels & ManagedImage.ImageChannels.Gray) != 0)
|
||||
++Components;
|
||||
if ((Image.Channels & ManagedImage.ImageChannels.Bump) != 0)
|
||||
++Components;
|
||||
if ((Image.Channels & ManagedImage.ImageChannels.Alpha) != 0)
|
||||
++Components;
|
||||
|
||||
/// <summary>
|
||||
/// Decodes the begin and end byte positions for each quality layer in
|
||||
/// the image
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public bool DecodeLayerBoundaries()
|
||||
{
|
||||
return OpenJPEG.DecodeLayerBoundaries(AssetData, out LayerInfo, out Components);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse.Assets
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* Copyright (c) 2021-2022, Sjofn LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
@@ -279,6 +280,29 @@ namespace OpenMetaverse
|
||||
remove { lock (m_AvatarInterestsReplyLock) { m_AvatarInterestsReply -= value; } }
|
||||
}
|
||||
|
||||
/// <summary>The event subscribers, null of no subscribers</summary>
|
||||
private EventHandler<AvatarNotesReplyEventArgs> m_AvatarNotesReply;
|
||||
|
||||
///<summary>Raises the AvatarNotesReply Event</summary>
|
||||
/// <param name="e">A AvatarNotesReplyEventArgs object containing
|
||||
/// the data sent from the simulator</param>
|
||||
protected virtual void OnAvatarNotesReply(AvatarNotesReplyEventArgs e)
|
||||
{
|
||||
EventHandler<AvatarNotesReplyEventArgs> handler = m_AvatarNotesReply;
|
||||
handler?.Invoke(this, e);
|
||||
}
|
||||
|
||||
/// <summary>Thread sync lock object</summary>
|
||||
private readonly object m_AvatarNotesReplyLock = new object();
|
||||
|
||||
/// <summary>Raised when the simulator sends us data containing
|
||||
/// the private notes listed in an agents profile</summary>
|
||||
public event EventHandler<AvatarNotesReplyEventArgs> AvatarNotesReply
|
||||
{
|
||||
add { lock (m_AvatarNotesReplyLock) { m_AvatarNotesReply += value; } }
|
||||
remove { lock (m_AvatarNotesReplyLock) { m_AvatarNotesReply -= value; } }
|
||||
}
|
||||
|
||||
/// <summary>The event subscribers, null of no subscribers</summary>
|
||||
private EventHandler<AvatarPropertiesReplyEventArgs> m_AvatarPropertiesReply;
|
||||
|
||||
@@ -561,6 +585,7 @@ namespace OpenMetaverse
|
||||
Client.Network.RegisterCallback(PacketType.AvatarPropertiesReply, AvatarPropertiesHandler);
|
||||
// Client.Network.RegisterCallback(PacketType.AvatarStatisticsReply, AvatarStatisticsHandler);
|
||||
Client.Network.RegisterCallback(PacketType.AvatarInterestsReply, AvatarInterestsHandler);
|
||||
Client.Network.RegisterCallback(PacketType.AvatarNotesReply, AvatarNotesHandler);
|
||||
|
||||
// Avatar group callback
|
||||
Client.Network.RegisterCallback(PacketType.AvatarGroupsReply, AvatarGroupsReplyHandler);
|
||||
@@ -709,7 +734,7 @@ namespace OpenMetaverse
|
||||
callback(false, null, null);
|
||||
}
|
||||
};
|
||||
cap.BeginGetResponse(null, string.Empty, Client.Settings.CAPS_TIMEOUT);
|
||||
cap.GetRequestAsync(Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -752,6 +777,36 @@ namespace OpenMetaverse
|
||||
Client.Network.SendPacket(aprp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Request avatar notes from simulator
|
||||
/// </summary>
|
||||
/// <param name="avatarid">Target agent UUID</param>
|
||||
public void RequestAvatarNotes(UUID avatarid)
|
||||
{
|
||||
GenericMessagePacket gmp = new GenericMessagePacket
|
||||
{
|
||||
AgentData =
|
||||
{
|
||||
AgentID = Client.Self.AgentID,
|
||||
SessionID = Client.Self.SessionID,
|
||||
TransactionID = UUID.Zero
|
||||
},
|
||||
MethodData =
|
||||
{
|
||||
Method = Utils.StringToBytes("avatarnotesrequest"),
|
||||
Invoice = UUID.Zero
|
||||
},
|
||||
ParamList = new GenericMessagePacket.ParamListBlock[1]
|
||||
};
|
||||
|
||||
gmp.ParamList[0] =
|
||||
new GenericMessagePacket.ParamListBlock
|
||||
{
|
||||
Parameter = Utils.StringToBytes(avatarid.ToString())
|
||||
};
|
||||
Client.Network.SendPacket(gmp);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start a request for Avatar Picks
|
||||
/// </summary>
|
||||
@@ -991,21 +1046,27 @@ namespace OpenMetaverse
|
||||
BornOn = Utils.BytesToString(reply.PropertiesData.BornOn)
|
||||
};
|
||||
|
||||
//properties.CharterMember = Utils.BytesToString(reply.PropertiesData.CharterMember);
|
||||
uint charter = Utils.BytesToUInt(reply.PropertiesData.CharterMember);
|
||||
if (charter == 0)
|
||||
if (reply.PropertiesData.CharterMember.Length == 1)
|
||||
{
|
||||
properties.CharterMember = "Resident";
|
||||
uint charter = Utils.BytesToUInt(reply.PropertiesData.CharterMember);
|
||||
if (charter == 0)
|
||||
{
|
||||
properties.CharterMember = "Resident";
|
||||
}
|
||||
else if (charter == 1)
|
||||
{
|
||||
properties.CharterMember = "Trial";
|
||||
}
|
||||
else if (charter == 2)
|
||||
{
|
||||
properties.CharterMember = "Charter";
|
||||
}
|
||||
else if (charter == 3)
|
||||
{
|
||||
properties.CharterMember = "Employee";
|
||||
}
|
||||
}
|
||||
else if (charter == 2)
|
||||
{
|
||||
properties.CharterMember = "Charter";
|
||||
}
|
||||
else if (charter == 3)
|
||||
{
|
||||
properties.CharterMember = "Linden";
|
||||
}
|
||||
else
|
||||
else if (reply.PropertiesData.CharterMember.Length > 1)
|
||||
{
|
||||
properties.CharterMember = Utils.BytesToString(reply.PropertiesData.CharterMember);
|
||||
}
|
||||
@@ -1038,6 +1099,18 @@ namespace OpenMetaverse
|
||||
}
|
||||
}
|
||||
|
||||
protected void AvatarNotesHandler(object sender, PacketReceivedEventArgs e)
|
||||
{
|
||||
if (m_AvatarNotesReply != null)
|
||||
{
|
||||
Packet packet = e.Packet;
|
||||
AvatarNotesReplyPacket anrp = (AvatarNotesReplyPacket)packet;
|
||||
string notes = Utils.BytesToString(anrp.Data.Notes);
|
||||
|
||||
OnAvatarNotesReply(new AvatarNotesReplyEventArgs(anrp.Data.TargetID, notes));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// EQ Message fired when someone nearby changes their display name
|
||||
/// </summary>
|
||||
@@ -1492,6 +1565,22 @@ namespace OpenMetaverse
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Represents the private notes from the profile of an agent</summary>
|
||||
public class AvatarNotesReplyEventArgs : EventArgs
|
||||
{
|
||||
/// <summary>Get the ID of the agent</summary>
|
||||
public UUID AvatarID { get; }
|
||||
|
||||
/// <summary>Get the interests of the agent</summary>
|
||||
public string Notes { get; }
|
||||
|
||||
public AvatarNotesReplyEventArgs(UUID avatarID, string notes)
|
||||
{
|
||||
this.AvatarID = avatarID;
|
||||
this.Notes = notes;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>The properties of an agent</summary>
|
||||
public class AvatarPropertiesReplyEventArgs : EventArgs
|
||||
{
|
||||
|
||||
@@ -43,14 +43,14 @@ namespace OpenMetaverse
|
||||
{
|
||||
get
|
||||
{
|
||||
if (bytePos != 0 && bitPos == 0)
|
||||
if (bytePos != 0 && BitPos == 0)
|
||||
return bytePos - 1;
|
||||
return bytePos;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary></summary>
|
||||
public int BitPos => bitPos;
|
||||
public int BitPos { get; private set; }
|
||||
|
||||
|
||||
private const int MAX_BITS = 8;
|
||||
@@ -58,8 +58,7 @@ namespace OpenMetaverse
|
||||
private static readonly byte[] Off = { 0 };
|
||||
|
||||
private int bytePos;
|
||||
private int bitPos;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor, initialize the bit packer / bit unpacker
|
||||
/// with a byte array and starting position
|
||||
@@ -301,7 +300,7 @@ namespace OpenMetaverse
|
||||
|
||||
public string UnpackString(int size)
|
||||
{
|
||||
if (bitPos != 0 || bytePos + size > Data.Length) throw new IndexOutOfRangeException();
|
||||
if (BitPos != 0 || bytePos + size > Data.Length) throw new IndexOutOfRangeException();
|
||||
|
||||
string str = System.Text.Encoding.UTF8.GetString(Data, bytePos, size);
|
||||
bytePos += size;
|
||||
@@ -310,7 +309,7 @@ namespace OpenMetaverse
|
||||
|
||||
public UUID UnpackUUID()
|
||||
{
|
||||
if (bitPos != 0) throw new IndexOutOfRangeException();
|
||||
if (BitPos != 0) throw new IndexOutOfRangeException();
|
||||
|
||||
UUID val = new UUID(Data, bytePos);
|
||||
bytePos += 16;
|
||||
@@ -338,7 +337,7 @@ namespace OpenMetaverse
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
byte curBit = (byte)(0x80 >> bitPos);
|
||||
byte curBit = (byte)(0x80 >> BitPos);
|
||||
|
||||
if ((data[curBytePos] & (0x01 << (count - 1))) != 0)
|
||||
Data[bytePos] |= curBit;
|
||||
@@ -346,12 +345,12 @@ namespace OpenMetaverse
|
||||
Data[bytePos] &= (byte)~curBit;
|
||||
|
||||
--count;
|
||||
++bitPos;
|
||||
++BitPos;
|
||||
++curBitPos;
|
||||
|
||||
if (bitPos >= MAX_BITS)
|
||||
if (BitPos >= MAX_BITS)
|
||||
{
|
||||
bitPos = 0;
|
||||
BitPos = 0;
|
||||
++bytePos;
|
||||
}
|
||||
if (curBitPos >= MAX_BITS)
|
||||
@@ -389,15 +388,15 @@ namespace OpenMetaverse
|
||||
output[curBytePos] <<= 1;
|
||||
|
||||
// Grab one bit
|
||||
if ((Data[bytePos] & (0x80 >> bitPos++)) != 0)
|
||||
if ((Data[bytePos] & (0x80 >> BitPos++)) != 0)
|
||||
++output[curBytePos];
|
||||
|
||||
--count;
|
||||
++curBitPos;
|
||||
|
||||
if (bitPos >= MAX_BITS)
|
||||
if (BitPos >= MAX_BITS)
|
||||
{
|
||||
bitPos = 0;
|
||||
BitPos = 0;
|
||||
++bytePos;
|
||||
}
|
||||
if (curBitPos >= MAX_BITS)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* Copyright (c) 2019, Cinderblocks Design Co.
|
||||
* Copyright (c) 2019-2022, Sjofn LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
@@ -30,12 +30,19 @@ using System.Net;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
using UnityEngine;
|
||||
|
||||
namespace OpenMetaverse.Http
|
||||
{
|
||||
public static class CapsBase
|
||||
{
|
||||
#region http methods
|
||||
public const string GET = "GET";
|
||||
public const string POST = "POST";
|
||||
public const string PUT = "PUT";
|
||||
public const string DELETE = "DELETE";
|
||||
public const string PATCH = "PATCH"; // rfc 5789
|
||||
#endregion http methods
|
||||
|
||||
public delegate void OpenWriteEventHandler(HttpWebRequest request);
|
||||
public delegate void DownloadProgressEventHandler(HttpWebRequest request, HttpWebResponse response, int bytesReceived, int totalBytesToReceive);
|
||||
public delegate void RequestCompletedEventHandler(HttpWebRequest request, HttpWebResponse response, byte[] responseData, Exception error);
|
||||
@@ -66,7 +73,17 @@ namespace OpenMetaverse.Http
|
||||
}
|
||||
}
|
||||
|
||||
public static HttpWebRequest UploadDataAsync(Uri address, X509Certificate2 clientCert, string contentType, byte[] data,
|
||||
public static HttpWebRequest GetStringAsync(Uri address, X509Certificate2 clientCert, int millisecondsTimeout,
|
||||
DownloadProgressEventHandler downloadProgressCallback, RequestCompletedEventHandler completedCallback)
|
||||
{
|
||||
// Create the request
|
||||
HttpWebRequest request = SetupRequest(address, clientCert);
|
||||
request.Method = GET;
|
||||
DownloadDataAsync(request, millisecondsTimeout, downloadProgressCallback, completedCallback);
|
||||
return request;
|
||||
}
|
||||
|
||||
public static HttpWebRequest PostDataAsync(Uri address, X509Certificate2 clientCert, string contentType, byte[] data,
|
||||
int millisecondsTimeout, OpenWriteEventHandler openWriteCallback, DownloadProgressEventHandler downloadProgressCallback,
|
||||
RequestCompletedEventHandler completedCallback)
|
||||
{
|
||||
@@ -75,7 +92,29 @@ namespace OpenMetaverse.Http
|
||||
request.ContentLength = data.Length;
|
||||
if (!string.IsNullOrEmpty(contentType))
|
||||
request.ContentType = contentType;
|
||||
request.Method = "POST";
|
||||
request.Method = POST;
|
||||
|
||||
// Create an object to hold all of the state for this request
|
||||
var state = new RequestState(request, data, millisecondsTimeout, openWriteCallback,
|
||||
downloadProgressCallback, completedCallback);
|
||||
|
||||
// Start the request for a stream to upload to
|
||||
IAsyncResult result = request.BeginGetRequestStream(OpenWrite, state);
|
||||
// Register a timeout for the request
|
||||
ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, TimeoutCallback, state, millisecondsTimeout, true);
|
||||
|
||||
return request;
|
||||
}
|
||||
public static HttpWebRequest PutDataAsync(Uri address, X509Certificate2 clientCert, string contentType, byte[] data,
|
||||
int millisecondsTimeout, OpenWriteEventHandler openWriteCallback, DownloadProgressEventHandler downloadProgressCallback,
|
||||
RequestCompletedEventHandler completedCallback)
|
||||
{
|
||||
// Create the request
|
||||
var request = SetupRequest(address, clientCert);
|
||||
request.ContentLength = data.Length;
|
||||
if (!string.IsNullOrEmpty(contentType))
|
||||
request.ContentType = contentType;
|
||||
request.Method = PUT;
|
||||
|
||||
// Create an object to hold all of the state for this request
|
||||
var state = new RequestState(request, data, millisecondsTimeout, openWriteCallback,
|
||||
@@ -89,13 +128,49 @@ namespace OpenMetaverse.Http
|
||||
return request;
|
||||
}
|
||||
|
||||
public static HttpWebRequest DownloadStringAsync(Uri address, X509Certificate2 clientCert, int millisecondsTimeout,
|
||||
DownloadProgressEventHandler downloadProgressCallback, RequestCompletedEventHandler completedCallback)
|
||||
public static HttpWebRequest DeleteDataAsync(Uri address, X509Certificate2 clientCert, string contentType, byte[] data,
|
||||
int millisecondsTimeout, OpenWriteEventHandler openWriteCallback, DownloadProgressEventHandler downloadProgressCallback,
|
||||
RequestCompletedEventHandler completedCallback)
|
||||
{
|
||||
// Create the request
|
||||
HttpWebRequest request = SetupRequest(address, clientCert);
|
||||
request.Method = "GET";
|
||||
DownloadDataAsync(request, millisecondsTimeout, downloadProgressCallback, completedCallback);
|
||||
var request = SetupRequest(address, clientCert);
|
||||
request.ContentLength = data.Length;
|
||||
if (!string.IsNullOrEmpty(contentType))
|
||||
request.ContentType = contentType;
|
||||
request.Method = DELETE;
|
||||
|
||||
// Create an object to hold all of the state for this request
|
||||
var state = new RequestState(request, data, millisecondsTimeout, openWriteCallback,
|
||||
downloadProgressCallback, completedCallback);
|
||||
|
||||
// Start the request for a stream to upload to
|
||||
IAsyncResult result = request.BeginGetRequestStream(OpenWrite, state);
|
||||
// Register a timeout for the request
|
||||
ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, TimeoutCallback, state, millisecondsTimeout, true);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
public static HttpWebRequest PatchDataAsync(Uri address, X509Certificate2 clientCert, string contentType, byte[] data,
|
||||
int millisecondsTimeout, OpenWriteEventHandler openWriteCallback, DownloadProgressEventHandler downloadProgressCallback,
|
||||
RequestCompletedEventHandler completedCallback)
|
||||
{
|
||||
// Create the request
|
||||
var request = SetupRequest(address, clientCert);
|
||||
request.ContentLength = data.Length;
|
||||
if (!string.IsNullOrEmpty(contentType))
|
||||
request.ContentType = contentType;
|
||||
request.Method = PATCH;
|
||||
|
||||
// Create an object to hold all of the state for this request
|
||||
var state = new RequestState(request, data, millisecondsTimeout, openWriteCallback,
|
||||
downloadProgressCallback, completedCallback);
|
||||
|
||||
// Start the request for a stream to upload to
|
||||
IAsyncResult result = request.BeginGetRequestStream(OpenWrite, state);
|
||||
// Register a timeout for the request
|
||||
ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, TimeoutCallback, state, millisecondsTimeout, true);
|
||||
|
||||
return request;
|
||||
}
|
||||
|
||||
@@ -108,7 +183,6 @@ namespace OpenMetaverse.Http
|
||||
|
||||
// Start the request for the remote server response
|
||||
IAsyncResult result = request.BeginGetResponse(GetResponse, state);
|
||||
|
||||
// Register a timeout for the request
|
||||
ThreadPool.RegisterWaitForSingleObject(result.AsyncWaitHandle, TimeoutCallback, state, millisecondsTimeout, true);
|
||||
}
|
||||
@@ -135,8 +209,8 @@ namespace OpenMetaverse.Http
|
||||
{
|
||||
Logger.Log(
|
||||
string.Format(
|
||||
"In CapsBase.SetupRequest() setting conn limit for {0}:{1} to {2}",
|
||||
address.Host, address.Port, Settings.MAX_HTTP_CONNECTIONS),
|
||||
"In CapsBase.SetupRequest() setting conn limit for {0}:{1} to {2}",
|
||||
address.Host, address.Port, Settings.MAX_HTTP_CONNECTIONS),
|
||||
Helpers.LogLevel.Debug);
|
||||
request.ServicePoint.ConnectionLimit = Settings.MAX_HTTP_CONNECTIONS;
|
||||
}
|
||||
@@ -205,7 +279,7 @@ namespace OpenMetaverse.Http
|
||||
int totalBytesRead = 0;
|
||||
int totalSize = nolength ? 0 : size;
|
||||
|
||||
while ((bytesRead = responseStream.Read(buffer, offset, size)) != 0)
|
||||
while (responseStream != null && (bytesRead = responseStream.Read(buffer, offset, size)) != 0)
|
||||
{
|
||||
totalBytesRead += bytesRead;
|
||||
|
||||
|
||||
@@ -52,16 +52,33 @@ namespace OpenMetaverse.Http
|
||||
protected OSD _Response;
|
||||
protected AutoResetEvent _ResponseEvent = new AutoResetEvent(false);
|
||||
|
||||
#region Constructors
|
||||
|
||||
/// <summary>
|
||||
/// CapsClient Ctor
|
||||
/// </summary>
|
||||
/// <param name="capability"><seealso cref="Uri"/> for simulator capability</param>
|
||||
public CapsClient(Uri capability)
|
||||
: this(capability, null, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// CapsClient Ctor with name
|
||||
/// </summary>
|
||||
/// <param name="capability"><seealso cref="Uri"/> for simulator capability</param>
|
||||
/// <param name="cap_name">Simulator capability name</param>
|
||||
public CapsClient(Uri capability, string cap_name)
|
||||
: this(capability, cap_name, null)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// CapsClient Ctor with name and certificate
|
||||
/// </summary>
|
||||
/// <param name="capability"><seealso cref="Uri"/> for simulator capability</param>
|
||||
/// <param name="cap_name">Simulator capability name</param>
|
||||
/// <param name="clientCert"><seealso cref="X509Certificate2"/> client certificate</param>
|
||||
public CapsClient(Uri capability, string cap_name, X509Certificate2 clientCert)
|
||||
{
|
||||
_Address = capability;
|
||||
@@ -69,37 +86,48 @@ namespace OpenMetaverse.Http
|
||||
_ClientCert = clientCert;
|
||||
}
|
||||
|
||||
public void BeginGetResponse(int millisecondsTimeout)
|
||||
{
|
||||
BeginGetResponse(null, null, millisecondsTimeout);
|
||||
}
|
||||
#endregion Constructors
|
||||
|
||||
public void BeginGetResponse(OSD data, OSDFormat format, int millisecondsTimeout)
|
||||
{
|
||||
byte[] postData;
|
||||
string contentType;
|
||||
#region GET requests
|
||||
|
||||
switch (format)
|
||||
public void GetRequestAsync(int msTimeout)
|
||||
{
|
||||
if (_Request != null)
|
||||
{
|
||||
case OSDFormat.Xml:
|
||||
postData = OSDParser.SerializeLLSDXmlBytes(data);
|
||||
contentType = "application/llsd+xml";
|
||||
break;
|
||||
case OSDFormat.Binary:
|
||||
postData = OSDParser.SerializeLLSDBinary(data);
|
||||
contentType = "application/llsd+binary";
|
||||
break;
|
||||
case OSDFormat.Json:
|
||||
default:
|
||||
postData = System.Text.Encoding.UTF8.GetBytes(OSDParser.SerializeJsonString(data));
|
||||
contentType = "application/llsd+json";
|
||||
break;
|
||||
_Request.Abort();
|
||||
_Request = null;
|
||||
}
|
||||
|
||||
BeginGetResponse(postData, contentType, millisecondsTimeout);
|
||||
// GET
|
||||
Logger.DebugLog("[CapsClient] GET " + _Address);
|
||||
_Request = CapsBase.GetStringAsync(_Address, _ClientCert, msTimeout, DownloadProgressHandler,
|
||||
RequestCompletedHandler);
|
||||
}
|
||||
|
||||
public void BeginGetResponse(byte[] postData, string contentType, int millisecondsTimeout)
|
||||
public OSD GetRequest(int msTimeout)
|
||||
{
|
||||
GetRequestAsync(msTimeout);
|
||||
_ResponseEvent.WaitOne(msTimeout, false);
|
||||
return _Response;
|
||||
}
|
||||
|
||||
#endregion GET requests
|
||||
|
||||
#region POST requests
|
||||
|
||||
public void PostRequestAsync(OSD data, OSDFormat format, int msTimeout)
|
||||
{
|
||||
serializeData(data, format, out byte[] serializedData, out string contentType);
|
||||
PostRequestAsync(serializedData, contentType, msTimeout);
|
||||
}
|
||||
|
||||
public OSD PostRequest(OSD data, OSDFormat format, int msTimeout)
|
||||
{
|
||||
PostRequestAsync(data, format, msTimeout);
|
||||
_ResponseEvent.WaitOne(msTimeout, false);
|
||||
return _Response;
|
||||
}
|
||||
|
||||
public void PostRequestAsync(byte[] postData, string contentType, int msTimeout)
|
||||
{
|
||||
_PostData = postData;
|
||||
_ContentType = contentType;
|
||||
@@ -109,44 +137,143 @@ namespace OpenMetaverse.Http
|
||||
_Request.Abort();
|
||||
_Request = null;
|
||||
}
|
||||
// POST
|
||||
Logger.DebugLog("[CapsClient] POST (" + postData.Length + " bytes) " + _Address);
|
||||
|
||||
if (postData == null)
|
||||
_Request = CapsBase.PostDataAsync(_Address, _ClientCert, contentType, postData, msTimeout,
|
||||
null, DownloadProgressHandler, RequestCompletedHandler);
|
||||
}
|
||||
|
||||
public OSD PostRequest(byte[] postData, string contentType, int msTimeout)
|
||||
{
|
||||
PostRequestAsync(postData, contentType, msTimeout);
|
||||
_ResponseEvent.WaitOne(msTimeout, false);
|
||||
return _Response;
|
||||
}
|
||||
|
||||
#endregion POST requests
|
||||
|
||||
#region PUT requests
|
||||
|
||||
public void PutRequestAsync(OSD data, OSDFormat format, int msTimeout)
|
||||
{
|
||||
serializeData(data, format, out byte[] serializedData, out string contentType);
|
||||
PutRequestAsync(serializedData, contentType, msTimeout);
|
||||
}
|
||||
|
||||
public OSD PutRequest(OSD data, OSDFormat format, int msTimeout)
|
||||
{
|
||||
PutRequestAsync(data, format, msTimeout);
|
||||
_ResponseEvent.WaitOne(msTimeout, false);
|
||||
return _Response;
|
||||
}
|
||||
|
||||
public void PutRequestAsync(byte[] postData, string contentType, int msTimeout)
|
||||
{
|
||||
_PostData = postData;
|
||||
_ContentType = contentType;
|
||||
|
||||
if (_Request != null)
|
||||
{
|
||||
// GET
|
||||
Logger.DebugLog("[CapsClient] GET " + _Address);
|
||||
_Request = CapsBase.DownloadStringAsync(_Address, _ClientCert, millisecondsTimeout, DownloadProgressHandler,
|
||||
RequestCompletedHandler);
|
||||
_Request.Abort();
|
||||
_Request = null;
|
||||
}
|
||||
else
|
||||
// PUT
|
||||
Logger.DebugLog("[CapsClient] PUT " + _Address);
|
||||
|
||||
_Request = CapsBase.PutDataAsync(_Address, _ClientCert, contentType, postData, msTimeout,
|
||||
null, DownloadProgressHandler, RequestCompletedHandler);
|
||||
}
|
||||
|
||||
public OSD PutRequest(byte[] postData, string contentType, int msTimeout)
|
||||
{
|
||||
PutRequestAsync(postData, contentType, msTimeout);
|
||||
_ResponseEvent.WaitOne(msTimeout, false);
|
||||
return _Response;
|
||||
}
|
||||
|
||||
#endregion PUT requests
|
||||
|
||||
#region PATCH requests
|
||||
|
||||
public void PatchRequestAsync(OSD data, OSDFormat format, int msTimeout)
|
||||
{
|
||||
serializeData(data, format, out byte[] serializedData, out string contentType);
|
||||
PatchRequestAsync(serializedData, contentType, msTimeout);
|
||||
}
|
||||
|
||||
public OSD PatchRequest(OSD data, OSDFormat format, int msTimeout)
|
||||
{
|
||||
PatchRequestAsync(data, format, msTimeout);
|
||||
_ResponseEvent.WaitOne(msTimeout, false);
|
||||
return _Response;
|
||||
}
|
||||
|
||||
public void PatchRequestAsync(byte[] postData, string contentType, int msTimeout)
|
||||
{
|
||||
_PostData = postData;
|
||||
_ContentType = contentType;
|
||||
|
||||
if (_Request != null)
|
||||
{
|
||||
// POST
|
||||
Logger.DebugLog("[CapsClient] POST (" + postData.Length + " bytes) " + _Address);
|
||||
_Request = CapsBase.UploadDataAsync(_Address, _ClientCert, contentType, postData, millisecondsTimeout, null,
|
||||
DownloadProgressHandler, RequestCompletedHandler);
|
||||
_Request.Abort();
|
||||
_Request = null;
|
||||
}
|
||||
// PATCH
|
||||
Logger.DebugLog("[CapsClient] PATCH " + _Address);
|
||||
_Request = CapsBase.PatchDataAsync(_Address, _ClientCert, contentType, postData, msTimeout,
|
||||
null, DownloadProgressHandler, RequestCompletedHandler);
|
||||
}
|
||||
|
||||
public OSD GetResponse(int millisecondsTimeout)
|
||||
public OSD PatchRequest(byte[] postData, string contentType, int msTimeout)
|
||||
{
|
||||
BeginGetResponse(millisecondsTimeout);
|
||||
_ResponseEvent.WaitOne(millisecondsTimeout, false);
|
||||
PatchRequestAsync(postData, contentType, msTimeout);
|
||||
_ResponseEvent.WaitOne(msTimeout, false);
|
||||
return _Response;
|
||||
}
|
||||
|
||||
public OSD GetResponse(OSD data, OSDFormat format, int millisecondsTimeout)
|
||||
#endregion PATCH requests
|
||||
|
||||
#region DELETE requests
|
||||
|
||||
public void DeleteRequestAsync(OSD data, OSDFormat format, int msTimeout)
|
||||
{
|
||||
BeginGetResponse(data, format, millisecondsTimeout);
|
||||
_ResponseEvent.WaitOne(millisecondsTimeout, false);
|
||||
serializeData(data, format, out byte[] serializedData, out string contentType);
|
||||
DeleteRequestAsync(serializedData, contentType, msTimeout);
|
||||
}
|
||||
|
||||
public OSD DeleteRequest(OSD data, OSDFormat format, int msTimeout)
|
||||
{
|
||||
DeleteRequestAsync(data, format, msTimeout);
|
||||
_ResponseEvent.WaitOne(msTimeout, false);
|
||||
return _Response;
|
||||
}
|
||||
|
||||
public OSD GetResponse(byte[] postData, string contentType, int millisecondsTimeout)
|
||||
public void DeleteRequestAsync(byte[] postData, string contentType, int msTimeout)
|
||||
{
|
||||
BeginGetResponse(postData, contentType, millisecondsTimeout);
|
||||
_ResponseEvent.WaitOne(millisecondsTimeout, false);
|
||||
_PostData = postData;
|
||||
_ContentType = contentType;
|
||||
|
||||
if (_Request != null)
|
||||
{
|
||||
_Request.Abort();
|
||||
_Request = null;
|
||||
}
|
||||
// DELETE
|
||||
Logger.DebugLog("[CapsClient] DELETE " + _Address);
|
||||
_Request = CapsBase.DeleteDataAsync(_Address, _ClientCert, contentType, postData, msTimeout,
|
||||
null, DownloadProgressHandler, RequestCompletedHandler);
|
||||
}
|
||||
|
||||
public OSD DeleteRequest(byte[] postData, string contentType, int msTimeout)
|
||||
{
|
||||
PatchRequestAsync(postData, contentType, msTimeout);
|
||||
_ResponseEvent.WaitOne(msTimeout, false);
|
||||
return _Response;
|
||||
}
|
||||
|
||||
#endregion DELETE requests
|
||||
|
||||
public void Cancel()
|
||||
{
|
||||
_Request?.Abort();
|
||||
@@ -181,6 +308,33 @@ namespace OpenMetaverse.Http
|
||||
FireCompleteCallback(result, error);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serializes OSD data for http request
|
||||
/// </summary>
|
||||
/// <param name="data"><seealso cref="OSD"/>formatted data for input</param>
|
||||
/// <param name="format">Format to serialize data to</param>
|
||||
/// <param name="serializedData">Output serialized data as byte array</param>
|
||||
/// <param name="contentType">content-type string of serialized data</param>
|
||||
private void serializeData(OSD data, OSDFormat format, out byte[] serializedData, out string contentType)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case OSDFormat.Xml:
|
||||
serializedData = OSDParser.SerializeLLSDXmlBytes(data);
|
||||
contentType = "application/llsd+xml";
|
||||
break;
|
||||
case OSDFormat.Binary:
|
||||
serializedData = OSDParser.SerializeLLSDBinary(data);
|
||||
contentType = "application/llsd+binary";
|
||||
break;
|
||||
case OSDFormat.Json:
|
||||
default:
|
||||
serializedData = System.Text.Encoding.UTF8.GetBytes(OSDParser.SerializeJsonString(data));
|
||||
contentType = "application/llsd+json";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void FireCompleteCallback(OSD result, Exception error)
|
||||
{
|
||||
CompleteCallback callback = OnComplete;
|
||||
|
||||
@@ -73,7 +73,7 @@ namespace OpenMetaverse.Http
|
||||
|
||||
byte[] postData = OSDParser.SerializeLLSDXmlBytes(request);
|
||||
|
||||
_Request = CapsBase.UploadDataAsync(_Address, null, REQUEST_CONTENT_TYPE, postData, REQUEST_TIMEOUT, OpenWriteHandler, null, RequestCompletedHandler);
|
||||
_Request = CapsBase.PostDataAsync(_Address, null, REQUEST_CONTENT_TYPE, postData, REQUEST_TIMEOUT, OpenWriteHandler, null, RequestCompletedHandler);
|
||||
}
|
||||
|
||||
public void Stop(bool immediate)
|
||||
@@ -211,7 +211,7 @@ namespace OpenMetaverse.Http
|
||||
|
||||
// Resume the connection. The event handler for the connection opening
|
||||
// just sets class _Request variable to the current HttpWebRequest
|
||||
CapsBase.UploadDataAsync(_Address, null, REQUEST_CONTENT_TYPE, postData, REQUEST_TIMEOUT,
|
||||
CapsBase.PostDataAsync(_Address, null, REQUEST_CONTENT_TYPE, postData, REQUEST_TIMEOUT,
|
||||
delegate(HttpWebRequest newRequest) { _Request = newRequest; }, null, RequestCompletedHandler);
|
||||
|
||||
// If the event queue is dead at this point, turn it off since
|
||||
|
||||
@@ -172,9 +172,7 @@ namespace OpenMetaverse
|
||||
"EnvironmentSettings",
|
||||
"EstateChangeInfo",
|
||||
"EventQueueGet",
|
||||
"FacebookConnect",
|
||||
"FlickrConnect",
|
||||
"TwitterConnect",
|
||||
"ExtEnvironment",
|
||||
"FetchLib2",
|
||||
"FetchLibDescendents2",
|
||||
"FetchInventory2",
|
||||
@@ -193,6 +191,7 @@ namespace OpenMetaverse
|
||||
"IsExperienceAdmin",
|
||||
"IsExperienceContributor",
|
||||
"RegionExperiences",
|
||||
"ExperienceQuery",
|
||||
"GetMesh",
|
||||
"GetMesh2",
|
||||
"GetMetadata",
|
||||
@@ -221,7 +220,6 @@ namespace OpenMetaverse
|
||||
"RemoteParcelRequest",
|
||||
"RenderMaterials",
|
||||
"RequestTextureDownload",
|
||||
"RequiredVoiceVersion",
|
||||
"ResourceCostSelected",
|
||||
"RetrieveNavMeshSrc",
|
||||
"SearchStatRequest",
|
||||
@@ -249,6 +247,7 @@ namespace OpenMetaverse
|
||||
"UploadBakedTexture",
|
||||
"UserInfo",
|
||||
"ViewerAsset",
|
||||
"ViewerBenefits",
|
||||
"ViewerMetrics",
|
||||
"ViewerStartAuction",
|
||||
"ViewerStats",
|
||||
@@ -259,7 +258,7 @@ namespace OpenMetaverse
|
||||
|
||||
_SeedRequest = new CapsClient(new Uri(_SeedCapsURI), "SeedCaps");
|
||||
_SeedRequest.OnComplete += SeedRequestCompleteHandler;
|
||||
_SeedRequest.BeginGetResponse(req, OSDFormat.Xml, Simulator.Client.Settings.CAPS_TIMEOUT);
|
||||
_SeedRequest.PostRequestAsync(req, OSDFormat.Xml, Simulator.Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
|
||||
private void SeedRequestCompleteHandler(CapsClient client, OSD result, Exception error)
|
||||
|
||||
@@ -355,7 +355,7 @@ namespace OpenMetaverse
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parcel information returned from a <see cref="StartPlacesSearch"/> request
|
||||
/// Parcel information returned from a <see cref="DirectoryManager.StartPlacesSearch"/> request
|
||||
/// <para>
|
||||
/// Represents one of the following:
|
||||
/// A parcel of land on the grid that has its Show In Search flag set
|
||||
@@ -514,8 +514,7 @@ namespace OpenMetaverse
|
||||
protected virtual void OnEventInfo(EventInfoReplyEventArgs e)
|
||||
{
|
||||
EventHandler<EventInfoReplyEventArgs> handler = m_EventInfoReply;
|
||||
if (handler != null)
|
||||
handler(this, e);
|
||||
handler?.Invoke(this, e);
|
||||
}
|
||||
|
||||
/// <summary>Thread sync lock object</summary>
|
||||
@@ -537,21 +536,20 @@ namespace OpenMetaverse
|
||||
protected virtual void OnDirEvents(DirEventsReplyEventArgs e)
|
||||
{
|
||||
EventHandler<DirEventsReplyEventArgs> handler = m_DirEvents;
|
||||
if (handler != null)
|
||||
handler(this, e);
|
||||
handler?.Invoke(this, e);
|
||||
}
|
||||
|
||||
/// <summary>Thread sync lock object</summary>
|
||||
private readonly object m_DirEventsLock = new object();
|
||||
|
||||
/// <summary>Raised when the data server responds to a <see cref="StartEventsSearch"/> request.</summary>
|
||||
/// <summary>Raised when the data server responds to a <see cref="DirectoryManager.StartEventsSearch"/> request.</summary>
|
||||
public event EventHandler<DirEventsReplyEventArgs> DirEventsReply
|
||||
{
|
||||
add { lock (m_DirEventsLock) { m_DirEvents += value; } }
|
||||
remove { lock (m_DirEventsLock) { m_DirEvents -= value; } }
|
||||
}
|
||||
|
||||
/// <summary>The event subscribers. null if no subcribers</summary>
|
||||
/// <summary>The event subscribers. null if no subscribers</summary>
|
||||
private EventHandler<PlacesReplyEventArgs> m_Places;
|
||||
|
||||
/// <summary>Raises the PlacesReply event</summary>
|
||||
@@ -560,21 +558,20 @@ namespace OpenMetaverse
|
||||
protected virtual void OnPlaces(PlacesReplyEventArgs e)
|
||||
{
|
||||
EventHandler<PlacesReplyEventArgs> handler = m_Places;
|
||||
if (handler != null)
|
||||
handler(this, e);
|
||||
handler?.Invoke(this, e);
|
||||
}
|
||||
|
||||
/// <summary>Thread sync lock object</summary>
|
||||
private readonly object m_PlacesLock = new object();
|
||||
|
||||
/// <summary>Raised when the data server responds to a <see cref="StartPlacesSearch"/> request.</summary>
|
||||
/// <summary>Raised when the data server responds to a <see cref="DirectoryManager.StartPlacesSearch"/> request.</summary>
|
||||
public event EventHandler<PlacesReplyEventArgs> PlacesReply
|
||||
{
|
||||
add { lock (m_PlacesLock) { m_Places += value; } }
|
||||
remove { lock (m_PlacesLock) { m_Places -= value; } }
|
||||
}
|
||||
|
||||
/// <summary>The event subscribers. null if no subcribers</summary>
|
||||
/// <summary>The event subscribers. null if no subscribers</summary>
|
||||
private EventHandler<DirPlacesReplyEventArgs> m_DirPlaces;
|
||||
|
||||
/// <summary>Raises the DirPlacesReply event</summary>
|
||||
@@ -583,14 +580,13 @@ namespace OpenMetaverse
|
||||
protected virtual void OnDirPlaces(DirPlacesReplyEventArgs e)
|
||||
{
|
||||
EventHandler<DirPlacesReplyEventArgs> handler = m_DirPlaces;
|
||||
if (handler != null)
|
||||
handler(this, e);
|
||||
handler?.Invoke(this, e);
|
||||
}
|
||||
|
||||
/// <summary>Thread sync lock object</summary>
|
||||
private readonly object m_DirPlacesLock = new object();
|
||||
|
||||
/// <summary>Raised when the data server responds to a <see cref="StartDirPlacesSearch"/> request.</summary>
|
||||
/// <summary>Raised when the data server responds to a <see cref="DirectoryManager.StartDirPlacesSearch"/> request.</summary>
|
||||
public event EventHandler<DirPlacesReplyEventArgs> DirPlacesReply
|
||||
{
|
||||
add { lock (m_DirPlacesLock) { m_DirPlaces += value; } }
|
||||
@@ -606,14 +602,13 @@ namespace OpenMetaverse
|
||||
protected virtual void OnDirClassifieds(DirClassifiedsReplyEventArgs e)
|
||||
{
|
||||
EventHandler<DirClassifiedsReplyEventArgs> handler = m_DirClassifieds;
|
||||
if (handler != null)
|
||||
handler(this, e);
|
||||
handler?.Invoke(this, e);
|
||||
}
|
||||
|
||||
/// <summary>Thread sync lock object</summary>
|
||||
private readonly object m_DirClassifiedsLock = new object();
|
||||
|
||||
/// <summary>Raised when the data server responds to a <see cref="StartClassifiedSearch"/> request.</summary>
|
||||
/// <summary>Raised when the data server responds to a <see cref="DirectoryManager.StartClassifiedSearch"/> request.</summary>
|
||||
public event EventHandler<DirClassifiedsReplyEventArgs> DirClassifiedsReply
|
||||
{
|
||||
add { lock (m_DirClassifiedsLock) { m_DirClassifieds += value; } }
|
||||
@@ -629,14 +624,13 @@ namespace OpenMetaverse
|
||||
protected virtual void OnDirGroups(DirGroupsReplyEventArgs e)
|
||||
{
|
||||
EventHandler<DirGroupsReplyEventArgs> handler = m_DirGroups;
|
||||
if (handler != null)
|
||||
handler(this, e);
|
||||
handler?.Invoke(this, e);
|
||||
}
|
||||
|
||||
/// <summary>Thread sync lock object</summary>
|
||||
private readonly object m_DirGroupsLock = new object();
|
||||
|
||||
/// <summary>Raised when the data server responds to a <see cref="StartGroupSearch"/> request.</summary>
|
||||
/// <summary>Raised when the data server responds to a <see cref="DirectoryManager.StartGroupSearch"/> request.</summary>
|
||||
public event EventHandler<DirGroupsReplyEventArgs> DirGroupsReply
|
||||
{
|
||||
add { lock (m_DirGroupsLock) { m_DirGroups += value; } }
|
||||
@@ -652,14 +646,13 @@ namespace OpenMetaverse
|
||||
protected virtual void OnDirPeople(DirPeopleReplyEventArgs e)
|
||||
{
|
||||
EventHandler<DirPeopleReplyEventArgs> handler = m_DirPeople;
|
||||
if (handler != null)
|
||||
handler(this, e);
|
||||
handler?.Invoke(this, e);
|
||||
}
|
||||
|
||||
/// <summary>Thread sync lock object</summary>
|
||||
private readonly object m_DirPeopleLock = new object();
|
||||
|
||||
/// <summary>Raised when the data server responds to a <see cref="StartPeopleSearch"/> request.</summary>
|
||||
/// <summary>Raised when the data server responds to a <see cref="DirectoryManager.StartPeopleSearch"/> request.</summary>
|
||||
public event EventHandler<DirPeopleReplyEventArgs> DirPeopleReply
|
||||
{
|
||||
add { lock (m_DirPeopleLock) { m_DirPeople += value; } }
|
||||
@@ -675,14 +668,13 @@ namespace OpenMetaverse
|
||||
protected virtual void OnDirLand(DirLandReplyEventArgs e)
|
||||
{
|
||||
EventHandler<DirLandReplyEventArgs> handler = m_DirLandReply;
|
||||
if (handler != null)
|
||||
handler(this, e);
|
||||
handler?.Invoke(this, e);
|
||||
}
|
||||
|
||||
/// <summary>Thread sync lock object</summary>
|
||||
private readonly object m_DirLandLock = new object();
|
||||
|
||||
/// <summary>Raised when the data server responds to a <see cref="StartLandSearch"/> request.</summary>
|
||||
/// <summary>Raised when the data server responds to a <see cref="DirectoryManager.StartLandSearch"/> request.</summary>
|
||||
public event EventHandler<DirLandReplyEventArgs> DirLandReply
|
||||
{
|
||||
add { lock (m_DirLandLock) { m_DirLandReply += value; } }
|
||||
@@ -1446,32 +1438,27 @@ namespace OpenMetaverse
|
||||
/// <summary>Contains the Event data returned from the data server from an EventInfoRequest</summary>
|
||||
public class EventInfoReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly DirectoryManager.EventInfo m_MatchedEvent;
|
||||
|
||||
/// <summary>
|
||||
/// A single EventInfo object containing the details of an event
|
||||
/// </summary>
|
||||
public DirectoryManager.EventInfo MatchedEvent { get { return m_MatchedEvent; } }
|
||||
public DirectoryManager.EventInfo MatchedEvent { get; }
|
||||
|
||||
/// <summary>Construct a new instance of the EventInfoReplyEventArgs class</summary>
|
||||
/// <param name="matchedEvent">A single EventInfo object containing the details of an event</param>
|
||||
public EventInfoReplyEventArgs(DirectoryManager.EventInfo matchedEvent)
|
||||
{
|
||||
this.m_MatchedEvent = matchedEvent;
|
||||
this.MatchedEvent = matchedEvent;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Contains the "Event" detail data returned from the data server</summary>
|
||||
public class DirEventsReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly UUID m_QueryID;
|
||||
/// <summary>The ID returned by <see cref="DirectoryManager.StartEventsSearch"/></summary>
|
||||
public UUID QueryID { get { return m_QueryID; } }
|
||||
|
||||
private readonly List<DirectoryManager.EventsSearchData> m_matchedEvents;
|
||||
public UUID QueryID { get; }
|
||||
|
||||
/// <summary>A list of "Events" returned by the data server</summary>
|
||||
public List<DirectoryManager.EventsSearchData> MatchedEvents { get { return m_matchedEvents; } }
|
||||
public List<DirectoryManager.EventsSearchData> MatchedEvents { get; }
|
||||
|
||||
/// <summary>Construct a new instance of the DirEventsReplyEventArgs class</summary>
|
||||
/// <param name="queryID">The ID of the query returned by the data server.
|
||||
@@ -1479,22 +1466,19 @@ namespace OpenMetaverse
|
||||
/// <param name="matchedEvents">A list containing the "Events" returned by the search query</param>
|
||||
public DirEventsReplyEventArgs(UUID queryID, List<DirectoryManager.EventsSearchData> matchedEvents)
|
||||
{
|
||||
this.m_QueryID = queryID;
|
||||
this.m_matchedEvents = matchedEvents;
|
||||
this.QueryID = queryID;
|
||||
this.MatchedEvents = matchedEvents;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Contains the "Event" list data returned from the data server</summary>
|
||||
public class PlacesReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly UUID m_QueryID;
|
||||
/// <summary>The ID returned by <see cref="DirectoryManager.StartPlacesSearch"/></summary>
|
||||
public UUID QueryID { get { return m_QueryID; } }
|
||||
|
||||
private readonly List<DirectoryManager.PlacesSearchData> m_MatchedPlaces;
|
||||
public UUID QueryID { get; }
|
||||
|
||||
/// <summary>A list of "Places" returned by the data server</summary>
|
||||
public List<DirectoryManager.PlacesSearchData> MatchedPlaces { get { return m_MatchedPlaces; } }
|
||||
public List<DirectoryManager.PlacesSearchData> MatchedPlaces { get; }
|
||||
|
||||
/// <summary>Construct a new instance of PlacesReplyEventArgs class</summary>
|
||||
/// <param name="queryID">The ID of the query returned by the data server.
|
||||
@@ -1502,60 +1486,53 @@ namespace OpenMetaverse
|
||||
/// <param name="matchedPlaces">A list containing the "Places" returned by the data server query</param>
|
||||
public PlacesReplyEventArgs(UUID queryID, List<DirectoryManager.PlacesSearchData> matchedPlaces)
|
||||
{
|
||||
this.m_QueryID = queryID;
|
||||
this.m_MatchedPlaces = matchedPlaces;
|
||||
this.QueryID = queryID;
|
||||
this.MatchedPlaces = matchedPlaces;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Contains the places data returned from the data server</summary>
|
||||
public class DirPlacesReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly UUID m_QueryID;
|
||||
/// <summary>The ID returned by <see cref="DirectoryManager.StartDirPlacesSearch"/></summary>
|
||||
public UUID QueryID { get { return m_QueryID; } }
|
||||
|
||||
private readonly List<DirectoryManager.DirectoryParcel> m_MatchedParcels;
|
||||
public UUID QueryID { get; }
|
||||
|
||||
/// <summary>A list containing Places data returned by the data server</summary>
|
||||
public List<DirectoryManager.DirectoryParcel> MatchedParcels { get { return m_MatchedParcels; } }
|
||||
|
||||
public List<DirectoryManager.DirectoryParcel> MatchedParcels { get; }
|
||||
|
||||
/// <summary>Construct a new instance of the DirPlacesReplyEventArgs class</summary>
|
||||
/// <param name="queryID">The ID of the query returned by the data server.
|
||||
/// This will correlate to the ID returned by the <see cref="StartDirPlacesSearch"/> method</param>
|
||||
/// <param name="matchedParcels">A list containing land data returned by the data server</param>
|
||||
public DirPlacesReplyEventArgs(UUID queryID, List<DirectoryManager.DirectoryParcel> matchedParcels)
|
||||
{
|
||||
this.m_QueryID = queryID;
|
||||
this.m_MatchedParcels = matchedParcels;
|
||||
this.QueryID = queryID;
|
||||
this.MatchedParcels = matchedParcels;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Contains the classified data returned from the data server</summary>
|
||||
public class DirClassifiedsReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly List<DirectoryManager.Classified> m_Classifieds;
|
||||
/// <summary>A list containing Classified Ads returned by the data server</summary>
|
||||
public List<DirectoryManager.Classified> Classifieds { get { return m_Classifieds; } }
|
||||
public List<DirectoryManager.Classified> Classifieds { get; }
|
||||
|
||||
/// <summary>Construct a new instance of the DirClassifiedsReplyEventArgs class</summary>
|
||||
/// <param name="classifieds">A list of classified ad data returned from the data server</param>
|
||||
public DirClassifiedsReplyEventArgs(List<DirectoryManager.Classified> classifieds)
|
||||
{
|
||||
this.m_Classifieds = classifieds;
|
||||
this.Classifieds = classifieds;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Contains the group data returned from the data server</summary>
|
||||
public class DirGroupsReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly UUID m_QueryID;
|
||||
/// <summary>The ID returned by <see cref="DirectoryManager.StartGroupSearch"/></summary>
|
||||
public UUID QueryID { get { return m_QueryID; } }
|
||||
|
||||
private readonly List<DirectoryManager.GroupSearchData> m_matchedGroups;
|
||||
public UUID QueryID { get; }
|
||||
|
||||
/// <summary>A list containing Groups data returned by the data server</summary>
|
||||
public List<DirectoryManager.GroupSearchData> MatchedGroups { get { return m_matchedGroups; } }
|
||||
public List<DirectoryManager.GroupSearchData> MatchedGroups { get; }
|
||||
|
||||
/// <summary>Construct a new instance of the DirGroupsReplyEventArgs class</summary>
|
||||
/// <param name="queryID">The ID of the query returned by the data server.
|
||||
@@ -1563,22 +1540,19 @@ namespace OpenMetaverse
|
||||
/// <param name="matchedGroups">A list of groups data returned by the data server</param>
|
||||
public DirGroupsReplyEventArgs(UUID queryID, List<DirectoryManager.GroupSearchData> matchedGroups)
|
||||
{
|
||||
this.m_QueryID = queryID;
|
||||
this.m_matchedGroups = matchedGroups;
|
||||
this.QueryID = queryID;
|
||||
this.MatchedGroups = matchedGroups;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Contains the people data returned from the data server</summary>
|
||||
public class DirPeopleReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly UUID m_QueryID;
|
||||
/// <summary>The ID returned by <see cref="DirectoryManager.StartPeopleSearch"/></summary>
|
||||
public UUID QueryID { get { return m_QueryID; } }
|
||||
|
||||
private readonly List<DirectoryManager.AgentSearchData> m_MatchedPeople;
|
||||
public UUID QueryID { get; }
|
||||
|
||||
/// <summary>A list containing People data returned by the data server</summary>
|
||||
public List<DirectoryManager.AgentSearchData> MatchedPeople { get { return m_MatchedPeople; } }
|
||||
public List<DirectoryManager.AgentSearchData> MatchedPeople { get; }
|
||||
|
||||
/// <summary>Construct a new instance of the DirPeopleReplyEventArgs class</summary>
|
||||
/// <param name="queryID">The ID of the query returned by the data server.
|
||||
@@ -1586,24 +1560,22 @@ namespace OpenMetaverse
|
||||
/// <param name="matchedPeople">A list of people data returned by the data server</param>
|
||||
public DirPeopleReplyEventArgs(UUID queryID, List<DirectoryManager.AgentSearchData> matchedPeople)
|
||||
{
|
||||
this.m_QueryID = queryID;
|
||||
this.m_MatchedPeople = matchedPeople;
|
||||
this.QueryID = queryID;
|
||||
this.MatchedPeople = matchedPeople;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Contains the land sales data returned from the data server</summary>
|
||||
public class DirLandReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly List<DirectoryManager.DirectoryParcel> m_DirParcels;
|
||||
|
||||
/// <summary>A list containing land forsale data returned by the data server</summary>
|
||||
public List<DirectoryManager.DirectoryParcel> DirParcels { get { return m_DirParcels; } }
|
||||
public List<DirectoryManager.DirectoryParcel> DirParcels { get; }
|
||||
|
||||
/// <summary>Construct a new instance of the DirLandReplyEventArgs class</summary>
|
||||
/// <param name="dirParcels">A list of parcels for sale returned by the data server</param>
|
||||
public DirLandReplyEventArgs(List<DirectoryManager.DirectoryParcel> dirParcels)
|
||||
{
|
||||
this.m_DirParcels = dirParcels;
|
||||
this.DirParcels = dirParcels;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -984,72 +984,66 @@ namespace OpenMetaverse
|
||||
/// <summary>Raised on LandStatReply when the report type is for "top colliders"</summary>
|
||||
public class TopCollidersReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly int m_objectCount;
|
||||
private readonly Dictionary<UUID, EstateTask> m_Tasks;
|
||||
|
||||
/// <summary>
|
||||
/// The number of returned items in LandStatReply
|
||||
/// </summary>
|
||||
public int ObjectCount { get { return m_objectCount; } }
|
||||
public int ObjectCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// A Dictionary of Object UUIDs to tasks returned in LandStatReply
|
||||
/// </summary>
|
||||
public Dictionary<UUID, EstateTask> Tasks { get { return m_Tasks; } }
|
||||
public Dictionary<UUID, EstateTask> Tasks { get; }
|
||||
|
||||
/// <summary>Construct a new instance of the TopCollidersReplyEventArgs class</summary>
|
||||
/// <param name="objectCount">The number of returned items in LandStatReply</param>
|
||||
/// <param name="tasks">Dictionary of Object UUIDs to tasks returned in LandStatReply</param>
|
||||
public TopCollidersReplyEventArgs(int objectCount, Dictionary<UUID, EstateTask> tasks)
|
||||
{
|
||||
this.m_objectCount = objectCount;
|
||||
this.m_Tasks = tasks;
|
||||
this.ObjectCount = objectCount;
|
||||
this.Tasks = tasks;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Raised on LandStatReply when the report type is for "top Scripts"</summary>
|
||||
public class TopScriptsReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly int m_objectCount;
|
||||
private readonly Dictionary<UUID, EstateTask> m_Tasks;
|
||||
|
||||
/// <summary>
|
||||
/// The number of scripts returned in LandStatReply
|
||||
/// </summary>
|
||||
public int ObjectCount { get { return m_objectCount; } }
|
||||
public int ObjectCount { get; }
|
||||
|
||||
/// <summary>
|
||||
/// A Dictionary of Object UUIDs to tasks returned in LandStatReply
|
||||
/// </summary>
|
||||
public Dictionary<UUID, EstateTask> Tasks { get { return m_Tasks; } }
|
||||
public Dictionary<UUID, EstateTask> Tasks { get; }
|
||||
|
||||
/// <summary>Construct a new instance of the TopScriptsReplyEventArgs class</summary>
|
||||
/// <param name="objectCount">The number of returned items in LandStatReply</param>
|
||||
/// <param name="tasks">Dictionary of Object UUIDs to tasks returned in LandStatReply</param>
|
||||
public TopScriptsReplyEventArgs(int objectCount, Dictionary<UUID, EstateTask> tasks)
|
||||
{
|
||||
this.m_objectCount = objectCount;
|
||||
this.m_Tasks = tasks;
|
||||
this.ObjectCount = objectCount;
|
||||
this.Tasks = tasks;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Returned, along with other info, upon a successful .RequestInfo()</summary>
|
||||
public class EstateBansReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly uint m_estateID;
|
||||
private readonly int m_count;
|
||||
private readonly List<UUID> m_banned;
|
||||
|
||||
/// <summary>
|
||||
/// The identifier of the estate
|
||||
/// </summary>
|
||||
public uint EstateID { get { return m_estateID; } }
|
||||
public uint EstateID { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of returned itmes
|
||||
/// </summary>
|
||||
public int Count { get { return m_count; } }
|
||||
public int Count { get; }
|
||||
|
||||
/// <summary>
|
||||
/// List of UUIDs of Banned Users
|
||||
/// </summary>
|
||||
public List<UUID> Banned { get { return m_banned; } }
|
||||
public List<UUID> Banned { get; }
|
||||
|
||||
/// <summary>Construct a new instance of the EstateBansReplyEventArgs class</summary>
|
||||
/// <param name="estateID">The estate's identifier on the grid</param>
|
||||
@@ -1057,31 +1051,29 @@ namespace OpenMetaverse
|
||||
/// <param name="banned">User UUIDs banned</param>
|
||||
public EstateBansReplyEventArgs(uint estateID, int count, List<UUID> banned)
|
||||
{
|
||||
this.m_estateID = estateID;
|
||||
this.m_count = count;
|
||||
this.m_banned = banned;
|
||||
this.EstateID = estateID;
|
||||
this.Count = count;
|
||||
this.Banned = banned;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Returned, along with other info, upon a successful .RequestInfo()</summary>
|
||||
public class EstateUsersReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly uint m_estateID;
|
||||
private readonly int m_count;
|
||||
private readonly List<UUID> m_allowedUsers;
|
||||
|
||||
/// <summary>
|
||||
/// The identifier of the estate
|
||||
/// </summary>
|
||||
public uint EstateID { get { return m_estateID; } }
|
||||
public uint EstateID { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of returned items
|
||||
/// </summary>
|
||||
public int Count { get { return m_count; } }
|
||||
public int Count { get; }
|
||||
|
||||
/// <summary>
|
||||
/// List of UUIDs of Allowed Users
|
||||
/// </summary>
|
||||
public List<UUID> AllowedUsers { get { return m_allowedUsers; } }
|
||||
public List<UUID> AllowedUsers { get; }
|
||||
|
||||
/// <summary>Construct a new instance of the EstateUsersReplyEventArgs class</summary>
|
||||
/// <param name="estateID">The estate's identifier on the grid</param>
|
||||
@@ -1089,31 +1081,29 @@ namespace OpenMetaverse
|
||||
/// <param name="allowedUsers">Allowed users UUIDs</param>
|
||||
public EstateUsersReplyEventArgs(uint estateID, int count, List<UUID> allowedUsers)
|
||||
{
|
||||
this.m_estateID = estateID;
|
||||
this.m_count = count;
|
||||
this.m_allowedUsers = allowedUsers;
|
||||
this.EstateID = estateID;
|
||||
this.Count = count;
|
||||
this.AllowedUsers = allowedUsers;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Returned, along with other info, upon a successful .RequestInfo()</summary>
|
||||
public class EstateGroupsReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly uint m_estateID;
|
||||
private readonly int m_count;
|
||||
private readonly List<UUID> m_allowedGroups;
|
||||
|
||||
/// <summary>
|
||||
/// The identifier of the estate
|
||||
/// </summary>
|
||||
public uint EstateID { get { return m_estateID; } }
|
||||
public uint EstateID { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of returned items
|
||||
/// </summary>
|
||||
public int Count { get { return m_count; } }
|
||||
public int Count { get; }
|
||||
|
||||
/// <summary>
|
||||
/// List of UUIDs of Allowed Groups
|
||||
/// </summary>
|
||||
public List<UUID> AllowedGroups { get { return m_allowedGroups; } }
|
||||
public List<UUID> AllowedGroups { get; }
|
||||
|
||||
/// <summary>Construct a new instance of the EstateGroupsReplyEventArgs class</summary>
|
||||
/// <param name="estateID">The estate's identifier on the grid</param>
|
||||
@@ -1121,31 +1111,29 @@ namespace OpenMetaverse
|
||||
/// <param name="allowedGroups">Allowed Groups UUIDs</param>
|
||||
public EstateGroupsReplyEventArgs(uint estateID, int count, List<UUID> allowedGroups)
|
||||
{
|
||||
this.m_estateID = estateID;
|
||||
this.m_count = count;
|
||||
this.m_allowedGroups = allowedGroups;
|
||||
this.EstateID = estateID;
|
||||
this.Count = count;
|
||||
this.AllowedGroups = allowedGroups;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Returned, along with other info, upon a successful .RequestInfo()</summary>
|
||||
public class EstateManagersReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly uint m_estateID;
|
||||
private readonly int m_count;
|
||||
private readonly List<UUID> m_Managers;
|
||||
|
||||
/// <summary>
|
||||
/// The identifier of the estate
|
||||
/// </summary>
|
||||
public uint EstateID { get { return m_estateID; } }
|
||||
public uint EstateID { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The number of returned items
|
||||
/// </summary>
|
||||
public int Count { get { return m_count; } }
|
||||
public int Count { get; }
|
||||
|
||||
/// <summary>
|
||||
/// List of UUIDs of the Estate's Managers
|
||||
/// </summary>
|
||||
public List<UUID> Managers { get { return m_Managers; } }
|
||||
public List<UUID> Managers { get; }
|
||||
|
||||
/// <summary>Construct a new instance of the EstateManagersReplyEventArgs class</summary>
|
||||
/// <param name="estateID">The estate's identifier on the grid</param>
|
||||
@@ -1153,36 +1141,34 @@ namespace OpenMetaverse
|
||||
/// <param name="managers"> Managers UUIDs</param>
|
||||
public EstateManagersReplyEventArgs(uint estateID, int count, List<UUID> managers)
|
||||
{
|
||||
this.m_estateID = estateID;
|
||||
this.m_count = count;
|
||||
this.m_Managers = managers;
|
||||
this.EstateID = estateID;
|
||||
this.Count = count;
|
||||
this.Managers = managers;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Returned, along with other info, upon a successful .RequestInfo()</summary>
|
||||
public class EstateCovenantReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly UUID m_covenantID;
|
||||
private readonly long m_timestamp;
|
||||
private readonly string m_estateName;
|
||||
private readonly UUID m_estateOwnerID;
|
||||
|
||||
/// <summary>
|
||||
/// The Covenant
|
||||
/// </summary>
|
||||
public UUID CovenantID { get { return m_covenantID; } }
|
||||
public UUID CovenantID { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The timestamp
|
||||
/// </summary>
|
||||
public long Timestamp { get { return m_timestamp; } }
|
||||
public long Timestamp { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The Estate name
|
||||
/// </summary>
|
||||
public String EstateName { get { return m_estateName; } }
|
||||
public String EstateName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The Estate Owner's ID (can be a GroupID)
|
||||
/// </summary>
|
||||
public UUID EstateOwnerID { get { return m_estateOwnerID; } }
|
||||
public UUID EstateOwnerID { get; }
|
||||
|
||||
/// <summary>Construct a new instance of the EstateCovenantReplyEventArgs class</summary>
|
||||
/// <param name="covenantID">The Covenant ID</param>
|
||||
@@ -1191,10 +1177,10 @@ namespace OpenMetaverse
|
||||
/// <param name="estateOwnerID">The Estate Owner's ID (can be a GroupID)</param>
|
||||
public EstateCovenantReplyEventArgs(UUID covenantID, long timestamp, string estateName, UUID estateOwnerID)
|
||||
{
|
||||
this.m_covenantID = covenantID;
|
||||
this.m_timestamp = timestamp;
|
||||
this.m_estateName = estateName;
|
||||
this.m_estateOwnerID = estateOwnerID;
|
||||
this.CovenantID = covenantID;
|
||||
this.Timestamp = timestamp;
|
||||
this.EstateName = estateName;
|
||||
this.EstateOwnerID = estateOwnerID;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1203,25 +1189,23 @@ namespace OpenMetaverse
|
||||
/// <summary>Returned, along with other info, upon a successful .RequestInfo()</summary>
|
||||
public class EstateUpdateInfoReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly uint m_estateID;
|
||||
private readonly bool m_denyNoPaymentInfo;
|
||||
private readonly string m_estateName;
|
||||
private readonly UUID m_estateOwner;
|
||||
|
||||
/// <summary>
|
||||
/// The estate's name
|
||||
/// </summary>
|
||||
public String EstateName { get { return m_estateName; } }
|
||||
public String EstateName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The Estate Owner's ID (can be a GroupID)
|
||||
/// </summary>
|
||||
public UUID EstateOwner { get { return m_estateOwner; } }
|
||||
public UUID EstateOwner { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The identifier of the estate on the grid
|
||||
/// </summary>
|
||||
public uint EstateID { get { return m_estateID; } }
|
||||
public uint EstateID { get; }
|
||||
|
||||
/// <summary></summary>
|
||||
public bool DenyNoPaymentInfo { get { return m_denyNoPaymentInfo; } }
|
||||
public bool DenyNoPaymentInfo { get; }
|
||||
|
||||
/// <summary>Construct a new instance of the EstateUpdateInfoReplyEventArgs class</summary>
|
||||
/// <param name="estateName">The estate's name</param>
|
||||
@@ -1230,10 +1214,10 @@ namespace OpenMetaverse
|
||||
/// <param name="denyNoPaymentInfo"></param>
|
||||
public EstateUpdateInfoReplyEventArgs(string estateName, UUID estateOwner, uint estateID, bool denyNoPaymentInfo)
|
||||
{
|
||||
this.m_estateName = estateName;
|
||||
this.m_estateOwner = estateOwner;
|
||||
this.m_estateID = estateID;
|
||||
this.m_denyNoPaymentInfo = denyNoPaymentInfo;
|
||||
this.EstateName = estateName;
|
||||
this.EstateOwner = estateOwner;
|
||||
this.EstateID = estateID;
|
||||
this.DenyNoPaymentInfo = denyNoPaymentInfo;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenMetaverse.Http;
|
||||
using OpenMetaverse.Packets;
|
||||
using OpenMetaverse.StructuredData;
|
||||
|
||||
namespace OpenMetaverse
|
||||
{
|
||||
@@ -53,40 +55,25 @@ namespace OpenMetaverse
|
||||
/// </summary>
|
||||
public class FriendInfo
|
||||
{
|
||||
private UUID m_id;
|
||||
private string m_name;
|
||||
private bool m_isOnline;
|
||||
private bool m_canSeeMeOnline;
|
||||
private bool m_canSeeMeOnMap;
|
||||
private bool m_canModifyMyObjects;
|
||||
private bool m_canSeeThemOnline;
|
||||
private bool m_canSeeThemOnMap;
|
||||
private bool m_canModifyTheirObjects;
|
||||
|
||||
#region Properties
|
||||
|
||||
/// <summary>
|
||||
/// System ID of the avatar
|
||||
/// </summary>
|
||||
public UUID UUID { get { return m_id; } }
|
||||
public UUID UUID { get; }
|
||||
|
||||
/// <summary>
|
||||
/// full name of the avatar
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get { return m_name; }
|
||||
set { m_name = value; }
|
||||
}
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// True if the avatar is online
|
||||
/// </summary>
|
||||
public bool IsOnline
|
||||
{
|
||||
get { return m_isOnline; }
|
||||
set { m_isOnline = value; }
|
||||
}
|
||||
public bool IsOnline { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// True if the friend can see if I am online
|
||||
@@ -121,26 +108,22 @@ namespace OpenMetaverse
|
||||
/// <summary>
|
||||
/// True if the freind can modify my objects
|
||||
/// </summary>
|
||||
public bool CanModifyMyObjects
|
||||
{
|
||||
get { return m_canModifyMyObjects; }
|
||||
set { m_canModifyMyObjects = value; }
|
||||
}
|
||||
public bool CanModifyMyObjects { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// True if I can see if my friend is online
|
||||
/// </summary>
|
||||
public bool CanSeeThemOnline { get { return m_canSeeThemOnline; } }
|
||||
public bool CanSeeThemOnline { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// True if I can see if my friend is on the map
|
||||
/// </summary>
|
||||
public bool CanSeeThemOnMap { get { return m_canSeeThemOnMap; } }
|
||||
public bool CanSeeThemOnMap { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// True if I can modify my friend's objects
|
||||
/// </summary>
|
||||
public bool CanModifyTheirObjects { get { return m_canModifyTheirObjects; } }
|
||||
public bool CanModifyTheirObjects { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// My friend's rights represented as bitmapped flags
|
||||
@@ -154,7 +137,7 @@ namespace OpenMetaverse
|
||||
results |= FriendRights.CanSeeOnline;
|
||||
if (m_canSeeMeOnMap)
|
||||
results |= FriendRights.CanSeeOnMap;
|
||||
if (m_canModifyMyObjects)
|
||||
if (CanModifyMyObjects)
|
||||
results |= FriendRights.CanModifyObjects;
|
||||
|
||||
return results;
|
||||
@@ -163,7 +146,7 @@ namespace OpenMetaverse
|
||||
{
|
||||
m_canSeeMeOnline = (value & FriendRights.CanSeeOnline) != 0;
|
||||
m_canSeeMeOnMap = (value & FriendRights.CanSeeOnMap) != 0;
|
||||
m_canModifyMyObjects = (value & FriendRights.CanModifyObjects) != 0;
|
||||
CanModifyMyObjects = (value & FriendRights.CanModifyObjects) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -175,20 +158,20 @@ namespace OpenMetaverse
|
||||
get
|
||||
{
|
||||
FriendRights results = FriendRights.None;
|
||||
if (m_canSeeThemOnline)
|
||||
if (CanSeeThemOnline)
|
||||
results |= FriendRights.CanSeeOnline;
|
||||
if (m_canSeeThemOnMap)
|
||||
if (CanSeeThemOnMap)
|
||||
results |= FriendRights.CanSeeOnMap;
|
||||
if (m_canModifyTheirObjects)
|
||||
if (CanModifyTheirObjects)
|
||||
results |= FriendRights.CanModifyObjects;
|
||||
|
||||
return results;
|
||||
}
|
||||
set
|
||||
{
|
||||
m_canSeeThemOnline = (value & FriendRights.CanSeeOnline) != 0;
|
||||
m_canSeeThemOnMap = (value & FriendRights.CanSeeOnMap) != 0;
|
||||
m_canModifyTheirObjects = (value & FriendRights.CanModifyObjects) != 0;
|
||||
CanSeeThemOnline = (value & FriendRights.CanSeeOnline) != 0;
|
||||
CanSeeThemOnMap = (value & FriendRights.CanSeeOnMap) != 0;
|
||||
CanModifyTheirObjects = (value & FriendRights.CanModifyObjects) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -202,14 +185,14 @@ namespace OpenMetaverse
|
||||
/// <param name="myRights">Rights you have to see your friend online and to modify their objects</param>
|
||||
internal FriendInfo(UUID id, FriendRights theirRights, FriendRights myRights)
|
||||
{
|
||||
m_id = id;
|
||||
UUID = id;
|
||||
m_canSeeMeOnline = (theirRights & FriendRights.CanSeeOnline) != 0;
|
||||
m_canSeeMeOnMap = (theirRights & FriendRights.CanSeeOnMap) != 0;
|
||||
m_canModifyMyObjects = (theirRights & FriendRights.CanModifyObjects) != 0;
|
||||
CanModifyMyObjects = (theirRights & FriendRights.CanModifyObjects) != 0;
|
||||
|
||||
m_canSeeThemOnline = (myRights & FriendRights.CanSeeOnline) != 0;
|
||||
m_canSeeThemOnMap = (myRights & FriendRights.CanSeeOnMap) != 0;
|
||||
m_canModifyTheirObjects = (myRights & FriendRights.CanModifyObjects) != 0;
|
||||
CanSeeThemOnline = (myRights & FriendRights.CanSeeOnline) != 0;
|
||||
CanSeeThemOnMap = (myRights & FriendRights.CanSeeOnMap) != 0;
|
||||
CanModifyTheirObjects = (myRights & FriendRights.CanModifyObjects) != 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -218,11 +201,11 @@ namespace OpenMetaverse
|
||||
/// <returns>A string reprentation of both my rights and my friends rights</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
if (!String.IsNullOrEmpty(m_name))
|
||||
return String.Format("{0} (Their Rights: {1}, My Rights: {2})", m_name, TheirFriendRights,
|
||||
if (!String.IsNullOrEmpty(Name))
|
||||
return String.Format("{0} (Their Rights: {1}, My Rights: {2})", Name, TheirFriendRights,
|
||||
MyFriendRights);
|
||||
else
|
||||
return String.Format("{0} (Their Rights: {1}, My Rights: {2})", m_id, TheirFriendRights,
|
||||
return String.Format("{0} (Their Rights: {1}, My Rights: {2})", UUID, TheirFriendRights,
|
||||
MyFriendRights);
|
||||
}
|
||||
}
|
||||
@@ -489,7 +472,7 @@ namespace OpenMetaverse
|
||||
/// <summary>
|
||||
/// Accept a friendship request
|
||||
/// </summary>
|
||||
/// <param name="fromAgentID">agentID of avatatar to form friendship with</param>
|
||||
/// <param name="fromAgentID">agentID of avatar to form friendship with</param>
|
||||
/// <param name="imSessionID">imSessionID of the friendship request message</param>
|
||||
public void AcceptFriendship(UUID fromAgentID, UUID imSessionID)
|
||||
{
|
||||
@@ -517,6 +500,63 @@ namespace OpenMetaverse
|
||||
Client.Avatars.RequestAvatarName(fromAgentID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Accept friendship request. Only to be used if request was sent via Offline Msg cap
|
||||
/// This can be determined by the presence of a <seealso cref="InstantMessageEventArgs.Simulator"/>
|
||||
/// value in <seealso cref="InstantMessageEventArgs" />
|
||||
/// </summary>
|
||||
/// <param name="fromAgentID">agentID of avatar to form friendship with</param>
|
||||
public void AcceptFriendshipCapability(UUID fromAgentID)
|
||||
{
|
||||
Uri acceptFriendshipCap = Client.Network.CurrentSim.Caps.CapabilityURI("AcceptFriendship");
|
||||
if (acceptFriendshipCap == null)
|
||||
{
|
||||
Logger.Log("AcceptFriendship capability not found.", Helpers.LogLevel.Warning);
|
||||
return;
|
||||
}
|
||||
UriBuilder builder = new UriBuilder(acceptFriendshipCap)
|
||||
{
|
||||
// Second Life has some infintely stupid escaped agent name as part of the uri query.
|
||||
// Hopefully we don't need it because it makes no goddamn sense at all. Period, but just in case:
|
||||
// ?from={fromAgentID}&agent_name=\"This%20Sucks\"
|
||||
Query = $"from={fromAgentID}"
|
||||
};
|
||||
acceptFriendshipCap = builder.Uri;
|
||||
|
||||
var request = new CapsClient(acceptFriendshipCap);
|
||||
var body = new OSD();
|
||||
request.OnComplete += delegate(CapsClient client, OSD result, Exception error)
|
||||
{
|
||||
if (error != null)
|
||||
{
|
||||
Logger.Log($"AcceptFriendship failed for {fromAgentID}. ({error.Message})",
|
||||
Helpers.LogLevel.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
if (result is OSDMap resMap
|
||||
&& !(resMap.ContainsKey("success") && resMap["success"].AsBoolean())) { return; }
|
||||
|
||||
FriendInfo friend = new FriendInfo(fromAgentID, FriendRights.CanSeeOnline, FriendRights.CanSeeOnline);
|
||||
|
||||
if (!FriendList.ContainsKey(fromAgentID))
|
||||
{
|
||||
FriendList.Add(friend.UUID, friend);
|
||||
}
|
||||
if (FriendRequests.ContainsKey(fromAgentID))
|
||||
{
|
||||
FriendRequests.Remove(fromAgentID);
|
||||
}
|
||||
Client.Avatars.RequestAvatarName(fromAgentID);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
request.PostRequestAsync(body, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decline a friendship request
|
||||
/// </summary>
|
||||
@@ -534,6 +574,53 @@ namespace OpenMetaverse
|
||||
FriendRequests.Remove(fromAgentID);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decline friendship request. Only to be used if request was sent via Offline Msg cap
|
||||
/// This can be determined by the presence of a <seealso cref="InstantMessageEventArgs.Simulator"/>
|
||||
/// value in <seealso cref="InstantMessageEventArgs" />
|
||||
/// </summary>
|
||||
/// <param name="fromAgentID"><seealso cref="UUID"/> of friend</param>
|
||||
public void DeclineFriendshipCap(UUID fromAgentID)
|
||||
{
|
||||
Uri declineFriendshipCap = Client.Network.CurrentSim.Caps.CapabilityURI("DeclineFriendship");
|
||||
if (declineFriendshipCap == null)
|
||||
{
|
||||
Logger.Log("DeclineFriendship capability not found.", Helpers.LogLevel.Warning);
|
||||
return;
|
||||
}
|
||||
UriBuilder builder = new UriBuilder(declineFriendshipCap)
|
||||
{
|
||||
Query = $"from={fromAgentID}"
|
||||
};
|
||||
declineFriendshipCap = builder.Uri;
|
||||
|
||||
var request = new CapsClient(declineFriendshipCap);
|
||||
var body = new OSD();
|
||||
request.OnComplete += delegate (CapsClient client, OSD result, Exception error)
|
||||
{
|
||||
if (error != null)
|
||||
{
|
||||
Logger.Log($"AcceptFriendship failed for {fromAgentID}. ({error.Message})",
|
||||
Helpers.LogLevel.Warning);
|
||||
return;
|
||||
}
|
||||
|
||||
if (result != null)
|
||||
{
|
||||
if (result is OSDMap resMap &&
|
||||
!(resMap.ContainsKey("success") && resMap["success"].AsBoolean())) { return; }
|
||||
|
||||
if (FriendRequests.ContainsKey(fromAgentID))
|
||||
{
|
||||
FriendRequests.Remove(fromAgentID);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
request.DeleteRequestAsync(body, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Overload: Offer friendship to an avatar.
|
||||
/// </summary>
|
||||
@@ -945,29 +1032,26 @@ namespace OpenMetaverse
|
||||
|
||||
public class FriendsReadyEventArgs : EventArgs
|
||||
{
|
||||
private readonly int m_count;
|
||||
|
||||
/// <summary>Number of friends we have</summary>
|
||||
public int Count { get { return m_count; } }
|
||||
public int Count { get; }
|
||||
|
||||
/// <summary>Get the name of the agent we requested a friendship with</summary>
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new instance of the FriendsReadyEventArgs class
|
||||
/// </summary>
|
||||
/// <param name="Count">The total number of people loaded into the friend list.</param>
|
||||
/// <param name="count">The total number of people loaded into the friend list.</param>
|
||||
public FriendsReadyEventArgs(int count)
|
||||
{
|
||||
this.m_count = count;
|
||||
this.Count = count;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Contains information on a member of our friends list</summary>
|
||||
public class FriendInfoEventArgs : EventArgs
|
||||
{
|
||||
private readonly FriendInfo m_Friend;
|
||||
|
||||
/// <summary>Get the FriendInfo</summary>
|
||||
public FriendInfo Friend { get { return m_Friend; } }
|
||||
public FriendInfo Friend { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new instance of the FriendInfoEventArgs class
|
||||
@@ -975,18 +1059,16 @@ namespace OpenMetaverse
|
||||
/// <param name="friend">The FriendInfo</param>
|
||||
public FriendInfoEventArgs(FriendInfo friend)
|
||||
{
|
||||
this.m_Friend = friend;
|
||||
this.Friend = friend;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Contains Friend Names</summary>
|
||||
public class FriendNamesEventArgs : EventArgs
|
||||
{
|
||||
private readonly Dictionary<UUID, string> m_Names;
|
||||
|
||||
/// <summary>A dictionary where the Key is the ID of the Agent,
|
||||
/// and the Value is a string containing their name</summary>
|
||||
public Dictionary<UUID, string> Names { get { return m_Names; } }
|
||||
public Dictionary<UUID, string> Names { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new instance of the FriendNamesEventArgs class
|
||||
@@ -995,24 +1077,22 @@ namespace OpenMetaverse
|
||||
/// and the Value is a string containing their name</param>
|
||||
public FriendNamesEventArgs(Dictionary<UUID, string> names)
|
||||
{
|
||||
this.m_Names = names;
|
||||
this.Names = names;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Sent when another agent requests a friendship with our agent</summary>
|
||||
public class FriendshipOfferedEventArgs : EventArgs
|
||||
{
|
||||
private readonly UUID m_AgentID;
|
||||
private readonly string m_AgentName;
|
||||
private readonly UUID m_SessionID;
|
||||
|
||||
/// <summary>Get the ID of the agent requesting friendship</summary>
|
||||
public UUID AgentID { get { return m_AgentID; } }
|
||||
public UUID AgentID { get; }
|
||||
|
||||
/// <summary>Get the name of the agent requesting friendship</summary>
|
||||
public string AgentName { get { return m_AgentName; } }
|
||||
public string AgentName { get; }
|
||||
|
||||
/// <summary>Get the ID of the session, used in accepting or declining the
|
||||
/// friendship offer</summary>
|
||||
public UUID SessionID { get { return m_SessionID; } }
|
||||
public UUID SessionID { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new instance of the FriendshipOfferedEventArgs class
|
||||
@@ -1023,25 +1103,23 @@ namespace OpenMetaverse
|
||||
/// friendship offer</param>
|
||||
public FriendshipOfferedEventArgs(UUID agentID, string agentName, UUID imSessionID)
|
||||
{
|
||||
this.m_AgentID = agentID;
|
||||
this.m_AgentName = agentName;
|
||||
this.m_SessionID = imSessionID;
|
||||
this.AgentID = agentID;
|
||||
this.AgentName = agentName;
|
||||
this.SessionID = imSessionID;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>A response containing the results of our request to form a friendship with another agent</summary>
|
||||
public class FriendshipResponseEventArgs : EventArgs
|
||||
{
|
||||
private readonly UUID m_AgentID;
|
||||
private readonly string m_AgentName;
|
||||
private readonly bool m_Accepted;
|
||||
|
||||
/// <summary>Get the ID of the agent we requested a friendship with</summary>
|
||||
public UUID AgentID { get { return m_AgentID; } }
|
||||
public UUID AgentID { get; }
|
||||
|
||||
/// <summary>Get the name of the agent we requested a friendship with</summary>
|
||||
public string AgentName { get { return m_AgentName; } }
|
||||
public string AgentName { get; }
|
||||
|
||||
/// <summary>true if the agent accepted our friendship offer</summary>
|
||||
public bool Accepted { get { return m_Accepted; } }
|
||||
public bool Accepted { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new instance of the FriendShipResponseEventArgs class
|
||||
@@ -1051,22 +1129,20 @@ namespace OpenMetaverse
|
||||
/// <param name="accepted">true if the agent accepted our friendship offer</param>
|
||||
public FriendshipResponseEventArgs(UUID agentID, string agentName, bool accepted)
|
||||
{
|
||||
this.m_AgentID = agentID;
|
||||
this.m_AgentName = agentName;
|
||||
this.m_Accepted = accepted;
|
||||
this.AgentID = agentID;
|
||||
this.AgentName = agentName;
|
||||
this.Accepted = accepted;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Contains data sent when a friend terminates a friendship with us</summary>
|
||||
public class FriendshipTerminatedEventArgs : EventArgs
|
||||
{
|
||||
private readonly UUID m_AgentID;
|
||||
private readonly string m_AgentName;
|
||||
|
||||
/// <summary>Get the ID of the agent that terminated the friendship with us</summary>
|
||||
public UUID AgentID { get { return m_AgentID; } }
|
||||
public UUID AgentID { get; }
|
||||
|
||||
/// <summary>Get the name of the agent that terminated the friendship with us</summary>
|
||||
public string AgentName { get { return m_AgentName; } }
|
||||
public string AgentName { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new instance of the FrindshipTerminatedEventArgs class
|
||||
@@ -1075,8 +1151,8 @@ namespace OpenMetaverse
|
||||
/// <param name="agentName">The name of the friend who terminated the friendship with us</param>
|
||||
public FriendshipTerminatedEventArgs(UUID agentID, string agentName)
|
||||
{
|
||||
this.m_AgentID = agentID;
|
||||
this.m_AgentName = agentName;
|
||||
this.AgentID = agentID;
|
||||
this.AgentName = agentName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1085,16 +1161,14 @@ namespace OpenMetaverse
|
||||
/// </summary>
|
||||
public class FriendFoundReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly UUID m_AgentID;
|
||||
private readonly ulong m_RegionHandle;
|
||||
private readonly Vector3 m_Location;
|
||||
|
||||
/// <summary>Get the ID of the agent we have received location information for</summary>
|
||||
public UUID AgentID { get { return m_AgentID; } }
|
||||
public UUID AgentID { get; }
|
||||
|
||||
/// <summary>Get the region handle where our mapped friend is located</summary>
|
||||
public ulong RegionHandle { get { return m_RegionHandle; } }
|
||||
public ulong RegionHandle { get; }
|
||||
|
||||
/// <summary>Get the simulator local position where our friend is located</summary>
|
||||
public Vector3 Location { get { return m_Location; } }
|
||||
public Vector3 Location { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new instance of the FriendFoundReplyEventArgs class
|
||||
@@ -1104,9 +1178,9 @@ namespace OpenMetaverse
|
||||
/// <param name="location">The simulator local position our friend is located</param>
|
||||
public FriendFoundReplyEventArgs(UUID agentID, ulong regionHandle, Vector3 location)
|
||||
{
|
||||
this.m_AgentID = agentID;
|
||||
this.m_RegionHandle = regionHandle;
|
||||
this.m_Location = location;
|
||||
this.AgentID = agentID;
|
||||
this.RegionHandle = regionHandle;
|
||||
this.Location = location;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using LibreMetaverse;
|
||||
|
||||
namespace OpenMetaverse
|
||||
|
||||
@@ -382,13 +382,16 @@ namespace OpenMetaverse
|
||||
#endregion Delegates
|
||||
|
||||
/// <summary>Unknown</summary>
|
||||
public float SunPhase { get { return sunPhase; } }
|
||||
/// <summary>Current direction of the sun</summary>
|
||||
public Vector3 SunDirection { get { return sunDirection; } }
|
||||
public float SunPhase { get; private set; }
|
||||
|
||||
/// <summary>Current direction of the sun</summary>
|
||||
public Vector3 SunDirection { get; private set; }
|
||||
|
||||
/// <summary>Current angular velocity of the sun</summary>
|
||||
public Vector3 SunAngVelocity { get { return sunAngVelocity; } }
|
||||
public Vector3 SunAngVelocity { get; private set; }
|
||||
|
||||
/// <summary>Microseconds since the start of SL 4-hour day</summary>
|
||||
public ulong TimeOfDay { get { return timeOfDay; } }
|
||||
public ulong TimeOfDay { get; private set; }
|
||||
|
||||
/// <summary>A dictionary of all the regions, indexed by region name</summary>
|
||||
internal Dictionary<string, GridRegion> Regions = new Dictionary<string, GridRegion>();
|
||||
@@ -396,10 +399,6 @@ namespace OpenMetaverse
|
||||
internal Dictionary<ulong, GridRegion> RegionsByHandle = new Dictionary<ulong, GridRegion>();
|
||||
|
||||
private GridClient Client;
|
||||
private float sunPhase;
|
||||
private Vector3 sunDirection;
|
||||
private Vector3 sunAngVelocity;
|
||||
private ulong timeOfDay;
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
@@ -430,7 +429,7 @@ namespace OpenMetaverse
|
||||
OSDMap body = new OSDMap {["Flags"] = OSD.FromInteger((int) layer)};
|
||||
|
||||
request.OnComplete += new CapsClient.CompleteCallback(MapLayerResponseHandler);
|
||||
request.BeginGetResponse(body, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
request.PostRequestAsync(body, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -624,9 +623,9 @@ namespace OpenMetaverse
|
||||
|
||||
if (m_GridLayer != null)
|
||||
{
|
||||
for (int i = 0; i < layerData.Count; i++)
|
||||
foreach (var data in layerData)
|
||||
{
|
||||
OSDMap thisLayerData = (OSDMap)layerData[i];
|
||||
OSDMap thisLayerData = (OSDMap)data;
|
||||
|
||||
GridLayer layer;
|
||||
layer.Bottom = thisLayerData["Bottom"].AsInteger();
|
||||
@@ -635,7 +634,7 @@ namespace OpenMetaverse
|
||||
layer.Right = thisLayerData["Right"].AsInteger();
|
||||
layer.ImageID = thisLayerData["ImageID"].AsUUID();
|
||||
|
||||
OnGridLayer(new GridLayerEventArgs(layer));
|
||||
OnGridLayer(new GridLayerEventArgs(layer));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -695,18 +694,18 @@ namespace OpenMetaverse
|
||||
GridItemType type = (GridItemType)reply.RequestData.ItemType;
|
||||
List<MapItem> items = new List<MapItem>();
|
||||
|
||||
for (int i = 0; i < reply.Data.Length; i++)
|
||||
foreach (var data in reply.Data)
|
||||
{
|
||||
string name = Utils.BytesToString(reply.Data[i].Name);
|
||||
string name = Utils.BytesToString(data.Name);
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case GridItemType.AgentLocations:
|
||||
MapAgentLocation location = new MapAgentLocation();
|
||||
location.GlobalX = reply.Data[i].X;
|
||||
location.GlobalY = reply.Data[i].Y;
|
||||
location.GlobalX = data.X;
|
||||
location.GlobalY = data.Y;
|
||||
location.Identifier = name;
|
||||
location.AvatarCount = reply.Data[i].Extra;
|
||||
location.AvatarCount = data.Extra;
|
||||
items.Add(location);
|
||||
break;
|
||||
case GridItemType.Classified:
|
||||
@@ -715,28 +714,28 @@ namespace OpenMetaverse
|
||||
break;
|
||||
case GridItemType.LandForSale:
|
||||
MapLandForSale landsale = new MapLandForSale();
|
||||
landsale.GlobalX = reply.Data[i].X;
|
||||
landsale.GlobalY = reply.Data[i].Y;
|
||||
landsale.ID = reply.Data[i].ID;
|
||||
landsale.GlobalX = data.X;
|
||||
landsale.GlobalY = data.Y;
|
||||
landsale.ID = data.ID;
|
||||
landsale.Name = name;
|
||||
landsale.Size = reply.Data[i].Extra;
|
||||
landsale.Price = reply.Data[i].Extra2;
|
||||
landsale.Size = data.Extra;
|
||||
landsale.Price = data.Extra2;
|
||||
items.Add(landsale);
|
||||
break;
|
||||
case GridItemType.MatureEvent:
|
||||
MapMatureEvent matureEvent = new MapMatureEvent();
|
||||
matureEvent.GlobalX = reply.Data[i].X;
|
||||
matureEvent.GlobalY = reply.Data[i].Y;
|
||||
matureEvent.GlobalX = data.X;
|
||||
matureEvent.GlobalY = data.Y;
|
||||
matureEvent.Description = name;
|
||||
matureEvent.Flags = (DirectoryManager.EventFlags)reply.Data[i].Extra2;
|
||||
matureEvent.Flags = (DirectoryManager.EventFlags)data.Extra2;
|
||||
items.Add(matureEvent);
|
||||
break;
|
||||
case GridItemType.PgEvent:
|
||||
MapPGEvent PGEvent = new MapPGEvent();
|
||||
PGEvent.GlobalX = reply.Data[i].X;
|
||||
PGEvent.GlobalY = reply.Data[i].Y;
|
||||
PGEvent.GlobalX = data.X;
|
||||
PGEvent.GlobalY = data.Y;
|
||||
PGEvent.Description = name;
|
||||
PGEvent.Flags = (DirectoryManager.EventFlags)reply.Data[i].Extra2;
|
||||
PGEvent.Flags = (DirectoryManager.EventFlags)data.Extra2;
|
||||
items.Add(PGEvent);
|
||||
break;
|
||||
case GridItemType.Popular:
|
||||
@@ -745,26 +744,26 @@ namespace OpenMetaverse
|
||||
break;
|
||||
case GridItemType.Telehub:
|
||||
MapTelehub teleHubItem = new MapTelehub();
|
||||
teleHubItem.GlobalX = reply.Data[i].X;
|
||||
teleHubItem.GlobalY = reply.Data[i].Y;
|
||||
teleHubItem.GlobalX = data.X;
|
||||
teleHubItem.GlobalY = data.Y;
|
||||
items.Add(teleHubItem);
|
||||
break;
|
||||
case GridItemType.AdultLandForSale:
|
||||
MapAdultLandForSale adultLandsale = new MapAdultLandForSale();
|
||||
adultLandsale.GlobalX = reply.Data[i].X;
|
||||
adultLandsale.GlobalY = reply.Data[i].Y;
|
||||
adultLandsale.ID = reply.Data[i].ID;
|
||||
adultLandsale.GlobalX = data.X;
|
||||
adultLandsale.GlobalY = data.Y;
|
||||
adultLandsale.ID = data.ID;
|
||||
adultLandsale.Name = name;
|
||||
adultLandsale.Size = reply.Data[i].Extra;
|
||||
adultLandsale.Price = reply.Data[i].Extra2;
|
||||
adultLandsale.Size = data.Extra;
|
||||
adultLandsale.Price = data.Extra2;
|
||||
items.Add(adultLandsale);
|
||||
break;
|
||||
case GridItemType.AdultEvent:
|
||||
MapAdultEvent adultEvent = new MapAdultEvent();
|
||||
adultEvent.GlobalX = reply.Data[i].X;
|
||||
adultEvent.GlobalY = reply.Data[i].Y;
|
||||
adultEvent.Description = Utils.BytesToString(reply.Data[i].Name);
|
||||
adultEvent.Flags = (DirectoryManager.EventFlags)reply.Data[i].Extra2;
|
||||
adultEvent.GlobalX = data.X;
|
||||
adultEvent.GlobalY = data.Y;
|
||||
adultEvent.Description = Utils.BytesToString(data.Name);
|
||||
adultEvent.Flags = (DirectoryManager.EventFlags)data.Extra2;
|
||||
items.Add(adultEvent);
|
||||
break;
|
||||
default:
|
||||
@@ -784,10 +783,10 @@ namespace OpenMetaverse
|
||||
{
|
||||
SimulatorViewerTimeMessagePacket time = (SimulatorViewerTimeMessagePacket)e.Packet;
|
||||
|
||||
sunPhase = time.TimeInfo.SunPhase;
|
||||
sunDirection = time.TimeInfo.SunDirection;
|
||||
sunAngVelocity = time.TimeInfo.SunAngVelocity;
|
||||
timeOfDay = time.TimeInfo.UsecSinceStart;
|
||||
SunPhase = time.TimeInfo.SunPhase;
|
||||
SunDirection = time.TimeInfo.SunDirection;
|
||||
SunAngVelocity = time.TimeInfo.SunAngVelocity;
|
||||
TimeOfDay = time.TimeInfo.UsecSinceStart;
|
||||
// TODO: Does anyone have a use for the time stuff?
|
||||
}
|
||||
|
||||
@@ -857,72 +856,59 @@ namespace OpenMetaverse
|
||||
|
||||
public class CoarseLocationUpdateEventArgs : EventArgs
|
||||
{
|
||||
private readonly Simulator m_Simulator;
|
||||
private readonly List<UUID> m_NewEntries;
|
||||
private readonly List<UUID> m_RemovedEntries;
|
||||
|
||||
public Simulator Simulator { get { return m_Simulator; } }
|
||||
public List<UUID> NewEntries { get { return m_NewEntries; } }
|
||||
public List<UUID> RemovedEntries { get { return m_RemovedEntries; } }
|
||||
public Simulator Simulator { get; }
|
||||
public List<UUID> NewEntries { get; }
|
||||
public List<UUID> RemovedEntries { get; }
|
||||
|
||||
public CoarseLocationUpdateEventArgs(Simulator simulator, List<UUID> newEntries, List<UUID> removedEntries)
|
||||
{
|
||||
this.m_Simulator = simulator;
|
||||
this.m_NewEntries = newEntries;
|
||||
this.m_RemovedEntries = removedEntries;
|
||||
this.Simulator = simulator;
|
||||
this.NewEntries = newEntries;
|
||||
this.RemovedEntries = removedEntries;
|
||||
}
|
||||
}
|
||||
|
||||
public class GridRegionEventArgs : EventArgs
|
||||
{
|
||||
private readonly GridRegion m_Region;
|
||||
public GridRegion Region { get { return m_Region; } }
|
||||
public GridRegion Region { get; }
|
||||
|
||||
public GridRegionEventArgs(GridRegion region)
|
||||
{
|
||||
this.m_Region = region;
|
||||
this.Region = region;
|
||||
}
|
||||
}
|
||||
|
||||
public class GridLayerEventArgs : EventArgs
|
||||
{
|
||||
private readonly GridLayer m_Layer;
|
||||
|
||||
public GridLayer Layer { get { return m_Layer; } }
|
||||
public GridLayer Layer { get; }
|
||||
|
||||
public GridLayerEventArgs(GridLayer layer)
|
||||
{
|
||||
this.m_Layer = layer;
|
||||
this.Layer = layer;
|
||||
}
|
||||
}
|
||||
|
||||
public class GridItemsEventArgs : EventArgs
|
||||
{
|
||||
private readonly GridItemType m_Type;
|
||||
private readonly List<MapItem> m_Items;
|
||||
|
||||
public GridItemType Type { get { return m_Type; } }
|
||||
public List<MapItem> Items { get { return m_Items; } }
|
||||
public GridItemType Type { get; }
|
||||
public List<MapItem> Items { get; }
|
||||
|
||||
public GridItemsEventArgs(GridItemType type, List<MapItem> items)
|
||||
{
|
||||
this.m_Type = type;
|
||||
this.m_Items = items;
|
||||
this.Type = type;
|
||||
this.Items = items;
|
||||
}
|
||||
}
|
||||
|
||||
public class RegionHandleReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly UUID m_RegionID;
|
||||
private readonly ulong m_RegionHandle;
|
||||
|
||||
public UUID RegionID { get { return m_RegionID; } }
|
||||
public ulong RegionHandle { get { return m_RegionHandle; } }
|
||||
public UUID RegionID { get; }
|
||||
public ulong RegionHandle { get; }
|
||||
|
||||
public RegionHandleReplyEventArgs(UUID regionID, ulong regionHandle)
|
||||
{
|
||||
this.m_RegionID = regionID;
|
||||
this.m_RegionHandle = regionHandle;
|
||||
this.RegionID = regionID;
|
||||
this.RegionHandle = regionHandle;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1058,7 +1058,7 @@ namespace OpenMetaverse
|
||||
};
|
||||
|
||||
OSDMap requestData = new OSDMap(1) {["group_id"] = @group};
|
||||
req.BeginGetResponse(requestData, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT * 4);
|
||||
req.PostRequestAsync(requestData, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT * 4);
|
||||
|
||||
return requestID;
|
||||
}
|
||||
@@ -1696,7 +1696,7 @@ namespace OpenMetaverse
|
||||
|
||||
};
|
||||
|
||||
req.BeginGetResponse(Client.Settings.CAPS_TIMEOUT);
|
||||
req.GetRequestAsync(Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -1737,7 +1737,7 @@ namespace OpenMetaverse
|
||||
}
|
||||
OSDRequest["ban_ids"] = banIDs;
|
||||
|
||||
req.BeginGetResponse(OSDRequest, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
req.PostRequestAsync(OSDRequest, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
//using System.Drawing;
|
||||
@@ -161,9 +160,16 @@ namespace OpenMetaverse.Imaging
|
||||
|
||||
if (bakeType == BakeType.Head)
|
||||
{
|
||||
DrawLayer(LoadResourceLayer("head_color.tga"), false);
|
||||
AddAlpha(bakedTexture.Image, LoadResourceLayer("head_alpha.tga"));
|
||||
MultiplyLayerFromAlpha(bakedTexture.Image, LoadResourceLayer("head_skingrain.tga"));
|
||||
if (DrawLayer(LoadResourceLayer("head_color.tga"), false) == true)
|
||||
{
|
||||
AddAlpha(bakedTexture.Image, LoadResourceLayer("head_alpha.tga"));
|
||||
MultiplyLayerFromAlpha(bakedTexture.Image, LoadResourceLayer("head_skingrain.tga"));
|
||||
Logger.Log("[Bake]: created head master bake", Helpers.LogLevel.Debug);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log("[Bake]: Unable to draw layer from texture file", Helpers.LogLevel.Debug);
|
||||
}
|
||||
}
|
||||
|
||||
if (skinTexture.Texture == null)
|
||||
@@ -424,8 +430,8 @@ namespace OpenMetaverse.Imaging
|
||||
|
||||
private bool MaskBelongsToBake(string mask)
|
||||
{
|
||||
return (bakeType != BakeType.LowerBody || !mask.Contains("upper"))
|
||||
&& (bakeType != BakeType.LowerBody || !mask.Contains("shirt"))
|
||||
return (bakeType != BakeType.LowerBody || !mask.Contains("upper"))
|
||||
&& (bakeType != BakeType.LowerBody || !mask.Contains("shirt"))
|
||||
&& (bakeType != BakeType.UpperBody || !mask.Contains("lower"));
|
||||
}
|
||||
|
||||
@@ -460,16 +466,25 @@ namespace OpenMetaverse.Imaging
|
||||
byte[] sourceAlpha = sourceHasAlpha ? source.Alpha : null;
|
||||
byte[] sourceBump = sourceHasBump ? source.Bump : null;
|
||||
|
||||
/* 4c506093003675ce6f24d7273812c4440adc87b7
|
||||
Update BakeLayer.cs
|
||||
add unneeded but nice debug info around head_color loading
|
||||
correct color loading due to alpha being broken
|
||||
*/
|
||||
bool loadedAlpha = false;
|
||||
for (int y = 0; y < bakeHeight; y++)
|
||||
{
|
||||
for (int x = 0; x < bakeWidth; x++)
|
||||
{
|
||||
loadedAlpha = false;
|
||||
alpha = 0;
|
||||
alphaInv = 0;
|
||||
|
||||
if (sourceHasAlpha)
|
||||
{
|
||||
if (sourceAlpha.Length > i)
|
||||
{
|
||||
loadedAlpha = true;
|
||||
alpha = sourceAlpha[i];
|
||||
alphaInv = (byte)(Byte.MaxValue - alpha);
|
||||
}
|
||||
@@ -481,9 +496,18 @@ namespace OpenMetaverse.Imaging
|
||||
{
|
||||
if ((sourceRed.Length > i) && (sourceGreen.Length > i) && (sourceBlue.Length > i))
|
||||
{
|
||||
bakedRed[i] = (byte)((bakedRed[i] * alphaInv + sourceRed[i] * alpha) >> 8);
|
||||
bakedGreen[i] = (byte)((bakedGreen[i] * alphaInv + sourceGreen[i] * alpha) >> 8);
|
||||
bakedBlue[i] = (byte)((bakedBlue[i] * alphaInv + sourceBlue[i] * alpha) >> 8);
|
||||
if (loadedAlpha == true)
|
||||
{
|
||||
bakedRed[i] = (byte)((bakedRed[i] * alphaInv + sourceRed[i] * alpha) >> 8);
|
||||
bakedGreen[i] = (byte)((bakedGreen[i] * alphaInv + sourceGreen[i] * alpha) >> 8);
|
||||
bakedBlue[i] = (byte)((bakedBlue[i] * alphaInv + sourceBlue[i] * alpha) >> 8);
|
||||
}
|
||||
else
|
||||
{
|
||||
bakedRed[i] = sourceRed[i];
|
||||
bakedGreen[i] = sourceGreen[i];
|
||||
bakedBlue[i] = sourceBlue[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -519,7 +543,7 @@ namespace OpenMetaverse.Imaging
|
||||
/// </summary>
|
||||
/// <param name="dest">Destination image</param>
|
||||
/// <param name="src">Source image</param>
|
||||
/// <returns>Sanitization was succefull</returns>
|
||||
/// <returns>Sanitization was successful</returns>
|
||||
private bool SanitizeLayers(ManagedImage dest, ManagedImage src)
|
||||
{
|
||||
if (dest == null || src == null) return false;
|
||||
|
||||
@@ -144,24 +144,24 @@ namespace OpenMetaverse.Imaging
|
||||
Alpha = new byte[pixelCount];
|
||||
|
||||
//BitmapData bd = bitmap.LockBits(new Rectangle(0, 0, Width, Height),
|
||||
// ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
|
||||
|
||||
//unsafe
|
||||
//{
|
||||
// byte* pixel = (byte*)bd.Scan0;
|
||||
|
||||
// for (int i = 0; i < pixelCount; i++)
|
||||
// {
|
||||
// // GDI+ gives us BGRA and we need to turn that in to RGBA
|
||||
// Blue[i] = *(pixel++);
|
||||
// Green[i] = *(pixel++);
|
||||
// Red[i] = *(pixel++);
|
||||
// Alpha[i] = *(pixel++);
|
||||
// }
|
||||
//}
|
||||
|
||||
//bitmap.UnlockBits(bd);
|
||||
// ImageLockMode.ReadOnly, PixelFormat.Format32bppArgb);
|
||||
/*
|
||||
unsafe
|
||||
{
|
||||
byte* pixel = (byte*)bd.Scan0;
|
||||
|
||||
for (int i = 0; i < pixelCount; i++)
|
||||
{
|
||||
// GDI+ gives us BGRA and we need to turn that in to RGBA
|
||||
Blue[i] = *(pixel++);
|
||||
Green[i] = *(pixel++);
|
||||
Red[i] = *(pixel++);
|
||||
Alpha[i] = *(pixel++);
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
|
||||
for (int i = 0; i < pixelCount; i++)
|
||||
{
|
||||
Color32 bit = tex.GetPixel(i%Width , i / Width);
|
||||
@@ -171,7 +171,10 @@ namespace OpenMetaverse.Imaging
|
||||
Alpha[i] = bit.a;
|
||||
|
||||
}
|
||||
//bitmap.UnlockBits(bd);
|
||||
}
|
||||
// this 16bit grayscale image format is commented-out for Raindrop and we need to investigate what its used for; can we just ignore it?
|
||||
// unity does not seem to support 16bit grayscale
|
||||
//else if (tex.format == TextureFormat.Alpha8) // PixelFormat.Format16bppGrayScale --- 16 bits per pixel. The color information specifies 65536 shades of gray.
|
||||
//{
|
||||
// Channels = ImageChannels.Gray;
|
||||
@@ -215,6 +218,7 @@ namespace OpenMetaverse.Imaging
|
||||
|
||||
}
|
||||
}
|
||||
// can we remove the following? this Format32bppRgb is a ridiculous format.
|
||||
else if (tex.format == TextureFormat.RGB24) // PixelFormat.Format32bppRgb) --- The remaining 8 bits are not used.
|
||||
{
|
||||
Channels = ImageChannels.Color;
|
||||
|
||||
@@ -1,28 +1,28 @@
|
||||
///*
|
||||
// * Copyright (c) 2006-2016, openmetaverse.co
|
||||
// * All rights reserved.
|
||||
// *
|
||||
// * - 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.
|
||||
// * - Neither the name of the openmetaverse.co 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR 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.
|
||||
// */
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* All rights reserved.
|
||||
*
|
||||
* - 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.
|
||||
* - Neither the name of the openmetaverse.co 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR 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.IO;
|
||||
@@ -130,192 +130,182 @@ namespace OpenMetaverse.Imaging
|
||||
}
|
||||
}
|
||||
|
||||
public static bool isRLE(string path)
|
||||
struct tgaCD
|
||||
{
|
||||
return true;
|
||||
public uint RMask, GMask, BMask, AMask;
|
||||
public byte RShift, GShift, BShift, AShift;
|
||||
public uint FinalOr;
|
||||
public bool NeedNoConvert;
|
||||
}
|
||||
|
||||
|
||||
public static Texture2D LoadTGAOld(System.IO.Stream source)
|
||||
static uint UnpackColor(
|
||||
uint sourceColor, ref tgaCD cd)
|
||||
{
|
||||
byte[] buffer = new byte[source.Length];
|
||||
source.Read(buffer, 0, buffer.Length);
|
||||
|
||||
System.IO.MemoryStream ms = new System.IO.MemoryStream(buffer);
|
||||
|
||||
using (System.IO.BinaryReader br = new System.IO.BinaryReader(ms))
|
||||
if (cd.RMask == 0xFF && cd.GMask == 0xFF && cd.BMask == 0xFF)
|
||||
{
|
||||
tgaHeader header = new tgaHeader();
|
||||
header.Read(br);
|
||||
|
||||
if (header.ImageSpec.PixelDepth != 8 &&
|
||||
header.ImageSpec.PixelDepth != 16 &&
|
||||
header.ImageSpec.PixelDepth != 24 &&
|
||||
header.ImageSpec.PixelDepth != 32)
|
||||
throw new ArgumentException("Not a supported tga file.");
|
||||
|
||||
//if (header.ImageSpec.PixelDepth == 8)
|
||||
// throw new ArgumentException("TGA texture had 8 bit depth.");
|
||||
//if (header.ImageSpec.PixelDepth == 16)
|
||||
// throw new ArgumentException("TGA texture had 16 bit depth.");
|
||||
|
||||
if (header.ImageSpec.AlphaBits > 8)
|
||||
throw new ArgumentException("Not a supported tga file: too many Alpha bits");
|
||||
|
||||
if (header.ImageSpec.Width > 4096 ||
|
||||
header.ImageSpec.Height > 4096)
|
||||
throw new ArgumentException("Image too large.");
|
||||
|
||||
|
||||
long len = br.BaseStream.Length;
|
||||
//if (header.ImageSpec.PixelDepth == 24)
|
||||
//{
|
||||
// long expectedBytes = header.ImageSpec.Width * header.ImageSpec.Height * 3;
|
||||
// if (len < expectedBytes)
|
||||
// {
|
||||
// //throw new ArgumentException("TGA texture has 24 bit depth, height and width of " +header.ImageSpec.Width+ " " + header.ImageSpec.Height+ " but the number of bytes in file is " + len);
|
||||
// throw new ArgumentException("the 24bit TGA file is smaller than expected");
|
||||
// }
|
||||
|
||||
//}
|
||||
//if (header.ImageSpec.PixelDepth == 32)
|
||||
//{
|
||||
// long expectedBytes = header.ImageSpec.Width * header.ImageSpec.Height * 4;
|
||||
// if (len < expectedBytes)
|
||||
// {
|
||||
// //throw new ArgumentException("TGA texture has 32 bit depth, height and width of " +header.ImageSpec.Width+ " " + header.ImageSpec.Height+ " but the number of bytes in file is " + len);
|
||||
// throw new ArgumentException("the 32bit TGA file is smaller than expected");
|
||||
// }
|
||||
|
||||
//}
|
||||
//if (header.ImageSpec.PixelDepth == 8)
|
||||
//{
|
||||
// long expectedBytes = header.ImageSpec.Width * header.ImageSpec.Height * 1;
|
||||
// if (len < expectedBytes)
|
||||
// {
|
||||
// //throw new ArgumentException("TGA texture has 32 bit depth, height and width of " +header.ImageSpec.Width+ " " + header.ImageSpec.Height+ " but the number of bytes in file is " + len);
|
||||
// throw new ArgumentException("the 8bit TGA file is smaller than expected");
|
||||
// }
|
||||
|
||||
//}
|
||||
|
||||
|
||||
Texture2D b;
|
||||
int width = header.ImageSpec.Width;
|
||||
int height = header.ImageSpec.Height;
|
||||
Color32[] pulledColors = new Color32[width * height];
|
||||
//BitmapData bd;
|
||||
|
||||
//NOTE NON COMPRESSED textures only!!!
|
||||
|
||||
// Create a bitmap for the image.
|
||||
// Only include an alpha layer when the image requires one.
|
||||
if (header.ImageSpec.AlphaBits > 0 ||
|
||||
header.ImageSpec.PixelDepth == 8 || // Assume 8 bit images are alpha only
|
||||
header.ImageSpec.PixelDepth == 32) // Assume 32 bit images are ARGB
|
||||
{ // Image needs an alpha layer
|
||||
b = new Texture2D(
|
||||
header.ImageSpec.Width,
|
||||
header.ImageSpec.Height,
|
||||
TextureFormat.ARGB32,
|
||||
false
|
||||
/*PixelFormat.Format32bppArgb*/);
|
||||
|
||||
//bd = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
|
||||
// ImageLockMode.WriteOnly,
|
||||
// PixelFormat.Format32bppPArgb);
|
||||
|
||||
//Debug.Log("Debug the color: " + pulledColors[5]); //ok we know these are correct.
|
||||
//Debug.Log("Debug the color: " + pulledColors[500]);
|
||||
//Debug.Log("Debug the color: " + pulledColors[50000]);
|
||||
}
|
||||
else
|
||||
{ // Image does not need an alpha layer, so do not include one.
|
||||
b = new Texture2D(
|
||||
header.ImageSpec.Width,
|
||||
header.ImageSpec.Height,
|
||||
TextureFormat.RGB24,
|
||||
false
|
||||
/*PixelFormat.Format32bppRgb*/);
|
||||
|
||||
//bd = b.LockBits(new Rectangle(0, 0, b.Width, b.Height),
|
||||
// ImageLockMode.WriteOnly,
|
||||
// PixelFormat.Format32bppRgb);
|
||||
|
||||
}
|
||||
|
||||
if (header.ImageSpec.PixelDepth == 8)
|
||||
{
|
||||
for (int i = 0; i < width * height; i++)
|
||||
{
|
||||
byte red = br.ReadByte();
|
||||
|
||||
pulledColors[i] = new Color32(0, 0, 0, red);
|
||||
}
|
||||
|
||||
} else if (header.ImageSpec.PixelDepth == 16)
|
||||
{
|
||||
throw new ArgumentException("TGA texture had 16 bit depth.");
|
||||
|
||||
} else if (header.ImageSpec.PixelDepth == 24) //TODO: handle the case of 'alpha channel is present'!
|
||||
{
|
||||
for (int i = 0; i < width * height; i++)
|
||||
{
|
||||
byte red = br.ReadByte();
|
||||
byte green = br.ReadByte();
|
||||
byte blue = br.ReadByte();
|
||||
|
||||
pulledColors[i] = new Color32(blue, green, red, 1);
|
||||
}
|
||||
|
||||
} else if (header.ImageSpec.PixelDepth == 32)
|
||||
{
|
||||
|
||||
for (int i = 0; i < width * height; i++)
|
||||
{
|
||||
byte red = br.ReadByte();
|
||||
byte green = br.ReadByte();
|
||||
byte blue = br.ReadByte();
|
||||
byte alpha = br.ReadByte();
|
||||
|
||||
pulledColors[i] = new Color32(blue, green, red, alpha);
|
||||
}
|
||||
}
|
||||
|
||||
//switch (header.ImageSpec.PixelDepth)
|
||||
//{
|
||||
// case 8:
|
||||
// decodeStandard8(bd, header, br);
|
||||
// break;
|
||||
// case 16:
|
||||
// if (header.ImageSpec.AlphaBits > 0)
|
||||
// decodeSpecial16(bd, header, br);
|
||||
// else
|
||||
// decodeStandard16(bd, header, br);
|
||||
// break;
|
||||
// case 24:
|
||||
// if (header.ImageSpec.AlphaBits > 0)
|
||||
// decodeSpecial24(bd, header, br);
|
||||
// else
|
||||
// decodeStandard24(bd, header, br);
|
||||
// break;
|
||||
// case 32:
|
||||
// decodeStandard32(bd, header, br);
|
||||
// break;
|
||||
// default:
|
||||
// b.UnlockBits(bd);
|
||||
// b.Dispose();
|
||||
// return null;
|
||||
//}
|
||||
|
||||
//b.UnlockBits(bd);
|
||||
b.SetPixels32(pulledColors);
|
||||
b.Apply();
|
||||
|
||||
return b;
|
||||
// Special case to deal with 8-bit TGA files that we treat as alpha masks
|
||||
return sourceColor << 24;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint rpermute = (sourceColor << cd.RShift) | (sourceColor >> (32 - cd.RShift));
|
||||
uint gpermute = (sourceColor << cd.GShift) | (sourceColor >> (32 - cd.GShift));
|
||||
uint bpermute = (sourceColor << cd.BShift) | (sourceColor >> (32 - cd.BShift));
|
||||
uint apermute = (sourceColor << cd.AShift) | (sourceColor >> (32 - cd.AShift));
|
||||
uint result =
|
||||
(rpermute & cd.RMask) | (gpermute & cd.GMask)
|
||||
| (bpermute & cd.BMask) | (apermute & cd.AMask) | cd.FinalOr;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
static unsafe void decodeLine(
|
||||
Color32[] b, int texWidth, int texHeight,
|
||||
int line,
|
||||
int byp,
|
||||
byte[] data,
|
||||
ref tgaCD cd)
|
||||
{
|
||||
if (cd.NeedNoConvert)
|
||||
{
|
||||
// fast copy
|
||||
uint offset_colorArray_scanline = (uint)(line * texWidth + 0); //should be large enough?
|
||||
//uint* linep = (uint*)((byte*)b.Scan0.ToPointer() + line * b.Stride);
|
||||
fixed (byte* ptr = data)
|
||||
{
|
||||
uint* sptr = (uint*)ptr;
|
||||
for (int i = 0; i < texWidth; ++i)
|
||||
{
|
||||
b[i + offset_colorArray_scanline] = makeColor32fromUInt(sptr[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//byte* linep = (byte*)b.Scan0.ToPointer() + line * b.Stride;
|
||||
uint offset_colorArray_scanline = (uint)(line * texWidth + 0);
|
||||
|
||||
//uint* up = (uint*)linep;
|
||||
|
||||
int rdi = 0;
|
||||
|
||||
fixed (byte* ptr = data)
|
||||
{
|
||||
for (int i = 0; i < texWidth; ++i)
|
||||
{
|
||||
uint x = 0;
|
||||
for (int j = 0; j < byp; ++j)
|
||||
{
|
||||
x |= ((uint)ptr[rdi]) << (j << 3); //load all bytes that represent the pixel's color into register x.
|
||||
++rdi;
|
||||
}
|
||||
uint unpackedColoByte = UnpackColor(x, ref cd);
|
||||
b[i+line*texWidth] = makeColor32fromUInt(unpackedColoByte);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void decodeRle(
|
||||
Color32[] b, int texWidth, int texHeight,
|
||||
int byp, tgaCD cd, System.IO.BinaryReader br, bool bottomUp)
|
||||
{
|
||||
try
|
||||
{
|
||||
int w = texWidth;
|
||||
// make buffer larger, so in case of emergency I can decode
|
||||
// over line ends.
|
||||
byte[] linebuffer = new byte[(w + 128) * byp];
|
||||
int maxindex = w * byp;
|
||||
int index = 0;
|
||||
|
||||
for (int j = 0; j < texHeight; ++j)
|
||||
{
|
||||
while (index < maxindex)
|
||||
{
|
||||
byte blocktype = br.ReadByte(); //MSB of blocktype: 1 means Raw packet(non-RLE), 0 means RLE packet
|
||||
|
||||
int bytestoread;
|
||||
int bytestocopy;
|
||||
|
||||
if (blocktype >= 0x80) // run-length packet. - read 1 color and replicate them by bytestocopy
|
||||
{
|
||||
int pixel_count_minus_1 = (blocktype - 0x80);
|
||||
bytestoread = byp; // pixel data
|
||||
bytestocopy = byp * pixel_count_minus_1;
|
||||
}
|
||||
else //raw packet (non run-lenght encoding.)
|
||||
{
|
||||
bytestoread = byp * (blocktype + 1);
|
||||
bytestocopy = 0;
|
||||
}
|
||||
|
||||
//if (index + bytestoread > maxindex)
|
||||
// throw new System.ArgumentException ("Corrupt TGA");
|
||||
|
||||
br.Read(linebuffer, index, bytestoread);
|
||||
index += bytestoread;
|
||||
|
||||
for (int i = 0; i != bytestocopy; ++i)
|
||||
{
|
||||
linebuffer[index + i] = linebuffer[index + i - bytestoread];
|
||||
}
|
||||
index += bytestocopy;
|
||||
}
|
||||
// todo: did i wrongly flip the orientation here? is the original actually correct?
|
||||
if (!bottomUp)
|
||||
decodeLine(b, texWidth, texHeight, j, byp, linebuffer, ref cd);
|
||||
else
|
||||
decodeLine(b, texWidth, texHeight, texHeight - j - 1, byp, linebuffer, ref cd);
|
||||
|
||||
if (index > maxindex)
|
||||
{
|
||||
Array.Copy(linebuffer, maxindex, linebuffer, 0, index - maxindex);
|
||||
index -= maxindex;
|
||||
}
|
||||
else
|
||||
index = 0;
|
||||
|
||||
}
|
||||
}
|
||||
catch (System.IO.EndOfStreamException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// decodes the non-RLE version of tga files.
|
||||
/// </summary>
|
||||
/// <param name="b">output reference to texture/bmp</param>
|
||||
/// <param name="byp">bytes-per-pixel</param>
|
||||
/// <param name="cd">???</param>
|
||||
/// <param name="br">binary reader that is reading the data file </param>
|
||||
/// <param name="bottomUp">if the image sh. </param>
|
||||
static void decodePlain(
|
||||
Color32[] b, int texWidth, int texHeight,
|
||||
int byp, tgaCD cd, System.IO.BinaryReader br, bool bottomUp)
|
||||
{
|
||||
int w = texWidth;
|
||||
byte[] linebuffer = new byte[w * byp];
|
||||
|
||||
for (int j = 0; j < texHeight; ++j)
|
||||
{
|
||||
br.Read(linebuffer, 0, w * byp);
|
||||
|
||||
// todo: did i wrongly flip the orientation here? is the original actually correct?
|
||||
if (!bottomUp)
|
||||
decodeLine(b, texWidth, texHeight, j, byp, linebuffer, ref cd);
|
||||
else
|
||||
decodeLine(b, texWidth, texHeight, texHeight - j - 1, byp, linebuffer, ref cd);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void decodeStandard8(
|
||||
Color32[] b, int texWidth, int texHeight,
|
||||
tgaHeader hdr,
|
||||
@@ -621,107 +611,6 @@ namespace OpenMetaverse.Imaging
|
||||
|
||||
|
||||
|
||||
struct tgaCD
|
||||
{
|
||||
public uint RMask, GMask, BMask, AMask;
|
||||
public byte RShift, GShift, BShift, AShift;
|
||||
public uint FinalOr;
|
||||
public bool NeedNoConvert;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// decodes the non-RLE version of tga files.
|
||||
/// </summary>
|
||||
/// <param name="b">output reference to texture/bmp</param>
|
||||
/// <param name="byp">bytes-per-pixel</param>
|
||||
/// <param name="cd">???</param>
|
||||
/// <param name="br">binary reader that is reading the data file </param>
|
||||
/// <param name="bottomUp">if the image sh. </param>
|
||||
static void decodePlain(
|
||||
Color32[] b, int texWidth, int texHeight,
|
||||
int byp, tgaCD cd, System.IO.BinaryReader br, bool bottomUp)
|
||||
{
|
||||
int w = texWidth;
|
||||
byte[] linebuffer = new byte[w * byp];
|
||||
|
||||
for (int j = 0; j < texHeight; ++j)
|
||||
{
|
||||
br.Read(linebuffer, 0, w * byp);
|
||||
|
||||
if (!bottomUp)
|
||||
decodeLine(b, texWidth, texHeight, j, byp, linebuffer, ref cd);
|
||||
else
|
||||
decodeLine(b, texWidth, texHeight, texHeight - j - 1, byp, linebuffer, ref cd);
|
||||
}
|
||||
}
|
||||
|
||||
static void decodeRle(
|
||||
Color32[] b, int texWidth, int texHeight,
|
||||
int byp, tgaCD cd, System.IO.BinaryReader br, bool bottomUp)
|
||||
{
|
||||
try
|
||||
{
|
||||
int w = texWidth;
|
||||
// make buffer larger, so in case of emergency I can decode
|
||||
// over line ends.
|
||||
byte[] linebuffer = new byte[(w + 128) * byp];
|
||||
int maxindex = w * byp;
|
||||
int index = 0;
|
||||
|
||||
for (int j = 0; j < texHeight; ++j)
|
||||
{
|
||||
while (index < maxindex)
|
||||
{
|
||||
byte blocktype = br.ReadByte(); //MSB of blocktype: 1 means Raw packet(non-RLE), 0 means RLE packet
|
||||
|
||||
int bytestoread;
|
||||
int bytestocopy;
|
||||
|
||||
if (blocktype >= 0x80) // run-length packet. - read 1 color and replicate them by bytestocopy
|
||||
{
|
||||
int pixel_count_minus_1 = (blocktype - 0x80);
|
||||
bytestoread = byp; // pixel data
|
||||
bytestocopy = byp * pixel_count_minus_1;
|
||||
}
|
||||
else //raw packet (non run-lenght encoding.)
|
||||
{
|
||||
bytestoread = byp * (blocktype + 1);
|
||||
bytestocopy = 0;
|
||||
}
|
||||
|
||||
//if (index + bytestoread > maxindex)
|
||||
// throw new System.ArgumentException ("Corrupt TGA");
|
||||
|
||||
br.Read(linebuffer, index, bytestoread);
|
||||
index += bytestoread;
|
||||
|
||||
for (int i = 0; i != bytestocopy; ++i)
|
||||
{
|
||||
linebuffer[index + i] = linebuffer[index + i - bytestoread];
|
||||
}
|
||||
index += bytestocopy;
|
||||
}
|
||||
if (!bottomUp)
|
||||
decodeLine(b, texWidth, texHeight, j, byp, linebuffer, ref cd);
|
||||
else
|
||||
decodeLine(b, texWidth, texHeight, texHeight - j - 1, byp, linebuffer, ref cd);
|
||||
|
||||
if (index > maxindex)
|
||||
{
|
||||
Array.Copy(linebuffer, maxindex, linebuffer, 0, index - maxindex);
|
||||
index -= maxindex;
|
||||
}
|
||||
else
|
||||
index = 0;
|
||||
|
||||
}
|
||||
}
|
||||
catch (System.IO.EndOfStreamException)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
static public Color32 makeColor32fromUInt(uint x)
|
||||
{
|
||||
return new Color32( (byte)( (x & 0x00FF0000) >> 16),
|
||||
@@ -730,75 +619,6 @@ namespace OpenMetaverse.Imaging
|
||||
(byte)((x & 0xFF000000) >> 24)); //alpha
|
||||
}
|
||||
|
||||
static uint UnpackColor(
|
||||
uint sourceColor, ref tgaCD cd)
|
||||
{
|
||||
if (cd.RMask == 0xFF && cd.GMask == 0xFF && cd.BMask == 0xFF)
|
||||
{
|
||||
// Special case to deal with 8-bit TGA files that we treat as alpha masks
|
||||
return sourceColor << 24;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint rpermute = (sourceColor << cd.RShift) | (sourceColor >> (32 - cd.RShift));
|
||||
uint gpermute = (sourceColor << cd.GShift) | (sourceColor >> (32 - cd.GShift));
|
||||
uint bpermute = (sourceColor << cd.BShift) | (sourceColor >> (32 - cd.BShift));
|
||||
uint apermute = (sourceColor << cd.AShift) | (sourceColor >> (32 - cd.AShift));
|
||||
uint result =
|
||||
(rpermute & cd.RMask) | (gpermute & cd.GMask)
|
||||
| (bpermute & cd.BMask) | (apermute & cd.AMask) | cd.FinalOr;
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
static unsafe void decodeLine(
|
||||
Color32[] b, int texWidth, int texHeight,
|
||||
int line,
|
||||
int byp,
|
||||
byte[] data,
|
||||
ref tgaCD cd)
|
||||
{
|
||||
if (cd.NeedNoConvert)
|
||||
{
|
||||
// fast copy
|
||||
uint offset_colorArray_scanline = (uint)(line * texWidth + 0); //should be large enough?
|
||||
//uint* linep = (uint*)((byte*)b.Scan0.ToPointer() + line * b.Stride);
|
||||
fixed (byte* ptr = data)
|
||||
{
|
||||
uint* sptr = (uint*)ptr;
|
||||
for (int i = 0; i < texWidth; ++i)
|
||||
{
|
||||
b[i + offset_colorArray_scanline] = makeColor32fromUInt(sptr[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//byte* linep = (byte*)b.Scan0.ToPointer() + line * b.Stride;
|
||||
uint offset_colorArray_scanline = (uint)(line * texWidth + 0);
|
||||
|
||||
//uint* up = (uint*)linep;
|
||||
|
||||
int rdi = 0;
|
||||
|
||||
fixed (byte* ptr = data)
|
||||
{
|
||||
for (int i = 0; i < texWidth; ++i)
|
||||
{
|
||||
uint x = 0;
|
||||
for (int j = 0; j < byp; ++j)
|
||||
{
|
||||
x |= ((uint)ptr[rdi]) << (j << 3); //load all bytes that represent the pixel's color into register x.
|
||||
++rdi;
|
||||
}
|
||||
uint unpackedColoByte = UnpackColor(x, ref cd);
|
||||
b[i+line*texWidth] = makeColor32fromUInt(unpackedColoByte);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -26,10 +26,6 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
using OpenMetaverse.StructuredData;
|
||||
using OpenMetaverse.Http;
|
||||
|
||||
@@ -149,16 +145,9 @@ namespace OpenMetaverse.ImportExport
|
||||
resources["mesh_list"] = meshList;
|
||||
|
||||
OSDArray textureList = new OSDArray();
|
||||
for (int i = 0; i < Images.Count; i++)
|
||||
foreach (var img in Images)
|
||||
{
|
||||
if (upload)
|
||||
{
|
||||
textureList.Add(new OSDBinary(Images[i]));
|
||||
}
|
||||
else
|
||||
{
|
||||
textureList.Add(new OSDBinary(Utils.EmptyBytes));
|
||||
}
|
||||
textureList.Add(upload ? new OSDBinary(img) : new OSDBinary(Utils.EmptyBytes));
|
||||
}
|
||||
|
||||
resources["texture_list"] = textureList;
|
||||
@@ -190,9 +179,8 @@ namespace OpenMetaverse.ImportExport
|
||||
return;
|
||||
}
|
||||
|
||||
if (result is OSDMap)
|
||||
if (result is OSDMap res)
|
||||
{
|
||||
var res = (OSDMap)result;
|
||||
Uri uploader = new Uri(res["uploader"]);
|
||||
PerformUpload(uploader, (contents =>
|
||||
{
|
||||
@@ -262,11 +250,11 @@ namespace OpenMetaverse.ImportExport
|
||||
return;
|
||||
}
|
||||
|
||||
Logger.Log("Response from mesh upload prepare:\n" + OSDParser.SerializeLLSDNotationFormatted(result), Helpers.LogLevel.Debug);
|
||||
Logger.Log("Response from mesh upload prepare:" + Environment.NewLine + OSDParser.SerializeLLSDNotationFormatted(result), Helpers.LogLevel.Debug);
|
||||
callback?.Invoke(result);
|
||||
};
|
||||
|
||||
request.BeginGetResponse(req, OSDFormat.Xml, 3 * 60 * 1000);
|
||||
request.PostRequestAsync(req, OSDFormat.Xml, 3 * 60 * 1000);
|
||||
|
||||
}
|
||||
|
||||
@@ -287,11 +275,12 @@ namespace OpenMetaverse.ImportExport
|
||||
return;
|
||||
}
|
||||
OSDMap res = (OSDMap)result;
|
||||
Logger.Log("Response from mesh upload perform:\n" + OSDParser.SerializeLLSDNotationFormatted(result), Helpers.LogLevel.Debug);
|
||||
Logger.Log("Response from mesh upload perform:" + Environment.NewLine
|
||||
+ OSDParser.SerializeLLSDNotationFormatted(result), Helpers.LogLevel.Debug);
|
||||
callback?.Invoke(res);
|
||||
};
|
||||
|
||||
request.BeginGetResponse(AssetResources(true), OSDFormat.Xml, 60 * 1000);
|
||||
request.PostRequestAsync(AssetResources(true), OSDFormat.Xml, 60 * 1000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,9 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace OpenMetaverse.Interfaces
|
||||
namespace OpenMetaverse.Interfaces
|
||||
{
|
||||
/// <summary>
|
||||
/// Interface to a class that can supply cached byte arrays
|
||||
|
||||
@@ -24,9 +24,6 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using OpenMetaverse.StructuredData;
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* Copyright (c) 2021-2022, Sjofn LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
@@ -132,7 +133,7 @@ namespace OpenMetaverse
|
||||
set
|
||||
{
|
||||
UpdateNodeFor(value);
|
||||
_RootNode = Items[value.UUID];
|
||||
RootNode = Items[value.UUID];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -145,28 +146,25 @@ namespace OpenMetaverse
|
||||
set
|
||||
{
|
||||
UpdateNodeFor(value);
|
||||
_LibraryRootNode = Items[value.UUID];
|
||||
LibraryRootNode = Items[value.UUID];
|
||||
}
|
||||
}
|
||||
|
||||
private InventoryNode _LibraryRootNode;
|
||||
private InventoryNode _RootNode;
|
||||
|
||||
/// <summary>
|
||||
/// The root node of the avatars inventory
|
||||
/// </summary>
|
||||
public InventoryNode RootNode => _RootNode;
|
||||
public InventoryNode RootNode { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The root node of the default shared library
|
||||
/// </summary>
|
||||
public InventoryNode LibraryRootNode => _LibraryRootNode;
|
||||
public InventoryNode LibraryRootNode { get; private set; }
|
||||
|
||||
public UUID Owner { get; }
|
||||
public UUID Owner { get; private set; }
|
||||
|
||||
private GridClient Client;
|
||||
//private InventoryManager Manager;
|
||||
public Dictionary<UUID, InventoryNode> Items = new Dictionary<UUID, InventoryNode>();
|
||||
public Dictionary<UUID, InventoryNode> Items;
|
||||
|
||||
public Inventory(GridClient client, InventoryManager manager)
|
||||
: this(client, manager, client.Self.AgentID) { }
|
||||
@@ -226,8 +224,10 @@ namespace OpenMetaverse
|
||||
if (item.ParentUUID != UUID.Zero && !Items.TryGetValue(item.ParentUUID, out itemParent))
|
||||
{
|
||||
// OK, we have no data on the parent, let's create a fake one.
|
||||
InventoryFolder fakeParent = new InventoryFolder(item.ParentUUID);
|
||||
fakeParent.DescendentCount = 1; // Dear god, please forgive me.
|
||||
InventoryFolder fakeParent = new InventoryFolder(item.ParentUUID)
|
||||
{
|
||||
DescendentCount = 1 // Dear god, please forgive me.
|
||||
};
|
||||
itemParent = new InventoryNode(fakeParent);
|
||||
Items[item.ParentUUID] = itemParent;
|
||||
// Unfortunately, this breaks the nice unified tree
|
||||
@@ -235,13 +235,6 @@ namespace OpenMetaverse
|
||||
// As soon as we get the parent, the tree repairs itself.
|
||||
//Logger.DebugLog("Attempting to update inventory child of " +
|
||||
// item.ParentUUID.ToString() + " when we have no local reference to that folder", Client);
|
||||
|
||||
if (Client.Settings.FETCH_MISSING_INVENTORY)
|
||||
{
|
||||
// Fetch the parent
|
||||
List<UUID> fetchreq = new List<UUID>(1) {item.ParentUUID};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
InventoryNode itemNode;
|
||||
@@ -349,7 +342,7 @@ namespace OpenMetaverse
|
||||
BinaryFormatter bformatter = new BinaryFormatter();
|
||||
lock (Items)
|
||||
{
|
||||
Logger.Log("Caching " + Items.Count.ToString() + " inventory items to " + filename, Helpers.LogLevel.Info);
|
||||
Logger.Log($"Caching {Items.Count} inventory items to {filename}", Helpers.LogLevel.Info);
|
||||
foreach (KeyValuePair<UUID, InventoryNode> kvp in Items)
|
||||
{
|
||||
bformatter.Serialize(stream, kvp.Value);
|
||||
@@ -359,7 +352,7 @@ namespace OpenMetaverse
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log("Error saving inventory cache to disk :"+e.Message,Helpers.LogLevel.Error);
|
||||
Logger.Log("Error saving inventory cache to disk", Helpers.LogLevel.Error, e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,7 +360,7 @@ namespace OpenMetaverse
|
||||
/// Loads in inventory cache file into the inventory structure. Note only valid to call after login has been successful.
|
||||
/// </summary>
|
||||
/// <param name="filename">Name of the cache file to load</param>
|
||||
/// <returns>The number of inventory items sucessfully reconstructed into the inventory node tree</returns>
|
||||
/// <returns>The number of inventory items successfully reconstructed into the inventory node tree</returns>
|
||||
public int RestoreFromDisk(string filename)
|
||||
{
|
||||
List<InventoryNode> nodes = new List<InventoryNode>();
|
||||
@@ -381,10 +374,9 @@ namespace OpenMetaverse
|
||||
using (Stream stream = File.Open(filename, FileMode.Open))
|
||||
{
|
||||
BinaryFormatter bformatter = new BinaryFormatter();
|
||||
|
||||
while (stream.Position < stream.Length)
|
||||
{
|
||||
OpenMetaverse.InventoryNode node = (InventoryNode)bformatter.Deserialize(stream);
|
||||
var node = (InventoryNode)bformatter.Deserialize(stream);
|
||||
nodes.Add(node);
|
||||
item_count++;
|
||||
}
|
||||
@@ -392,11 +384,11 @@ namespace OpenMetaverse
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Logger.Log("Error accessing inventory cache file :" + e.Message, Helpers.LogLevel.Error);
|
||||
Logger.Log("Error accessing inventory cache file", Helpers.LogLevel.Error, e);
|
||||
return -1;
|
||||
}
|
||||
|
||||
Logger.Log("Read " + item_count.ToString() + " items from inventory cache file", Helpers.LogLevel.Info);
|
||||
Logger.Log($"Read {item_count} items from inventory cache file", Helpers.LogLevel.Info);
|
||||
|
||||
item_count = 0;
|
||||
List<InventoryNode> del_nodes = new List<InventoryNode>(); //nodes that we have processed and will delete
|
||||
@@ -478,7 +470,7 @@ namespace OpenMetaverse
|
||||
del_nodes.Clear();
|
||||
}
|
||||
|
||||
Logger.Log("Reassembled " + item_count.ToString() + " items from inventory cache file", Helpers.LogLevel.Info);
|
||||
Logger.Log($"Reassembled {item_count} items from inventory cache file", Helpers.LogLevel.Info);
|
||||
return item_count;
|
||||
}
|
||||
|
||||
@@ -506,9 +498,10 @@ namespace OpenMetaverse
|
||||
{
|
||||
// Log a warning if there is a UUID mismatch, this will cause problems
|
||||
if (value.UUID != uuid)
|
||||
Logger.Log("Inventory[uuid]: uuid " + uuid.ToString() + " is not equal to value.UUID " +
|
||||
value.UUID.ToString(), Helpers.LogLevel.Warning, Client);
|
||||
|
||||
{
|
||||
Logger.Log($"Inventory[uuid]: uuid {uuid} is not equal to value.UUID {value.UUID}",
|
||||
Helpers.LogLevel.Warning, Client);
|
||||
}
|
||||
UpdateNodeFor(value);
|
||||
}
|
||||
else
|
||||
|
||||
@@ -1,10 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2019-2022, Sjofn LLC
|
||||
* All rights reserved.
|
||||
*
|
||||
* - 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.
|
||||
* - Neither the name of the openmetaverse.co 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR 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.ComponentModel;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using OpenMetaverse;
|
||||
@@ -26,7 +49,7 @@ namespace LibreMetaverse
|
||||
{
|
||||
Client = client;
|
||||
httpClient.DefaultRequestHeaders.Accept.Clear();
|
||||
httpClient.DefaultRequestHeaders.Add("User-Agent", "LibreMetaverse AIS Client");
|
||||
httpClient.DefaultRequestHeaders.Add("User-Agent", $"{Settings.USER_AGENT} AIS Client");
|
||||
}
|
||||
|
||||
public bool IsAvailable => (Client.Network.CurrentSim.Caps != null &&
|
||||
|
||||
@@ -1,7 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* Copyright (c) 2021-2022, Sjofn LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* - 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.
|
||||
* - Neither the name of the openmetaverse.co 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR 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.Runtime.Serialization;
|
||||
using System.Text;
|
||||
using OpenMetaverse.StructuredData;
|
||||
|
||||
namespace OpenMetaverse
|
||||
@@ -9,7 +34,7 @@ namespace OpenMetaverse
|
||||
/// <summary>
|
||||
/// Base Class for Inventory Items
|
||||
/// </summary>
|
||||
[Serializable()]
|
||||
[Serializable]
|
||||
public abstract class InventoryBase : ISerializable
|
||||
{
|
||||
/// <summary><seealso cref="OpenMetaverse.UUID"/> of item/folder</summary>
|
||||
@@ -69,7 +94,7 @@ namespace OpenMetaverse
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine whether the specified <seealso cref="OpenMetaverse.InventoryBase"/> object is equal to the current object
|
||||
/// Determine whether the specified <seealso cref="InventoryBase"/> object is equal to the current object
|
||||
/// </summary>
|
||||
/// <param name="obj">InventoryBase object to compare against</param>
|
||||
/// <returns>true if objects are the same</returns>
|
||||
@@ -79,7 +104,7 @@ namespace OpenMetaverse
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine whether the specified <seealso cref="OpenMetaverse.InventoryBase"/> object is equal to the current object
|
||||
/// Determine whether the specified <seealso cref="InventoryBase"/> object is equal to the current object
|
||||
/// </summary>
|
||||
/// <param name="o">InventoryBase object to compare against</param>
|
||||
/// <returns>true if objects are the same</returns>
|
||||
@@ -106,10 +131,9 @@ namespace OpenMetaverse
|
||||
{
|
||||
public override string ToString()
|
||||
{
|
||||
return AssetType + " " + AssetUUID + " (" + InventoryType + " " + UUID + ") '" + Name + "'/'" +
|
||||
Description + "' " + Permissions;
|
||||
return $"{AssetType} {AssetUUID} ({InventoryType} {UUID}) '{Name}'/'{Description}' {Permissions}";
|
||||
}
|
||||
/// <summary>The <seealso cref="OpenMetaverse.UUID"/> of this item</summary>
|
||||
/// <summary>The <seealso cref="UUID"/> of this item</summary>
|
||||
public UUID AssetUUID;
|
||||
/// <summary>The combined <seealso cref="OpenMetaverse.Permissions"/> of this item</summary>
|
||||
public Permissions Permissions;
|
||||
@@ -117,11 +141,11 @@ namespace OpenMetaverse
|
||||
public AssetType AssetType;
|
||||
/// <summary>The type of item from the <seealso cref="OpenMetaverse.InventoryType"/> enum</summary>
|
||||
public InventoryType InventoryType;
|
||||
/// <summary>The <seealso cref="OpenMetaverse.UUID"/> of the creator of this item</summary>
|
||||
/// <summary>The <seealso cref="UUID"/> of the creator of this item</summary>
|
||||
public UUID CreatorID;
|
||||
/// <summary>A Description of this item</summary>
|
||||
public string Description;
|
||||
/// <summary>The <seealso cref="OpenMetaverse.Group"/>s <seealso cref="OpenMetaverse.UUID"/> this item is set to or owned by</summary>
|
||||
/// <summary>The <seealso cref="Group"/>s <seealso cref="UUID"/> this item is set to or owned by</summary>
|
||||
public UUID GroupID;
|
||||
/// <summary>If true, item is owned by a group</summary>
|
||||
public bool GroupOwned;
|
||||
@@ -129,20 +153,20 @@ namespace OpenMetaverse
|
||||
public int SalePrice;
|
||||
/// <summary>The type of sale from the <seealso cref="OpenMetaverse.SaleType"/> enum</summary>
|
||||
public SaleType SaleType;
|
||||
/// <summary>Combined flags from <seealso cref="OpenMetaverse.InventoryItemFlags"/></summary>
|
||||
/// <summary>Combined flags from <seealso cref="InventoryItemFlags"/></summary>
|
||||
public uint Flags;
|
||||
/// <summary>Time and date this inventory item was created, stored as
|
||||
/// UTC (Coordinated Universal Time)</summary>
|
||||
public DateTime CreationDate;
|
||||
/// <summary>Used to update the AssetID in requests sent to the server</summary>
|
||||
public UUID TransactionID;
|
||||
/// <summary>The <seealso cref="OpenMetaverse.UUID"/> of the previous owner of the item</summary>
|
||||
/// <summary>The <seealso cref="UUID"/> of the previous owner of the item</summary>
|
||||
public UUID LastOwnerID;
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new InventoryItem object
|
||||
/// </summary>
|
||||
/// <param name="itemID">The <seealso cref="OpenMetaverse.UUID"/> of the item</param>
|
||||
/// <param name="itemID">The <seealso cref="UUID"/> of the item</param>
|
||||
public InventoryItem(UUID itemID)
|
||||
: base(itemID) { }
|
||||
|
||||
@@ -245,9 +269,9 @@ namespace OpenMetaverse
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Determine whether the specified <seealso cref="OpenMetaverse.InventoryItem"/> object is equal to the current object
|
||||
/// Determine whether the specified <seealso cref="InventoryItem"/> object is equal to the current object
|
||||
/// </summary>
|
||||
/// <param name="o">The <seealso cref="OpenMetaverse.InventoryItem"/> object to compare against</param>
|
||||
/// <param name="o">The <seealso cref="InventoryItem"/> object to compare against</param>
|
||||
/// <returns>true if objects are the same</returns>
|
||||
public bool Equals(InventoryItem o)
|
||||
{
|
||||
@@ -348,14 +372,14 @@ namespace OpenMetaverse
|
||||
/// InventoryTexture Class representing a graphical image
|
||||
/// </summary>
|
||||
/// <seealso cref="T:OpenMetaverse.Imaging.ManagedImage" />
|
||||
[Serializable()]
|
||||
[Serializable]
|
||||
public class InventoryTexture : InventoryItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct an InventoryTexture object
|
||||
/// </summary>
|
||||
/// <param name="itemID">A <seealso cref="OpenMetaverse.UUID"/> which becomes the
|
||||
/// <seealso cref="OpenMetaverse.InventoryItem"/> objects AssetUUID</param>
|
||||
/// <param name="itemID">A <seealso cref="UUID"/> which becomes the
|
||||
/// <seealso cref="InventoryItem"/> objects AssetUUID</param>
|
||||
public InventoryTexture(UUID itemID)
|
||||
: base(itemID)
|
||||
{
|
||||
@@ -376,14 +400,14 @@ namespace OpenMetaverse
|
||||
/// <summary>
|
||||
/// InventorySound Class representing a playable sound
|
||||
/// </summary>
|
||||
[Serializable()]
|
||||
[Serializable]
|
||||
public class InventorySound : InventoryItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct an InventorySound object
|
||||
/// </summary>
|
||||
/// <param name="itemID">A <seealso cref="OpenMetaverse.UUID"/> which becomes the
|
||||
/// <seealso cref="OpenMetaverse.InventoryItem"/> objects AssetUUID</param>
|
||||
/// <param name="itemID">A <seealso cref="UUID"/> which becomes the
|
||||
/// <seealso cref="InventoryItem"/> objects AssetUUID</param>
|
||||
public InventorySound(UUID itemID)
|
||||
: base(itemID)
|
||||
{
|
||||
@@ -404,14 +428,14 @@ namespace OpenMetaverse
|
||||
/// <summary>
|
||||
/// InventoryCallingCard Class, contains information on another avatar
|
||||
/// </summary>
|
||||
[Serializable()]
|
||||
[Serializable]
|
||||
public class InventoryCallingCard : InventoryItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct an InventoryCallingCard object
|
||||
/// </summary>
|
||||
/// <param name="itemID">A <seealso cref="OpenMetaverse.UUID"/> which becomes the
|
||||
/// <seealso cref="OpenMetaverse.InventoryItem"/> objects AssetUUID</param>
|
||||
/// <param name="itemID">A <seealso cref="UUID"/> which becomes the
|
||||
/// <seealso cref="InventoryItem"/> objects AssetUUID</param>
|
||||
public InventoryCallingCard(UUID itemID)
|
||||
: base(itemID)
|
||||
{
|
||||
@@ -432,14 +456,14 @@ namespace OpenMetaverse
|
||||
/// <summary>
|
||||
/// InventoryLandmark Class, contains details on a specific location
|
||||
/// </summary>
|
||||
[Serializable()]
|
||||
[Serializable]
|
||||
public class InventoryLandmark : InventoryItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct an InventoryLandmark object
|
||||
/// </summary>
|
||||
/// <param name="itemID">A <seealso cref="OpenMetaverse.UUID"/> which becomes the
|
||||
/// <seealso cref="OpenMetaverse.InventoryItem"/> objects AssetUUID</param>
|
||||
/// <param name="itemID">A <seealso cref="UUID"/> which becomes the
|
||||
/// <seealso cref="InventoryItem"/> objects AssetUUID</param>
|
||||
public InventoryLandmark(UUID itemID)
|
||||
: base(itemID)
|
||||
{
|
||||
@@ -474,14 +498,14 @@ namespace OpenMetaverse
|
||||
/// <summary>
|
||||
/// InventoryObject Class contains details on a primitive or coalesced set of primitives
|
||||
/// </summary>
|
||||
[Serializable()]
|
||||
[Serializable]
|
||||
public class InventoryObject : InventoryItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct an InventoryObject object
|
||||
/// </summary>
|
||||
/// <param name="itemID">A <seealso cref="OpenMetaverse.UUID"/> which becomes the
|
||||
/// <seealso cref="OpenMetaverse.InventoryItem"/> objects AssetUUID</param>
|
||||
/// <param name="itemID">A <seealso cref="UUID"/> which becomes the
|
||||
/// <seealso cref="InventoryItem"/> objects AssetUUID</param>
|
||||
public InventoryObject(UUID itemID)
|
||||
: base(itemID)
|
||||
{
|
||||
@@ -520,14 +544,14 @@ namespace OpenMetaverse
|
||||
/// <summary>
|
||||
/// InventoryNotecard Class, contains details on an encoded text document
|
||||
/// </summary>
|
||||
[Serializable()]
|
||||
[Serializable]
|
||||
public class InventoryNotecard : InventoryItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct an InventoryNotecard object
|
||||
/// </summary>
|
||||
/// <param name="itemID">A <seealso cref="OpenMetaverse.UUID"/> which becomes the
|
||||
/// <seealso cref="OpenMetaverse.InventoryItem"/> objects AssetUUID</param>
|
||||
/// <param name="itemID">A <seealso cref="UUID"/> which becomes the
|
||||
/// <seealso cref="InventoryItem"/> objects AssetUUID</param>
|
||||
public InventoryNotecard(UUID itemID)
|
||||
: base(itemID)
|
||||
{
|
||||
@@ -549,14 +573,14 @@ namespace OpenMetaverse
|
||||
/// InventoryCategory Class
|
||||
/// </summary>
|
||||
/// <remarks>TODO: Is this even used for anything?</remarks>
|
||||
[Serializable()]
|
||||
[Serializable]
|
||||
public class InventoryCategory : InventoryItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct an InventoryCategory object
|
||||
/// </summary>
|
||||
/// <param name="itemID">A <seealso cref="OpenMetaverse.UUID"/> which becomes the
|
||||
/// <seealso cref="OpenMetaverse.InventoryItem"/> objects AssetUUID</param>
|
||||
/// <param name="itemID">A <seealso cref="UUID"/> which becomes the
|
||||
/// <seealso cref="InventoryItem"/> objects AssetUUID</param>
|
||||
public InventoryCategory(UUID itemID)
|
||||
: base(itemID)
|
||||
{
|
||||
@@ -577,14 +601,14 @@ namespace OpenMetaverse
|
||||
/// <summary>
|
||||
/// InventoryLSL Class, represents a Linden Scripting Language object
|
||||
/// </summary>
|
||||
[Serializable()]
|
||||
[Serializable]
|
||||
public class InventoryLSL : InventoryItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct an InventoryLSL object
|
||||
/// </summary>
|
||||
/// <param name="itemID">A <seealso cref="OpenMetaverse.UUID"/> which becomes the
|
||||
/// <seealso cref="OpenMetaverse.InventoryItem"/> objects AssetUUID</param>
|
||||
/// <param name="itemID">A <seealso cref="UUID"/> which becomes the
|
||||
/// <seealso cref="InventoryItem"/> objects AssetUUID</param>
|
||||
public InventoryLSL(UUID itemID)
|
||||
: base(itemID)
|
||||
{
|
||||
@@ -605,7 +629,7 @@ namespace OpenMetaverse
|
||||
/// <summary>
|
||||
/// InventorySnapshot Class, an image taken with the viewer
|
||||
/// </summary>
|
||||
[Serializable()]
|
||||
[Serializable]
|
||||
public class InventorySnapshot : InventoryItem
|
||||
{
|
||||
/// <inheritdoc />
|
||||
@@ -633,14 +657,14 @@ namespace OpenMetaverse
|
||||
/// <summary>
|
||||
/// InventoryAttachment Class, contains details on an attachable object
|
||||
/// </summary>
|
||||
[Serializable()]
|
||||
[Serializable]
|
||||
public class InventoryAttachment : InventoryItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct an InventoryAttachment object
|
||||
/// </summary>
|
||||
/// <param name="itemID">A <seealso cref="OpenMetaverse.UUID"/> which becomes the
|
||||
/// <seealso cref="OpenMetaverse.InventoryItem"/> objects AssetUUID</param>
|
||||
/// <param name="itemID">A <seealso cref="UUID"/> which becomes the
|
||||
/// <seealso cref="InventoryItem"/> objects AssetUUID</param>
|
||||
public InventoryAttachment(UUID itemID)
|
||||
: base(itemID)
|
||||
{
|
||||
@@ -670,14 +694,14 @@ namespace OpenMetaverse
|
||||
/// <summary>
|
||||
/// InventoryWearable Class, details on a clothing item or body part
|
||||
/// </summary>
|
||||
[Serializable()]
|
||||
[Serializable]
|
||||
public class InventoryWearable : InventoryItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct an InventoryWearable object
|
||||
/// </summary>
|
||||
/// <param name="itemID">A <seealso cref="OpenMetaverse.UUID"/> which becomes the
|
||||
/// <seealso cref="OpenMetaverse.InventoryItem"/> objects AssetUUID</param>
|
||||
/// <param name="itemID">A <seealso cref="UUID"/> which becomes the
|
||||
/// <seealso cref="InventoryItem"/> objects AssetUUID</param>
|
||||
public InventoryWearable(UUID itemID) : base(itemID) { InventoryType = InventoryType.Wearable; }
|
||||
|
||||
/// <summary>
|
||||
@@ -703,14 +727,14 @@ namespace OpenMetaverse
|
||||
/// <summary>
|
||||
/// InventoryAnimation Class, A bvh encoded object which animates an avatar
|
||||
/// </summary>
|
||||
[Serializable()]
|
||||
[Serializable]
|
||||
public class InventoryAnimation : InventoryItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct an InventoryAnimation object
|
||||
/// </summary>
|
||||
/// <param name="itemID">A <seealso cref="OpenMetaverse.UUID"/> which becomes the
|
||||
/// <seealso cref="OpenMetaverse.InventoryItem"/> objects AssetUUID</param>
|
||||
/// <param name="itemID">A <seealso cref="UUID"/> which becomes the
|
||||
/// <seealso cref="InventoryItem"/> objects AssetUUID</param>
|
||||
public InventoryAnimation(UUID itemID)
|
||||
: base(itemID)
|
||||
{
|
||||
@@ -731,14 +755,14 @@ namespace OpenMetaverse
|
||||
/// <summary>
|
||||
/// InventoryGesture Class, details on a series of animations, sounds, and actions
|
||||
/// </summary>
|
||||
[Serializable()]
|
||||
[Serializable]
|
||||
public class InventoryGesture : InventoryItem
|
||||
{
|
||||
/// <summary>
|
||||
/// Construct an InventoryGesture object
|
||||
/// </summary>
|
||||
/// <param name="itemID">A <seealso cref="OpenMetaverse.UUID"/> which becomes the
|
||||
/// <seealso cref="OpenMetaverse.InventoryItem"/> objects AssetUUID</param>
|
||||
/// <param name="itemID">A <seealso cref="UUID"/> which becomes the
|
||||
/// <seealso cref="InventoryItem"/> objects AssetUUID</param>
|
||||
public InventoryGesture(UUID itemID)
|
||||
: base(itemID)
|
||||
{
|
||||
@@ -760,7 +784,7 @@ namespace OpenMetaverse
|
||||
/// A folder contains <seealso cref="T:OpenMetaverse.InventoryItem" />s and has certain attributes specific
|
||||
/// to itself
|
||||
/// </summary>
|
||||
[Serializable()]
|
||||
[Serializable]
|
||||
public class InventoryFolder : InventoryBase
|
||||
{
|
||||
/// <summary>The Preferred <seealso cref="T:OpenMetaverse.FolderType"/> for a folder.</summary>
|
||||
|
||||
@@ -29,8 +29,6 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Threading;
|
||||
using System.Runtime.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
using OpenMetaverse.Http;
|
||||
using OpenMetaverse.Messages.Linden;
|
||||
using OpenMetaverse.StructuredData;
|
||||
@@ -548,8 +546,7 @@ namespace OpenMetaverse
|
||||
if (itemIDs.Count != ownerIDs.Count)
|
||||
throw new ArgumentException("itemIDs and ownerIDs must contain the same number of entries");
|
||||
|
||||
if (Client.Settings.HTTP_INVENTORY &&
|
||||
Client.Network.CurrentSim.Caps != null &&
|
||||
if (Client.Network.CurrentSim.Caps != null &&
|
||||
Client.Network.CurrentSim.Caps.CapabilityURI("FetchInventory2") != null)
|
||||
{
|
||||
RequestFetchInventoryCap(itemIDs, ownerIDs);
|
||||
@@ -590,8 +587,7 @@ namespace OpenMetaverse
|
||||
if (itemIDs.Count != ownerIDs.Count)
|
||||
throw new ArgumentException("itemIDs and ownerIDs must contain the same number of entries");
|
||||
|
||||
if (Client.Settings.HTTP_INVENTORY &&
|
||||
Client.Network.CurrentSim.Caps != null &&
|
||||
if (Client.Network.CurrentSim.Caps != null &&
|
||||
Client.Network.CurrentSim.Caps.CapabilityURI("FetchInventory2") != null)
|
||||
{
|
||||
CapsClient request = Client.Network.CurrentSim.Caps.CreateCapsClient("FetchInventory2");
|
||||
@@ -633,7 +629,7 @@ namespace OpenMetaverse
|
||||
|
||||
OSDRequest["items"] = items;
|
||||
|
||||
request.BeginGetResponse(OSDRequest, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
request.PostRequestAsync(OSDRequest, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
@@ -647,7 +643,7 @@ namespace OpenMetaverse
|
||||
/// <param name="order">sort order to return results in</param>
|
||||
/// <param name="timeoutMS">a integer representing the number of milliseconds to wait for results</param>
|
||||
/// <param name="fast_loading">when false uses links and does not attempt to get the real object</param>
|
||||
/// <returns>keypair with a status message, and List<InventoryBase>
|
||||
/// <returns>keypair with a status message, and List<seealso cref="InventoryBase"/>
|
||||
/// if the status message is retry you should check again in a bit is is currently loading
|
||||
/// links using RequestFetchInventoryCap
|
||||
/// </returns>
|
||||
@@ -764,8 +760,7 @@ namespace OpenMetaverse
|
||||
{
|
||||
string cap = owner == Client.Self.AgentID ? "FetchInventoryDescendents2" : "FetchLibDescendents2";
|
||||
|
||||
if (Client.Settings.HTTP_INVENTORY &&
|
||||
Client.Network.CurrentSim.Caps != null &&
|
||||
if (Client.Network.CurrentSim.Caps != null &&
|
||||
Client.Network.CurrentSim.Caps.CapabilityURI(cap) != null)
|
||||
{
|
||||
RequestFolderContentsCap(folder, owner, folders, items, order);
|
||||
@@ -909,8 +904,8 @@ namespace OpenMetaverse
|
||||
}
|
||||
catch (Exception exc)
|
||||
{
|
||||
Logger.Log($"Failed to fetch inventory descendants: {exc.Message}\n" +
|
||||
$"{exc.StackTrace.ToString()}",
|
||||
Logger.Log($"Failed to fetch inventory descendants: {exc.Message}" + Environment.NewLine +
|
||||
$"{exc.StackTrace}",
|
||||
Helpers.LogLevel.Warning, Client);
|
||||
foreach (var f in batch)
|
||||
{
|
||||
@@ -937,11 +932,11 @@ namespace OpenMetaverse
|
||||
}
|
||||
OSDMap req = new OSDMap(1) { ["folders"] = requestedFolders };
|
||||
|
||||
request.BeginGetResponse(req, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
request.PostRequestAsync(req, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.Log($"Failed to fetch inventory descendants: {ex.Message}\n" +
|
||||
Logger.Log($"Failed to fetch inventory descendants: {ex.Message}" + Environment.NewLine +
|
||||
$"{ex.StackTrace}",
|
||||
Helpers.LogLevel.Warning, Client);
|
||||
foreach (var f in batch)
|
||||
@@ -1778,31 +1773,29 @@ namespace OpenMetaverse
|
||||
|
||||
CapsClient request = Client.Network.CurrentSim.Caps.CreateCapsClient("NewFileAgentInventory");
|
||||
|
||||
if (request != null)
|
||||
{
|
||||
OSDMap query = new OSDMap
|
||||
{
|
||||
{"folder_id", OSD.FromUUID(folderID)},
|
||||
{"asset_type", OSD.FromString(Utils.AssetTypeToString(assetType))},
|
||||
{"inventory_type", OSD.FromString(Utils.InventoryTypeToString(invType))},
|
||||
{"name", OSD.FromString(name)},
|
||||
{"description", OSD.FromString(description)},
|
||||
{"everyone_mask", OSD.FromInteger((int) permissions.EveryoneMask)},
|
||||
{"group_mask", OSD.FromInteger((int) permissions.GroupMask)},
|
||||
{"next_owner_mask", OSD.FromInteger((int) permissions.NextOwnerMask)},
|
||||
{"expected_upload_cost", OSD.FromInteger(Client.Settings.UPLOAD_COST)}
|
||||
};
|
||||
|
||||
// Make the request
|
||||
request.OnComplete += CreateItemFromAssetResponse;
|
||||
request.UserData = new object[] { callback, data, Client.Settings.CAPS_TIMEOUT, query };
|
||||
|
||||
request.BeginGetResponse(query, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (request == null) {
|
||||
throw new Exception("NewFileAgentInventory capability is not currently available");
|
||||
}
|
||||
|
||||
OSDMap query = new OSDMap
|
||||
{
|
||||
{"folder_id", OSD.FromUUID(folderID)},
|
||||
{"asset_type", OSD.FromString(Utils.AssetTypeToString(assetType))},
|
||||
{"inventory_type", OSD.FromString(Utils.InventoryTypeToString(invType))},
|
||||
{"name", OSD.FromString(name)},
|
||||
{"description", OSD.FromString(description)},
|
||||
{"everyone_mask", OSD.FromInteger((int) permissions.EveryoneMask)},
|
||||
{"group_mask", OSD.FromInteger((int) permissions.GroupMask)},
|
||||
{"next_owner_mask", OSD.FromInteger((int) permissions.NextOwnerMask)},
|
||||
{"expected_upload_cost", OSD.FromInteger(Client.Settings.UPLOAD_COST)}
|
||||
};
|
||||
|
||||
// Make the request
|
||||
request.OnComplete += CreateItemFromAssetResponse;
|
||||
request.UserData = new object[] { callback, data, Client.Settings.CAPS_TIMEOUT, query };
|
||||
|
||||
request.PostRequestAsync(query, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -2009,7 +2002,7 @@ namespace OpenMetaverse
|
||||
ObjectID = objectID
|
||||
};
|
||||
|
||||
request.BeginGetResponse(message.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
request.PostRequestAsync(message.Serialize(),OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2163,7 +2156,7 @@ namespace OpenMetaverse
|
||||
// Make the request
|
||||
request.OnComplete += UploadInventoryAssetResponse;
|
||||
request.UserData = new object[] { new KeyValuePair<InventoryUploadedAssetCallback, byte[]>(callback, data), notecardID };
|
||||
request.BeginGetResponse(query, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
request.PostRequestAsync(query, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2196,7 +2189,7 @@ namespace OpenMetaverse
|
||||
// Make the request
|
||||
request.OnComplete += UploadInventoryAssetResponse;
|
||||
request.UserData = new object[] { new KeyValuePair<InventoryUploadedAssetCallback, byte[]>(callback, data), notecardID };
|
||||
request.BeginGetResponse(query, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
request.PostRequestAsync(query, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2224,7 +2217,7 @@ namespace OpenMetaverse
|
||||
// Make the request
|
||||
request.OnComplete += UploadInventoryAssetResponse;
|
||||
request.UserData = new object[] { new KeyValuePair<InventoryUploadedAssetCallback, byte[]>(callback, data), gestureID };
|
||||
request.BeginGetResponse(query, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
request.PostRequestAsync(query, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2253,7 +2246,7 @@ namespace OpenMetaverse
|
||||
|
||||
request.OnComplete += new CapsClient.CompleteCallback(UpdateScriptAgentInventoryResponse);
|
||||
request.UserData = new object[2] { new KeyValuePair<ScriptUpdatedCallback, byte[]>(callback, data), itemID };
|
||||
request.BeginGetResponse(msg.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
request.PostRequestAsync(msg.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2286,7 +2279,7 @@ namespace OpenMetaverse
|
||||
|
||||
request.OnComplete += new CapsClient.CompleteCallback(UpdateScriptAgentInventoryResponse);
|
||||
request.UserData = new object[2] { new KeyValuePair<ScriptUpdatedCallback, byte[]>(callback, data), itemID };
|
||||
request.BeginGetResponse(msg.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
request.PostRequestAsync(msg.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2563,7 +2556,7 @@ namespace OpenMetaverse
|
||||
/// <summary>
|
||||
/// Recurse inventory category and return folders and items. Does NOT contain parent folder being searched
|
||||
/// </summary>
|
||||
/// <param name="folder">Inventory category to recursively search</param>
|
||||
/// <param name="folderID">Inventory category to recursively search</param>
|
||||
/// <param name="owner">Owner of folder</param>
|
||||
/// <param name="cats">reference to list of categories</param>
|
||||
/// <param name="items">reference to list of items</param>
|
||||
@@ -3589,6 +3582,7 @@ namespace OpenMetaverse
|
||||
break;
|
||||
}
|
||||
imp.MessageBlock.BinaryBucket = args.FolderID.GetBytes();
|
||||
RequestFetchInventory(objectID, e.IM.ToAgentID);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3609,7 +3603,7 @@ namespace OpenMetaverse
|
||||
imp.MessageBlock.BinaryBucket = Utils.EmptyBytes;
|
||||
}
|
||||
|
||||
Client.Network.SendPacket(imp, e.Simulator);
|
||||
Client.Network.SendPacket(imp, e.Simulator ?? Client.Network.CurrentSim);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -3660,7 +3654,7 @@ namespace OpenMetaverse
|
||||
CapsClient upload = new CapsClient(new Uri(uploadURL), "CreateItemFromAsset");
|
||||
upload.OnComplete += CreateItemFromAssetResponse;
|
||||
upload.UserData = new object[] { callback, itemData, millisecondsTimeout, request };
|
||||
upload.BeginGetResponse(itemData, "application/octet-stream", millisecondsTimeout);
|
||||
upload.PostRequestAsync(itemData, "application/octet-stream", millisecondsTimeout);
|
||||
}
|
||||
else if (status == "complete")
|
||||
{
|
||||
@@ -3739,7 +3733,7 @@ namespace OpenMetaverse
|
||||
CapsClient upload = new CapsClient(uploadURL, "UploadItemResponse");
|
||||
upload.OnComplete += UploadInventoryAssetResponse;
|
||||
upload.UserData = new object[2] { kvp, (UUID)(((object[])client.UserData)[1]) };
|
||||
upload.BeginGetResponse(itemData, "application/octet-stream", Client.Settings.CAPS_TIMEOUT);
|
||||
upload.PostRequestAsync(itemData, "application/octet-stream", Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3810,7 +3804,7 @@ namespace OpenMetaverse
|
||||
CapsClient upload = new CapsClient(new Uri(uploadURL), "ScriptAgentInventoryResponse");
|
||||
upload.OnComplete += UpdateScriptAgentInventoryResponse;
|
||||
upload.UserData = new object[2] { kvp, (UUID)(((object[])client.UserData)[1]) };
|
||||
upload.BeginGetResponse(itemData, "application/octet-stream", Client.Settings.CAPS_TIMEOUT);
|
||||
upload.PostRequestAsync(itemData, "application/octet-stream", Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
else if (status == "complete" && callback != null)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* Copyright (c) 2021-2022, Sjofn LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
@@ -34,13 +35,12 @@ namespace OpenMetaverse
|
||||
{
|
||||
private InventoryBase data;
|
||||
private InventoryNode parent;
|
||||
private UUID parentID; //used for de-seralization
|
||||
private UUID parentID; //used for deseralization
|
||||
private InventoryNodeDictionary nodes;
|
||||
private bool needsUpdate = true;
|
||||
[NonSerialized]
|
||||
private object tag;
|
||||
|
||||
/// <summary></summary>
|
||||
public InventoryBase Data
|
||||
{
|
||||
get => data;
|
||||
@@ -54,24 +54,35 @@ namespace OpenMetaverse
|
||||
set => tag = value;
|
||||
}
|
||||
|
||||
/// <summary></summary>
|
||||
public InventoryNode Parent
|
||||
{
|
||||
get => parent;
|
||||
set => parent = value;
|
||||
}
|
||||
|
||||
/// <summary></summary>
|
||||
public UUID ParentID => parentID;
|
||||
public UUID ParentID
|
||||
{
|
||||
get => parentID;
|
||||
private set => parentID = value;
|
||||
}
|
||||
|
||||
/// <summary></summary>
|
||||
public InventoryNodeDictionary Nodes
|
||||
{
|
||||
get { return nodes ?? (nodes = new InventoryNodeDictionary(this)); }
|
||||
get => nodes ?? (nodes = new InventoryNodeDictionary(this));
|
||||
set => nodes = value;
|
||||
}
|
||||
|
||||
public System.DateTime ModifyTime
|
||||
/// <summary>
|
||||
/// For inventory folder nodes specifies weather the folder needs to be
|
||||
/// refreshed from the server
|
||||
/// </summary>
|
||||
public bool NeedsUpdate
|
||||
{
|
||||
get => needsUpdate;
|
||||
set => needsUpdate = value;
|
||||
}
|
||||
|
||||
public DateTime ModifyTime
|
||||
{
|
||||
get
|
||||
{
|
||||
@@ -97,16 +108,6 @@ namespace OpenMetaverse
|
||||
Nodes.Sort();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// For inventory folder nodes specifies weather the folder needs to be
|
||||
/// refreshed from the server
|
||||
/// </summary>
|
||||
public bool NeedsUpdate
|
||||
{
|
||||
get { return needsUpdate; }
|
||||
set { needsUpdate = value; }
|
||||
}
|
||||
|
||||
public InventoryNode()
|
||||
{
|
||||
}
|
||||
@@ -151,8 +152,8 @@ namespace OpenMetaverse
|
||||
Type type = (Type)info.GetValue("Type", typeof(Type));
|
||||
|
||||
// Construct a new inventory object based on the Type stored in Type
|
||||
System.Reflection.ConstructorInfo ctr = type.GetConstructor(new Type[] {typeof(SerializationInfo),typeof(StreamingContext)});
|
||||
data = (InventoryBase) ctr.Invoke(new Object[] { info, ctxt });
|
||||
System.Reflection.ConstructorInfo ctr = type.GetConstructor(new[] {typeof(SerializationInfo),typeof(StreamingContext)});
|
||||
if (ctr != null) data = (InventoryBase)ctr.Invoke(new object[] { info, ctxt });
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
|
||||
+120
-73
@@ -1,4 +1,6 @@
|
||||
/* Copyright (c) 2008 Robert Adams
|
||||
* Copyright (c) 2021-2022, Sjofn LLC. All rights reserved.
|
||||
*
|
||||
* 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
|
||||
@@ -37,8 +39,6 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using OpenMetaverse.StructuredData;
|
||||
using LibreMetaverse.PrimMesher;
|
||||
using OMV = OpenMetaverse;
|
||||
using OMVR = OpenMetaverse.Rendering;
|
||||
//using Catnip.Drawing;
|
||||
using UnityEngine;
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace OpenMetaverse.Rendering
|
||||
/// Meshing code based on the Idealist Viewer (20081213).
|
||||
/// </summary>
|
||||
[RendererName("MeshmerizerR")]
|
||||
public class MeshmerizerR : OMVR.IRendering
|
||||
public class MeshmerizerR : IRendering
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates a basic mesh structure from a primitive
|
||||
@@ -57,9 +57,9 @@ namespace OpenMetaverse.Rendering
|
||||
/// <param name="prim">Primitive to generate the mesh from</param>
|
||||
/// <param name="lod">Level of detail to generate the mesh at</param>
|
||||
/// <returns>The generated mesh or null on failure</returns>
|
||||
public OMVR.SimpleMesh GenerateSimpleMesh(OMV.Primitive prim, OMVR.DetailLevel lod)
|
||||
public SimpleMesh GenerateSimpleMesh(Primitive prim, DetailLevel lod)
|
||||
{
|
||||
LibreMetaverse.PrimMesher.PrimMesh newPrim = GeneratePrimMesh(prim, lod, false);
|
||||
PrimMesh newPrim = GeneratePrimMesh(prim, lod, false);
|
||||
if (newPrim == null)
|
||||
return null;
|
||||
|
||||
@@ -86,6 +86,44 @@ namespace OpenMetaverse.Rendering
|
||||
return mesh;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Generates a basic mesh structure from a primitive, adding normals data.
|
||||
/// A 'SimpleMesh' is just the prim's overall shape with no material information.
|
||||
/// </summary>
|
||||
/// <param name="prim">Primitive to generate the mesh from</param>
|
||||
/// <param name="lod">Level of detail to generate the mesh at</param>
|
||||
/// <returns>The generated mesh or null on failure</returns>
|
||||
public SimpleMesh GenerateSimpleMeshWithNormals(Primitive prim, DetailLevel lod) {
|
||||
PrimMesh newPrim = GeneratePrimMesh(prim, lod, true);
|
||||
if(newPrim == null)
|
||||
return null;
|
||||
|
||||
SimpleMesh mesh = new SimpleMesh {
|
||||
Path = new Path(),
|
||||
Prim = prim,
|
||||
Profile = new Profile(),
|
||||
Vertices = new List<Vertex>(newPrim.coords.Count)
|
||||
};
|
||||
|
||||
for(int i = 0; i < newPrim.coords.Count; i++) {
|
||||
Coord c = newPrim.coords[i];
|
||||
// Also saving the normal within the vertice
|
||||
Coord n = newPrim.normals[i];
|
||||
mesh.Vertices.Add(new Vertex {Position = new Vector3(c.X, c.Y, c.Z), Normal = new Vector3(n.X, n.Y, n.Z)});
|
||||
}
|
||||
|
||||
mesh.Indices = new List<ushort>(newPrim.faces.Count * 3);
|
||||
foreach(var face in newPrim.faces) {
|
||||
mesh.Indices.Add((ushort) face.v1);
|
||||
mesh.Indices.Add((ushort) face.v2);
|
||||
mesh.Indices.Add((ushort) face.v3);
|
||||
}
|
||||
|
||||
return mesh;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Generates a basic mesh structure from a sculpted primitive.
|
||||
/// 'SimpleMesh's have a single mesh and no faces or material information.
|
||||
@@ -94,7 +132,9 @@ namespace OpenMetaverse.Rendering
|
||||
/// <param name="sculptTexture">Sculpt texture</param>
|
||||
/// <param name="lod">Level of detail to generate the mesh at</param>
|
||||
/// <returns>The generated mesh or null on failure</returns>
|
||||
public SimpleMesh GenerateSimpleSculptMesh(Primitive prim, Texture2D sculptTexture, DetailLevel lod)
|
||||
public SimpleMesh GenerateSimpleSculptMesh( Primitive prim,
|
||||
Texture2D sculptTexture,
|
||||
DetailLevel lod)
|
||||
{
|
||||
var faceted = GenerateFacetedSculptMesh(prim, sculptTexture, lod);
|
||||
|
||||
@@ -130,41 +170,41 @@ namespace OpenMetaverse.Rendering
|
||||
/// <returns>The generated mesh</returns >
|
||||
public FacetedMesh GenerateFacetedMesh(Primitive prim, DetailLevel lod)
|
||||
{
|
||||
bool isSphere = ((OMV.ProfileCurve)(prim.PrimData.profileCurve & 0x07) == OMV.ProfileCurve.HalfCircle);
|
||||
LibreMetaverse.PrimMesher.PrimMesh newPrim = GeneratePrimMesh(prim, lod, true);
|
||||
bool isSphere = ((ProfileCurve)(prim.PrimData.profileCurve & 0x07) == ProfileCurve.HalfCircle);
|
||||
PrimMesh newPrim = GeneratePrimMesh(prim, lod, true);
|
||||
if (newPrim == null)
|
||||
return null;
|
||||
|
||||
// copy the vertex information into OMVR.IRendering structures
|
||||
var omvrmesh = new OMVR.FacetedMesh
|
||||
// copy the vertex information into IRendering structures
|
||||
var omvrmesh = new FacetedMesh
|
||||
{
|
||||
Faces = new List<OMVR.Face>(),
|
||||
Faces = new List<Face>(),
|
||||
Prim = prim,
|
||||
Profile = new OMVR.Profile
|
||||
Profile = new Profile
|
||||
{
|
||||
Faces = new List<OMVR.ProfileFace>(),
|
||||
Positions = new List<OMV.Vector3>()
|
||||
Faces = new List<ProfileFace>(),
|
||||
Positions = new List<Vector3>()
|
||||
},
|
||||
Path = new OMVR.Path {Points = new List<OMVR.PathPoint>()}
|
||||
Path = new Path {Points = new List<PathPoint>()}
|
||||
};
|
||||
var indexer = newPrim.GetVertexIndexer();
|
||||
|
||||
for (int i = 0; i < indexer.numPrimFaces; i++)
|
||||
{
|
||||
OMVR.Face oface = new OMVR.Face
|
||||
Face oface = new Face
|
||||
{
|
||||
Vertices = new List<OMVR.Vertex>(),
|
||||
Vertices = new List<Vertex>(),
|
||||
Indices = new List<ushort>(),
|
||||
TextureFace = prim.Textures.GetFace((uint) i)
|
||||
};
|
||||
|
||||
for (int j = 0; j < indexer.viewerVertices[i].Count; j++)
|
||||
{
|
||||
var vert = new OMVR.Vertex();
|
||||
var vert = new Vertex();
|
||||
var m = indexer.viewerVertices[i][j];
|
||||
vert.Position = new Vector3(m.v.X, m.v.Y, m.v.Z);
|
||||
vert.Normal = new Vector3(m.n.X, m.n.Y, m.n.Z);
|
||||
vert.TexCoord = new OMV.Vector2(m.uv.U, 1.0f - m.uv.V);
|
||||
vert.TexCoord = new Vector2(m.uv.U, 1.0f - m.uv.V);
|
||||
oface.Vertices.Add(vert);
|
||||
}
|
||||
|
||||
@@ -189,25 +229,27 @@ namespace OpenMetaverse.Rendering
|
||||
/// routine since all the context for finding teh texture is elsewhere.
|
||||
/// </summary>
|
||||
/// <returns>The faceted mesh or null if can't do it</returns>
|
||||
public OMVR.FacetedMesh GenerateFacetedSculptMesh(Primitive prim, Texture2D scupltTexture, DetailLevel lod)
|
||||
public FacetedMesh GenerateFacetedSculptMesh( Primitive prim,
|
||||
Texture2D scupltTexture,
|
||||
DetailLevel lod)
|
||||
{
|
||||
LibreMetaverse.PrimMesher.SculptMesh.SculptType smSculptType;
|
||||
switch (prim.Sculpt.Type)
|
||||
{
|
||||
case SculptType.Cylinder:
|
||||
smSculptType = LibreMetaverse.PrimMesher.SculptMesh.SculptType.cylinder;
|
||||
smSculptType = SculptMesh.SculptType.cylinder;
|
||||
break;
|
||||
case SculptType.Plane:
|
||||
smSculptType = LibreMetaverse.PrimMesher.SculptMesh.SculptType.plane;
|
||||
smSculptType = SculptMesh.SculptType.plane;
|
||||
break;
|
||||
case SculptType.Sphere:
|
||||
smSculptType = LibreMetaverse.PrimMesher.SculptMesh.SculptType.sphere;
|
||||
smSculptType = SculptMesh.SculptType.sphere;
|
||||
break;
|
||||
case SculptType.Torus:
|
||||
smSculptType = LibreMetaverse.PrimMesher.SculptMesh.SculptType.torus;
|
||||
smSculptType = SculptMesh.SculptType.torus;
|
||||
break;
|
||||
default:
|
||||
smSculptType = LibreMetaverse.PrimMesher.SculptMesh.SculptType.plane;
|
||||
smSculptType = SculptMesh.SculptType.plane;
|
||||
break;
|
||||
}
|
||||
// The lod for sculpties is the resolution of the texture passed.
|
||||
@@ -216,40 +258,40 @@ namespace OpenMetaverse.Rendering
|
||||
int mesherLod = 32; // number used in Idealist viewer
|
||||
switch (lod)
|
||||
{
|
||||
case OMVR.DetailLevel.Highest:
|
||||
case DetailLevel.Highest:
|
||||
break;
|
||||
case OMVR.DetailLevel.High:
|
||||
case DetailLevel.High:
|
||||
break;
|
||||
case OMVR.DetailLevel.Medium:
|
||||
case DetailLevel.Medium:
|
||||
mesherLod /= 2;
|
||||
break;
|
||||
case OMVR.DetailLevel.Low:
|
||||
case DetailLevel.Low:
|
||||
mesherLod /= 4;
|
||||
break;
|
||||
}
|
||||
LibreMetaverse.PrimMesher.SculptMesh newMesh =
|
||||
new LibreMetaverse.PrimMesher.SculptMesh(scupltTexture, smSculptType, mesherLod, true, prim.Sculpt.Mirror, prim.Sculpt.Invert);
|
||||
SculptMesh newMesh =
|
||||
new SculptMesh(scupltTexture, smSculptType, mesherLod, true, prim.Sculpt.Mirror, prim.Sculpt.Invert);
|
||||
|
||||
int numPrimFaces = 1; // a scuplty has only one face
|
||||
|
||||
// copy the vertex information into OMVR.IRendering structures
|
||||
FacetedMesh omvrmesh = new OMVR.FacetedMesh
|
||||
// copy the vertex information into IRendering structures
|
||||
FacetedMesh omvrmesh = new FacetedMesh
|
||||
{
|
||||
Faces = new List<OMVR.Face>(),
|
||||
Faces = new List<Face>(),
|
||||
Prim = prim,
|
||||
Profile = new OMVR.Profile
|
||||
Profile = new Profile
|
||||
{
|
||||
Faces = new List<OMVR.ProfileFace>(),
|
||||
Positions = new List<OMV.Vector3>()
|
||||
Faces = new List<ProfileFace>(),
|
||||
Positions = new List<Vector3>()
|
||||
},
|
||||
Path = new OMVR.Path {Points = new List<OMVR.PathPoint>()}
|
||||
Path = new Path {Points = new List<PathPoint>()}
|
||||
};
|
||||
|
||||
for (int ii = 0; ii < numPrimFaces; ii++)
|
||||
{
|
||||
Face oface = new OMVR.Face
|
||||
Face oface = new Face
|
||||
{
|
||||
Vertices = new List<OMVR.Vertex>(),
|
||||
Vertices = new List<Vertex>(),
|
||||
Indices = new List<ushort>(),
|
||||
TextureFace = prim.Textures.GetFace((uint) ii)
|
||||
};
|
||||
@@ -257,7 +299,7 @@ namespace OpenMetaverse.Rendering
|
||||
|
||||
for (int j = 0; j < faceVertices; j++)
|
||||
{
|
||||
var vert = new OMVR.Vertex
|
||||
var vert = new Vertex
|
||||
{
|
||||
Position = new Vector3(newMesh.coords[j].X, newMesh.coords[j].Y, newMesh.coords[j].Z),
|
||||
Normal = new Vector3(newMesh.normals[j].X, newMesh.normals[j].Y, newMesh.normals[j].Z),
|
||||
@@ -286,12 +328,16 @@ namespace OpenMetaverse.Rendering
|
||||
|
||||
/// <summary>
|
||||
/// Apply texture coordinate modifications from a
|
||||
/// <seealso cref="TextureEntryFace"/> to a list of vertices
|
||||
/// <seealso cref="OpenMetaverse.Primative.TextureEntryFace"/> to a list of vertices
|
||||
/// </summary>
|
||||
/// <param name="vertices">Vertex list to modify texture coordinates for</param>
|
||||
/// <param name="center">Center-point of the face</param>
|
||||
/// <param name="teFace">Face texture parameters</param>
|
||||
public void TransformTexCoords(List<OMVR.Vertex> vertices, OMV.Vector3 center, OMV.Primitive.TextureEntryFace teFace, Vector3 primScale)
|
||||
/// <param name="primScale">Prim scale vector</param>
|
||||
public void TransformTexCoords( List<Vertex> vertices,
|
||||
Vector3 center,
|
||||
Primitive.TextureEntryFace teFace,
|
||||
Vector3 primScale)
|
||||
{
|
||||
// compute trig stuff up front
|
||||
float cosineAngle = (float)Math.Cos(teFace.Rotation);
|
||||
@@ -346,7 +392,7 @@ namespace OpenMetaverse.Rendering
|
||||
// var facetedMesh = MeshSubMeshAsFacetedMesh(prim, meshParts["medium_lod"]):
|
||||
// 3. Get a simple mesh from one of the submeshes (good if just getting a physics version):
|
||||
// OSDMap meshParts = UnpackMesh(meshData);
|
||||
// OMV.Mesh flatMesh = MeshSubMeshAsSimpleMesh(prim, meshParts["physics_mesh"]);
|
||||
// Mesh flatMesh = MeshSubMeshAsSimpleMesh(prim, meshParts["physics_mesh"]);
|
||||
//
|
||||
// "physics_convex" is specially formatted so there is another routine to unpack
|
||||
// that section:
|
||||
@@ -364,9 +410,9 @@ namespace OpenMetaverse.Rendering
|
||||
/// routine since all the context for finding the data is elsewhere.
|
||||
/// </summary>
|
||||
/// <returns>The faceted mesh or null if can't do it</returns>
|
||||
public OMVR.FacetedMesh GenerateFacetedMeshMesh(OMV.Primitive prim, byte[] meshData)
|
||||
public FacetedMesh GenerateFacetedMeshMesh(Primitive prim, byte[] meshData)
|
||||
{
|
||||
OMVR.FacetedMesh ret = null;
|
||||
FacetedMesh ret = null;
|
||||
OSDMap meshParts = UnpackMesh(meshData);
|
||||
if (meshParts != null)
|
||||
{
|
||||
@@ -391,18 +437,18 @@ namespace OpenMetaverse.Rendering
|
||||
|
||||
// A version of GenerateFacetedMeshMesh that takes LOD spec so it's similar in calling convention of
|
||||
// the other Generate* methods.
|
||||
public OMVR.FacetedMesh GenerateFacetedMeshMesh(OMV.Primitive prim, byte[] meshData, OMVR.DetailLevel lod) {
|
||||
OMVR.FacetedMesh ret = null;
|
||||
public FacetedMesh GenerateFacetedMeshMesh(Primitive prim, byte[] meshData, DetailLevel lod) {
|
||||
FacetedMesh ret = null;
|
||||
string partName = null;
|
||||
switch (lod)
|
||||
{
|
||||
case OMVR.DetailLevel.Highest:
|
||||
case DetailLevel.Highest:
|
||||
partName = "high_lod"; break;
|
||||
case OMVR.DetailLevel.High:
|
||||
case DetailLevel.High:
|
||||
partName = "medium_lod"; break;
|
||||
case OMVR.DetailLevel.Medium:
|
||||
case DetailLevel.Medium:
|
||||
partName = "low_lod"; break;
|
||||
case OMVR.DetailLevel.Low:
|
||||
case DetailLevel.Low:
|
||||
partName = "lowest_lod"; break;
|
||||
}
|
||||
if (partName != null)
|
||||
@@ -424,7 +470,7 @@ namespace OpenMetaverse.Rendering
|
||||
}
|
||||
|
||||
// Convert a compressed submesh buffer into a FacetedMesh.
|
||||
public FacetedMesh MeshSubMeshAsFacetedMesh(OMV.Primitive prim, byte[] compressedMeshData)
|
||||
public FacetedMesh MeshSubMeshAsFacetedMesh(Primitive prim, byte[] compressedMeshData)
|
||||
{
|
||||
FacetedMesh ret = null;
|
||||
OSD meshOSD = Helpers.DecompressOSD(compressedMeshData);
|
||||
@@ -443,24 +489,27 @@ namespace OpenMetaverse.Rendering
|
||||
|
||||
|
||||
// Convert a compressed submesh buffer into a SimpleMesh.
|
||||
public OMVR.SimpleMesh MeshSubMeshAsSimpleMesh(OMV.Primitive prim, byte[] compressedMeshData)
|
||||
public SimpleMesh MeshSubMeshAsSimpleMesh(Primitive prim, byte[] compressedMeshData)
|
||||
{
|
||||
OMVR.SimpleMesh ret = null;
|
||||
SimpleMesh ret = null;
|
||||
OSD meshOSD = Helpers.DecompressOSD(compressedMeshData);
|
||||
|
||||
OSDArray meshFaces = meshOSD as OSDArray;
|
||||
if (meshOSD != null)
|
||||
{
|
||||
ret = new SimpleMesh();
|
||||
foreach (OSD subMesh in meshFaces)
|
||||
if (meshFaces != null)
|
||||
{
|
||||
AddSubMesh(subMesh, ref ret);
|
||||
foreach (OSD subMesh in meshFaces)
|
||||
{
|
||||
AddSubMesh(subMesh, ref ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public List<List<Vector3>> MeshSubMeshAsConvexHulls(OMV.Primitive prim, byte[] compressedMeshData)
|
||||
public List<List<Vector3>> MeshSubMeshAsConvexHulls(Primitive prim, byte[] compressedMeshData)
|
||||
{
|
||||
List<List<Vector3>> hulls = new List<List<Vector3>>();
|
||||
try {
|
||||
@@ -529,7 +578,7 @@ namespace OpenMetaverse.Rendering
|
||||
}
|
||||
|
||||
// Add the submesh to the passed SimpleMesh
|
||||
private void AddSubMesh(OSD subMeshOsd, ref OMVR.SimpleMesh holdingMesh) {
|
||||
private void AddSubMesh(OSD subMeshOsd, ref SimpleMesh holdingMesh) {
|
||||
if (subMeshOsd is OSDMap subMeshMap)
|
||||
{
|
||||
// As per http://wiki.secondlife.com/wiki/Mesh/Mesh_Asset_Format, some Mesh Level
|
||||
@@ -544,7 +593,7 @@ namespace OpenMetaverse.Rendering
|
||||
}
|
||||
|
||||
// Add the submesh to the passed FacetedMesh as a new face.
|
||||
private void AddSubMesh(OMV.Primitive prim, int faceIndex, OSD subMeshOsd, ref OMVR.FacetedMesh holdingMesh) {
|
||||
private void AddSubMesh(Primitive prim, int faceIndex, OSD subMeshOsd, ref FacetedMesh holdingMesh) {
|
||||
if (subMeshOsd is OSDMap subMesh)
|
||||
{
|
||||
// As per http://wiki.secondlife.com/wiki/Mesh/Mesh_Asset_Format, some Mesh Level
|
||||
@@ -673,13 +722,11 @@ namespace OpenMetaverse.Rendering
|
||||
return indices;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decodes mesh asset.
|
||||
/// <summary>Decodes mesh asset.</summary>
|
||||
/// <returns>OSDMap of all of the submeshes in the mesh. The value of the submesh name
|
||||
/// is the uncompressed data for that mesh.
|
||||
/// The OSDMap is made up of the asset_header section (which includes a lot of stuff)
|
||||
/// plus each of the submeshes unpacked into compressed byte arrays.
|
||||
/// </returns>
|
||||
/// plus each of the submeshes unpacked into compressed byte arrays.</returns>
|
||||
public OSDMap UnpackMesh(byte[] assetData)
|
||||
{
|
||||
OSDMap meshData = new OSDMap();
|
||||
@@ -723,7 +770,7 @@ namespace OpenMetaverse.Rendering
|
||||
|
||||
// Local routine to create a mesh from prim parameters.
|
||||
// Collects parameters and calls PrimMesher to create all the faces of the prim.
|
||||
private LibreMetaverse.PrimMesher.PrimMesh GeneratePrimMesh(Primitive prim, DetailLevel lod, bool viewerMode)
|
||||
private PrimMesh GeneratePrimMesh(Primitive prim, DetailLevel lod, bool viewerMode)
|
||||
{
|
||||
Primitive.ConstructionData primData = prim.PrimData;
|
||||
int sides = 4;
|
||||
@@ -734,14 +781,14 @@ namespace OpenMetaverse.Rendering
|
||||
|
||||
bool isSphere = false;
|
||||
|
||||
if ((ProfileCurve)(primData.profileCurve & 0x07) == OMV.ProfileCurve.Circle)
|
||||
if ((ProfileCurve)(primData.profileCurve & 0x07) == ProfileCurve.Circle)
|
||||
{
|
||||
switch (lod)
|
||||
{
|
||||
case OMVR.DetailLevel.Low:
|
||||
case DetailLevel.Low:
|
||||
sides = 6;
|
||||
break;
|
||||
case OMVR.DetailLevel.Medium:
|
||||
case DetailLevel.Medium:
|
||||
sides = 12;
|
||||
break;
|
||||
default:
|
||||
@@ -749,18 +796,18 @@ namespace OpenMetaverse.Rendering
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if ((ProfileCurve)(primData.profileCurve & 0x07) == OMV.ProfileCurve.EqualTriangle)
|
||||
else if ((ProfileCurve)(primData.profileCurve & 0x07) == ProfileCurve.EqualTriangle)
|
||||
sides = 3;
|
||||
else if ((ProfileCurve)(primData.profileCurve & 0x07) == OMV.ProfileCurve.HalfCircle)
|
||||
else if ((ProfileCurve)(primData.profileCurve & 0x07) == ProfileCurve.HalfCircle)
|
||||
{
|
||||
// half circle, prim is a sphere
|
||||
isSphere = true;
|
||||
switch (lod)
|
||||
{
|
||||
case OMVR.DetailLevel.Low:
|
||||
case DetailLevel.Low:
|
||||
sides = 6;
|
||||
break;
|
||||
case OMVR.DetailLevel.Medium:
|
||||
case DetailLevel.Medium:
|
||||
sides = 12;
|
||||
break;
|
||||
default:
|
||||
@@ -858,7 +905,7 @@ namespace OpenMetaverse.Rendering
|
||||
|
||||
for (int j = 0; j < faceVertices; j++)
|
||||
{
|
||||
var vert = new OMVR.Vertex
|
||||
var vert = new Vertex
|
||||
{
|
||||
Position = new Vector3(newMesh.coords[j].X, newMesh.coords[j].Y, newMesh.coords[j].Z),
|
||||
Normal = new Vector3(newMesh.normals[j].X, newMesh.normals[j].Y, newMesh.normals[j].Z),
|
||||
|
||||
@@ -122,18 +122,16 @@ namespace LitJson
|
||||
|
||||
#region IDictionary Indexer
|
||||
object IDictionary.this[object key] {
|
||||
get {
|
||||
return EnsureDictionary ()[key];
|
||||
}
|
||||
get => EnsureDictionary ()[key];
|
||||
|
||||
set {
|
||||
if (! (key is String))
|
||||
if (! (key is string str))
|
||||
throw new ArgumentException (
|
||||
"The key has to be a string");
|
||||
|
||||
JsonData data = ToJsonData (value);
|
||||
|
||||
this[(string) key] = data;
|
||||
this[str] = data;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -30,8 +30,6 @@ namespace LitJson
|
||||
internal struct ArrayMetadata
|
||||
{
|
||||
private Type element_type;
|
||||
private bool is_array;
|
||||
private bool is_list;
|
||||
|
||||
|
||||
public Type ElementType {
|
||||
@@ -45,24 +43,15 @@ namespace LitJson
|
||||
set { element_type = value; }
|
||||
}
|
||||
|
||||
public bool IsArray {
|
||||
get { return is_array; }
|
||||
set { is_array = value; }
|
||||
}
|
||||
public bool IsArray { get; set; }
|
||||
|
||||
public bool IsList {
|
||||
get { return is_list; }
|
||||
set { is_list = value; }
|
||||
}
|
||||
public bool IsList { get; set; }
|
||||
}
|
||||
|
||||
|
||||
internal struct ObjectMetadata
|
||||
{
|
||||
private Type element_type;
|
||||
private bool is_dictionary;
|
||||
|
||||
private IDictionary<string, PropertyMetadata> properties;
|
||||
|
||||
|
||||
public Type ElementType {
|
||||
@@ -76,15 +65,9 @@ namespace LitJson
|
||||
set { element_type = value; }
|
||||
}
|
||||
|
||||
public bool IsDictionary {
|
||||
get { return is_dictionary; }
|
||||
set { is_dictionary = value; }
|
||||
}
|
||||
public bool IsDictionary { get; set; }
|
||||
|
||||
public IDictionary<string, PropertyMetadata> Properties {
|
||||
get { return properties; }
|
||||
set { properties = value; }
|
||||
}
|
||||
public IDictionary<string, PropertyMetadata> Properties { get; set; }
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -46,16 +46,13 @@ namespace LitJson
|
||||
private Stack<int> automaton_stack;
|
||||
private int current_input;
|
||||
private int current_symbol;
|
||||
private bool end_of_json;
|
||||
private bool end_of_input;
|
||||
private Lexer lexer;
|
||||
private bool parser_in_string;
|
||||
private bool parser_return;
|
||||
private bool read_started;
|
||||
private TextReader reader;
|
||||
private bool reader_is_owned;
|
||||
private object token_value;
|
||||
private JsonToken token;
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
@@ -70,13 +67,13 @@ namespace LitJson
|
||||
set { lexer.AllowSingleQuotedStrings = value; }
|
||||
}
|
||||
|
||||
public bool EndOfInput => end_of_input;
|
||||
public bool EndOfInput { get; private set; }
|
||||
|
||||
public bool EndOfJson => end_of_json;
|
||||
public bool EndOfJson { get; private set; }
|
||||
|
||||
public JsonToken Token => token;
|
||||
public JsonToken Token { get; private set; }
|
||||
|
||||
public object Value => token_value;
|
||||
public object Value { get; private set; }
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -112,8 +109,8 @@ namespace LitJson
|
||||
|
||||
lexer = new Lexer (reader);
|
||||
|
||||
end_of_input = false;
|
||||
end_of_json = false;
|
||||
EndOfInput = false;
|
||||
EndOfJson = false;
|
||||
|
||||
this.reader = reader;
|
||||
reader_is_owned = owned;
|
||||
@@ -250,8 +247,8 @@ namespace LitJson
|
||||
|
||||
double n_double;
|
||||
if (Double.TryParse (number, out n_double)) {
|
||||
token = JsonToken.Double;
|
||||
token_value = n_double;
|
||||
Token = JsonToken.Double;
|
||||
Value = n_double;
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -259,41 +256,41 @@ namespace LitJson
|
||||
|
||||
int n_int32;
|
||||
if (Int32.TryParse (number, out n_int32)) {
|
||||
token = JsonToken.Int;
|
||||
token_value = n_int32;
|
||||
Token = JsonToken.Int;
|
||||
Value = n_int32;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
long n_int64;
|
||||
if (Int64.TryParse (number, out n_int64)) {
|
||||
token = JsonToken.Long;
|
||||
token_value = n_int64;
|
||||
Token = JsonToken.Long;
|
||||
Value = n_int64;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Shouldn't happen, but just in case, return something
|
||||
token = JsonToken.Int;
|
||||
token_value = 0;
|
||||
Token = JsonToken.Int;
|
||||
Value = 0;
|
||||
}
|
||||
|
||||
private void ProcessSymbol ()
|
||||
{
|
||||
if (current_symbol == '[') {
|
||||
token = JsonToken.ArrayStart;
|
||||
Token = JsonToken.ArrayStart;
|
||||
parser_return = true;
|
||||
|
||||
} else if (current_symbol == ']') {
|
||||
token = JsonToken.ArrayEnd;
|
||||
Token = JsonToken.ArrayEnd;
|
||||
parser_return = true;
|
||||
|
||||
} else if (current_symbol == '{') {
|
||||
token = JsonToken.ObjectStart;
|
||||
Token = JsonToken.ObjectStart;
|
||||
parser_return = true;
|
||||
|
||||
} else if (current_symbol == '}') {
|
||||
token = JsonToken.ObjectEnd;
|
||||
Token = JsonToken.ObjectEnd;
|
||||
parser_return = true;
|
||||
|
||||
} else if (current_symbol == '"') {
|
||||
@@ -303,22 +300,22 @@ namespace LitJson
|
||||
parser_return = true;
|
||||
|
||||
} else {
|
||||
if (token == JsonToken.None)
|
||||
token = JsonToken.String;
|
||||
if (Token == JsonToken.None)
|
||||
Token = JsonToken.String;
|
||||
|
||||
parser_in_string = true;
|
||||
}
|
||||
|
||||
} else if (current_symbol == (int) ParserToken.CharSeq) {
|
||||
token_value = lexer.StringValue;
|
||||
Value = lexer.StringValue;
|
||||
|
||||
} else if (current_symbol == (int) ParserToken.False) {
|
||||
token = JsonToken.Boolean;
|
||||
token_value = false;
|
||||
Token = JsonToken.Boolean;
|
||||
Value = false;
|
||||
parser_return = true;
|
||||
|
||||
} else if (current_symbol == (int) ParserToken.Null) {
|
||||
token = JsonToken.Null;
|
||||
Token = JsonToken.Null;
|
||||
parser_return = true;
|
||||
|
||||
} else if (current_symbol == (int) ParserToken.Number) {
|
||||
@@ -327,11 +324,11 @@ namespace LitJson
|
||||
parser_return = true;
|
||||
|
||||
} else if (current_symbol == (int) ParserToken.Pair) {
|
||||
token = JsonToken.PropertyName;
|
||||
Token = JsonToken.PropertyName;
|
||||
|
||||
} else if (current_symbol == (int) ParserToken.True) {
|
||||
token = JsonToken.Boolean;
|
||||
token_value = true;
|
||||
Token = JsonToken.Boolean;
|
||||
Value = true;
|
||||
parser_return = true;
|
||||
|
||||
}
|
||||
@@ -339,7 +336,7 @@ namespace LitJson
|
||||
|
||||
private bool ReadToken ()
|
||||
{
|
||||
if (end_of_input)
|
||||
if (EndOfInput)
|
||||
return false;
|
||||
|
||||
lexer.NextToken ();
|
||||
@@ -359,11 +356,11 @@ namespace LitJson
|
||||
|
||||
public void Close ()
|
||||
{
|
||||
if (end_of_input)
|
||||
if (EndOfInput)
|
||||
return;
|
||||
|
||||
end_of_input = true;
|
||||
end_of_json = true;
|
||||
EndOfInput = true;
|
||||
EndOfJson = true;
|
||||
|
||||
if (reader_is_owned)
|
||||
reader.Close ();
|
||||
@@ -373,11 +370,11 @@ namespace LitJson
|
||||
|
||||
public bool Read ()
|
||||
{
|
||||
if (end_of_input)
|
||||
if (EndOfInput)
|
||||
return false;
|
||||
|
||||
if (end_of_json) {
|
||||
end_of_json = false;
|
||||
if (EndOfJson) {
|
||||
EndOfJson = false;
|
||||
automaton_stack.Clear ();
|
||||
automaton_stack.Push ((int) ParserToken.End);
|
||||
automaton_stack.Push ((int) ParserToken.Text);
|
||||
@@ -386,8 +383,8 @@ namespace LitJson
|
||||
parser_in_string = false;
|
||||
parser_return = false;
|
||||
|
||||
token = JsonToken.None;
|
||||
token_value = null;
|
||||
Token = JsonToken.None;
|
||||
Value = null;
|
||||
|
||||
if (! read_started) {
|
||||
read_started = true;
|
||||
@@ -400,7 +397,7 @@ namespace LitJson
|
||||
while (true) {
|
||||
if (parser_return) {
|
||||
if (automaton_stack.Peek () == (int) ParserToken.End)
|
||||
end_of_json = true;
|
||||
EndOfJson = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* Copyright (c) 2021-2022, Sjofn LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
@@ -28,7 +29,6 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using System.Xml.Schema;
|
||||
using System.Text;
|
||||
|
||||
namespace OpenMetaverse.StructuredData
|
||||
@@ -38,46 +38,75 @@ namespace OpenMetaverse.StructuredData
|
||||
/// </summary>
|
||||
public static partial class OSDParser
|
||||
{
|
||||
private static XmlSchema XmlSchema;
|
||||
private static XmlTextReader XmlTextReader;
|
||||
private static string LastXmlErrors = string.Empty;
|
||||
private static object XmlValidationLock = new object();
|
||||
private static string linden_lab_loves_bad_pi = "<? LLSD/";
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// Deserialize LLSD/XML stream
|
||||
/// </summary>
|
||||
/// <param name="xmlData"></param>
|
||||
/// <param name="xmlStream">a <see cref="Stream" /> containing the serialized data</param>
|
||||
/// <returns></returns>
|
||||
public static OSD DeserializeLLSDXml(Stream xmlStream)
|
||||
{
|
||||
// XmlReader don't take no shit from nobody. Parse out Linden Lab's bad PI.
|
||||
bool match = true;
|
||||
for (int i = 0; i < linden_lab_loves_bad_pi.Length; ++i)
|
||||
{
|
||||
if (xmlStream.ReadByte() != linden_lab_loves_bad_pi[i])
|
||||
{
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (match)
|
||||
{
|
||||
// read until the linebreak >
|
||||
while (xmlStream.ReadByte() != '\n')
|
||||
{ }
|
||||
} else {
|
||||
xmlStream.Seek(0, SeekOrigin.Begin);
|
||||
}
|
||||
|
||||
XmlReaderSettings settings = new XmlReaderSettings
|
||||
{
|
||||
ValidationType = ValidationType.None,
|
||||
CheckCharacters = false,
|
||||
IgnoreComments = true,
|
||||
IgnoreProcessingInstructions = false,
|
||||
DtdProcessing = DtdProcessing.Ignore
|
||||
};
|
||||
using (XmlReader xrd = XmlReader.Create(xmlStream))
|
||||
{
|
||||
return DeserializeLLSDXml(xrd);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deserialize LLSD/XML stream
|
||||
/// </summary>
|
||||
/// <param name="xmlData">Data as a byte array</param>
|
||||
/// <returns></returns>
|
||||
public static OSD DeserializeLLSDXml(byte[] xmlData)
|
||||
{
|
||||
using(XmlTextReader xrd = new XmlTextReader(new MemoryStream(xmlData, false)))
|
||||
return DeserializeLLSDXml(xrd);
|
||||
}
|
||||
|
||||
public static OSD DeserializeLLSDXml(Stream xmlStream)
|
||||
{
|
||||
using(XmlTextReader xrd = new XmlTextReader(xmlStream))
|
||||
return DeserializeLLSDXml(xrd);
|
||||
return DeserializeLLSDXml(new MemoryStream(xmlData, false));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// Deserialize LLSD/XML stream
|
||||
/// </summary>
|
||||
/// <param name="xmlData"></param>
|
||||
/// <param name="xmlData">Serialized data as a <see cref="string" /></param>
|
||||
/// <returns></returns>
|
||||
public static OSD DeserializeLLSDXml(string xmlData)
|
||||
{
|
||||
byte[] bytes = Utils.StringToBytes(xmlData);
|
||||
using(XmlTextReader xrd = new XmlTextReader(new MemoryStream(bytes, false)))
|
||||
return DeserializeLLSDXml(xrd);
|
||||
return DeserializeLLSDXml(bytes);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// Deserialize LLSD/XML stream
|
||||
/// </summary>
|
||||
/// <param name="xmlData"></param>
|
||||
/// <param name="xmlData">Serialized data as a <see cref="XmlReader" /></param>
|
||||
/// <returns></returns>
|
||||
public static OSD DeserializeLLSDXml(XmlTextReader xmlData)
|
||||
public static OSD DeserializeLLSDXml(XmlReader xmlData)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -89,17 +118,18 @@ namespace OpenMetaverse.StructuredData
|
||||
|
||||
return ret;
|
||||
}
|
||||
catch
|
||||
catch (XmlException ex)
|
||||
{
|
||||
string exs = ex.ToString();
|
||||
return new OSD();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// Serialize an OSD object in LLSD/XML
|
||||
/// </summary>
|
||||
/// <param name="data"></param>
|
||||
/// <returns></returns>
|
||||
/// <param name="data">OSD object to serialize</param>
|
||||
/// <returns>Serialized data as a byte aray</returns>
|
||||
public static byte[] SerializeLLSDXmlBytes(OSD data)
|
||||
{
|
||||
return Encoding.UTF8.GetBytes(SerializeLLSDXmlString(data));
|
||||
@@ -113,7 +143,7 @@ namespace OpenMetaverse.StructuredData
|
||||
public static string SerializeLLSDXmlString(OSD data)
|
||||
{
|
||||
StringWriter sw = new StringWriter();
|
||||
using(XmlTextWriter writer = new XmlTextWriter(sw))
|
||||
using (XmlTextWriter writer = new XmlTextWriter(sw))
|
||||
{
|
||||
writer.Formatting = Formatting.None;
|
||||
|
||||
@@ -143,7 +173,7 @@ namespace OpenMetaverse.StructuredData
|
||||
/// </summary>
|
||||
/// <param name="writer"></param>
|
||||
/// <param name="data"></param>
|
||||
public static void SerializeLLSDXmlElement(XmlTextWriter writer, OSD data)
|
||||
public static void SerializeLLSDXmlElement(XmlWriter writer, OSD data)
|
||||
{
|
||||
switch (data.Type)
|
||||
{
|
||||
@@ -224,59 +254,12 @@ namespace OpenMetaverse.StructuredData
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="xmlData"></param>
|
||||
/// <param name="error"></param>
|
||||
/// <returns></returns>
|
||||
public static bool TryValidateLLSDXml(XmlTextReader xmlData, out string error)
|
||||
{
|
||||
lock (XmlValidationLock)
|
||||
{
|
||||
LastXmlErrors = string.Empty;
|
||||
XmlTextReader = xmlData;
|
||||
|
||||
CreateLLSDXmlSchema();
|
||||
|
||||
XmlReaderSettings readerSettings = new XmlReaderSettings();
|
||||
readerSettings.ValidationType = ValidationType.Schema;
|
||||
readerSettings.Schemas.Add(XmlSchema);
|
||||
readerSettings.ValidationEventHandler += new ValidationEventHandler(LLSDXmlSchemaValidationHandler);
|
||||
|
||||
using(XmlReader reader = XmlReader.Create(xmlData, readerSettings))
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
while (reader.Read()) { }
|
||||
}
|
||||
catch (XmlException)
|
||||
{
|
||||
error = LastXmlErrors;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (LastXmlErrors == string.Empty)
|
||||
{
|
||||
error = null;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
error = LastXmlErrors;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="reader"></param>
|
||||
/// <returns></returns>
|
||||
private static OSD ParseLLSDXmlElement(XmlTextReader reader)
|
||||
private static OSD ParseLLSDXmlElement(XmlReader reader)
|
||||
{
|
||||
SkipWhitespace(reader);
|
||||
|
||||
@@ -464,7 +447,7 @@ namespace OpenMetaverse.StructuredData
|
||||
return ret;
|
||||
}
|
||||
|
||||
private static OSDMap ParseLLSDXmlMap(XmlTextReader reader)
|
||||
private static OSDMap ParseLLSDXmlMap(XmlReader reader)
|
||||
{
|
||||
if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "map")
|
||||
throw new NotImplementedException("Expected <map>");
|
||||
@@ -507,7 +490,7 @@ namespace OpenMetaverse.StructuredData
|
||||
return map;
|
||||
}
|
||||
|
||||
private static OSDArray ParseLLSDXmlArray(XmlTextReader reader)
|
||||
private static OSDArray ParseLLSDXmlArray(XmlReader reader)
|
||||
{
|
||||
if (reader.NodeType != XmlNodeType.Element || reader.LocalName != "array")
|
||||
throw new OSDException("Expected <array>");
|
||||
@@ -539,7 +522,7 @@ namespace OpenMetaverse.StructuredData
|
||||
return array;
|
||||
}
|
||||
|
||||
private static void SkipWhitespace(XmlTextReader reader)
|
||||
private static void SkipWhitespace(XmlReader reader)
|
||||
{
|
||||
while (
|
||||
reader.NodeType == XmlNodeType.Comment ||
|
||||
@@ -550,121 +533,5 @@ namespace OpenMetaverse.StructuredData
|
||||
reader.Read();
|
||||
}
|
||||
}
|
||||
|
||||
private static void CreateLLSDXmlSchema()
|
||||
{
|
||||
if (XmlSchema == null)
|
||||
{
|
||||
#region XSD
|
||||
const string schemaText = @"
|
||||
<?xml version=""1.0"" encoding=""utf-8""?>
|
||||
<xs:schema elementFormDefault=""qualified"" xmlns:xs=""http://www.w3.org/2001/XMLSchema"">
|
||||
<xs:import schemaLocation=""xml.xsd"" namespace=""http://www.w3.org/XML/1998/namespace"" />
|
||||
<xs:element name=""uri"" type=""xs:string"" />
|
||||
<xs:element name=""uuid"" type=""xs:string"" />
|
||||
<xs:element name=""KEYDATA"">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element ref=""key"" />
|
||||
<xs:element ref=""DATA"" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name=""date"" type=""xs:string"" />
|
||||
<xs:element name=""key"" type=""xs:string"" />
|
||||
<xs:element name=""boolean"" type=""xs:string"" />
|
||||
<xs:element name=""undef"">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element ref=""EMPTY"" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name=""map"">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element minOccurs=""0"" maxOccurs=""unbounded"" ref=""KEYDATA"" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name=""real"" type=""xs:string"" />
|
||||
<xs:element name=""ATOMIC"">
|
||||
<xs:complexType>
|
||||
<xs:choice>
|
||||
<xs:element ref=""undef"" />
|
||||
<xs:element ref=""boolean"" />
|
||||
<xs:element ref=""integer"" />
|
||||
<xs:element ref=""real"" />
|
||||
<xs:element ref=""uuid"" />
|
||||
<xs:element ref=""string"" />
|
||||
<xs:element ref=""date"" />
|
||||
<xs:element ref=""uri"" />
|
||||
<xs:element ref=""binary"" />
|
||||
</xs:choice>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name=""DATA"">
|
||||
<xs:complexType>
|
||||
<xs:choice>
|
||||
<xs:element ref=""ATOMIC"" />
|
||||
<xs:element ref=""map"" />
|
||||
<xs:element ref=""array"" />
|
||||
</xs:choice>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name=""llsd"">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element ref=""DATA"" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name=""binary"">
|
||||
<xs:complexType>
|
||||
<xs:simpleContent>
|
||||
<xs:extension base=""xs:string"">
|
||||
<xs:attribute default=""base64"" name=""encoding"" type=""xs:string"" />
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name=""array"">
|
||||
<xs:complexType>
|
||||
<xs:sequence>
|
||||
<xs:element minOccurs=""0"" maxOccurs=""unbounded"" ref=""DATA"" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
<xs:element name=""integer"" type=""xs:string"" />
|
||||
<xs:element name=""string"">
|
||||
<xs:complexType>
|
||||
<xs:simpleContent>
|
||||
<xs:extension base=""xs:string"">
|
||||
<xs:attribute ref=""xml:space"" />
|
||||
</xs:extension>
|
||||
</xs:simpleContent>
|
||||
</xs:complexType>
|
||||
</xs:element>
|
||||
</xs:schema>
|
||||
";
|
||||
#endregion XSD
|
||||
|
||||
MemoryStream stream = new MemoryStream(Encoding.ASCII.GetBytes(schemaText));
|
||||
|
||||
XmlSchema = new XmlSchema();
|
||||
XmlSchema = XmlSchema.Read(stream, new ValidationEventHandler(LLSDXmlSchemaValidationHandler));
|
||||
}
|
||||
}
|
||||
|
||||
private static void LLSDXmlSchemaValidationHandler(object sender, ValidationEventArgs args)
|
||||
{
|
||||
string error =
|
||||
$"Line: {XmlTextReader.LineNumber} - Position: {XmlTextReader.LinePosition} - {args.Message}";
|
||||
|
||||
if (LastXmlErrors == string.Empty)
|
||||
LastXmlErrors = error;
|
||||
else
|
||||
LastXmlErrors += Environment.NewLine + error;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* Copyright (c) 2021-2022, Sjofn LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
@@ -892,6 +893,11 @@ namespace OpenMetaverse.StructuredData
|
||||
return new OSDMap(new Dictionary<string, OSD>(_mMap));
|
||||
}
|
||||
|
||||
public Hashtable ToHashtable()
|
||||
{
|
||||
return new Hashtable(_mMap);
|
||||
}
|
||||
|
||||
#region IDictionary Implementation
|
||||
|
||||
public int Count => _mMap.Count;
|
||||
@@ -1124,6 +1130,11 @@ namespace OpenMetaverse.StructuredData
|
||||
return OSDParser.SerializeJsonString(this, true);
|
||||
}
|
||||
|
||||
public ArrayList ToArrayList()
|
||||
{
|
||||
return new ArrayList(_mArray);
|
||||
}
|
||||
|
||||
#region IList Implementation
|
||||
|
||||
public int Count => _mArray.Count;
|
||||
@@ -1246,7 +1257,7 @@ namespace OpenMetaverse.StructuredData
|
||||
|
||||
public static OSD Deserialize(Stream stream)
|
||||
{
|
||||
if (!stream.CanSeek) throw new OSDException("Cannot deserialize structured data from unseekable streams");
|
||||
if (!stream.CanSeek) { throw new OSDException("Cannot deserialize structured data from unseekable streams"); }
|
||||
|
||||
byte[] headerData = new byte[14];
|
||||
stream.Read(headerData, 0, 14);
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
|
||||
namespace OpenMetaverse
|
||||
{
|
||||
public class CRC32
|
||||
|
||||
@@ -321,6 +321,15 @@ namespace OpenMetaverse
|
||||
//}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert quaternion to euler angles vector
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Vector3 ToEulerVector() {
|
||||
GetEulerAngles(out float r, out float p, out float y);
|
||||
return new Vector3(r, p, y);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert this quaternion to an angle around an axis
|
||||
/// </summary>
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* All rights reserved.
|
||||
*
|
||||
* - 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.
|
||||
* - Neither the name of the openmetaverse.co 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR 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.
|
||||
*/
|
||||
|
||||
namespace OpenMetaverse
|
||||
{
|
||||
public struct Ray
|
||||
{
|
||||
public Vector3 Origin;
|
||||
public Vector3 Direction;
|
||||
|
||||
public Ray(Vector3 origin, Vector3 direction)
|
||||
{
|
||||
Origin = origin;
|
||||
Direction = direction;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: dfd7f6aa761fa8344ae0221058b55cf3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -55,10 +55,7 @@ namespace OpenMetaverse
|
||||
/// parent. The parent bucket will limit the aggregate bandwidth of all
|
||||
/// of its children buckets
|
||||
/// </summary>
|
||||
public TokenBucket Parent
|
||||
{
|
||||
get { return parent; }
|
||||
}
|
||||
public TokenBucket Parent => parent;
|
||||
|
||||
/// <summary>
|
||||
/// Maximum burst rate in bytes per second. This is the maximum number
|
||||
@@ -66,8 +63,8 @@ namespace OpenMetaverse
|
||||
/// </summary>
|
||||
public int MaxBurst
|
||||
{
|
||||
get { return maxBurst; }
|
||||
set { maxBurst = (value >= 0 ? value : 0); }
|
||||
get => maxBurst;
|
||||
set => maxBurst = (value >= 0 ? value : 0);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -75,11 +72,11 @@ namespace OpenMetaverse
|
||||
/// number of tokens that are added to the bucket per second
|
||||
/// </summary>
|
||||
/// <remarks>Tokens are added to the bucket any time
|
||||
/// <seealso cref="RemoveTokens"/> is called, at the granularity of
|
||||
/// <seealso cref="TokenBucket.RemoveTokens"/> is called, at the granularity of
|
||||
/// the system tick interval (typically around 15-22ms)</remarks>
|
||||
public int DripRate
|
||||
{
|
||||
get { return tokensPerMS * 1000; }
|
||||
get => tokensPerMS * 1000;
|
||||
set
|
||||
{
|
||||
if (value == 0)
|
||||
@@ -95,13 +92,10 @@ namespace OpenMetaverse
|
||||
/// The number of bytes that can be sent at this moment. This is the
|
||||
/// current number of tokens in the bucket
|
||||
/// <remarks>If this bucket has a parent bucket that does not have
|
||||
/// enough tokens for a request, <seealso cref="RemoveTokens"/> will
|
||||
/// enough tokens for a request, <seealso cref="TokenBucket.RemoveTokens"/> will
|
||||
/// return false regardless of the content of this bucket</remarks>
|
||||
/// </summary>
|
||||
public int Content
|
||||
{
|
||||
get { return content; }
|
||||
}
|
||||
public int Content => content;
|
||||
|
||||
#endregion Properties
|
||||
|
||||
|
||||
@@ -297,9 +297,8 @@ namespace OpenMetaverse
|
||||
/// <returns>True if the object is a UUID and both UUIDs are equal</returns>
|
||||
public override bool Equals(object o)
|
||||
{
|
||||
if (!(o is UUID)) return false;
|
||||
if (!(o is UUID uuid)) return false;
|
||||
|
||||
UUID uuid = (UUID)o;
|
||||
return Guid == uuid.Guid;
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
@@ -654,7 +655,7 @@ namespace OpenMetaverse
|
||||
/// <example>0x7fffffff</example>
|
||||
public static string UIntToHexString(uint i)
|
||||
{
|
||||
return string.Format("{0:x8}", i);
|
||||
return $"{i:x8}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -680,7 +681,7 @@ namespace OpenMetaverse
|
||||
|
||||
private static string GetString(byte[] bytes, int index, int count)
|
||||
{
|
||||
string cnv = UTF8Encoding.UTF8.GetString(bytes, index, count);
|
||||
string cnv = Encoding.UTF8.GetString(bytes, index, count);
|
||||
return InternStrings ? string.Intern(cnv) : cnv;
|
||||
}
|
||||
|
||||
@@ -729,7 +730,8 @@ namespace OpenMetaverse
|
||||
if (j != 0)
|
||||
output.Append(' ');
|
||||
|
||||
output.Append(String.Format("{0:X2}", bytes[i + j]));
|
||||
//output.Append(String.Format("{0:X2}", bytes[i + j]));
|
||||
output.Append($"{bytes[i + j]:X2}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -744,9 +746,11 @@ namespace OpenMetaverse
|
||||
/// <returns>A null-terminated UTF8 byte array</returns>
|
||||
public static byte[] StringToBytes(string str)
|
||||
{
|
||||
if (String.IsNullOrEmpty(str)) { return EmptyBytes; }
|
||||
if (!str.EndsWith("\0")) { str += "\0"; }
|
||||
return UTF8Encoding.UTF8.GetBytes(str);
|
||||
if (string.IsNullOrEmpty(str)) { return EmptyBytes; }
|
||||
// HACK: Say it ain't so .NET5
|
||||
return str.EndsWith("\0", StringComparison.Ordinal)
|
||||
? Encoding.UTF8.GetBytes(str)
|
||||
: Encoding.UTF8.GetBytes(str + '\0');
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -767,9 +771,9 @@ namespace OpenMetaverse
|
||||
char c;
|
||||
|
||||
// remove all non A-F, 0-9, characters
|
||||
for (int i = 0; i < hexString.Length; i++)
|
||||
foreach (var str in hexString)
|
||||
{
|
||||
c = hexString[i];
|
||||
c = str;
|
||||
if (IsHexDigit(c))
|
||||
stripped.Append(c);
|
||||
}
|
||||
@@ -801,14 +805,14 @@ namespace OpenMetaverse
|
||||
/// </summary>
|
||||
/// <param name="c">Character to test</param>
|
||||
/// <returns>true if hex digit, false if not</returns>
|
||||
private static bool IsHexDigit(Char c)
|
||||
private static bool IsHexDigit(char c)
|
||||
{
|
||||
const int numA = 65;
|
||||
const int num0 = 48;
|
||||
|
||||
int numChar;
|
||||
|
||||
c = Char.ToUpper(c);
|
||||
c = char.ToUpper(c);
|
||||
numChar = Convert.ToInt32(c);
|
||||
|
||||
if (numChar >= numA && numChar < (numA + 6))
|
||||
@@ -1217,9 +1221,7 @@ namespace OpenMetaverse
|
||||
/// <param name="rhs">Second value</param>
|
||||
public static void Swap<T>(ref T lhs, ref T rhs)
|
||||
{
|
||||
T temp = lhs;
|
||||
lhs = rhs;
|
||||
rhs = temp;
|
||||
(lhs, rhs) = (rhs, lhs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2022, Sjofn, LLC
|
||||
* All rights reserved.
|
||||
*
|
||||
* - 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.
|
||||
* - Neither the name of the openmetaverse.co 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR 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;
|
||||
|
||||
namespace OpenMetaverse
|
||||
{
|
||||
public class LocationParser
|
||||
{
|
||||
public string Sim { get; }
|
||||
public int X { get; }
|
||||
public int Y { get; }
|
||||
public int Z { get; }
|
||||
|
||||
public LocationParser(string location)
|
||||
{
|
||||
if (location == null ) { throw new ArgumentNullException("Location cannot be null."); }
|
||||
if (location.Length == 0) { throw new ArgumentException("Location cannot be empty."); }
|
||||
|
||||
string toParse;
|
||||
if (location.StartsWith("secondlife://")) { toParse = location.Substring(13); }
|
||||
else if (location.StartsWith("uri:")) { toParse = location.Substring(4); }
|
||||
else { toParse = location; }
|
||||
|
||||
string[] elements = toParse.Split('/');
|
||||
Sim = elements[0];
|
||||
int parsed;
|
||||
X = (elements.Length > 1 && int.TryParse(elements[1], out parsed)) ? parsed : 128;
|
||||
Y = (elements.Length > 2 && int.TryParse(elements[2], out parsed)) ? parsed : 128;
|
||||
Z = (elements.Length > 3 && int.TryParse(elements[3], out parsed)) ? parsed : 0;
|
||||
}
|
||||
|
||||
public string GetRawLocation()
|
||||
{
|
||||
return $"{Sim}/{X}/{Y}/{Z}";
|
||||
}
|
||||
|
||||
public string GetSlurl()
|
||||
{
|
||||
return $"secondlife://{Sim}/{X}/{Y}/{Z}/";
|
||||
}
|
||||
|
||||
public string GetStartLocationUri()
|
||||
{
|
||||
return $"uri:{Sim}&{X}&{Y}&{Z}";
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7c55f03914703744682d029a8cfbceda
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* Copyright (c) 2021-2022, Sjofn LLC
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
@@ -1401,9 +1402,7 @@ namespace OpenMetaverse.Messages.Linden
|
||||
{
|
||||
FolderDataInfo ret = new FolderDataInfo();
|
||||
|
||||
if (!(data is OSDMap)) return ret;
|
||||
|
||||
OSDMap map = (OSDMap)data;
|
||||
if (!(data is OSDMap map)) return ret;
|
||||
|
||||
ret.FolderID = map["FolderID"];
|
||||
ret.ParentID = map["ParentID"];
|
||||
@@ -1442,9 +1441,7 @@ namespace OpenMetaverse.Messages.Linden
|
||||
{
|
||||
ItemDataInfo ret = new ItemDataInfo();
|
||||
|
||||
if (!(data is OSDMap)) return ret;
|
||||
|
||||
OSDMap map = (OSDMap)data;
|
||||
if (!(data is OSDMap map)) return ret;
|
||||
|
||||
ret.ItemID = map["ItemID"];
|
||||
ret.CallbackID = map["CallbackID"];
|
||||
|
||||
@@ -25,12 +25,10 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Threading;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Channels;
|
||||
using System.Threading.Tasks;
|
||||
using OpenMetaverse.Packets;
|
||||
@@ -38,7 +36,7 @@ using OpenMetaverse.Interfaces;
|
||||
using OpenMetaverse.Messages.Linden;
|
||||
|
||||
namespace OpenMetaverse
|
||||
{
|
||||
{
|
||||
/// <summary>
|
||||
/// NetworkManager is responsible for managing the network layer of
|
||||
/// OpenMetaverse. It tracks all the server connections, serializes
|
||||
@@ -316,7 +314,7 @@ namespace OpenMetaverse
|
||||
|
||||
/// <summary>Shows whether the network layer is logged in to the
|
||||
/// grid or not</summary>
|
||||
public bool Connected => connected;
|
||||
public bool Connected { get; private set; }
|
||||
|
||||
/// <summary>Number of packets in the incoming queue</summary>
|
||||
public int InboxCount => _packetInboxCount;
|
||||
@@ -346,7 +344,6 @@ namespace OpenMetaverse
|
||||
|
||||
private GridClient Client;
|
||||
private Timer DisconnectTimer;
|
||||
private bool connected;
|
||||
|
||||
private long lastpacketwarning = 0;
|
||||
|
||||
@@ -587,7 +584,7 @@ namespace OpenMetaverse
|
||||
{
|
||||
// Mark that we are connecting/connected to the grid
|
||||
//
|
||||
connected = true;
|
||||
Connected = true;
|
||||
|
||||
// raise the SimConnecting event and allow any event
|
||||
// subscribers to cancel the connection
|
||||
@@ -746,7 +743,7 @@ namespace OpenMetaverse
|
||||
}
|
||||
|
||||
// This will catch a Logout when the client is not logged in
|
||||
if (CurrentSim == null || !connected)
|
||||
if (CurrentSim == null || !Connected)
|
||||
{
|
||||
Logger.Log("Ignoring RequestLogout(), client is already logged out", Helpers.LogLevel.Warning, Client);
|
||||
return;
|
||||
@@ -865,7 +862,7 @@ namespace OpenMetaverse
|
||||
Interlocked.Exchange(ref _packetInboxCount, 0);
|
||||
Interlocked.Exchange(ref _packetOutboxCount, 0);
|
||||
|
||||
connected = false;
|
||||
Connected = false;
|
||||
|
||||
// Fire the disconnected callback
|
||||
if (m_Disconnected != null)
|
||||
@@ -923,7 +920,7 @@ namespace OpenMetaverse
|
||||
// FIXME: This is kind of ridiculous. Port the HTB code from Simian over ASAP!
|
||||
var stopwatch = new System.Diagnostics.Stopwatch();
|
||||
|
||||
while (await reader.WaitToReadAsync() && connected)
|
||||
while (await reader.WaitToReadAsync() && Connected)
|
||||
{
|
||||
while (reader.TryRead(out var outgoingPacket))
|
||||
{
|
||||
@@ -956,7 +953,7 @@ namespace OpenMetaverse
|
||||
{
|
||||
var reader = _packetInbox.Reader;
|
||||
|
||||
while (await reader.WaitToReadAsync() && connected)
|
||||
while (await reader.WaitToReadAsync() && Connected)
|
||||
{
|
||||
while (reader.TryRead(out var incomingPacket))
|
||||
{
|
||||
@@ -1006,14 +1003,14 @@ namespace OpenMetaverse
|
||||
|
||||
private void DisconnectTimer_Elapsed(object obj)
|
||||
{
|
||||
if (!connected || CurrentSim == null)
|
||||
if (!Connected || CurrentSim == null)
|
||||
{
|
||||
if (DisconnectTimer != null)
|
||||
{
|
||||
DisconnectTimer.Dispose();
|
||||
DisconnectTimer = null;
|
||||
}
|
||||
connected = false;
|
||||
Connected = false;
|
||||
}
|
||||
else if (CurrentSim.DisconnectCandidate)
|
||||
{
|
||||
@@ -1027,7 +1024,7 @@ namespace OpenMetaverse
|
||||
DisconnectTimer = null;
|
||||
}
|
||||
|
||||
connected = false;
|
||||
Connected = false;
|
||||
|
||||
// Shutdown the network layer
|
||||
Shutdown(DisconnectType.NetworkTimeout);
|
||||
|
||||
@@ -1696,7 +1696,7 @@ namespace OpenMetaverse
|
||||
}
|
||||
};
|
||||
|
||||
request.BeginGetResponse(req.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
request.PostRequestAsync(req.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1725,7 +1725,7 @@ namespace OpenMetaverse
|
||||
Logger.Log("ObjectMediaUpdate: " + error.Message, Helpers.LogLevel.Error, Client);
|
||||
}
|
||||
};
|
||||
request.BeginGetResponse(req.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
request.PostRequestAsync(req.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1781,7 +1781,7 @@ namespace OpenMetaverse
|
||||
}
|
||||
};
|
||||
|
||||
request.BeginGetResponse(req.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
request.PostRequestAsync(req.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -3359,22 +3359,20 @@ namespace OpenMetaverse
|
||||
/// <seealso cref="AvatarUpdateEventArgs"/>
|
||||
public class PrimEventArgs : EventArgs
|
||||
{
|
||||
private readonly Simulator m_Simulator;
|
||||
private readonly bool m_IsNew;
|
||||
private readonly bool m_IsAttachment;
|
||||
private readonly Primitive m_Prim;
|
||||
private readonly ushort m_TimeDilation;
|
||||
|
||||
/// <summary>Get the simulator the <see cref="Primitive"/> originated from</summary>
|
||||
public Simulator Simulator { get { return m_Simulator; } }
|
||||
public Simulator Simulator { get; }
|
||||
|
||||
/// <summary>Get the <see cref="Primitive"/> details</summary>
|
||||
public Primitive Prim { get { return m_Prim; } }
|
||||
public Primitive Prim { get; }
|
||||
|
||||
/// <summary>true if the <see cref="Primitive"/> did not exist in the dictionary before this update (always true if object tracking has been disabled)</summary>
|
||||
public bool IsNew { get { return m_IsNew; } }
|
||||
public bool IsNew { get; }
|
||||
|
||||
/// <summary>true if the <see cref="Primitive"/> is attached to an <see cref="Avatar"/></summary>
|
||||
public bool IsAttachment { get { return m_IsAttachment; } }
|
||||
public bool IsAttachment { get; }
|
||||
|
||||
/// <summary>Get the simulator Time Dilation</summary>
|
||||
public ushort TimeDilation { get { return m_TimeDilation; } }
|
||||
public ushort TimeDilation { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new instance of the PrimEventArgs class
|
||||
@@ -3386,11 +3384,11 @@ namespace OpenMetaverse
|
||||
/// <param name="isAttachment">true if the primitive represents an attachment to an agent</param>
|
||||
public PrimEventArgs(Simulator simulator, Primitive prim, ushort timeDilation, bool isNew, bool isAttachment)
|
||||
{
|
||||
this.m_Simulator = simulator;
|
||||
this.m_IsNew = isNew;
|
||||
this.m_IsAttachment = isAttachment;
|
||||
this.m_Prim = prim;
|
||||
this.m_TimeDilation = timeDilation;
|
||||
this.Simulator = simulator;
|
||||
this.IsNew = isNew;
|
||||
this.IsAttachment = isAttachment;
|
||||
this.Prim = prim;
|
||||
this.TimeDilation = timeDilation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3440,19 +3438,17 @@ namespace OpenMetaverse
|
||||
/// <seealso cref="PrimEventArgs"/>
|
||||
public class AvatarUpdateEventArgs : EventArgs
|
||||
{
|
||||
private readonly Simulator m_Simulator;
|
||||
private readonly Avatar m_Avatar;
|
||||
private readonly ushort m_TimeDilation;
|
||||
private readonly bool m_IsNew;
|
||||
|
||||
/// <summary>Get the simulator the object originated from</summary>
|
||||
public Simulator Simulator { get { return m_Simulator; } }
|
||||
public Simulator Simulator { get; }
|
||||
|
||||
/// <summary>Get the <see cref="Avatar"/> data</summary>
|
||||
public Avatar Avatar { get { return m_Avatar; } }
|
||||
public Avatar Avatar { get; }
|
||||
|
||||
/// <summary>Get the simulator time dilation</summary>
|
||||
public ushort TimeDilation { get { return m_TimeDilation; } }
|
||||
public ushort TimeDilation { get; }
|
||||
|
||||
/// <summary>true if the <see cref="Avatar"/> did not exist in the dictionary before this update (always true if avatar tracking has been disabled)</summary>
|
||||
public bool IsNew { get { return m_IsNew; } }
|
||||
public bool IsNew { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new instance of the AvatarUpdateEventArgs class
|
||||
@@ -3463,24 +3459,22 @@ namespace OpenMetaverse
|
||||
/// <param name="isNew">The avatar was not in the dictionary before this update</param>
|
||||
public AvatarUpdateEventArgs(Simulator simulator, Avatar avatar, ushort timeDilation, bool isNew)
|
||||
{
|
||||
this.m_Simulator = simulator;
|
||||
this.m_Avatar = avatar;
|
||||
this.m_TimeDilation = timeDilation;
|
||||
this.m_IsNew = isNew;
|
||||
this.Simulator = simulator;
|
||||
this.Avatar = avatar;
|
||||
this.TimeDilation = timeDilation;
|
||||
this.IsNew = isNew;
|
||||
}
|
||||
}
|
||||
|
||||
public class ParticleUpdateEventArgs : EventArgs {
|
||||
private readonly Simulator m_Simulator;
|
||||
private readonly Primitive.ParticleSystem m_ParticleSystem;
|
||||
private readonly Primitive m_Source;
|
||||
|
||||
/// <summary>Get the simulator the object originated from</summary>
|
||||
public Simulator Simulator { get { return m_Simulator; } }
|
||||
public Simulator Simulator { get; }
|
||||
|
||||
/// <summary>Get the <see cref="ParticleSystem"/> data</summary>
|
||||
public Primitive.ParticleSystem ParticleSystem { get { return m_ParticleSystem; } }
|
||||
public Primitive.ParticleSystem ParticleSystem { get; }
|
||||
|
||||
/// <summary>Get <see cref="Primitive"/> source</summary>
|
||||
public Primitive Source { get { return m_Source; } }
|
||||
public Primitive Source { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new instance of the ParticleUpdateEventArgs class
|
||||
@@ -3489,9 +3483,9 @@ namespace OpenMetaverse
|
||||
/// <param name="particlesystem">The ParticleSystem data</param>
|
||||
/// <param name="source">The Primitive source</param>
|
||||
public ParticleUpdateEventArgs(Simulator simulator, Primitive.ParticleSystem particlesystem, Primitive source) {
|
||||
this.m_Simulator = simulator;
|
||||
this.m_ParticleSystem = particlesystem;
|
||||
this.m_Source = source;
|
||||
this.Simulator = simulator;
|
||||
this.ParticleSystem = particlesystem;
|
||||
this.Source = source;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3548,11 +3542,8 @@ namespace OpenMetaverse
|
||||
/// </remarks>
|
||||
public class ObjectPropertiesUpdatedEventArgs : ObjectPropertiesEventArgs
|
||||
{
|
||||
|
||||
private readonly Primitive m_Prim;
|
||||
|
||||
/// <summary>Get the primitive details</summary>
|
||||
public Primitive Prim { get { return m_Prim; } }
|
||||
public Primitive Prim { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new instance of the ObjectPropertiesUpdatedEvenrArgs class
|
||||
@@ -3562,7 +3553,7 @@ namespace OpenMetaverse
|
||||
/// <param name="props">The primitive Properties</param>
|
||||
public ObjectPropertiesUpdatedEventArgs(Simulator simulator, Primitive prim, Primitive.ObjectProperties props) : base(simulator, props)
|
||||
{
|
||||
this.m_Prim = prim;
|
||||
this.Prim = prim;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3575,22 +3566,20 @@ namespace OpenMetaverse
|
||||
/// </remarks>
|
||||
public class ObjectPropertiesFamilyEventArgs : EventArgs
|
||||
{
|
||||
private readonly Simulator m_Simulator;
|
||||
private readonly Primitive.ObjectProperties m_Properties;
|
||||
private readonly ReportType m_Type;
|
||||
|
||||
/// <summary>Get the simulator the object is located</summary>
|
||||
public Simulator Simulator { get { return m_Simulator; } }
|
||||
public Simulator Simulator { get; }
|
||||
|
||||
/// <summary></summary>
|
||||
public Primitive.ObjectProperties Properties { get { return m_Properties; } }
|
||||
public Primitive.ObjectProperties Properties { get; }
|
||||
|
||||
/// <summary></summary>
|
||||
public ReportType Type { get { return m_Type; } }
|
||||
public ReportType Type { get; }
|
||||
|
||||
public ObjectPropertiesFamilyEventArgs(Simulator simulator, Primitive.ObjectProperties props, ReportType type)
|
||||
{
|
||||
this.m_Simulator = simulator;
|
||||
this.m_Properties = props;
|
||||
this.m_Type = type;
|
||||
this.Simulator = simulator;
|
||||
this.Properties = props;
|
||||
this.Type = type;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3599,26 +3588,24 @@ namespace OpenMetaverse
|
||||
/// </remarks>
|
||||
public class TerseObjectUpdateEventArgs : EventArgs
|
||||
{
|
||||
private readonly Simulator m_Simulator;
|
||||
private readonly Primitive m_Prim;
|
||||
private readonly ObjectMovementUpdate m_Update;
|
||||
private readonly ushort m_TimeDilation;
|
||||
|
||||
/// <summary>Get the simulator the object is located</summary>
|
||||
public Simulator Simulator { get { return m_Simulator; } }
|
||||
public Simulator Simulator { get; }
|
||||
|
||||
/// <summary>Get the primitive details</summary>
|
||||
public Primitive Prim { get { return m_Prim; } }
|
||||
public Primitive Prim { get; }
|
||||
|
||||
/// <summary></summary>
|
||||
public ObjectMovementUpdate Update { get { return m_Update; } }
|
||||
public ObjectMovementUpdate Update { get; }
|
||||
|
||||
/// <summary></summary>
|
||||
public ushort TimeDilation { get { return m_TimeDilation; } }
|
||||
public ushort TimeDilation { get; }
|
||||
|
||||
public TerseObjectUpdateEventArgs(Simulator simulator, Primitive prim, ObjectMovementUpdate update, ushort timeDilation)
|
||||
{
|
||||
this.m_Simulator = simulator;
|
||||
this.m_Prim = prim;
|
||||
this.m_Update = update;
|
||||
this.m_TimeDilation = timeDilation;
|
||||
this.Simulator = simulator;
|
||||
this.Prim = prim;
|
||||
this.Update = update;
|
||||
this.TimeDilation = timeDilation;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3627,35 +3614,33 @@ namespace OpenMetaverse
|
||||
/// </summary>
|
||||
public class ObjectDataBlockUpdateEventArgs : EventArgs
|
||||
{
|
||||
private readonly Simulator m_Simulator;
|
||||
private readonly Primitive m_Prim;
|
||||
private readonly Primitive.ConstructionData m_ConstructionData;
|
||||
private readonly ObjectUpdatePacket.ObjectDataBlock m_Block;
|
||||
private readonly ObjectMovementUpdate m_Update;
|
||||
private readonly NameValue[] m_NameValues;
|
||||
|
||||
/// <summary>Get the simulator the object is located</summary>
|
||||
public Simulator Simulator { get { return m_Simulator; } }
|
||||
public Simulator Simulator { get; }
|
||||
|
||||
/// <summary>Get the primitive details</summary>
|
||||
public Primitive Prim { get { return m_Prim; } }
|
||||
public Primitive Prim { get; }
|
||||
|
||||
/// <summary></summary>
|
||||
public Primitive.ConstructionData ConstructionData { get { return m_ConstructionData; } }
|
||||
public Primitive.ConstructionData ConstructionData { get; }
|
||||
|
||||
/// <summary></summary>
|
||||
public ObjectUpdatePacket.ObjectDataBlock Block { get { return m_Block; } }
|
||||
public ObjectUpdatePacket.ObjectDataBlock Block { get; }
|
||||
|
||||
/// <summary></summary>
|
||||
public ObjectMovementUpdate Update { get { return m_Update; } }
|
||||
public ObjectMovementUpdate Update { get; }
|
||||
|
||||
/// <summary></summary>
|
||||
public NameValue[] NameValues { get { return m_NameValues; } }
|
||||
public NameValue[] NameValues { get; }
|
||||
|
||||
public ObjectDataBlockUpdateEventArgs(Simulator simulator, Primitive prim, Primitive.ConstructionData constructionData,
|
||||
ObjectUpdatePacket.ObjectDataBlock block, ObjectMovementUpdate objectupdate, NameValue[] nameValues)
|
||||
{
|
||||
this.m_Simulator = simulator;
|
||||
this.m_Prim = prim;
|
||||
this.m_ConstructionData = constructionData;
|
||||
this.m_Block = block;
|
||||
this.m_Update = objectupdate;
|
||||
this.m_NameValues = nameValues;
|
||||
this.Simulator = simulator;
|
||||
this.Prim = prim;
|
||||
this.ConstructionData = constructionData;
|
||||
this.Block = block;
|
||||
this.Update = objectupdate;
|
||||
this.NameValues = nameValues;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3663,18 +3648,16 @@ namespace OpenMetaverse
|
||||
/// <see cref="ObjectManager.KillObject"/> event</summary>
|
||||
public class KillObjectEventArgs : EventArgs
|
||||
{
|
||||
private readonly Simulator m_Simulator;
|
||||
private readonly uint m_ObjectLocalID;
|
||||
|
||||
/// <summary>Get the simulator the object is located</summary>
|
||||
public Simulator Simulator { get { return m_Simulator; } }
|
||||
public Simulator Simulator { get; }
|
||||
|
||||
/// <summary>The LocalID of the object</summary>
|
||||
public uint ObjectLocalID { get { return m_ObjectLocalID; } }
|
||||
public uint ObjectLocalID { get; }
|
||||
|
||||
public KillObjectEventArgs(Simulator simulator, uint objectID)
|
||||
{
|
||||
this.m_Simulator = simulator;
|
||||
this.m_ObjectLocalID = objectID;
|
||||
this.Simulator = simulator;
|
||||
this.ObjectLocalID = objectID;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3682,18 +3665,16 @@ namespace OpenMetaverse
|
||||
/// <see cref="ObjectManager.KillObjects"/> event</summary>
|
||||
public class KillObjectsEventArgs : EventArgs
|
||||
{
|
||||
private readonly Simulator m_Simulator;
|
||||
private readonly uint[] m_ObjectLocalIDs;
|
||||
|
||||
/// <summary>Get the simulator the object is located</summary>
|
||||
public Simulator Simulator { get { return m_Simulator; } }
|
||||
public Simulator Simulator { get; }
|
||||
|
||||
/// <summary>The LocalID of the object</summary>
|
||||
public uint[] ObjectLocalIDs { get { return m_ObjectLocalIDs; } }
|
||||
public uint[] ObjectLocalIDs { get; }
|
||||
|
||||
public KillObjectsEventArgs(Simulator simulator, uint[] objectIDs)
|
||||
{
|
||||
this.m_Simulator = simulator;
|
||||
this.m_ObjectLocalIDs = objectIDs;
|
||||
this.Simulator = simulator;
|
||||
this.ObjectLocalIDs = objectIDs;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3702,26 +3683,24 @@ namespace OpenMetaverse
|
||||
/// </summary>
|
||||
public class AvatarSitChangedEventArgs : EventArgs
|
||||
{
|
||||
private readonly Simulator m_Simulator;
|
||||
private readonly Avatar m_Avatar;
|
||||
private readonly uint m_SittingOn;
|
||||
private readonly uint m_OldSeat;
|
||||
|
||||
/// <summary>Get the simulator the object is located</summary>
|
||||
public Simulator Simulator { get { return m_Simulator; } }
|
||||
public Simulator Simulator { get; }
|
||||
|
||||
/// <summary></summary>
|
||||
public Avatar Avatar { get { return m_Avatar; } }
|
||||
public Avatar Avatar { get; }
|
||||
|
||||
/// <summary></summary>
|
||||
public uint SittingOn { get { return m_SittingOn; } }
|
||||
public uint SittingOn { get; }
|
||||
|
||||
/// <summary></summary>
|
||||
public uint OldSeat { get { return m_OldSeat; } }
|
||||
public uint OldSeat { get; }
|
||||
|
||||
public AvatarSitChangedEventArgs(Simulator simulator, Avatar avatar, uint sittingOn, uint oldSeat)
|
||||
{
|
||||
this.m_Simulator = simulator;
|
||||
this.m_Avatar = avatar;
|
||||
this.m_SittingOn = sittingOn;
|
||||
this.m_OldSeat = oldSeat;
|
||||
this.Simulator = simulator;
|
||||
this.Avatar = avatar;
|
||||
this.SittingOn = sittingOn;
|
||||
this.OldSeat = oldSeat;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3730,26 +3709,24 @@ namespace OpenMetaverse
|
||||
/// </summary>
|
||||
public class PayPriceReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly Simulator m_Simulator;
|
||||
private readonly UUID m_ObjectID;
|
||||
private readonly int m_DefaultPrice;
|
||||
private readonly int[] m_ButtonPrices;
|
||||
|
||||
/// <summary>Get the simulator the object is located</summary>
|
||||
public Simulator Simulator { get { return m_Simulator; } }
|
||||
public Simulator Simulator { get; }
|
||||
|
||||
/// <summary></summary>
|
||||
public UUID ObjectID { get { return m_ObjectID; } }
|
||||
public UUID ObjectID { get; }
|
||||
|
||||
/// <summary></summary>
|
||||
public int DefaultPrice { get { return m_DefaultPrice; } }
|
||||
public int DefaultPrice { get; }
|
||||
|
||||
/// <summary></summary>
|
||||
public int[] ButtonPrices { get { return m_ButtonPrices; } }
|
||||
public int[] ButtonPrices { get; }
|
||||
|
||||
public PayPriceReplyEventArgs(Simulator simulator, UUID objectID, int defaultPrice, int[] buttonPrices)
|
||||
{
|
||||
this.m_Simulator = simulator;
|
||||
this.m_ObjectID = objectID;
|
||||
this.m_DefaultPrice = defaultPrice;
|
||||
this.m_ButtonPrices = buttonPrices;
|
||||
this.Simulator = simulator;
|
||||
this.ObjectID = objectID;
|
||||
this.DefaultPrice = defaultPrice;
|
||||
this.ButtonPrices = buttonPrices;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,6 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* Copyright (c) 2021-2022, Sjofn LLC
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
@@ -570,6 +571,12 @@ namespace OpenMetaverse
|
||||
public bool ObscureMusic;
|
||||
/// <summary>A struct containing media details</summary>
|
||||
public ParcelMedia Media;
|
||||
/// <summary>Parcel privacy see avatars outside/inside parcel</summary>
|
||||
public bool SeeAVs;
|
||||
/// <summary>Parcel privacy play sounds attached to avatars outside/inside parcel</summary>
|
||||
public bool AnyAVSounds;
|
||||
/// <summary>Parcel privacy play sounds for group members</summary>
|
||||
public bool GroupAVSounds;
|
||||
|
||||
/// <summary>
|
||||
/// Displays a parcel object in string format
|
||||
@@ -635,12 +642,15 @@ namespace OpenMetaverse
|
||||
SalePrice = (uint) SalePrice,
|
||||
SnapshotID = SnapshotID,
|
||||
UserLocation = UserLocation,
|
||||
UserLookAt = UserLookAt
|
||||
UserLookAt = UserLookAt,
|
||||
SeeAVs = SeeAVs,
|
||||
AnyAVSounds = AnyAVSounds,
|
||||
GroupAVSounds = GroupAVSounds
|
||||
};
|
||||
|
||||
OSDMap body = req.Serialize();
|
||||
|
||||
request.BeginGetResponse(body, OSDFormat.Xml, simulator.Client.Settings.CAPS_TIMEOUT);
|
||||
request.PostRequestAsync(body, OSDFormat.Xml, simulator.Client.Settings.CAPS_TIMEOUT);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1661,9 +1671,9 @@ namespace OpenMetaverse
|
||||
|
||||
try
|
||||
{
|
||||
OSD result = request.GetResponse(msg.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
OSDMap result = request.PostRequest(msg.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT) as OSDMap;
|
||||
RemoteParcelRequestReply response = new RemoteParcelRequestReply();
|
||||
response.Deserialize((OSDMap)result);
|
||||
response.Deserialize(result);
|
||||
return response.ParcelID;
|
||||
}
|
||||
catch (Exception)
|
||||
@@ -1700,7 +1710,7 @@ namespace OpenMetaverse
|
||||
response.Deserialize((OSDMap)result);
|
||||
|
||||
CapsClient summaryRequest = new CapsClient(response.ScriptResourceSummary, "ScriptResourceSummary");
|
||||
OSD summaryResponse = summaryRequest.GetResponse(Client.Settings.CAPS_TIMEOUT);
|
||||
OSD summaryResponse = summaryRequest.GetRequest(Client.Settings.CAPS_TIMEOUT);
|
||||
|
||||
LandResourcesInfo res = new LandResourcesInfo();
|
||||
res.Deserialize((OSDMap)summaryResponse);
|
||||
@@ -1708,7 +1718,7 @@ namespace OpenMetaverse
|
||||
if (response.ScriptResourceDetails != null && getDetails)
|
||||
{
|
||||
CapsClient detailRequest = new CapsClient(response.ScriptResourceDetails, "ScriptResourceDetails");
|
||||
OSD detailResponse = detailRequest.GetResponse(Client.Settings.CAPS_TIMEOUT);
|
||||
OSD detailResponse = detailRequest.GetRequest(Client.Settings.CAPS_TIMEOUT);
|
||||
res.Deserialize((OSDMap)detailResponse);
|
||||
}
|
||||
callback(true, res);
|
||||
@@ -1721,7 +1731,7 @@ namespace OpenMetaverse
|
||||
};
|
||||
|
||||
LandResourcesRequest param = new LandResourcesRequest {ParcelID = parcelID};
|
||||
request.BeginGetResponse(param.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
request.PostRequestAsync(param.Serialize(), OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -1842,7 +1852,11 @@ namespace OpenMetaverse
|
||||
RegionDenyAgeUnverified = msg.RegionDenyAgeUnverified,
|
||||
RegionDenyAnonymous = msg.RegionDenyAnonymous,
|
||||
RegionPushOverride = msg.RegionPushOverride,
|
||||
RentPrice = msg.RentPrice
|
||||
RentPrice = msg.RentPrice,
|
||||
SeeAVs = msg.SeeAVs,
|
||||
AnyAVSounds = msg.AnyAVSounds,
|
||||
GroupAVSounds = msg.GroupAVSounds
|
||||
|
||||
};
|
||||
|
||||
ParcelResult result = msg.RequestResult;
|
||||
@@ -2100,18 +2114,14 @@ namespace OpenMetaverse
|
||||
/// <summary>Contains a parcels dwell data returned from the simulator in response to an <see cref="RequestParcelDwell"/></summary>
|
||||
public class ParcelDwellReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly UUID m_ParcelID;
|
||||
private readonly int m_LocalID;
|
||||
private readonly float m_Dwell;
|
||||
|
||||
/// <summary>Get the global ID of the parcel</summary>
|
||||
public UUID ParcelID => m_ParcelID;
|
||||
public UUID ParcelID { get; }
|
||||
|
||||
/// <summary>Get the simulator specific ID of the parcel</summary>
|
||||
public int LocalID => m_LocalID;
|
||||
public int LocalID { get; }
|
||||
|
||||
/// <summary>Get the calculated dwell</summary>
|
||||
public float Dwell => m_Dwell;
|
||||
public float Dwell { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new instance of the ParcelDwellReplyEventArgs class
|
||||
@@ -2121,20 +2131,18 @@ namespace OpenMetaverse
|
||||
/// <param name="dwell">The calculated dwell for the parcel</param>
|
||||
public ParcelDwellReplyEventArgs(UUID parcelID, int localID, float dwell)
|
||||
{
|
||||
m_ParcelID = parcelID;
|
||||
m_LocalID = localID;
|
||||
m_Dwell = dwell;
|
||||
ParcelID = parcelID;
|
||||
LocalID = localID;
|
||||
Dwell = dwell;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Contains basic parcel information data returned from the
|
||||
/// simulator in response to an <see cref="RequestParcelInfo"/> request</summary>
|
||||
public class ParcelInfoReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly ParcelInfo m_Parcel;
|
||||
|
||||
{
|
||||
/// <summary>Get the <see cref="ParcelInfo"/> object containing basic parcel info</summary>
|
||||
public ParcelInfo Parcel => m_Parcel;
|
||||
public ParcelInfo Parcel { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new instance of the ParcelInfoReplyEventArgs class
|
||||
@@ -2142,40 +2150,33 @@ namespace OpenMetaverse
|
||||
/// <param name="parcel">The <see cref="ParcelInfo"/> object containing basic parcel info</param>
|
||||
public ParcelInfoReplyEventArgs(ParcelInfo parcel)
|
||||
{
|
||||
m_Parcel = parcel;
|
||||
Parcel = parcel;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Contains basic parcel information data returned from the simulator in response to an <see cref="RequestParcelInfo"/> request</summary>
|
||||
public class ParcelPropertiesEventArgs : EventArgs
|
||||
{
|
||||
private readonly Simulator m_Simulator;
|
||||
private Parcel m_Parcel;
|
||||
private readonly ParcelResult m_Result;
|
||||
private readonly int m_SelectedPrims;
|
||||
private readonly int m_SequenceID;
|
||||
private readonly bool m_SnapSelection;
|
||||
|
||||
/// <summary>Get the simulator the parcel is located in</summary>
|
||||
public Simulator Simulator => m_Simulator;
|
||||
public Simulator Simulator { get; }
|
||||
|
||||
/// <summary>Get the <see cref="Parcel"/> object containing the details</summary>
|
||||
/// <remarks>If Result is NoData, this object will not contain valid data</remarks>
|
||||
public Parcel Parcel => m_Parcel;
|
||||
public Parcel Parcel { get; }
|
||||
|
||||
/// <summary>Get the result of the request</summary>
|
||||
public ParcelResult Result => m_Result;
|
||||
public ParcelResult Result { get; }
|
||||
|
||||
/// <summary>Get the number of primitieves your agent is
|
||||
/// currently selecting and or sitting on in this parcel</summary>
|
||||
public int SelectedPrims => m_SelectedPrims;
|
||||
public int SelectedPrims { get; }
|
||||
|
||||
/// <summary>Get the user assigned ID used to correlate a request with
|
||||
/// these results</summary>
|
||||
public int SequenceID => m_SequenceID;
|
||||
public int SequenceID { get; }
|
||||
|
||||
/// <summary>TODO:</summary>
|
||||
public bool SnapSelection => m_SnapSelection;
|
||||
public bool SnapSelection { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new instance of the ParcelPropertiesEventArgs class
|
||||
@@ -2191,39 +2192,33 @@ namespace OpenMetaverse
|
||||
public ParcelPropertiesEventArgs(Simulator simulator, Parcel parcel, ParcelResult result, int selectedPrims,
|
||||
int sequenceID, bool snapSelection)
|
||||
{
|
||||
m_Simulator = simulator;
|
||||
m_Parcel = parcel;
|
||||
m_Result = result;
|
||||
m_SelectedPrims = selectedPrims;
|
||||
m_SequenceID = sequenceID;
|
||||
m_SnapSelection = snapSelection;
|
||||
Simulator = simulator;
|
||||
Parcel = parcel;
|
||||
Result = result;
|
||||
SelectedPrims = selectedPrims;
|
||||
SequenceID = sequenceID;
|
||||
SnapSelection = snapSelection;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Contains blacklist and whitelist data returned from the simulator in response to an <see cref="RequestParcelAccesslist"/> request</summary>
|
||||
public class ParcelAccessListReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly Simulator m_Simulator;
|
||||
private readonly int m_SequenceID;
|
||||
private readonly int m_LocalID;
|
||||
private readonly uint m_Flags;
|
||||
private readonly List<ParcelManager.ParcelAccessEntry> m_AccessList;
|
||||
|
||||
/// <summary>Get the simulator the parcel is located in</summary>
|
||||
public Simulator Simulator => m_Simulator;
|
||||
public Simulator Simulator { get; }
|
||||
|
||||
/// <summary>Get the user assigned ID used to correlate a request with
|
||||
/// these results</summary>
|
||||
public int SequenceID => m_SequenceID;
|
||||
public int SequenceID { get; }
|
||||
|
||||
/// <summary>Get the simulator specific ID of the parcel</summary>
|
||||
public int LocalID => m_LocalID;
|
||||
public int LocalID { get; }
|
||||
|
||||
/// <summary>TODO</summary>
|
||||
public uint Flags => m_Flags;
|
||||
public uint Flags { get; }
|
||||
|
||||
/// <summary>Get the list containing the white/blacklisted agents for the parcel</summary>
|
||||
public List<ParcelManager.ParcelAccessEntry> AccessList => m_AccessList;
|
||||
public List<ParcelManager.ParcelAccessEntry> AccessList { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new instance of the ParcelAccessListReplyEventArgs class
|
||||
@@ -2236,11 +2231,11 @@ namespace OpenMetaverse
|
||||
/// <param name="accessEntries">The list containing the white/blacklisted agents for the parcel</param>
|
||||
public ParcelAccessListReplyEventArgs(Simulator simulator, int sequenceID, int localID, uint flags, List<ParcelManager.ParcelAccessEntry> accessEntries)
|
||||
{
|
||||
m_Simulator = simulator;
|
||||
m_SequenceID = sequenceID;
|
||||
m_LocalID = localID;
|
||||
m_Flags = flags;
|
||||
m_AccessList = accessEntries;
|
||||
Simulator = simulator;
|
||||
SequenceID = sequenceID;
|
||||
LocalID = localID;
|
||||
Flags = flags;
|
||||
AccessList = accessEntries;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2248,14 +2243,11 @@ namespace OpenMetaverse
|
||||
/// simulator in response to an <see cref="RequestParcelAccesslist"/> request</summary>
|
||||
public class ParcelObjectOwnersReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly Simulator m_Simulator;
|
||||
private readonly List<ParcelManager.ParcelPrimOwners> m_Owners;
|
||||
|
||||
/// <summary>Get the simulator the parcel is located in</summary>
|
||||
public Simulator Simulator => m_Simulator;
|
||||
public Simulator Simulator { get; }
|
||||
|
||||
/// <summary>Get the list containing prim ownership counts</summary>
|
||||
public List<ParcelManager.ParcelPrimOwners> PrimOwners => m_Owners;
|
||||
public List<ParcelManager.ParcelPrimOwners> PrimOwners { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new instance of the ParcelObjectOwnersReplyEventArgs class
|
||||
@@ -2264,27 +2256,23 @@ namespace OpenMetaverse
|
||||
/// <param name="primOwners">The list containing prim ownership counts</param>
|
||||
public ParcelObjectOwnersReplyEventArgs(Simulator simulator, List<ParcelManager.ParcelPrimOwners> primOwners)
|
||||
{
|
||||
m_Simulator = simulator;
|
||||
m_Owners = primOwners;
|
||||
Simulator = simulator;
|
||||
PrimOwners = primOwners;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Contains the data returned when all parcel data has been retrieved from a simulator</summary>
|
||||
public class SimParcelsDownloadedEventArgs : EventArgs
|
||||
{
|
||||
private readonly Simulator m_Simulator;
|
||||
private readonly InternalDictionary<int, Parcel> m_Parcels;
|
||||
private readonly int[,] m_ParcelMap;
|
||||
|
||||
/// <summary>Get the simulator the parcel data was retrieved from</summary>
|
||||
public Simulator Simulator => m_Simulator;
|
||||
public Simulator Simulator { get; }
|
||||
|
||||
/// <summary>A dictionary containing the parcel data where the key correlates to the ParcelMap entry</summary>
|
||||
public InternalDictionary<int, Parcel> Parcels => m_Parcels;
|
||||
public InternalDictionary<int, Parcel> Parcels { get; }
|
||||
|
||||
/// <summary>Get the multidimensional array containing a x,y grid mapped
|
||||
/// to each 64x64 parcel's LocalID.</summary>
|
||||
public int[,] ParcelMap => m_ParcelMap;
|
||||
public int[,] ParcelMap { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new instance of the SimParcelsDownloadedEventArgs class
|
||||
@@ -2295,28 +2283,24 @@ namespace OpenMetaverse
|
||||
/// to each 64x64 parcel's LocalID.</param>
|
||||
public SimParcelsDownloadedEventArgs(Simulator simulator, InternalDictionary<int, Parcel> simParcels, int[,] parcelMap)
|
||||
{
|
||||
m_Simulator = simulator;
|
||||
m_Parcels = simParcels;
|
||||
m_ParcelMap = parcelMap;
|
||||
Simulator = simulator;
|
||||
Parcels = simParcels;
|
||||
ParcelMap = parcelMap;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Contains the data returned when a <see cref="RequestForceSelectObjects"/> request</summary>
|
||||
public class ForceSelectObjectsReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly Simulator m_Simulator;
|
||||
private readonly List<uint> m_ObjectIDs;
|
||||
private readonly bool m_ResetList;
|
||||
|
||||
/// <summary>Get the simulator the parcel data was retrieved from</summary>
|
||||
public Simulator Simulator => m_Simulator;
|
||||
public Simulator Simulator { get; }
|
||||
|
||||
/// <summary>Get the list of primitive IDs</summary>
|
||||
public List<uint> ObjectIDs => m_ObjectIDs;
|
||||
public List<uint> ObjectIDs { get; }
|
||||
|
||||
/// <summary>true if the list is clean and contains the information
|
||||
/// only for a given request</summary>
|
||||
public bool ResetList => m_ResetList;
|
||||
public bool ResetList { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new instance of the ForceSelectObjectsReplyEventArgs class
|
||||
@@ -2327,23 +2311,20 @@ namespace OpenMetaverse
|
||||
/// only for a given request</param>
|
||||
public ForceSelectObjectsReplyEventArgs(Simulator simulator, List<uint> objectIDs, bool resetList)
|
||||
{
|
||||
this.m_Simulator = simulator;
|
||||
this.m_ObjectIDs = objectIDs;
|
||||
this.m_ResetList = resetList;
|
||||
this.Simulator = simulator;
|
||||
this.ObjectIDs = objectIDs;
|
||||
this.ResetList = resetList;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Contains data when the media data for a parcel the avatar is on changes</summary>
|
||||
public class ParcelMediaUpdateReplyEventArgs : EventArgs
|
||||
{
|
||||
private readonly Simulator m_Simulator;
|
||||
private readonly ParcelMedia m_ParcelMedia;
|
||||
|
||||
/// <summary>Get the simulator the parcel media data was updated in</summary>
|
||||
public Simulator Simulator => m_Simulator;
|
||||
public Simulator Simulator { get; }
|
||||
|
||||
/// <summary>Get the updated media information</summary>
|
||||
public ParcelMedia Media => m_ParcelMedia;
|
||||
public ParcelMedia Media { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new instance of the ParcelMediaUpdateReplyEventArgs class
|
||||
@@ -2352,34 +2333,28 @@ namespace OpenMetaverse
|
||||
/// <param name="media">The updated media information</param>
|
||||
public ParcelMediaUpdateReplyEventArgs(Simulator simulator, ParcelMedia media)
|
||||
{
|
||||
this.m_Simulator = simulator;
|
||||
this.m_ParcelMedia = media;
|
||||
this.Simulator = simulator;
|
||||
this.Media = media;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>Contains the media command for a parcel the agent is currently on</summary>
|
||||
public class ParcelMediaCommandEventArgs : EventArgs
|
||||
{
|
||||
private readonly Simulator m_Simulator;
|
||||
private readonly uint m_Sequence;
|
||||
private readonly ParcelFlags m_ParcelFlags;
|
||||
private readonly ParcelMediaCommand m_MediaCommand;
|
||||
private readonly float m_Time;
|
||||
|
||||
/// <summary>Get the simulator the parcel media command was issued in</summary>
|
||||
public Simulator Simulator => m_Simulator;
|
||||
public Simulator Simulator { get; }
|
||||
|
||||
/// <summary></summary>
|
||||
public uint Sequence => m_Sequence;
|
||||
public uint Sequence { get; }
|
||||
|
||||
/// <summary></summary>
|
||||
public ParcelFlags ParcelFlags => m_ParcelFlags;
|
||||
public ParcelFlags ParcelFlags { get; }
|
||||
|
||||
/// <summary>Get the media command that was sent</summary>
|
||||
public ParcelMediaCommand MediaCommand => m_MediaCommand;
|
||||
public ParcelMediaCommand MediaCommand { get; }
|
||||
|
||||
/// <summary></summary>
|
||||
public float Time => m_Time;
|
||||
public float Time { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new instance of the ParcelMediaCommandEventArgs class
|
||||
@@ -2391,11 +2366,11 @@ namespace OpenMetaverse
|
||||
/// <param name="time"></param>
|
||||
public ParcelMediaCommandEventArgs(Simulator simulator, uint sequence, ParcelFlags flags, ParcelMediaCommand command, float time)
|
||||
{
|
||||
m_Simulator = simulator;
|
||||
m_Sequence = sequence;
|
||||
m_ParcelFlags = flags;
|
||||
m_MediaCommand = command;
|
||||
m_Time = time;
|
||||
Simulator = simulator;
|
||||
Sequence = sequence;
|
||||
ParcelFlags = flags;
|
||||
MediaCommand = command;
|
||||
Time = time;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -29,9 +29,6 @@ using OpenMetaverse.StructuredData;
|
||||
|
||||
namespace OpenMetaverse
|
||||
{
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum PermissionMask : uint
|
||||
{
|
||||
@@ -47,9 +44,6 @@ namespace OpenMetaverse
|
||||
All = (1 << 13) | (1 << 14) | (1 << 15) | (1 << 19)
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum PermissionWho : byte
|
||||
{
|
||||
@@ -67,10 +61,7 @@ namespace OpenMetaverse
|
||||
All = 0x1F
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
[Serializable()]
|
||||
[Serializable]
|
||||
public struct Permissions
|
||||
{
|
||||
public PermissionMask BaseMask;
|
||||
|
||||
@@ -66,7 +66,7 @@ namespace LibreMetaverse.PrimMesher
|
||||
|
||||
while (!s.EndOfStream)
|
||||
{
|
||||
var line = s.ReadLine().Trim();
|
||||
var line = s.ReadLine()?.Trim();
|
||||
var tokens = Regex.Split(line, @"\s+");
|
||||
|
||||
// Skip blank lines and comments
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#define VERTEX_INDEXER
|
||||
|
||||
#define VERTEX_INDEXER
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
@@ -73,9 +73,8 @@ namespace LibreMetaverse.PrimMesher
|
||||
try
|
||||
{
|
||||
if (needsScaling)
|
||||
bm.Resize(width,height);
|
||||
//bm = ScaleImage(bm, width, height,
|
||||
// InterpolationMode.NearestNeighbor);
|
||||
//bm.Resize(width,height);
|
||||
ScaleImage(bm, width, height);
|
||||
}
|
||||
|
||||
catch (Exception e)
|
||||
@@ -167,6 +166,12 @@ namespace LibreMetaverse.PrimMesher
|
||||
return rows;
|
||||
}
|
||||
|
||||
private void ScaleImage(Texture2D srcImage, int destWidth, int destHeight)
|
||||
{
|
||||
srcImage.Resize(destWidth, destHeight);
|
||||
srcImage.Apply();
|
||||
}
|
||||
|
||||
//private Bitmap ScaleImage(Bitmap srcImage, int destWidth, int destHeight,
|
||||
// InterpolationMode interpMode)
|
||||
//{
|
||||
|
||||
@@ -58,18 +58,9 @@ namespace LibreMetaverse.PrimMesher
|
||||
//<Deprecated : Sculptie from image file>
|
||||
//public SculptMesh(string fileName, int sculptType, int lod, int viewerMode, int mirror, int invert)
|
||||
//{
|
||||
// //var bitmap = (Bitmap) Image.FromFile(fileName);
|
||||
// var myreader = new BMPLoader();
|
||||
// BMPImage myimg = myreader.LoadBMP(fileName);
|
||||
// Texture2D tex = myimg.ToTexture2D();
|
||||
// Texture2D fakebmp = new Texture2D(tex);
|
||||
|
||||
// _SculptMesh(fakebmp, (SculptType) sculptType, lod, viewerMode != 0, mirror != 0, invert != 0);
|
||||
// //bitmap.Dispose();
|
||||
|
||||
// fakebmp.delete();
|
||||
|
||||
|
||||
// var bitmap = (Bitmap) Image.FromFile(fileName);
|
||||
// _SculptMesh(bitmap, (SculptType) sculptType, lod, viewerMode != 0, mirror != 0, invert != 0);
|
||||
// bitmap.Dispose();
|
||||
//}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using OpenMetaverse.StructuredData;
|
||||
|
||||
namespace OpenMetaverse
|
||||
@@ -46,6 +44,7 @@ namespace OpenMetaverse
|
||||
/// <summary>
|
||||
/// Particle source pattern
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum SourcePattern : byte
|
||||
{
|
||||
/// <summary>None</summary>
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenMetaverse.StructuredData;
|
||||
|
||||
namespace OpenMetaverse
|
||||
@@ -744,9 +743,8 @@ namespace OpenMetaverse
|
||||
{
|
||||
PhysicsProperties ret = new PhysicsProperties();
|
||||
|
||||
if (osd is OSDMap)
|
||||
if (osd is OSDMap map)
|
||||
{
|
||||
OSDMap map = (OSDMap)osd;
|
||||
ret.LocalID = map["LocalID"];
|
||||
ret.Density = map["Density"];
|
||||
ret.Friction = map["Friction"];
|
||||
@@ -1317,7 +1315,7 @@ namespace OpenMetaverse
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return (obj is Primitive) ? this == (Primitive)obj : false;
|
||||
return (obj is Primitive primitive) && this == primitive;
|
||||
}
|
||||
|
||||
public bool Equals(Primitive other)
|
||||
|
||||
@@ -116,7 +116,7 @@ namespace OpenMetaverse.Rendering
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return (obj is Vertex) && this == (Vertex)obj;
|
||||
return (obj is Vertex vertex) && this == vertex;
|
||||
}
|
||||
|
||||
public bool Equals(Vertex other)
|
||||
@@ -301,11 +301,9 @@ namespace OpenMetaverse.Rendering
|
||||
OSD subMeshOsd = decodedMeshOsdArray[faceNr];
|
||||
|
||||
// Decode each individual face
|
||||
if (subMeshOsd is OSDMap)
|
||||
if (subMeshOsd is OSDMap subMeshMap)
|
||||
{
|
||||
OSDMap subMeshMap = (OSDMap)subMeshOsd;
|
||||
|
||||
// As per http://wiki.secondlife.com/wiki/Mesh/Mesh_Asset_Format, some Mesh Level
|
||||
// As per http://wiki.secondlife.com/wiki/Mesh/Mesh_Asset_Format, some Mesh Level
|
||||
// of Detail Blocks (maps) contain just a NoGeometry key to signal there is no
|
||||
// geometry for this submesh.
|
||||
if (subMeshMap.ContainsKey("NoGeometry") && ((OSDBoolean)subMeshMap["NoGeometry"]))
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* Copyright (c) 2021-2022, Sjofn LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
@@ -37,6 +38,8 @@ namespace OpenMetaverse
|
||||
/// happen at login or dynamically</remarks>
|
||||
public class Settings
|
||||
{
|
||||
public static string USER_AGENT = "LibreMetaverse";
|
||||
|
||||
#region Login/Networking Settings
|
||||
|
||||
/// <summary>Main grid login server</summary>
|
||||
@@ -55,7 +58,7 @@ namespace OpenMetaverse
|
||||
public static System.Net.IPAddress BIND_ADDR = System.Net.IPAddress.Any;
|
||||
|
||||
/// <summary>Use XML-RPC Login or LLSD Login, default is XML-RPC Login</summary>
|
||||
public bool USE_LLSD_LOGIN = true;
|
||||
public bool USE_LLSD_LOGIN = true; //why is the false by default?
|
||||
|
||||
/// <summary>
|
||||
/// Maximum number of HTTP connections to open to a particular endpoint.
|
||||
@@ -80,10 +83,6 @@ namespace OpenMetaverse
|
||||
/// GridClient initializes an Inventory store for the library.
|
||||
/// </summary>
|
||||
public const bool ENABLE_LIBRARY_STORE = true;
|
||||
/// <summary>
|
||||
/// Use Caps for fetching inventory where available
|
||||
/// </summary>
|
||||
public bool HTTP_INVENTORY = true;
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -227,10 +226,6 @@ namespace OpenMetaverse
|
||||
/// re-establish a connection. Set this to true to log those 502 errors</summary>
|
||||
public bool LOG_ALL_CAPS_ERRORS = false;
|
||||
|
||||
/// <summary>If true, any reference received for a folder or item
|
||||
/// the library is not aware of will automatically be fetched</summary>
|
||||
public bool FETCH_MISSING_INVENTORY = true;
|
||||
|
||||
/// <summary>If true, and <code>SEND_AGENT_UPDATES</code> is true,
|
||||
/// AgentUpdate packets will continuously be sent out to give the bot
|
||||
/// smoother movement and autopiloting</summary>
|
||||
@@ -302,7 +297,7 @@ namespace OpenMetaverse
|
||||
|
||||
/// <summary>Cost of uploading an asset</summary>
|
||||
/// <remarks>Read-only since this value is dynamically fetched at login</remarks>
|
||||
public int UPLOAD_COST => priceUpload;
|
||||
public int UPLOAD_COST { get; private set; } = 0;
|
||||
|
||||
/// <summary>Maximum number of times to resend a failed packet</summary>
|
||||
public int MAX_RESEND_COUNT = 3;
|
||||
@@ -310,9 +305,6 @@ namespace OpenMetaverse
|
||||
/// <summary>Throttle outgoing packet rate</summary>
|
||||
public bool THROTTLE_OUTGOING_PACKETS = true;
|
||||
|
||||
/// <summary>UUID of a texture used by some viewers to indentify type of client used</summary>
|
||||
public UUID CLIENT_IDENTIFICATION_TAG = UUID.Zero;
|
||||
|
||||
#endregion
|
||||
#region Texture Pipeline
|
||||
|
||||
@@ -362,7 +354,6 @@ namespace OpenMetaverse
|
||||
#region Private Fields
|
||||
|
||||
private GridClient Client;
|
||||
private int priceUpload = 0;
|
||||
public static bool SORT_INVENTORY = false;
|
||||
|
||||
/// <summary>Constructor</summary>
|
||||
@@ -383,7 +374,7 @@ namespace OpenMetaverse
|
||||
{
|
||||
EconomyDataPacket econ = (EconomyDataPacket)e.Packet;
|
||||
|
||||
priceUpload = econ.Info.PriceUpload; //TODO: is this thread safe? no lock
|
||||
UPLOAD_COST = econ.Info.PriceUpload; //TODO: is this thread safe? no lock
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -343,18 +343,14 @@ namespace OpenMetaverse
|
||||
/// changes its volume level</remarks>
|
||||
public class AttachedSoundGainChangeEventArgs : EventArgs
|
||||
{
|
||||
private readonly Simulator m_Simulator;
|
||||
private readonly UUID m_ObjectID;
|
||||
private readonly float m_Gain;
|
||||
|
||||
/// <summary>Simulator where the event originated</summary>
|
||||
public Simulator Simulator => m_Simulator;
|
||||
public Simulator Simulator { get; }
|
||||
|
||||
/// <summary>Get the ID of the Object</summary>
|
||||
public UUID ObjectID => m_ObjectID;
|
||||
public UUID ObjectID { get; }
|
||||
|
||||
/// <summary>Get the volume level</summary>
|
||||
public float Gain => m_Gain;
|
||||
public float Gain { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new instance of the AttachedSoundGainChangedEventArgs class
|
||||
@@ -364,9 +360,9 @@ namespace OpenMetaverse
|
||||
/// <param name="gain">The new volume level</param>
|
||||
public AttachedSoundGainChangeEventArgs(Simulator sim, UUID objectID, float gain)
|
||||
{
|
||||
m_Simulator = sim;
|
||||
m_ObjectID = objectID;
|
||||
m_Gain = gain;
|
||||
Simulator = sim;
|
||||
ObjectID = objectID;
|
||||
Gain = gain;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -398,38 +394,29 @@ namespace OpenMetaverse
|
||||
/// </example>
|
||||
public class SoundTriggerEventArgs : EventArgs
|
||||
{
|
||||
private readonly Simulator m_Simulator;
|
||||
private readonly UUID m_SoundID;
|
||||
private readonly UUID m_OwnerID;
|
||||
private readonly UUID m_ObjectID;
|
||||
private readonly UUID m_ParentID;
|
||||
private readonly float m_Gain;
|
||||
private readonly ulong m_RegionHandle;
|
||||
private readonly Vector3 m_Position;
|
||||
|
||||
/// <summary>Simulator where the event originated</summary>
|
||||
public Simulator Simulator => m_Simulator;
|
||||
public Simulator Simulator { get; }
|
||||
|
||||
/// <summary>Get the sound asset id</summary>
|
||||
public UUID SoundID => m_SoundID;
|
||||
public UUID SoundID { get; }
|
||||
|
||||
/// <summary>Get the ID of the owner</summary>
|
||||
public UUID OwnerID => m_OwnerID;
|
||||
public UUID OwnerID { get; }
|
||||
|
||||
/// <summary>Get the ID of the Object</summary>
|
||||
public UUID ObjectID => m_ObjectID;
|
||||
public UUID ObjectID { get; }
|
||||
|
||||
/// <summary>Get the ID of the objects parent</summary>
|
||||
public UUID ParentID => m_ParentID;
|
||||
public UUID ParentID { get; }
|
||||
|
||||
/// <summary>Get the volume level</summary>
|
||||
public float Gain => m_Gain;
|
||||
public float Gain { get; }
|
||||
|
||||
/// <summary>Get the regionhandle</summary>
|
||||
public ulong RegionHandle => m_RegionHandle;
|
||||
public ulong RegionHandle { get; }
|
||||
|
||||
/// <summary>Get the source position</summary>
|
||||
public Vector3 Position => m_Position;
|
||||
public Vector3 Position { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new instance of the SoundTriggerEventArgs class
|
||||
@@ -444,14 +431,14 @@ namespace OpenMetaverse
|
||||
/// <param name="position">The source position</param>
|
||||
public SoundTriggerEventArgs(Simulator sim, UUID soundID, UUID ownerID, UUID objectID, UUID parentID, float gain, ulong regionHandle, Vector3 position)
|
||||
{
|
||||
m_Simulator = sim;
|
||||
m_SoundID = soundID;
|
||||
m_OwnerID = ownerID;
|
||||
m_ObjectID = objectID;
|
||||
m_ParentID = parentID;
|
||||
m_Gain = gain;
|
||||
m_RegionHandle = regionHandle;
|
||||
m_Position = position;
|
||||
Simulator = sim;
|
||||
SoundID = soundID;
|
||||
OwnerID = ownerID;
|
||||
ObjectID = objectID;
|
||||
ParentID = parentID;
|
||||
Gain = gain;
|
||||
RegionHandle = regionHandle;
|
||||
Position = position;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -474,22 +461,17 @@ namespace OpenMetaverse
|
||||
/// </example>
|
||||
public class PreloadSoundEventArgs : EventArgs
|
||||
{
|
||||
private readonly Simulator m_Simulator;
|
||||
private readonly UUID m_SoundID;
|
||||
private readonly UUID m_OwnerID;
|
||||
private readonly UUID m_ObjectID;
|
||||
|
||||
/// <summary>Simulator where the event originated</summary>
|
||||
public Simulator Simulator => m_Simulator;
|
||||
public Simulator Simulator { get; }
|
||||
|
||||
/// <summary>Get the sound asset id</summary>
|
||||
public UUID SoundID => m_SoundID;
|
||||
public UUID SoundID { get; }
|
||||
|
||||
/// <summary>Get the ID of the owner</summary>
|
||||
public UUID OwnerID => m_OwnerID;
|
||||
public UUID OwnerID { get; }
|
||||
|
||||
/// <summary>Get the ID of the Object</summary>
|
||||
public UUID ObjectID => m_ObjectID;
|
||||
public UUID ObjectID { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new instance of the PreloadSoundEventArgs class
|
||||
@@ -500,10 +482,10 @@ namespace OpenMetaverse
|
||||
/// <param name="objectID">The ID of the object</param>
|
||||
public PreloadSoundEventArgs(Simulator sim, UUID soundID, UUID ownerID, UUID objectID)
|
||||
{
|
||||
m_Simulator = sim;
|
||||
m_SoundID = soundID;
|
||||
m_OwnerID = ownerID;
|
||||
m_ObjectID = objectID;
|
||||
Simulator = sim;
|
||||
SoundID = soundID;
|
||||
OwnerID = ownerID;
|
||||
ObjectID = objectID;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Reflection;
|
||||
using System.Collections.Generic;
|
||||
|
||||
|
||||
@@ -193,34 +193,28 @@ namespace OpenMetaverse
|
||||
// <summary>Provides data for LandPatchReceived</summary>
|
||||
public class LandPatchReceivedEventArgs : EventArgs
|
||||
{
|
||||
private readonly Simulator m_Simulator;
|
||||
private readonly int m_X;
|
||||
private readonly int m_Y;
|
||||
private readonly int m_PatchSize;
|
||||
private readonly float[] m_HeightMap;
|
||||
|
||||
/// <summary>Simulator from that sent tha data</summary>
|
||||
public Simulator Simulator => m_Simulator;
|
||||
public Simulator Simulator { get; }
|
||||
|
||||
/// <summary>Sim coordinate of the patch</summary>
|
||||
public int X => m_X;
|
||||
public int X { get; }
|
||||
|
||||
/// <summary>Sim coordinate of the patch</summary>
|
||||
public int Y => m_Y;
|
||||
public int Y { get; }
|
||||
|
||||
/// <summary>Size of tha patch</summary>
|
||||
public int PatchSize => m_PatchSize;
|
||||
public int PatchSize { get; }
|
||||
|
||||
/// <summary>Heightmap for the patch</summary>
|
||||
public float[] HeightMap => m_HeightMap;
|
||||
public float[] HeightMap { get; }
|
||||
|
||||
public LandPatchReceivedEventArgs(Simulator simulator, int x, int y, int patchSize, float[] heightMap)
|
||||
{
|
||||
m_Simulator = simulator;
|
||||
m_X = x;
|
||||
m_Y = y;
|
||||
m_PatchSize = patchSize;
|
||||
m_HeightMap = heightMap;
|
||||
Simulator = simulator;
|
||||
X = x;
|
||||
Y = y;
|
||||
PatchSize = patchSize;
|
||||
HeightMap = heightMap;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
using System.Net;
|
||||
|
||||
namespace OpenMetaverse
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* Copyright (c) 2021-2022, Sjofn LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
@@ -28,13 +29,13 @@ using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
|
||||
namespace OpenMetaverse.Voice
|
||||
namespace LibreMetaverse.Voice
|
||||
{
|
||||
public class TCPPipe
|
||||
{
|
||||
protected class SocketPacket
|
||||
{
|
||||
public System.Net.Sockets.Socket TCPSocket;
|
||||
public Socket TCPSocket;
|
||||
public byte[] DataBuffer = new byte[1];
|
||||
}
|
||||
|
||||
@@ -47,12 +48,9 @@ namespace OpenMetaverse.Voice
|
||||
protected Socket _TCPSocket;
|
||||
protected IAsyncResult _Result;
|
||||
protected AsyncCallback _Callback;
|
||||
protected string _Buffer = String.Empty;
|
||||
protected string _Buffer = string.Empty;
|
||||
|
||||
public bool Connected
|
||||
{
|
||||
get { return _TCPSocket != null && _TCPSocket.Connected; }
|
||||
}
|
||||
public bool Connected => _TCPSocket != null && _TCPSocket.Connected;
|
||||
|
||||
public SocketException Connect(string address, int port)
|
||||
{
|
||||
@@ -117,8 +115,10 @@ namespace OpenMetaverse.Voice
|
||||
try
|
||||
{
|
||||
if (_Callback == null) _Callback = new AsyncCallback(OnDataReceived);
|
||||
SocketPacket packet = new SocketPacket();
|
||||
packet.TCPSocket = _TCPSocket;
|
||||
SocketPacket packet = new SocketPacket
|
||||
{
|
||||
TCPSocket = _TCPSocket
|
||||
};
|
||||
_Result = _TCPSocket.BeginReceive(packet.DataBuffer, 0, packet.DataBuffer.Length, SocketFlags.None, _Callback, packet);
|
||||
}
|
||||
catch (SocketException se)
|
||||
@@ -127,8 +127,8 @@ namespace OpenMetaverse.Voice
|
||||
}
|
||||
}
|
||||
|
||||
static char[] splitNull = { '\0' };
|
||||
static string[] splitLines = { "\r", "\n", "\r\n" };
|
||||
static readonly char[] splitNull = { '\0' };
|
||||
static readonly string[] splitLines = { "\r", "\n", "\r\n" };
|
||||
|
||||
void ReceiveData(string data)
|
||||
{
|
||||
@@ -159,7 +159,7 @@ namespace OpenMetaverse.Voice
|
||||
char[] chars = new char[end + 1];
|
||||
System.Text.Decoder d = System.Text.Encoding.UTF8.GetDecoder();
|
||||
d.GetChars(packet.DataBuffer, 0, end, chars, 0);
|
||||
System.String data = new System.String(chars);
|
||||
string data = new string(chars);
|
||||
ReceiveData(data);
|
||||
WaitForData();
|
||||
}
|
||||
@@ -171,8 +171,9 @@ namespace OpenMetaverse.Voice
|
||||
{
|
||||
if (!_TCPSocket.Connected)
|
||||
{
|
||||
if (OnDisconnected != null)
|
||||
OnDisconnected(se);
|
||||
// if (OnDisconnected != null)
|
||||
// OnDisconnected(se);
|
||||
OnDisconnected?.Invoke(se);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* Copyright (c) 2021-2022, Sjofn LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
@@ -24,11 +25,9 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OpenMetaverse.Voice
|
||||
namespace LibreMetaverse.Voice
|
||||
{
|
||||
public partial class VoiceGateway
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* Copyright (c) 2021-2022, Sjofn LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
@@ -24,11 +25,7 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OpenMetaverse.Voice
|
||||
namespace LibreMetaverse.Voice
|
||||
{
|
||||
public partial class VoiceGateway
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* Copyright (c) 2021-2022, Sjofn LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
@@ -24,11 +25,9 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace OpenMetaverse.Voice
|
||||
namespace LibreMetaverse.Voice
|
||||
{
|
||||
public partial class VoiceGateway
|
||||
{
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* Copyright (c) 2021-2022, Sjofn LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
@@ -27,15 +28,14 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading;
|
||||
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.StructuredData;
|
||||
using OpenMetaverse.Http;
|
||||
|
||||
namespace OpenMetaverse.Voice
|
||||
namespace LibreMetaverse.Voice
|
||||
{
|
||||
public partial class VoiceGateway : IDisposable
|
||||
{
|
||||
@@ -71,7 +71,7 @@ namespace OpenMetaverse.Voice
|
||||
private string spatialCredentials;
|
||||
|
||||
// Session management
|
||||
private Dictionary<string, VoiceSession> sessions;
|
||||
private readonly Dictionary<string, VoiceSession> sessions;
|
||||
private VoiceSession spatialSession;
|
||||
private Uri currentParcelCap;
|
||||
private Uri nextParcelCap;
|
||||
@@ -82,21 +82,21 @@ namespace OpenMetaverse.Voice
|
||||
private CancellationTokenSource posTokenSource;
|
||||
private ManualResetEvent posRestart;
|
||||
public GridClient Client;
|
||||
private VoicePosition position;
|
||||
private readonly VoicePosition position;
|
||||
private Vector3d oldPosition;
|
||||
private Vector3d oldAt;
|
||||
|
||||
// Audio interfaces
|
||||
private List<string> inputDevices;
|
||||
/// <summary>
|
||||
/// List of audio input devices
|
||||
/// </summary>
|
||||
public List<string> CaptureDevices { get { return inputDevices; } }
|
||||
private List<string> outputDevices;
|
||||
public List<string> CaptureDevices { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// List of audio output devices
|
||||
/// </summary>
|
||||
public List<string> PlaybackDevices { get { return outputDevices; } }
|
||||
public List<string> PlaybackDevices { get; private set; }
|
||||
|
||||
private string currentCaptureDevice;
|
||||
private string currentPlaybackDevice;
|
||||
private bool testing = false;
|
||||
@@ -110,15 +110,17 @@ namespace OpenMetaverse.Voice
|
||||
|
||||
public VoiceGateway(GridClient c)
|
||||
{
|
||||
Random rand = new Random();
|
||||
var rand = new Random();
|
||||
daemonPort = rand.Next(34000, 44000);
|
||||
|
||||
Client = c;
|
||||
|
||||
sessions = new Dictionary<string, VoiceSession>();
|
||||
position = new VoicePosition();
|
||||
position.UpOrientation = new Vector3d(0.0, 1.0, 0.0);
|
||||
position.Velocity = new Vector3d(0.0, 0.0, 0.0);
|
||||
position = new VoicePosition
|
||||
{
|
||||
UpOrientation = new Vector3d(0.0, 1.0, 0.0),
|
||||
Velocity = new Vector3d(0.0, 0.0, 0.0)
|
||||
};
|
||||
oldPosition = new Vector3d(0, 0, 0);
|
||||
oldAt = new Vector3d(1, 0, 0);
|
||||
|
||||
@@ -140,60 +142,48 @@ namespace OpenMetaverse.Voice
|
||||
}
|
||||
|
||||
posTokenSource = new CancellationTokenSource();
|
||||
posThread = new Thread(new ThreadStart(PositionThreadBody));
|
||||
posThread.Name = "VoicePositionUpdate";
|
||||
posThread.IsBackground = true;
|
||||
posThread = new Thread(PositionThreadBody)
|
||||
{
|
||||
Name = "VoicePositionUpdate",
|
||||
IsBackground = true
|
||||
};
|
||||
posRestart = new ManualResetEvent(false);
|
||||
posThread.Start();
|
||||
|
||||
Client.Network.EventQueueRunning += new EventHandler<EventQueueRunningEventArgs>(Network_EventQueueRunning);
|
||||
Client.Network.EventQueueRunning += Network_EventQueueRunning;
|
||||
|
||||
// Connection events
|
||||
OnDaemonRunning +=
|
||||
new VoiceGateway.DaemonRunningCallback(connector_OnDaemonRunning);
|
||||
OnDaemonCouldntRun +=
|
||||
new VoiceGateway.DaemonCouldntRunCallback(connector_OnDaemonCouldntRun);
|
||||
OnConnectorCreateResponse +=
|
||||
new EventHandler<VoiceGateway.VoiceConnectorEventArgs>(connector_OnConnectorCreateResponse);
|
||||
OnDaemonConnected +=
|
||||
new DaemonConnectedCallback(connector_OnDaemonConnected);
|
||||
OnDaemonCouldntConnect +=
|
||||
new DaemonCouldntConnectCallback(connector_OnDaemonCouldntConnect);
|
||||
OnAuxAudioPropertiesEvent +=
|
||||
new EventHandler<AudioPropertiesEventArgs>(connector_OnAuxAudioPropertiesEvent);
|
||||
OnDaemonRunning += connector_OnDaemonRunning;
|
||||
OnDaemonCouldntRun += connector_OnDaemonCouldntRun;
|
||||
OnConnectorCreateResponse += connector_OnConnectorCreateResponse;
|
||||
OnDaemonConnected += connector_OnDaemonConnected;
|
||||
OnDaemonCouldntConnect += connector_OnDaemonCouldntConnect;
|
||||
OnAuxAudioPropertiesEvent += connector_OnAuxAudioPropertiesEvent;
|
||||
|
||||
// Session events
|
||||
OnSessionStateChangeEvent +=
|
||||
new EventHandler<SessionStateChangeEventArgs>(connector_OnSessionStateChangeEvent);
|
||||
OnSessionAddedEvent +=
|
||||
new EventHandler<SessionAddedEventArgs>(connector_OnSessionAddedEvent);
|
||||
OnSessionStateChangeEvent += connector_OnSessionStateChangeEvent;
|
||||
OnSessionAddedEvent += connector_OnSessionAddedEvent;
|
||||
|
||||
// Session Participants events
|
||||
OnSessionParticipantUpdatedEvent +=
|
||||
new EventHandler<ParticipantUpdatedEventArgs>(connector_OnSessionParticipantUpdatedEvent);
|
||||
OnSessionParticipantAddedEvent +=
|
||||
new EventHandler<ParticipantAddedEventArgs>(connector_OnSessionParticipantAddedEvent);
|
||||
OnSessionParticipantUpdatedEvent += connector_OnSessionParticipantUpdatedEvent;
|
||||
OnSessionParticipantAddedEvent += connector_OnSessionParticipantAddedEvent;
|
||||
|
||||
// Device events
|
||||
OnAuxGetCaptureDevicesResponse +=
|
||||
new EventHandler<VoiceDevicesEventArgs>(connector_OnAuxGetCaptureDevicesResponse);
|
||||
OnAuxGetRenderDevicesResponse +=
|
||||
new EventHandler<VoiceDevicesEventArgs>(connector_OnAuxGetRenderDevicesResponse);
|
||||
OnAuxGetCaptureDevicesResponse += connector_OnAuxGetCaptureDevicesResponse;
|
||||
OnAuxGetRenderDevicesResponse += connector_OnAuxGetRenderDevicesResponse;
|
||||
|
||||
// Generic status response
|
||||
OnVoiceResponse += new EventHandler<VoiceResponseEventArgs>(connector_OnVoiceResponse);
|
||||
OnVoiceResponse += connector_OnVoiceResponse;
|
||||
|
||||
// Account events
|
||||
OnAccountLoginResponse +=
|
||||
new EventHandler<VoiceAccountEventArgs>(connector_OnAccountLoginResponse);
|
||||
OnAccountLoginResponse += connector_OnAccountLoginResponse;
|
||||
|
||||
Logger.Log("Voice initialized", Helpers.LogLevel.Info);
|
||||
|
||||
// If voice provisioning capability is already available,
|
||||
// proceed with voice startup. Otherwise the EventQueueRunning
|
||||
// event will do it.
|
||||
System.Uri vCap =
|
||||
Client.Network.CurrentSim.Caps.CapabilityURI("ProvisionVoiceAccountRequest");
|
||||
var vCap = Client.Network.CurrentSim.Caps.CapabilityURI("ProvisionVoiceAccountRequest");
|
||||
if (vCap != null)
|
||||
RequestVoiceProvision(vCap);
|
||||
|
||||
@@ -205,55 +195,39 @@ namespace OpenMetaverse.Voice
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
/// ///<remarks>If something goes wrong, we log it.</remarks>
|
||||
void connector_OnVoiceResponse(object sender, VoiceGateway.VoiceResponseEventArgs e)
|
||||
void connector_OnVoiceResponse(object sender, VoiceResponseEventArgs e)
|
||||
{
|
||||
if (e.StatusCode == 0)
|
||||
return;
|
||||
|
||||
Logger.Log(e.Message + " on " + sender as string, Helpers.LogLevel.Error);
|
||||
if (e.StatusCode == 0) { return; }
|
||||
Logger.Log($"{e.Message} on {sender}", Helpers.LogLevel.Error);
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
Client.Network.EventQueueRunning -= new EventHandler<EventQueueRunningEventArgs>(Network_EventQueueRunning);
|
||||
Client.Network.EventQueueRunning -= Network_EventQueueRunning;
|
||||
|
||||
// Connection events
|
||||
OnDaemonRunning -=
|
||||
new VoiceGateway.DaemonRunningCallback(connector_OnDaemonRunning);
|
||||
OnDaemonCouldntRun -=
|
||||
new VoiceGateway.DaemonCouldntRunCallback(connector_OnDaemonCouldntRun);
|
||||
OnConnectorCreateResponse -=
|
||||
new EventHandler<VoiceGateway.VoiceConnectorEventArgs>(connector_OnConnectorCreateResponse);
|
||||
OnDaemonConnected -=
|
||||
new VoiceGateway.DaemonConnectedCallback(connector_OnDaemonConnected);
|
||||
OnDaemonCouldntConnect -=
|
||||
new VoiceGateway.DaemonCouldntConnectCallback(connector_OnDaemonCouldntConnect);
|
||||
OnAuxAudioPropertiesEvent -=
|
||||
new EventHandler<AudioPropertiesEventArgs>(connector_OnAuxAudioPropertiesEvent);
|
||||
OnDaemonRunning -= connector_OnDaemonRunning;
|
||||
OnDaemonCouldntRun -= connector_OnDaemonCouldntRun;
|
||||
OnConnectorCreateResponse -= connector_OnConnectorCreateResponse;
|
||||
OnDaemonConnected -= connector_OnDaemonConnected;
|
||||
OnDaemonCouldntConnect -= connector_OnDaemonCouldntConnect;
|
||||
OnAuxAudioPropertiesEvent -= connector_OnAuxAudioPropertiesEvent;
|
||||
|
||||
// Session events
|
||||
OnSessionStateChangeEvent -=
|
||||
new EventHandler<SessionStateChangeEventArgs>(connector_OnSessionStateChangeEvent);
|
||||
OnSessionAddedEvent -=
|
||||
new EventHandler<SessionAddedEventArgs>(connector_OnSessionAddedEvent);
|
||||
OnSessionStateChangeEvent -= connector_OnSessionStateChangeEvent;
|
||||
OnSessionAddedEvent -= connector_OnSessionAddedEvent;
|
||||
|
||||
// Session Participants events
|
||||
OnSessionParticipantUpdatedEvent -=
|
||||
new EventHandler<ParticipantUpdatedEventArgs>(connector_OnSessionParticipantUpdatedEvent);
|
||||
OnSessionParticipantAddedEvent -=
|
||||
new EventHandler<ParticipantAddedEventArgs>(connector_OnSessionParticipantAddedEvent);
|
||||
OnSessionParticipantRemovedEvent -=
|
||||
new EventHandler<ParticipantRemovedEventArgs>(connector_OnSessionParticipantRemovedEvent);
|
||||
OnSessionParticipantUpdatedEvent -= connector_OnSessionParticipantUpdatedEvent;
|
||||
OnSessionParticipantAddedEvent -= connector_OnSessionParticipantAddedEvent;
|
||||
OnSessionParticipantRemovedEvent -= connector_OnSessionParticipantRemovedEvent;
|
||||
|
||||
// Tuning events
|
||||
OnAuxGetCaptureDevicesResponse -=
|
||||
new EventHandler<VoiceGateway.VoiceDevicesEventArgs>(connector_OnAuxGetCaptureDevicesResponse);
|
||||
OnAuxGetRenderDevicesResponse -=
|
||||
new EventHandler<VoiceGateway.VoiceDevicesEventArgs>(connector_OnAuxGetRenderDevicesResponse);
|
||||
OnAuxGetCaptureDevicesResponse -= connector_OnAuxGetCaptureDevicesResponse;
|
||||
OnAuxGetRenderDevicesResponse -= connector_OnAuxGetRenderDevicesResponse;
|
||||
|
||||
// Account events
|
||||
OnAccountLoginResponse -=
|
||||
new EventHandler<VoiceGateway.VoiceAccountEventArgs>(connector_OnAccountLoginResponse);
|
||||
OnAccountLoginResponse -= connector_OnAccountLoginResponse;
|
||||
|
||||
// Stop the background thread
|
||||
if (posThread != null)
|
||||
@@ -267,10 +241,9 @@ namespace OpenMetaverse.Voice
|
||||
}
|
||||
|
||||
// Close all sessions
|
||||
foreach (VoiceSession s in sessions.Values)
|
||||
foreach (var s in sessions.Values)
|
||||
{
|
||||
if (OnSessionRemove != null)
|
||||
OnSessionRemove(s, EventArgs.Empty);
|
||||
OnSessionRemove?.Invoke(s, EventArgs.Empty);
|
||||
s.Close();
|
||||
}
|
||||
|
||||
@@ -309,56 +282,46 @@ namespace OpenMetaverse.Voice
|
||||
|
||||
internal string GetVoiceDaemonPath()
|
||||
{
|
||||
string myDir =
|
||||
var myDir =
|
||||
Path.GetDirectoryName(
|
||||
(System.Reflection.Assembly.GetEntryAssembly() ?? typeof (VoiceGateway).Assembly).Location);
|
||||
|
||||
if (Environment.OSVersion.Platform != PlatformID.MacOSX &&
|
||||
Environment.OSVersion.Platform != PlatformID.Unix)
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
string localDaemon = Path.Combine(myDir, Path.Combine("voice", "SLVoice.exe"));
|
||||
if (myDir != null)
|
||||
{
|
||||
var localDaemon = Path.Combine(myDir, Path.Combine("voice", "SLVoice.exe"));
|
||||
|
||||
if (File.Exists(localDaemon))
|
||||
return localDaemon;
|
||||
|
||||
string progFiles;
|
||||
if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("ProgramFiles(x86)")))
|
||||
{
|
||||
progFiles = Environment.GetEnvironmentVariable("ProgramFiles(x86)");
|
||||
}
|
||||
else
|
||||
{
|
||||
progFiles = Environment.GetEnvironmentVariable("ProgramFiles");
|
||||
if (File.Exists(localDaemon))
|
||||
return localDaemon;
|
||||
}
|
||||
|
||||
if (System.IO.File.Exists(Path.Combine(progFiles, @"SecondLife" + Path.DirectorySeparatorChar + @"SLVoice.exe")))
|
||||
{
|
||||
return Path.Combine(progFiles, @"SecondLife" + Path.DirectorySeparatorChar + @"SLVoice.exe");
|
||||
}
|
||||
|
||||
return Path.Combine(myDir, @"SLVoice.exe");
|
||||
var progFiles = Environment.GetEnvironmentVariable(
|
||||
!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("ProgramFiles(x86)"))
|
||||
? "ProgramFiles(x86)" : "ProgramFiles");
|
||||
|
||||
return progFiles != null && File.Exists(Path.Combine(progFiles, @"SecondLife" + Path.DirectorySeparatorChar + @"SLVoice.exe"))
|
||||
? Path.Combine(progFiles, @"SecondLife" + Path.DirectorySeparatorChar + @"SLVoice.exe")
|
||||
: Path.Combine(myDir, @"SLVoice.exe");
|
||||
}
|
||||
else
|
||||
|
||||
if (myDir != null)
|
||||
{
|
||||
string localDaemon = Path.Combine(myDir, Path.Combine("voice", "SLVoice"));
|
||||
|
||||
if (File.Exists(localDaemon))
|
||||
return localDaemon;
|
||||
|
||||
return Path.Combine(myDir,"SLVoice");
|
||||
var localDaemon = Path.Combine(myDir, Path.Combine("voice", "SLVoice"));
|
||||
return File.Exists(localDaemon) ? localDaemon : Path.Combine(myDir,"SLVoice");
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
void RequestVoiceProvision(System.Uri cap)
|
||||
void RequestVoiceProvision(Uri cap)
|
||||
{
|
||||
Http.CapsClient capClient = new Http.CapsClient(cap, "ReqVoiceProvision");
|
||||
var capClient = new CapsClient(cap, "ReqVoiceProvision");
|
||||
capClient.OnComplete += cClient_OnComplete;
|
||||
OSD postData = new OSD();
|
||||
|
||||
// STEP 0
|
||||
Logger.Log("Requesting voice capability", Helpers.LogLevel.Info);
|
||||
capClient.BeginGetResponse(postData, OSDFormat.Xml, 10000);
|
||||
capClient.PostRequestAsync(new OSD(), OSDFormat.Xml, 10000);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -382,8 +345,7 @@ namespace OpenMetaverse.Voice
|
||||
// 5. Create session
|
||||
|
||||
// Get the voice provisioning data
|
||||
System.Uri vCap =
|
||||
Client.Network.CurrentSim.Caps.CapabilityURI("ProvisionVoiceAccountRequest");
|
||||
var vCap = Client.Network.CurrentSim.Caps.CapabilityURI("ProvisionVoiceAccountRequest");
|
||||
|
||||
// Do we have voice capability?
|
||||
if (vCap == null)
|
||||
@@ -409,9 +371,8 @@ namespace OpenMetaverse.Voice
|
||||
|
||||
void connector_OnSessionParticipantUpdatedEvent(object sender, ParticipantUpdatedEventArgs e)
|
||||
{
|
||||
VoiceSession s = FindSession(e.SessionHandle, false);
|
||||
if (s == null) return;
|
||||
s.ParticipantUpdate(e.URI, e.IsMuted, e.IsSpeaking, e.Volume, e.Energy);
|
||||
var s = FindSession(e.SessionHandle, false);
|
||||
s?.ParticipantUpdate(e.URI, e.IsMuted, e.IsSpeaking, e.Volume, e.Energy);
|
||||
}
|
||||
|
||||
public string SIPFromUUID(UUID id)
|
||||
@@ -435,7 +396,7 @@ namespace OpenMetaverse.Voice
|
||||
// Base64 encode and replace the pieces of base64 that are less compatible
|
||||
// with e-mail local-parts.
|
||||
// See RFC-4648 "Base 64 Encoding with URL and Filename Safe Alphabet"
|
||||
byte[] encbuff = id.GetBytes();
|
||||
var encbuff = id.GetBytes();
|
||||
result += Convert.ToBase64String(encbuff);
|
||||
result = result.Replace('+', '-');
|
||||
result = result.Replace('/', '_');
|
||||
@@ -445,7 +406,7 @@ namespace OpenMetaverse.Voice
|
||||
|
||||
void connector_OnSessionParticipantAddedEvent(object sender, ParticipantAddedEventArgs e)
|
||||
{
|
||||
VoiceSession s = FindSession(e.SessionHandle, false);
|
||||
var s = FindSession(e.SessionHandle, false);
|
||||
if (s == null)
|
||||
{
|
||||
Logger.Log("Orphan participant", Helpers.LogLevel.Error);
|
||||
@@ -456,9 +417,8 @@ namespace OpenMetaverse.Voice
|
||||
|
||||
void connector_OnSessionParticipantRemovedEvent(object sender, ParticipantRemovedEventArgs e)
|
||||
{
|
||||
VoiceSession s = FindSession(e.SessionHandle, false);
|
||||
if (s == null) return;
|
||||
s.RemoveParticipant(e.URI);
|
||||
var s = FindSession(e.SessionHandle, false);
|
||||
s?.RemoveParticipant(e.URI);
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -468,14 +428,13 @@ namespace OpenMetaverse.Voice
|
||||
sessionHandle = e.SessionHandle;
|
||||
|
||||
// Create our session context.
|
||||
VoiceSession s = FindSession(sessionHandle, true);
|
||||
var s = FindSession(sessionHandle, true);
|
||||
s.RegionName = regionName;
|
||||
|
||||
spatialSession = s;
|
||||
|
||||
// Tell any user-facing code.
|
||||
if (OnSessionCreate != null)
|
||||
OnSessionCreate(s, null);
|
||||
OnSessionCreate?.Invoke(s, null);
|
||||
|
||||
Logger.Log("Added voice session in " + regionName, Helpers.LogLevel.Info);
|
||||
}
|
||||
@@ -489,7 +448,7 @@ namespace OpenMetaverse.Voice
|
||||
|
||||
switch (e.State)
|
||||
{
|
||||
case VoiceGateway.SessionState.Connected:
|
||||
case SessionState.Connected:
|
||||
s = FindSession(e.SessionHandle, true);
|
||||
sessionHandle = e.SessionHandle;
|
||||
s.RegionName = regionName;
|
||||
@@ -497,11 +456,10 @@ namespace OpenMetaverse.Voice
|
||||
|
||||
Logger.Log("Voice connected in " + regionName, Helpers.LogLevel.Info);
|
||||
// Tell any user-facing code.
|
||||
if (OnSessionCreate != null)
|
||||
OnSessionCreate(s, null);
|
||||
OnSessionCreate?.Invoke(s, null);
|
||||
break;
|
||||
|
||||
case VoiceGateway.SessionState.Disconnected:
|
||||
case SessionState.Disconnected:
|
||||
s = FindSession(sessionHandle, false);
|
||||
sessions.Remove(sessionHandle);
|
||||
|
||||
@@ -510,8 +468,7 @@ namespace OpenMetaverse.Voice
|
||||
Logger.Log("Voice disconnected in " + s.RegionName, Helpers.LogLevel.Info);
|
||||
|
||||
// Inform interested parties
|
||||
if (OnSessionRemove != null)
|
||||
OnSessionRemove(s, null);
|
||||
OnSessionRemove?.Invoke(s, null);
|
||||
|
||||
if (s == spatialSession)
|
||||
spatialSession = null;
|
||||
@@ -526,6 +483,20 @@ namespace OpenMetaverse.Voice
|
||||
RequestParcelInfo(currentParcelCap);
|
||||
}
|
||||
break;
|
||||
case SessionState.Idle:
|
||||
break;
|
||||
case SessionState.Answering:
|
||||
break;
|
||||
case SessionState.InProgress:
|
||||
break;
|
||||
case SessionState.Hold:
|
||||
break;
|
||||
case SessionState.Refer:
|
||||
break;
|
||||
case SessionState.Ringing:
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
|
||||
|
||||
@@ -544,7 +515,7 @@ namespace OpenMetaverse.Voice
|
||||
ReportConnectionState(ConnectionState.AccountLogin);
|
||||
|
||||
// Clean up spatial pointers.
|
||||
VoiceSession s = sessions[sessionHandle];
|
||||
var s = sessions[sessionHandle];
|
||||
if (s.IsSpatial)
|
||||
{
|
||||
spatialSession = null;
|
||||
@@ -555,8 +526,7 @@ namespace OpenMetaverse.Voice
|
||||
sessions.Remove(sessionHandle);
|
||||
|
||||
// Let any user-facing code clean up.
|
||||
if (OnSessionRemove != null)
|
||||
OnSessionRemove(s, null);
|
||||
OnSessionRemove?.Invoke(s, null);
|
||||
|
||||
// Tell SLVoice to clean it up as well.
|
||||
SessionTerminate(sessionHandle);
|
||||
@@ -574,7 +544,7 @@ namespace OpenMetaverse.Voice
|
||||
if (!make) return null;
|
||||
|
||||
// Create a new session and add it to the sessions list.
|
||||
VoiceSession s = new VoiceSession(this, sessionHandle);
|
||||
var s = new VoiceSession(this, sessionHandle);
|
||||
|
||||
// Turn on position updating for spatial sessions
|
||||
// (For now, only spatial sessions are supported)
|
||||
@@ -592,17 +562,14 @@ namespace OpenMetaverse.Voice
|
||||
|
||||
void connector_OnAuxAudioPropertiesEvent(object sender, AudioPropertiesEventArgs e)
|
||||
{
|
||||
if (OnVoiceMicTest != null)
|
||||
OnVoiceMicTest(e.MicEnergy);
|
||||
OnVoiceMicTest?.Invoke(e.MicEnergy);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void ReportConnectionState(ConnectionState s)
|
||||
{
|
||||
if (OnVoiceConnectionChange == null) return;
|
||||
|
||||
OnVoiceConnectionChange(s);
|
||||
OnVoiceConnectionChange?.Invoke(s);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -611,8 +578,8 @@ namespace OpenMetaverse.Voice
|
||||
/// <param name="client"></param>
|
||||
/// <param name="result"></param>
|
||||
/// <param name="error"></param>
|
||||
void cClient_OnComplete(OpenMetaverse.Http.CapsClient client,
|
||||
OpenMetaverse.StructuredData.OSD result,
|
||||
void cClient_OnComplete(CapsClient client,
|
||||
OSD result,
|
||||
Exception error)
|
||||
{
|
||||
if (error != null)
|
||||
@@ -624,25 +591,26 @@ namespace OpenMetaverse.Voice
|
||||
Logger.Log("Voice provisioned", Helpers.LogLevel.Info);
|
||||
ReportConnectionState(ConnectionState.Provisioned);
|
||||
|
||||
OpenMetaverse.StructuredData.OSDMap pMap = result as OpenMetaverse.StructuredData.OSDMap;
|
||||
|
||||
// We can get back 4 interesting values:
|
||||
// voice_sip_uri_hostname
|
||||
// voice_account_server_name (actually a full URI)
|
||||
// username
|
||||
// password
|
||||
if (pMap.ContainsKey("voice_sip_uri_hostname"))
|
||||
sipServer = pMap["voice_sip_uri_hostname"].AsString();
|
||||
if (pMap.ContainsKey("voice_account_server_name"))
|
||||
acctServer = pMap["voice_account_server_name"].AsString();
|
||||
voiceUser = pMap["username"].AsString();
|
||||
voicePassword = pMap["password"].AsString();
|
||||
if (result is OSDMap pMap)
|
||||
{
|
||||
if (pMap.ContainsKey("voice_sip_uri_hostname"))
|
||||
sipServer = pMap["voice_sip_uri_hostname"].AsString();
|
||||
if (pMap.ContainsKey("voice_account_server_name"))
|
||||
acctServer = pMap["voice_account_server_name"].AsString();
|
||||
voiceUser = pMap["username"].AsString();
|
||||
voicePassword = pMap["password"].AsString();
|
||||
}
|
||||
|
||||
// Start the SLVoice daemon
|
||||
slvoicePath = GetVoiceDaemonPath();
|
||||
|
||||
// Test if the executable exists
|
||||
if (!System.IO.File.Exists(slvoicePath))
|
||||
if (!File.Exists(slvoicePath))
|
||||
{
|
||||
Logger.Log("SLVoice is missing", Helpers.LogLevel.Error);
|
||||
return;
|
||||
@@ -669,7 +637,7 @@ namespace OpenMetaverse.Voice
|
||||
void connector_OnDaemonRunning()
|
||||
{
|
||||
OnDaemonRunning -=
|
||||
new VoiceGateway.DaemonRunningCallback(connector_OnDaemonRunning);
|
||||
connector_OnDaemonRunning;
|
||||
|
||||
Logger.Log("Daemon started", Helpers.LogLevel.Info);
|
||||
ReportConnectionState(ConnectionState.DaemonStarted);
|
||||
@@ -688,8 +656,8 @@ namespace OpenMetaverse.Voice
|
||||
ReportConnectionState(ConnectionState.DaemonConnected);
|
||||
|
||||
// The connector is what does the logging.
|
||||
VoiceGateway.VoiceLoggingSettings vLog =
|
||||
new VoiceGateway.VoiceLoggingSettings();
|
||||
var vLog =
|
||||
new VoiceLoggingSettings();
|
||||
|
||||
#if DEBUG_VOICE
|
||||
vLog.Enabled = true;
|
||||
@@ -698,7 +666,7 @@ namespace OpenMetaverse.Voice
|
||||
vLog.LogLevel = 4;
|
||||
#endif
|
||||
// STEP 3
|
||||
int reqId = ConnectorCreate(
|
||||
var reqId = ConnectorCreate(
|
||||
"V2 SDK", // Magic value keeps SLVoice happy
|
||||
acctServer, // Account manager server
|
||||
30000, 30099, // port range
|
||||
@@ -714,7 +682,7 @@ namespace OpenMetaverse.Voice
|
||||
/// </summary>
|
||||
void connector_OnConnectorCreateResponse(
|
||||
object sender,
|
||||
VoiceGateway.VoiceConnectorEventArgs e)
|
||||
VoiceConnectorEventArgs e)
|
||||
{
|
||||
Logger.Log("Voice daemon protocol started " + e.Message, Helpers.LogLevel.Info);
|
||||
|
||||
@@ -737,9 +705,9 @@ namespace OpenMetaverse.Voice
|
||||
|
||||
void connector_OnAccountLoginResponse(
|
||||
object sender,
|
||||
VoiceGateway.VoiceAccountEventArgs e)
|
||||
VoiceAccountEventArgs e)
|
||||
{
|
||||
Logger.Log("Account Login " + e.Message, Helpers.LogLevel.Info);
|
||||
Logger.Log($"Account Login {e.Message}", Helpers.LogLevel.Info);
|
||||
accountHandle = e.AccountHandle;
|
||||
ReportConnectionState(ConnectionState.AccountLogin);
|
||||
ParcelChanged();
|
||||
@@ -751,9 +719,9 @@ namespace OpenMetaverse.Voice
|
||||
/// </summary>
|
||||
void connector_OnAuxGetRenderDevicesResponse(
|
||||
object sender,
|
||||
VoiceGateway.VoiceDevicesEventArgs e)
|
||||
VoiceDevicesEventArgs e)
|
||||
{
|
||||
outputDevices = e.Devices;
|
||||
PlaybackDevices = e.Devices;
|
||||
currentPlaybackDevice = e.CurrentDevice;
|
||||
}
|
||||
|
||||
@@ -762,15 +730,15 @@ namespace OpenMetaverse.Voice
|
||||
/// </summary>
|
||||
void connector_OnAuxGetCaptureDevicesResponse(
|
||||
object sender,
|
||||
VoiceGateway.VoiceDevicesEventArgs e)
|
||||
VoiceDevicesEventArgs e)
|
||||
{
|
||||
inputDevices = e.Devices;
|
||||
CaptureDevices = e.Devices;
|
||||
currentCaptureDevice = e.CurrentDevice;
|
||||
}
|
||||
|
||||
public string CurrentCaptureDevice
|
||||
{
|
||||
get { return currentCaptureDevice; }
|
||||
get => currentCaptureDevice;
|
||||
set
|
||||
{
|
||||
currentCaptureDevice = value;
|
||||
@@ -779,7 +747,7 @@ namespace OpenMetaverse.Voice
|
||||
}
|
||||
public string PlaybackDevice
|
||||
{
|
||||
get { return currentPlaybackDevice; }
|
||||
get => currentPlaybackDevice;
|
||||
set
|
||||
{
|
||||
currentPlaybackDevice = value;
|
||||
@@ -789,33 +757,21 @@ namespace OpenMetaverse.Voice
|
||||
|
||||
public int MicLevel
|
||||
{
|
||||
set
|
||||
{
|
||||
ConnectorSetLocalMicVolume(connectionHandle, value);
|
||||
}
|
||||
set => ConnectorSetLocalMicVolume(connectionHandle, value);
|
||||
}
|
||||
public int SpkrLevel
|
||||
{
|
||||
set
|
||||
{
|
||||
ConnectorSetLocalSpeakerVolume(connectionHandle, value);
|
||||
}
|
||||
set => ConnectorSetLocalSpeakerVolume(connectionHandle, value);
|
||||
}
|
||||
|
||||
public bool MicMute
|
||||
{
|
||||
set
|
||||
{
|
||||
ConnectorMuteLocalMic(connectionHandle, value);
|
||||
}
|
||||
set => ConnectorMuteLocalMic(connectionHandle, value);
|
||||
}
|
||||
|
||||
public bool SpkrMute
|
||||
{
|
||||
set
|
||||
{
|
||||
ConnectorMuteLocalSpeaker(connectionHandle, value);
|
||||
}
|
||||
set => ConnectorMuteLocalSpeaker(connectionHandle, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -823,7 +779,7 @@ namespace OpenMetaverse.Voice
|
||||
/// </summary>
|
||||
public bool TestMode
|
||||
{
|
||||
get { return testing; }
|
||||
get => testing;
|
||||
set
|
||||
{
|
||||
testing = value;
|
||||
@@ -855,8 +811,8 @@ namespace OpenMetaverse.Voice
|
||||
internal void ParcelChanged()
|
||||
{
|
||||
// Get the capability for this parcel.
|
||||
Caps c = Client.Network.CurrentSim.Caps;
|
||||
System.Uri pCap = c.CapabilityURI("ParcelVoiceInfoRequest");
|
||||
var c = Client.Network.CurrentSim.Caps;
|
||||
var pCap = c.CapabilityURI("ParcelVoiceInfoRequest");
|
||||
|
||||
if (pCap == null)
|
||||
{
|
||||
@@ -875,7 +831,7 @@ namespace OpenMetaverse.Voice
|
||||
RequestParcelInfo(pCap);
|
||||
}
|
||||
|
||||
private OpenMetaverse.Http.CapsClient parcelCap;
|
||||
private CapsClient parcelCap;
|
||||
|
||||
/// <summary>
|
||||
/// Request info from a parcel capability Uri.
|
||||
@@ -886,13 +842,12 @@ namespace OpenMetaverse.Voice
|
||||
{
|
||||
Logger.Log("Requesting region voice info", Helpers.LogLevel.Info);
|
||||
|
||||
parcelCap = new OpenMetaverse.Http.CapsClient(cap, "RequestParcelInfo");
|
||||
parcelCap = new CapsClient(cap, "RequestParcelInfo");
|
||||
parcelCap.OnComplete +=
|
||||
pCap_OnComplete;
|
||||
OSD postData = new OSD();
|
||||
|
||||
currentParcelCap = cap;
|
||||
parcelCap.BeginGetResponse(postData, OSDFormat.Xml, 10000);
|
||||
parcelCap.PostRequestAsync(new OSD(), OSDFormat.Xml, 10000);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -901,12 +856,11 @@ namespace OpenMetaverse.Voice
|
||||
/// <param name="client"></param>
|
||||
/// <param name="result"></param>
|
||||
/// <param name="error"></param>
|
||||
void pCap_OnComplete(OpenMetaverse.Http.CapsClient client,
|
||||
OpenMetaverse.StructuredData.OSD result,
|
||||
void pCap_OnComplete(CapsClient client,
|
||||
OSD result,
|
||||
Exception error)
|
||||
{
|
||||
parcelCap.OnComplete -=
|
||||
new OpenMetaverse.Http.CapsClient.CompleteCallback(pCap_OnComplete);
|
||||
parcelCap.OnComplete -= pCap_OnComplete;
|
||||
parcelCap = null;
|
||||
|
||||
if (error != null)
|
||||
@@ -915,20 +869,21 @@ namespace OpenMetaverse.Voice
|
||||
return;
|
||||
}
|
||||
|
||||
OpenMetaverse.StructuredData.OSDMap pMap = result as OpenMetaverse.StructuredData.OSDMap;
|
||||
|
||||
regionName = pMap["region_name"].AsString();
|
||||
ReportConnectionState(ConnectionState.RegionCapAvailable);
|
||||
|
||||
if (pMap.ContainsKey("voice_credentials"))
|
||||
if (result is OSDMap pMap)
|
||||
{
|
||||
OpenMetaverse.StructuredData.OSDMap cred =
|
||||
pMap["voice_credentials"] as OpenMetaverse.StructuredData.OSDMap;
|
||||
regionName = pMap["region_name"].AsString();
|
||||
ReportConnectionState(ConnectionState.RegionCapAvailable);
|
||||
|
||||
if (cred.ContainsKey("channel_uri"))
|
||||
spatialUri = cred["channel_uri"].AsString();
|
||||
if (cred.ContainsKey("channel_credentials"))
|
||||
spatialCredentials = cred["channel_credentials"].AsString();
|
||||
if (pMap.ContainsKey("voice_credentials"))
|
||||
{
|
||||
var cred =
|
||||
pMap["voice_credentials"] as OSDMap;
|
||||
|
||||
if (cred.ContainsKey("channel_uri"))
|
||||
spatialUri = cred["channel_uri"].AsString();
|
||||
if (cred.ContainsKey("channel_credentials"))
|
||||
spatialCredentials = cred["channel_credentials"].AsString();
|
||||
}
|
||||
}
|
||||
|
||||
if (string.IsNullOrEmpty(spatialUri))
|
||||
@@ -940,7 +895,7 @@ namespace OpenMetaverse.Voice
|
||||
Logger.Log("Voice connecting for region " + regionName, Helpers.LogLevel.Info);
|
||||
|
||||
// STEP 5
|
||||
int reqId = SessionCreate(
|
||||
var reqId = SessionCreate(
|
||||
accountHandle,
|
||||
spatialUri, // uri
|
||||
"", // Channel name seems to be always null
|
||||
@@ -962,7 +917,7 @@ namespace OpenMetaverse.Voice
|
||||
internal void UpdatePosition(AgentManager self)
|
||||
{
|
||||
// Get position in Global coordinates
|
||||
Vector3d OMVpos = new Vector3d(self.GlobalPosition);
|
||||
var OMVpos = new Vector3d(self.GlobalPosition);
|
||||
|
||||
// Do not send trivial updates.
|
||||
if (OMVpos.ApproxEquals(oldPosition, 1.0))
|
||||
@@ -979,7 +934,7 @@ namespace OpenMetaverse.Voice
|
||||
|
||||
// Get azimuth from the facing Quaternion.
|
||||
// By definition, facing.W = Cos( angle/2 )
|
||||
double angle = 2.0 * Math.Acos(self.Movement.BodyRotation.W);
|
||||
var angle = 2.0 * Math.Acos(self.Movement.BodyRotation.W);
|
||||
|
||||
position.LeftOrientation = new Vector3d(-1.0, 0.0, 0.0);
|
||||
position.AtOrientation = new Vector3d((float)Math.Acos(angle), 0.0, -(float)Math.Asin(angle));
|
||||
@@ -1005,7 +960,7 @@ namespace OpenMetaverse.Voice
|
||||
private void PositionThreadBody()
|
||||
{
|
||||
var token = posTokenSource.Token;
|
||||
while (true)
|
||||
while (!token.IsCancellationRequested)
|
||||
{
|
||||
posRestart.WaitOne();
|
||||
token.ThrowIfCancellationRequested();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* Copyright (c) 2021-2022, Sjofn LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
@@ -26,10 +27,10 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Xml;
|
||||
using System.Xml.Serialization;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse.Voice
|
||||
namespace LibreMetaverse.Voice
|
||||
{
|
||||
public partial class VoiceGateway
|
||||
{
|
||||
@@ -424,16 +425,14 @@ namespace OpenMetaverse.Voice
|
||||
#region Connector Delegates
|
||||
public class VoiceConnectorEventArgs : VoiceResponseEventArgs
|
||||
{
|
||||
private readonly string m_Version;
|
||||
private readonly string m_ConnectorHandle;
|
||||
public string Version { get { return m_Version; } }
|
||||
public string Handle { get { return m_ConnectorHandle; } }
|
||||
public string Version { get; }
|
||||
public string Handle { get; }
|
||||
|
||||
public VoiceConnectorEventArgs(int rcode, int scode, string text, string version, string handle) :
|
||||
base(ResponseType.ConnectorCreate, rcode, scode, text)
|
||||
{
|
||||
m_Version = version;
|
||||
m_ConnectorHandle = handle;
|
||||
Version = version;
|
||||
Handle = handle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -443,16 +442,14 @@ namespace OpenMetaverse.Voice
|
||||
#region Aux Event Args
|
||||
public class VoiceDevicesEventArgs : VoiceResponseEventArgs
|
||||
{
|
||||
private readonly string m_CurrentDevice;
|
||||
private readonly List<string> m_Available;
|
||||
public string CurrentDevice { get { return m_CurrentDevice; } }
|
||||
public List<string> Devices { get { return m_Available; } }
|
||||
public string CurrentDevice { get; }
|
||||
public List<string> Devices { get; }
|
||||
|
||||
public VoiceDevicesEventArgs(ResponseType type, int rcode, int scode, string text, string current, List<string> avail) :
|
||||
base(type, rcode, scode, text)
|
||||
{
|
||||
m_CurrentDevice = current;
|
||||
m_Available = avail;
|
||||
CurrentDevice = current;
|
||||
Devices = avail;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -478,13 +475,12 @@ namespace OpenMetaverse.Voice
|
||||
#region Account Event Args
|
||||
public class VoiceAccountEventArgs : VoiceResponseEventArgs
|
||||
{
|
||||
private readonly string m_AccountHandle;
|
||||
public string AccountHandle { get { return m_AccountHandle; } }
|
||||
public string AccountHandle { get; }
|
||||
|
||||
public VoiceAccountEventArgs(int rcode, int scode, string text, string ahandle) :
|
||||
base(ResponseType.AccountLogin, rcode, scode, text)
|
||||
{
|
||||
this.m_AccountHandle = ahandle;
|
||||
this.AccountHandle = ahandle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -612,7 +608,7 @@ namespace OpenMetaverse.Voice
|
||||
public string RequestId;
|
||||
[XmlAttribute("action")]
|
||||
public string Action;
|
||||
public string ReturnCode;
|
||||
public int ReturnCode;
|
||||
public VoiceResponseResults Results;
|
||||
public VoiceInputXml InputXml;
|
||||
}
|
||||
@@ -630,7 +626,7 @@ namespace OpenMetaverse.Voice
|
||||
public class VoiceResponseResults
|
||||
{
|
||||
public string VersionID;
|
||||
public string StatusCode;
|
||||
public int StatusCode;
|
||||
public string StatusString;
|
||||
public string ConnectorHandle;
|
||||
public string AccountHandle;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* Copyright (c) 2021-2022, Sjofn LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
@@ -31,8 +32,9 @@ using System.Net.Sockets;
|
||||
using System.Diagnostics;
|
||||
using System.Threading;
|
||||
using System.Text;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse.Voice
|
||||
namespace LibreMetaverse.Voice
|
||||
{
|
||||
public partial class VoiceGateway
|
||||
{
|
||||
@@ -50,9 +52,9 @@ namespace OpenMetaverse.Voice
|
||||
public event DaemonDisconnectedCallback OnDaemonDisconnected;
|
||||
public event DaemonCouldntConnectCallback OnDaemonCouldntConnect;
|
||||
|
||||
public bool DaemonIsRunning { get { return daemonIsRunning; } }
|
||||
public bool DaemonIsConnected { get { return daemonIsConnected; } }
|
||||
public int RequestId { get { return requestId; } }
|
||||
public bool DaemonIsRunning => daemonIsRunning;
|
||||
public bool DaemonIsConnected => daemonIsConnected;
|
||||
public int RequestId => requestId;
|
||||
|
||||
protected Process daemonProcess;
|
||||
protected ManualResetEvent daemonLoopSignal = new ManualResetEvent(false);
|
||||
@@ -232,7 +234,7 @@ namespace OpenMetaverse.Voice
|
||||
if (daemonIsConnected)
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append(String.Format("<Request requestId=\"{0}\" action=\"{1}\"", requestId++, action));
|
||||
sb.Append($"<Request requestId=\"{requestId++}\" action=\"{action}\"");
|
||||
if (string.IsNullOrEmpty(requestXML))
|
||||
{
|
||||
sb.Append(" />");
|
||||
@@ -267,10 +269,9 @@ namespace OpenMetaverse.Voice
|
||||
|
||||
public static string MakeXML(string name, string text)
|
||||
{
|
||||
if (string.IsNullOrEmpty(text))
|
||||
return string.Format("<{0} />", name);
|
||||
else
|
||||
return string.Format("<{0}>{1}</{0}>", name, text);
|
||||
return string.IsNullOrEmpty(text)
|
||||
? string.Format("<{0} />", name)
|
||||
: string.Format("<{0}>{1}</{0}>", name, text);
|
||||
}
|
||||
|
||||
private void daemonPipe_OnReceiveLine(string line)
|
||||
@@ -299,26 +300,23 @@ namespace OpenMetaverse.Voice
|
||||
// These first responses carry useful information beyond simple status,
|
||||
// so they each have a specific Event.
|
||||
case "Connector.Create.1":
|
||||
if (OnConnectorCreateResponse != null)
|
||||
{
|
||||
OnConnectorCreateResponse(
|
||||
rsp.InputXml.Request,
|
||||
new VoiceConnectorEventArgs(
|
||||
int.Parse(rsp.ReturnCode),
|
||||
int.Parse(rsp.Results.StatusCode),
|
||||
rsp.Results.StatusString,
|
||||
rsp.Results.VersionID,
|
||||
rsp.Results.ConnectorHandle));
|
||||
}
|
||||
OnConnectorCreateResponse?.Invoke(
|
||||
rsp.InputXml.Request,
|
||||
new VoiceConnectorEventArgs(
|
||||
rsp.ReturnCode,
|
||||
rsp.Results.StatusCode,
|
||||
rsp.Results.StatusString,
|
||||
rsp.Results.VersionID,
|
||||
rsp.Results.ConnectorHandle));
|
||||
break;
|
||||
case "Aux.GetCaptureDevices.1":
|
||||
inputDevices = new List<string>();
|
||||
CaptureDevices = new List<string>();
|
||||
|
||||
if (rsp.Results.CaptureDevices.Count == 0 || rsp.Results.CurrentCaptureDevice == null)
|
||||
break;
|
||||
|
||||
foreach (CaptureDevice device in rsp.Results.CaptureDevices)
|
||||
inputDevices.Add(device.Device);
|
||||
CaptureDevices.Add(device.Device);
|
||||
currentCaptureDevice = rsp.Results.CurrentCaptureDevice.Device;
|
||||
|
||||
if (OnAuxGetCaptureDevicesResponse != null && rsp.Results.CaptureDevices.Count > 0)
|
||||
@@ -327,21 +325,21 @@ namespace OpenMetaverse.Voice
|
||||
rsp.InputXml.Request,
|
||||
new VoiceDevicesEventArgs(
|
||||
ResponseType.GetCaptureDevices,
|
||||
int.Parse(rsp.ReturnCode),
|
||||
int.Parse(rsp.Results.StatusCode),
|
||||
rsp.ReturnCode,
|
||||
rsp.Results.StatusCode,
|
||||
rsp.Results.StatusString,
|
||||
rsp.Results.CurrentCaptureDevice.Device,
|
||||
inputDevices));
|
||||
CaptureDevices));
|
||||
}
|
||||
break;
|
||||
case "Aux.GetRenderDevices.1":
|
||||
outputDevices = new List<string>();
|
||||
PlaybackDevices = new List<string>();
|
||||
|
||||
if (rsp.Results.RenderDevices.Count == 0 || rsp.Results.CurrentRenderDevice == null)
|
||||
break;
|
||||
|
||||
foreach (RenderDevice device in rsp.Results.RenderDevices)
|
||||
outputDevices.Add(device.Device);
|
||||
PlaybackDevices.Add(device.Device);
|
||||
|
||||
|
||||
currentPlaybackDevice = rsp.Results.CurrentRenderDevice.Device;
|
||||
@@ -352,11 +350,11 @@ namespace OpenMetaverse.Voice
|
||||
rsp.InputXml.Request,
|
||||
new VoiceDevicesEventArgs(
|
||||
ResponseType.GetCaptureDevices,
|
||||
int.Parse(rsp.ReturnCode),
|
||||
int.Parse(rsp.Results.StatusCode),
|
||||
rsp.ReturnCode,
|
||||
rsp.Results.StatusCode,
|
||||
rsp.Results.StatusString,
|
||||
rsp.Results.CurrentRenderDevice.Device,
|
||||
outputDevices));
|
||||
PlaybackDevices));
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -365,8 +363,8 @@ namespace OpenMetaverse.Voice
|
||||
{
|
||||
OnAccountLoginResponse(rsp.InputXml.Request,
|
||||
new VoiceAccountEventArgs(
|
||||
int.Parse(rsp.ReturnCode),
|
||||
int.Parse(rsp.Results.StatusCode),
|
||||
rsp.ReturnCode,
|
||||
rsp.Results.StatusCode,
|
||||
rsp.Results.StatusString,
|
||||
rsp.Results.AccountHandle));
|
||||
}
|
||||
@@ -378,8 +376,8 @@ namespace OpenMetaverse.Voice
|
||||
OnSessionCreateResponse(
|
||||
rsp.InputXml.Request,
|
||||
new VoiceSessionEventArgs(
|
||||
int.Parse(rsp.ReturnCode),
|
||||
int.Parse(rsp.Results.StatusCode),
|
||||
rsp.ReturnCode,
|
||||
rsp.Results.StatusCode,
|
||||
rsp.Results.StatusString,
|
||||
rsp.Results.SessionHandle));
|
||||
}
|
||||
@@ -456,8 +454,8 @@ namespace OpenMetaverse.Voice
|
||||
OnVoiceResponse(rsp.InputXml.Request,
|
||||
new VoiceResponseEventArgs(
|
||||
genericResponse,
|
||||
int.Parse(rsp.ReturnCode),
|
||||
int.Parse(rsp.Results.StatusCode),
|
||||
rsp.ReturnCode,
|
||||
rsp.Results.StatusCode,
|
||||
rsp.Results.StatusString));
|
||||
}
|
||||
}
|
||||
@@ -478,15 +476,12 @@ namespace OpenMetaverse.Voice
|
||||
{
|
||||
case "LoginStateChangeEvent":
|
||||
case "AccountLoginStateChangeEvent":
|
||||
if (OnAccountLoginStateChangeEvent != null)
|
||||
{
|
||||
OnAccountLoginStateChangeEvent(this,
|
||||
new AccountLoginStateChangeEventArgs(
|
||||
evt.AccountHandle,
|
||||
int.Parse(evt.StatusCode),
|
||||
evt.StatusString,
|
||||
(LoginState)int.Parse(evt.State)));
|
||||
}
|
||||
OnAccountLoginStateChangeEvent?.Invoke(this,
|
||||
new AccountLoginStateChangeEventArgs(
|
||||
evt.AccountHandle,
|
||||
int.Parse(evt.StatusCode),
|
||||
evt.StatusString,
|
||||
(LoginState)int.Parse(evt.State)));
|
||||
break;
|
||||
|
||||
case "SessionNewEvent":
|
||||
|
||||
@@ -0,0 +1,815 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* Copyright (c) 2021-2022, Sjofn LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* - 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.
|
||||
* - Neither the name of the openmetaverse.co 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR 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.Net.Sockets;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Xml;
|
||||
using OpenMetaverse.StructuredData;
|
||||
using OpenMetaverse;
|
||||
using OpenMetaverse.Http;
|
||||
using OpenMetaverse.Interfaces;
|
||||
using OpenMetaverse.Messages.Linden;
|
||||
|
||||
namespace LibreMetaverse.Voice
|
||||
{
|
||||
public enum VoiceStatus
|
||||
{
|
||||
StatusLoginRetry,
|
||||
StatusLoggedIn,
|
||||
StatusJoining,
|
||||
StatusJoined,
|
||||
StatusLeftChannel,
|
||||
BeginErrorStatus,
|
||||
ErrorChannelFull,
|
||||
ErrorChannelLocked,
|
||||
ErrorNotAvailable,
|
||||
ErrorUnknown
|
||||
}
|
||||
|
||||
public enum VoiceServiceType
|
||||
{
|
||||
/// <summary>Unknown voice service level</summary>
|
||||
Unknown,
|
||||
/// <summary>Spatialized local chat</summary>
|
||||
TypeA,
|
||||
/// <summary>Remote multi-party chat</summary>
|
||||
TypeB,
|
||||
/// <summary>One-to-one and small group chat</summary>
|
||||
TypeC
|
||||
}
|
||||
|
||||
public partial class VoiceManager
|
||||
{
|
||||
public const int VOICE_MAJOR_VERSION = 1;
|
||||
public const string DAEMON_ARGS = " -p tcp -h -c -ll ";
|
||||
public const int DAEMON_LOG_LEVEL = 1;
|
||||
public const int DAEMON_PORT = 44124;
|
||||
public const string VOICE_RELEASE_SERVER = "bhr.vivox.com";
|
||||
public const string VOICE_DEBUG_SERVER = "bhd.vivox.com";
|
||||
public const string REQUEST_TERMINATOR = "\n\n\n";
|
||||
|
||||
public delegate void LoginStateChangeCallback(int cookie, string accountHandle, int statusCode, string statusString, int state);
|
||||
public delegate void NewSessionCallback(int cookie, string accountHandle, string eventSessionHandle, int state, string nameString, string uriString);
|
||||
public delegate void SessionStateChangeCallback(int cookie, string uriString, int statusCode, string statusString, string eventSessionHandle, int state, bool isChannel, string nameString);
|
||||
public delegate void ParticipantStateChangeCallback(int cookie, string uriString, int statusCode, string statusString, int state, string nameString, string displayNameString, int participantType);
|
||||
public delegate void ParticipantPropertiesCallback(int cookie, string uriString, int statusCode, string statusString, bool isLocallyMuted, bool isModeratorMuted, bool isSpeaking, int volume, float energy);
|
||||
public delegate void AuxAudioPropertiesCallback(int cookie, float energy);
|
||||
public delegate void BasicActionCallback(int cookie, int statusCode, string statusString);
|
||||
public delegate void ConnectorCreatedCallback(int cookie, int statusCode, string statusString, string connectorHandle);
|
||||
public delegate void LoginCallback(int cookie, int statusCode, string statusString, string accountHandle);
|
||||
public delegate void SessionCreatedCallback(int cookie, int statusCode, string statusString, string sessionHandle);
|
||||
public delegate void DevicesCallback(int cookie, int statusCode, string statusString, string currentDevice);
|
||||
public delegate void ProvisionAccountCallback(string username, string password);
|
||||
public delegate void ParcelVoiceInfoCallback(string regionName, int localID, string channelURI);
|
||||
|
||||
public event LoginStateChangeCallback OnLoginStateChange;
|
||||
public event NewSessionCallback OnNewSession;
|
||||
public event SessionStateChangeCallback OnSessionStateChange;
|
||||
public event ParticipantStateChangeCallback OnParticipantStateChange;
|
||||
public event ParticipantPropertiesCallback OnParticipantProperties;
|
||||
public event AuxAudioPropertiesCallback OnAuxAudioProperties;
|
||||
public event ConnectorCreatedCallback OnConnectorCreated;
|
||||
public event LoginCallback OnLogin;
|
||||
public event SessionCreatedCallback OnSessionCreated;
|
||||
public event BasicActionCallback OnSessionConnected;
|
||||
public event BasicActionCallback OnAccountLogout;
|
||||
public event BasicActionCallback OnConnectorInitiateShutdown;
|
||||
public event BasicActionCallback OnAccountChannelGetList;
|
||||
public event BasicActionCallback OnSessionTerminated;
|
||||
public event DevicesCallback OnCaptureDevices;
|
||||
public event DevicesCallback OnRenderDevices;
|
||||
public event ProvisionAccountCallback OnProvisionAccount;
|
||||
public event ParcelVoiceInfoCallback OnParcelVoiceInfo;
|
||||
|
||||
public GridClient Client;
|
||||
public string VoiceServer = VOICE_RELEASE_SERVER;
|
||||
public bool Enabled;
|
||||
|
||||
protected Voice.TCPPipe _DaemonPipe;
|
||||
protected VoiceStatus _Status;
|
||||
protected int _CommandCookie = 0;
|
||||
protected string _TuningSoundFile = string.Empty;
|
||||
protected Dictionary<string, string> _ChannelMap = new Dictionary<string, string>();
|
||||
protected List<string> _CaptureDevices = new List<string>();
|
||||
protected List<string> _RenderDevices = new List<string>();
|
||||
|
||||
#region Response Processing Variables
|
||||
|
||||
private bool isEvent;
|
||||
private bool isChannel;
|
||||
private bool isLocallyMuted;
|
||||
private bool isModeratorMuted;
|
||||
private bool isSpeaking;
|
||||
private int cookie;
|
||||
//private int returnCode;
|
||||
private int statusCode;
|
||||
private int volume;
|
||||
private int state;
|
||||
private int participantType;
|
||||
private float energy;
|
||||
private string statusString = string.Empty;
|
||||
//private string uuidString = string.Empty;
|
||||
private string actionString = string.Empty;
|
||||
private string connectorHandle = string.Empty;
|
||||
private string accountHandle = string.Empty;
|
||||
private string sessionHandle = string.Empty;
|
||||
private string eventSessionHandle = string.Empty;
|
||||
private string eventTypeString = string.Empty;
|
||||
private string uriString = string.Empty;
|
||||
private string nameString = string.Empty;
|
||||
//private string audioMediaString = string.Empty;
|
||||
private string displayNameString = string.Empty;
|
||||
|
||||
#endregion Response Processing Variables
|
||||
|
||||
public VoiceManager(GridClient client)
|
||||
{
|
||||
Client = client;
|
||||
Client.Network.RegisterEventCallback("RequiredVoiceVersion", RequiredVoiceVersionEventHandler);
|
||||
|
||||
// Register callback handlers for the blocking functions
|
||||
RegisterCallbacks();
|
||||
|
||||
Enabled = true;
|
||||
}
|
||||
|
||||
public bool IsDaemonRunning()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool StartDaemon()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public void StopDaemon()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public bool ConnectToDaemon()
|
||||
{
|
||||
if (!Enabled) return false;
|
||||
|
||||
return ConnectToDaemon("127.0.0.1", DAEMON_PORT);
|
||||
}
|
||||
|
||||
public bool ConnectToDaemon(string address, int port)
|
||||
{
|
||||
if (!Enabled) return false;
|
||||
|
||||
_DaemonPipe = new Voice.TCPPipe();
|
||||
_DaemonPipe.OnDisconnected += _DaemonPipe_OnDisconnected;
|
||||
_DaemonPipe.OnReceiveLine += _DaemonPipe_OnReceiveLine;
|
||||
|
||||
var se = _DaemonPipe.Connect(address, port);
|
||||
|
||||
if (se == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
Console.WriteLine("Connection failed: " + se.Message);
|
||||
return false;
|
||||
}
|
||||
|
||||
public Dictionary<string, string> GetChannelMap()
|
||||
{
|
||||
return new Dictionary<string, string>(_ChannelMap);
|
||||
}
|
||||
|
||||
public List<string> CurrentCaptureDevices()
|
||||
{
|
||||
return new List<string>(_CaptureDevices);
|
||||
}
|
||||
|
||||
public List<string> CurrentRenderDevices()
|
||||
{
|
||||
return new List<string>(_RenderDevices);
|
||||
}
|
||||
|
||||
public string VoiceAccountFromUUID(UUID id)
|
||||
{
|
||||
var result = "x" + Convert.ToBase64String(id.GetBytes());
|
||||
return result.Replace('+', '-').Replace('/', '_');
|
||||
}
|
||||
|
||||
public UUID UUIDFromVoiceAccount(string accountName)
|
||||
{
|
||||
if (accountName.Length == 25 && accountName[0] == 'x' && accountName[23] == '=' && accountName[24] == '=')
|
||||
{
|
||||
accountName = accountName.Replace('/', '_').Replace('+', '-');
|
||||
var idBytes = Convert.FromBase64String(accountName);
|
||||
|
||||
return idBytes.Length == 16 ? new UUID(idBytes, 0) : UUID.Zero;
|
||||
}
|
||||
return UUID.Zero;
|
||||
}
|
||||
|
||||
public string SIPURIFromVoiceAccount(string account)
|
||||
{
|
||||
return $"sip:{account}@{VoiceServer}";
|
||||
}
|
||||
|
||||
public int RequestCaptureDevices()
|
||||
{
|
||||
if (_DaemonPipe.Connected)
|
||||
{
|
||||
_DaemonPipe.SendData(Encoding.ASCII.GetBytes(
|
||||
$"<Request requestId=\"{_CommandCookie++}\" action=\"Aux.GetCaptureDevices.1\"></Request>{REQUEST_TERMINATOR}"));
|
||||
|
||||
return _CommandCookie - 1;
|
||||
}
|
||||
Logger.Log("VoiceManager.RequestCaptureDevices() called when the daemon pipe is disconnected", Helpers.LogLevel.Error, Client);
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int RequestRenderDevices()
|
||||
{
|
||||
if (_DaemonPipe.Connected)
|
||||
{
|
||||
_DaemonPipe.SendData(Encoding.ASCII.GetBytes(
|
||||
$"<Request requestId=\"{_CommandCookie++}\" action=\"Aux.GetRenderDevices.1\"></Request>{REQUEST_TERMINATOR}"));
|
||||
|
||||
return _CommandCookie - 1;
|
||||
}
|
||||
Logger.Log("VoiceManager.RequestRenderDevices() called when the daemon pipe is disconnected", Helpers.LogLevel.Error, Client);
|
||||
return -1;
|
||||
}
|
||||
|
||||
public int RequestCreateConnector()
|
||||
{
|
||||
return RequestCreateConnector(VoiceServer);
|
||||
}
|
||||
|
||||
public int RequestCreateConnector(string voiceServer)
|
||||
{
|
||||
if (_DaemonPipe.Connected)
|
||||
{
|
||||
VoiceServer = voiceServer;
|
||||
|
||||
var accountServer = $"https://www.{VoiceServer}/api2/";
|
||||
var logPath = ".";
|
||||
|
||||
var request = new StringBuilder();
|
||||
request.Append($"<Request requestId=\"{_CommandCookie++}\" action=\"Connector.Create.1\">");
|
||||
request.Append("<ClientName>V2 SDK</ClientName>");
|
||||
request.Append($"<AccountManagementServer>{accountServer}</AccountManagementServer>");
|
||||
request.Append("<Logging>");
|
||||
request.Append("<Enabled>false</Enabled>");
|
||||
request.Append($"<Folder>{logPath}</Folder>");
|
||||
request.Append("<FileNamePrefix>vivox-gateway</FileNamePrefix>");
|
||||
request.Append("<FileNameSuffix>.log</FileNameSuffix>");
|
||||
request.Append("<LogLevel>0</LogLevel>");
|
||||
request.Append("</Logging>");
|
||||
request.Append("</Request>");
|
||||
request.Append(REQUEST_TERMINATOR);
|
||||
|
||||
_DaemonPipe.SendData(Encoding.ASCII.GetBytes(request.ToString()));
|
||||
|
||||
return _CommandCookie - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log("VoiceManager.CreateConnector() called when the daemon pipe is disconnected", Helpers.LogLevel.Error, Client);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
private bool RequestVoiceInternal(string me, CapsClient.CompleteCallback callback, string capsName)
|
||||
{
|
||||
if (Enabled && Client.Network.Connected)
|
||||
{
|
||||
if (Client.Network.CurrentSim != null && Client.Network.CurrentSim.Caps != null)
|
||||
{
|
||||
var url = Client.Network.CurrentSim.Caps.CapabilityURI(capsName);
|
||||
|
||||
if (url != null)
|
||||
{
|
||||
var request = new CapsClient(url);
|
||||
var body = new OSDMap();
|
||||
request.OnComplete += callback;
|
||||
request.PostRequestAsync(body, OSDFormat.Xml, Client.Settings.CAPS_TIMEOUT);
|
||||
|
||||
return true;
|
||||
}
|
||||
Logger.Log("VoiceManager." + me + "(): " + capsName + " capability is missing",
|
||||
Helpers.LogLevel.Info, Client);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Logger.Log("VoiceManager.RequestVoiceInternal(): Voice system is currently disabled",
|
||||
Helpers.LogLevel.Info, Client);
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
public bool RequestProvisionAccount()
|
||||
{
|
||||
return RequestVoiceInternal("RequestProvisionAccount", ProvisionCapsResponse, "ProvisionVoiceAccountRequest");
|
||||
}
|
||||
|
||||
public bool RequestParcelVoiceInfo()
|
||||
{
|
||||
return RequestVoiceInternal("RequestParcelVoiceInfo", ParcelVoiceInfoResponse, "ParcelVoiceInfoRequest");
|
||||
}
|
||||
|
||||
public int RequestLogin(string accountName, string password, string connectorHandle)
|
||||
{
|
||||
if (_DaemonPipe.Connected)
|
||||
{
|
||||
var request = new StringBuilder();
|
||||
request.Append($"<Request requestId=\"{_CommandCookie++}\" action=\"Account.Login.1\">");
|
||||
request.Append($"<ConnectorHandle>{connectorHandle}</ConnectorHandle>");
|
||||
request.Append($"<AccountName>{accountName}</AccountName>");
|
||||
request.Append($"<AccountPassword>{password}</AccountPassword>");
|
||||
request.Append("<AudioSessionAnswerMode>VerifyAnswer</AudioSessionAnswerMode>");
|
||||
request.Append("<AccountURI />");
|
||||
request.Append("<ParticipantPropertyFrequency>10</ParticipantPropertyFrequency>");
|
||||
request.Append("<EnableBuddiesAndPresence>false</EnableBuddiesAndPresence>");
|
||||
request.Append("</Request>");
|
||||
request.Append(REQUEST_TERMINATOR);
|
||||
|
||||
_DaemonPipe.SendData(Encoding.ASCII.GetBytes(request.ToString()));
|
||||
|
||||
return _CommandCookie - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log("VoiceManager.Login() called when the daemon pipe is disconnected", Helpers.LogLevel.Error, Client);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public int RequestSetRenderDevice(string deviceName)
|
||||
{
|
||||
if (_DaemonPipe.Connected)
|
||||
{
|
||||
_DaemonPipe.SendData(Encoding.ASCII.GetBytes(
|
||||
$"<Request requestId=\"{_CommandCookie}\" action=\"Aux.SetRenderDevice.1\"><RenderDeviceSpecifier>{deviceName}</RenderDeviceSpecifier></Request>{REQUEST_TERMINATOR}"));
|
||||
|
||||
return _CommandCookie - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log("VoiceManager.RequestSetRenderDevice() called when the daemon pipe is disconnected", Helpers.LogLevel.Error, Client);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public int RequestStartTuningMode(int duration)
|
||||
{
|
||||
if (_DaemonPipe.Connected)
|
||||
{
|
||||
_DaemonPipe.SendData(Encoding.ASCII.GetBytes(
|
||||
$"<Request requestId=\"{_CommandCookie}\" action=\"Aux.CaptureAudioStart.1\"><Duration>{duration}</Duration></Request>{REQUEST_TERMINATOR}"));
|
||||
|
||||
return _CommandCookie - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log("VoiceManager.RequestStartTuningMode() called when the daemon pipe is disconnected", Helpers.LogLevel.Error, Client);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public int RequestStopTuningMode()
|
||||
{
|
||||
if (_DaemonPipe.Connected)
|
||||
{
|
||||
_DaemonPipe.SendData(Encoding.ASCII.GetBytes(
|
||||
$"<Request requestId=\"{_CommandCookie}\" action=\"Aux.CaptureAudioStop.1\"></Request>{REQUEST_TERMINATOR}"));
|
||||
|
||||
return _CommandCookie - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log("VoiceManager.RequestStopTuningMode() called when the daemon pipe is disconnected", Helpers.LogLevel.Error, Client);
|
||||
return _CommandCookie - 1;
|
||||
}
|
||||
}
|
||||
|
||||
public int RequestSetSpeakerVolume(int volume_)
|
||||
{
|
||||
if (volume_ < 0 || volume_ > 100)
|
||||
throw new ArgumentException("volume must be between 0 and 100", nameof(volume_));
|
||||
|
||||
if (_DaemonPipe.Connected)
|
||||
{
|
||||
_DaemonPipe.SendData(Encoding.ASCII.GetBytes(
|
||||
$"<Request requestId=\"{_CommandCookie}\" action=\"Aux.SetSpeakerLevel.1\"><Level>{volume_}</Level></Request>{REQUEST_TERMINATOR}"));
|
||||
|
||||
return _CommandCookie - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log("VoiceManager.RequestSetSpeakerVolume() called when the daemon pipe is disconnected", Helpers.LogLevel.Error, Client);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public int RequestSetCaptureVolume(int volume_)
|
||||
{
|
||||
if (volume_ < 0 || volume_ > 100)
|
||||
throw new ArgumentException("volume must be between 0 and 100", nameof(volume_));
|
||||
|
||||
if (_DaemonPipe.Connected)
|
||||
{
|
||||
_DaemonPipe.SendData(Encoding.ASCII.GetBytes(
|
||||
$"<Request requestId=\"{_CommandCookie}\" action=\"Aux.SetMicLevel.1\"><Level>{volume_}</Level></Request>{REQUEST_TERMINATOR}"));
|
||||
|
||||
return _CommandCookie - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log("VoiceManager.RequestSetCaptureVolume() called when the daemon pipe is disconnected", Helpers.LogLevel.Error, Client);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Does not appear to be working
|
||||
/// </summary>
|
||||
/// <param name="fileName"></param>
|
||||
/// <param name="loop"></param>
|
||||
public int RequestRenderAudioStart(string fileName, bool loop)
|
||||
{
|
||||
if (_DaemonPipe.Connected)
|
||||
{
|
||||
_TuningSoundFile = fileName;
|
||||
|
||||
_DaemonPipe.SendData(Encoding.ASCII.GetBytes(
|
||||
$"<Request requestId=\"{_CommandCookie++}\" action=\"Aux.RenderAudioStart.1\"><SoundFilePath>{_TuningSoundFile}</SoundFilePath><Loop>{(loop ? "1" : "0")}</Loop></Request>{REQUEST_TERMINATOR}"));
|
||||
|
||||
return _CommandCookie - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log("VoiceManager.RequestRenderAudioStart() called when the daemon pipe is disconnected", Helpers.LogLevel.Error, Client);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public int RequestRenderAudioStop()
|
||||
{
|
||||
if (_DaemonPipe.Connected)
|
||||
{
|
||||
_DaemonPipe.SendData(Encoding.ASCII.GetBytes(
|
||||
$"<Request requestId=\"{_CommandCookie++}\" action=\"Aux.RenderAudioStop.1\"><SoundFilePath>{_TuningSoundFile}</SoundFilePath></Request>{REQUEST_TERMINATOR}"));
|
||||
|
||||
return _CommandCookie - 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.Log("VoiceManager.RequestRenderAudioStop() called when the daemon pipe is disconnected", Helpers.LogLevel.Error, Client);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
#region Callbacks
|
||||
|
||||
private void RequiredVoiceVersionEventHandler(string capsKey, IMessage message, Simulator simulator)
|
||||
{
|
||||
var msg = (RequiredVoiceVersionMessage)message;
|
||||
|
||||
if (VOICE_MAJOR_VERSION != msg.MajorVersion)
|
||||
{
|
||||
Logger.Log(
|
||||
$"Voice version mismatch! Got {msg.MajorVersion}, expecting {VOICE_MAJOR_VERSION}. Disabling the voice manager", Helpers.LogLevel.Error, Client);
|
||||
Enabled = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.DebugLog("Voice version " + msg.MajorVersion + " verified", Client);
|
||||
}
|
||||
}
|
||||
|
||||
private void ProvisionCapsResponse(CapsClient client, OSD response, Exception error)
|
||||
{
|
||||
if (!(response is OSDMap respMap)) return;
|
||||
|
||||
if (OnProvisionAccount == null) return;
|
||||
try { OnProvisionAccount(respMap["username"].AsString(), respMap["password"].AsString()); }
|
||||
catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); }
|
||||
}
|
||||
|
||||
private void ParcelVoiceInfoResponse(CapsClient client, OSD response, Exception error)
|
||||
{
|
||||
if (!(response is OSDMap respMap)) return;
|
||||
|
||||
var regionName = respMap["region_name"].AsString();
|
||||
var localID = respMap["parcel_local_id"].AsInteger();
|
||||
|
||||
string channelURI = null;
|
||||
if (respMap["voice_credentials"] is OSDMap)
|
||||
{
|
||||
var creds = (OSDMap)respMap["voice_credentials"];
|
||||
channelURI = creds["channel_uri"].AsString();
|
||||
}
|
||||
|
||||
OnParcelVoiceInfo?.Invoke(regionName, localID, channelURI);
|
||||
}
|
||||
|
||||
private static void _DaemonPipe_OnDisconnected(SocketException se)
|
||||
{
|
||||
if (se != null) Console.WriteLine("Disconnected! " + se.Message);
|
||||
else Console.WriteLine("Disconnected!");
|
||||
}
|
||||
|
||||
private void _DaemonPipe_OnReceiveLine(string line)
|
||||
{
|
||||
var reader = new XmlTextReader(new StringReader(line));
|
||||
|
||||
while (reader.Read())
|
||||
{
|
||||
switch (reader.NodeType)
|
||||
{
|
||||
case XmlNodeType.Element:
|
||||
{
|
||||
if (reader.Depth == 0)
|
||||
{
|
||||
isEvent = (reader.Name == "Event");
|
||||
|
||||
if (isEvent || reader.Name == "Response")
|
||||
{
|
||||
for (var i = 0; i < reader.AttributeCount; i++)
|
||||
{
|
||||
reader.MoveToAttribute(i);
|
||||
|
||||
if (reader.Name == "action")
|
||||
actionString = reader.Value;
|
||||
else if (reader.Name == "type")
|
||||
eventTypeString = reader.Value;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (reader.Name)
|
||||
{
|
||||
case "InputXml":
|
||||
cookie = -1;
|
||||
|
||||
// Parse through here to get the cookie value
|
||||
reader.Read();
|
||||
if (reader.Name == "Request")
|
||||
{
|
||||
for (var i = 0; i < reader.AttributeCount; i++)
|
||||
{
|
||||
reader.MoveToAttribute(i);
|
||||
|
||||
if (reader.Name != "requestId") continue;
|
||||
int.TryParse(reader.Value, out cookie);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (cookie == -1)
|
||||
{
|
||||
Logger.Log(
|
||||
"VoiceManager._DaemonPipe_OnReceiveLine(): Failed to parse InputXml for the cookie",
|
||||
Helpers.LogLevel.Warning, Client);
|
||||
}
|
||||
break;
|
||||
case "CaptureDevices":
|
||||
_CaptureDevices.Clear();
|
||||
break;
|
||||
case "RenderDevices":
|
||||
_RenderDevices.Clear();
|
||||
break;
|
||||
// case "ReturnCode":
|
||||
// returnCode = reader.ReadElementContentAsInt();
|
||||
// break;
|
||||
case "StatusCode":
|
||||
statusCode = reader.ReadElementContentAsInt();
|
||||
break;
|
||||
case "StatusString":
|
||||
statusString = reader.ReadElementContentAsString();
|
||||
break;
|
||||
case "State":
|
||||
state = reader.ReadElementContentAsInt();
|
||||
break;
|
||||
case "ConnectorHandle":
|
||||
connectorHandle = reader.ReadElementContentAsString();
|
||||
break;
|
||||
case "AccountHandle":
|
||||
accountHandle = reader.ReadElementContentAsString();
|
||||
break;
|
||||
case "SessionHandle":
|
||||
sessionHandle = reader.ReadElementContentAsString();
|
||||
break;
|
||||
case "URI":
|
||||
uriString = reader.ReadElementContentAsString();
|
||||
break;
|
||||
case "IsChannel":
|
||||
isChannel = reader.ReadElementContentAsBoolean();
|
||||
break;
|
||||
case "Name":
|
||||
nameString = reader.ReadElementContentAsString();
|
||||
break;
|
||||
// case "AudioMedia":
|
||||
// audioMediaString = reader.ReadElementContentAsString();
|
||||
// break;
|
||||
case "ChannelName":
|
||||
nameString = reader.ReadElementContentAsString();
|
||||
break;
|
||||
case "ParticipantURI":
|
||||
uriString = reader.ReadElementContentAsString();
|
||||
break;
|
||||
case "DisplayName":
|
||||
displayNameString = reader.ReadElementContentAsString();
|
||||
break;
|
||||
case "AccountName":
|
||||
nameString = reader.ReadElementContentAsString();
|
||||
break;
|
||||
case "ParticipantType":
|
||||
participantType = reader.ReadElementContentAsInt();
|
||||
break;
|
||||
case "IsLocallyMuted":
|
||||
isLocallyMuted = reader.ReadElementContentAsBoolean();
|
||||
break;
|
||||
case "IsModeratorMuted":
|
||||
isModeratorMuted = reader.ReadElementContentAsBoolean();
|
||||
break;
|
||||
case "IsSpeaking":
|
||||
isSpeaking = reader.ReadElementContentAsBoolean();
|
||||
break;
|
||||
case "Volume":
|
||||
volume = reader.ReadElementContentAsInt();
|
||||
break;
|
||||
case "Energy":
|
||||
energy = reader.ReadElementContentAsFloat();
|
||||
break;
|
||||
case "MicEnergy":
|
||||
energy = reader.ReadElementContentAsFloat();
|
||||
break;
|
||||
case "ChannelURI":
|
||||
uriString = reader.ReadElementContentAsString();
|
||||
break;
|
||||
case "ChannelListResult":
|
||||
_ChannelMap[nameString] = uriString;
|
||||
break;
|
||||
case "CaptureDevice":
|
||||
reader.Read();
|
||||
_CaptureDevices.Add(reader.ReadElementContentAsString());
|
||||
break;
|
||||
case "CurrentCaptureDevice":
|
||||
reader.Read();
|
||||
nameString = reader.ReadElementContentAsString();
|
||||
break;
|
||||
case "RenderDevice":
|
||||
reader.Read();
|
||||
_RenderDevices.Add(reader.ReadElementContentAsString());
|
||||
break;
|
||||
case "CurrentRenderDevice":
|
||||
reader.Read();
|
||||
nameString = reader.ReadElementContentAsString();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case XmlNodeType.EndElement:
|
||||
if (reader.Depth == 0)
|
||||
ProcessEvent();
|
||||
break;
|
||||
case XmlNodeType.None:
|
||||
break;
|
||||
case XmlNodeType.Attribute:
|
||||
break;
|
||||
case XmlNodeType.Text:
|
||||
break;
|
||||
case XmlNodeType.CDATA:
|
||||
break;
|
||||
case XmlNodeType.EntityReference:
|
||||
break;
|
||||
case XmlNodeType.Entity:
|
||||
break;
|
||||
case XmlNodeType.ProcessingInstruction:
|
||||
break;
|
||||
case XmlNodeType.Comment:
|
||||
break;
|
||||
case XmlNodeType.Document:
|
||||
break;
|
||||
case XmlNodeType.DocumentType:
|
||||
break;
|
||||
case XmlNodeType.DocumentFragment:
|
||||
break;
|
||||
case XmlNodeType.Notation:
|
||||
break;
|
||||
case XmlNodeType.Whitespace:
|
||||
break;
|
||||
case XmlNodeType.SignificantWhitespace:
|
||||
break;
|
||||
case XmlNodeType.EndEntity:
|
||||
break;
|
||||
case XmlNodeType.XmlDeclaration:
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
if (isEvent)
|
||||
{
|
||||
}
|
||||
|
||||
//Client.DebugLog("VOICE: " + line);
|
||||
}
|
||||
|
||||
private void ProcessEvent()
|
||||
{
|
||||
if (isEvent)
|
||||
{
|
||||
switch (eventTypeString)
|
||||
{
|
||||
case "LoginStateChangeEvent":
|
||||
OnLoginStateChange?.Invoke(cookie, accountHandle, statusCode, statusString, state);
|
||||
break;
|
||||
case "SessionNewEvent":
|
||||
OnNewSession?.Invoke(cookie, accountHandle, eventSessionHandle, state, nameString, uriString);
|
||||
break;
|
||||
case "SessionStateChangeEvent":
|
||||
OnSessionStateChange?.Invoke(cookie, uriString, statusCode, statusString, eventSessionHandle, state, isChannel, nameString);
|
||||
break;
|
||||
case "ParticipantStateChangeEvent":
|
||||
OnParticipantStateChange?.Invoke(cookie, uriString, statusCode, statusString, state, nameString, displayNameString, participantType);
|
||||
break;
|
||||
case "ParticipantPropertiesEvent":
|
||||
OnParticipantProperties?.Invoke(cookie, uriString, statusCode, statusString, isLocallyMuted, isModeratorMuted, isSpeaking, volume, energy);
|
||||
break;
|
||||
case "AuxAudioPropertiesEvent":
|
||||
OnAuxAudioProperties?.Invoke(cookie, energy);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (actionString)
|
||||
{
|
||||
case "Connector.Create.1":
|
||||
OnConnectorCreated?.Invoke(cookie, statusCode, statusString, connectorHandle);
|
||||
break;
|
||||
case "Account.Login.1":
|
||||
OnLogin?.Invoke(cookie, statusCode, statusString, accountHandle);
|
||||
break;
|
||||
case "Session.Create.1":
|
||||
OnSessionCreated?.Invoke(cookie, statusCode, statusString, sessionHandle);
|
||||
break;
|
||||
case "Session.Connect.1":
|
||||
OnSessionConnected?.Invoke(cookie, statusCode, statusString);
|
||||
break;
|
||||
case "Session.Terminate.1":
|
||||
OnSessionTerminated?.Invoke(cookie, statusCode, statusString);
|
||||
break;
|
||||
case "Account.Logout.1":
|
||||
OnAccountLogout?.Invoke(cookie, statusCode, statusString);
|
||||
break;
|
||||
case "Connector.InitiateShutdown.1":
|
||||
OnConnectorInitiateShutdown?.Invoke(cookie, statusCode, statusString);
|
||||
break;
|
||||
case "Account.ChannelGetList.1":
|
||||
OnAccountChannelGetList?.Invoke(cookie, statusCode, statusString);
|
||||
break;
|
||||
case "Aux.GetCaptureDevices.1":
|
||||
OnCaptureDevices?.Invoke(cookie, statusCode, statusString, nameString);
|
||||
break;
|
||||
case "Aux.GetRenderDevices.1":
|
||||
OnRenderDevices?.Invoke(cookie, statusCode, statusString, nameString);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endregion Callbacks
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 41f5cff506a7762458aa0fa06a3a635b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* Copyright (c) 2021-2022, Sjofn LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* - 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.
|
||||
* - Neither the name of the openmetaverse.co 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 COPYRIGHT HOLDERS AND CONTRIBUTORS "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 COPYRIGHT OWNER OR 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.Collections.Generic;
|
||||
using System.Threading;
|
||||
|
||||
namespace LibreMetaverse.Voice
|
||||
{
|
||||
public partial class VoiceManager
|
||||
{
|
||||
/// <summary>Amount of time to wait for the voice daemon to respond.
|
||||
/// The value needs to stay relatively high because some of the calls
|
||||
/// require the voice daemon to make remote queries before replying</summary>
|
||||
public int BlockingTimeout = 30 * 1000;
|
||||
|
||||
protected Dictionary<int, AutoResetEvent> Events = new Dictionary<int, AutoResetEvent>();
|
||||
|
||||
public List<string> CaptureDevices()
|
||||
{
|
||||
var evt = new AutoResetEvent(false);
|
||||
Events[_CommandCookie] = evt;
|
||||
|
||||
if (RequestCaptureDevices() == -1)
|
||||
{
|
||||
Events.Remove(_CommandCookie);
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
return evt.WaitOne(BlockingTimeout, false) ? CurrentCaptureDevices() : new List<string>();
|
||||
}
|
||||
|
||||
public List<string> RenderDevices()
|
||||
{
|
||||
var evt = new AutoResetEvent(false);
|
||||
Events[_CommandCookie] = evt;
|
||||
|
||||
if (RequestRenderDevices() == -1)
|
||||
{
|
||||
Events.Remove(_CommandCookie);
|
||||
return new List<string>();
|
||||
}
|
||||
|
||||
return evt.WaitOne(BlockingTimeout, false) ? CurrentRenderDevices() : new List<string>();
|
||||
}
|
||||
|
||||
public string CreateConnector(out int status)
|
||||
{
|
||||
status = 0;
|
||||
|
||||
var evt = new AutoResetEvent(false);
|
||||
Events[_CommandCookie] = evt;
|
||||
|
||||
if (RequestCreateConnector() == -1)
|
||||
{
|
||||
Events.Remove(_CommandCookie);
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var success = evt.WaitOne(BlockingTimeout, false);
|
||||
status = statusCode;
|
||||
|
||||
return success && statusCode == 0 ? connectorHandle : string.Empty;
|
||||
}
|
||||
|
||||
public string Login(string accountName, string password, string connectorHandle, out int status)
|
||||
{
|
||||
status = 0;
|
||||
|
||||
var evt = new AutoResetEvent(false);
|
||||
Events[_CommandCookie] = evt;
|
||||
|
||||
if (RequestLogin(accountName, password, connectorHandle) == -1)
|
||||
{
|
||||
Events.Remove(_CommandCookie);
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
var success = evt.WaitOne(BlockingTimeout, false);
|
||||
status = statusCode;
|
||||
|
||||
return success && statusCode == 0 ? accountHandle : string.Empty;
|
||||
}
|
||||
|
||||
protected void RegisterCallbacks()
|
||||
{
|
||||
OnCaptureDevices += VoiceManager_OnCaptureDevices;
|
||||
OnRenderDevices += VoiceManager_OnRenderDevices;
|
||||
OnConnectorCreated += VoiceManager_OnConnectorCreated;
|
||||
OnLogin += VoiceManager_OnLogin;
|
||||
}
|
||||
|
||||
#region Callbacks
|
||||
|
||||
private void VoiceManager_OnCaptureDevices(int cookie, int statusCode, string statusString, string currentDevice)
|
||||
{
|
||||
if (Events.ContainsKey(cookie))
|
||||
Events[cookie].Set();
|
||||
}
|
||||
|
||||
private void VoiceManager_OnRenderDevices(int cookie, int statusCode, string statusString, string currentDevice)
|
||||
{
|
||||
if (Events.ContainsKey(cookie))
|
||||
Events[cookie].Set();
|
||||
}
|
||||
|
||||
private void VoiceManager_OnConnectorCreated(int cookie, int statusCode, string statusString, string connectorHandle)
|
||||
{
|
||||
if (Events.ContainsKey(cookie))
|
||||
Events[cookie].Set();
|
||||
}
|
||||
|
||||
private void VoiceManager_OnLogin(int cookie, int statusCode, string statusString, string accountHandle)
|
||||
{
|
||||
if (Events.ContainsKey(cookie))
|
||||
Events[cookie].Set();
|
||||
}
|
||||
|
||||
#endregion Callbacks
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9b80357650347d34e93d925b1fb0941d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* Copyright (c) 2021-2022, Sjofn LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
@@ -25,34 +26,29 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse.Voice
|
||||
namespace LibreMetaverse.Voice
|
||||
{
|
||||
public class VoiceParticipant
|
||||
{
|
||||
private string Sip;
|
||||
private string AvatarName { get; set; }
|
||||
private UUID id;
|
||||
|
||||
private bool muted;
|
||||
private int volume;
|
||||
private VoiceSession session;
|
||||
private float energy;
|
||||
private readonly VoiceSession session;
|
||||
|
||||
public float Energy { get { return energy; } }
|
||||
private bool speaking;
|
||||
public bool IsSpeaking { get { return speaking; } }
|
||||
public string URI { get { return Sip; } }
|
||||
public UUID ID { get { return id; } }
|
||||
public float Energy { get; private set; }
|
||||
public bool IsSpeaking { get; private set; }
|
||||
public string URI { get; }
|
||||
public UUID ID { get; }
|
||||
|
||||
public VoiceParticipant(string puri, VoiceSession s)
|
||||
{
|
||||
id = IDFromName(puri);
|
||||
Sip = puri;
|
||||
ID = IDFromName(puri);
|
||||
URI = puri;
|
||||
session = s;
|
||||
}
|
||||
|
||||
@@ -92,7 +88,7 @@ namespace OpenMetaverse.Voice
|
||||
|
||||
private static string Encode64(string str)
|
||||
{
|
||||
byte[] encbuff = System.Text.Encoding.UTF8.GetBytes(str);
|
||||
byte[] encbuff = Encoding.UTF8.GetBytes(str);
|
||||
return Convert.ToBase64String(encbuff);
|
||||
}
|
||||
private static byte[] Decode64(string str)
|
||||
@@ -116,43 +112,43 @@ namespace OpenMetaverse.Voice
|
||||
|
||||
public string Name
|
||||
{
|
||||
get { return AvatarName; }
|
||||
set { AvatarName = value; }
|
||||
get => AvatarName;
|
||||
set => AvatarName = value;
|
||||
}
|
||||
|
||||
public bool IsMuted
|
||||
{
|
||||
get { return muted; }
|
||||
get => muted;
|
||||
set
|
||||
{
|
||||
muted = value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append(OpenMetaverse.Voice.VoiceGateway.MakeXML("SessionHandle", session.Handle));
|
||||
sb.Append(OpenMetaverse.Voice.VoiceGateway.MakeXML("ParticipantURI", Sip));
|
||||
sb.Append(OpenMetaverse.Voice.VoiceGateway.MakeXML("Mute", muted ? "1" : "0"));
|
||||
sb.Append(VoiceGateway.MakeXML("SessionHandle", session.Handle));
|
||||
sb.Append(VoiceGateway.MakeXML("ParticipantURI", URI));
|
||||
sb.Append(VoiceGateway.MakeXML("Mute", muted ? "1" : "0"));
|
||||
session.Connector.Request("Session.SetParticipantMuteForMe.1", sb.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
public int Volume
|
||||
{
|
||||
get { return volume; }
|
||||
get => volume;
|
||||
set
|
||||
{
|
||||
volume = value;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.Append(OpenMetaverse.Voice.VoiceGateway.MakeXML("SessionHandle", session.Handle));
|
||||
sb.Append(OpenMetaverse.Voice.VoiceGateway.MakeXML("ParticipantURI", Sip));
|
||||
sb.Append(OpenMetaverse.Voice.VoiceGateway.MakeXML("Volume", volume.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("SessionHandle", session.Handle));
|
||||
sb.Append(VoiceGateway.MakeXML("ParticipantURI", URI));
|
||||
sb.Append(VoiceGateway.MakeXML("Volume", volume.ToString()));
|
||||
session.Connector.Request("Session.SetParticipantVolumeForMe.1", sb.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
internal void SetProperties(bool speak, bool mute, float en)
|
||||
{
|
||||
speaking = speak;
|
||||
IsSpeaking = speak;
|
||||
muted = mute;
|
||||
energy = en;
|
||||
Energy = en;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2016, openmetaverse.co
|
||||
* Copyright (c) 2021-2022, Sjofn LLC.
|
||||
* All rights reserved.
|
||||
*
|
||||
* - Redistribution and use in source and binary forms, with or without
|
||||
@@ -24,27 +25,23 @@
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.Text;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse.Voice
|
||||
namespace LibreMetaverse.Voice
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a single Voice Session to the Vivox service.
|
||||
/// </summary>
|
||||
public class VoiceSession
|
||||
{
|
||||
private string m_Handle;
|
||||
private static Dictionary<string, VoiceParticipant> knownParticipants;
|
||||
public string RegionName;
|
||||
private bool m_spatial;
|
||||
public bool IsSpatial { get { return m_spatial; } }
|
||||
private VoiceGateway connector;
|
||||
public bool IsSpatial { get; }
|
||||
|
||||
public VoiceGateway Connector { get { return connector; } }
|
||||
public string Handle { get { return m_Handle; } }
|
||||
public VoiceGateway Connector { get; }
|
||||
public string Handle { get; }
|
||||
|
||||
public event System.EventHandler OnParticipantAdded;
|
||||
public event System.EventHandler OnParticipantUpdate;
|
||||
@@ -52,10 +49,10 @@ namespace OpenMetaverse.Voice
|
||||
|
||||
public VoiceSession(VoiceGateway conn, string handle)
|
||||
{
|
||||
m_Handle = handle;
|
||||
connector = conn;
|
||||
Handle = handle;
|
||||
Connector = conn;
|
||||
|
||||
m_spatial = true;
|
||||
IsSpatial = true;
|
||||
knownParticipants = new Dictionary<string, VoiceParticipant>();
|
||||
}
|
||||
|
||||
@@ -150,7 +147,7 @@ namespace OpenMetaverse.Voice
|
||||
|
||||
public void Set3DPosition(VoicePosition SpeakerPosition, VoicePosition ListenerPosition)
|
||||
{
|
||||
connector.SessionSet3DPosition(m_Handle, SpeakerPosition, ListenerPosition);
|
||||
Connector.SessionSet3DPosition(Handle, SpeakerPosition, ListenerPosition);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,56 +260,56 @@ namespace OpenMetaverse.Voice
|
||||
sb.Append(VoiceGateway.MakeXML("SessionHandle", SessionHandle));
|
||||
sb.Append("<SpeakerPosition>");
|
||||
sb.Append("<Position>");
|
||||
sb.Append(VoiceGateway.MakeXML("X", SpeakerPosition.Position.X.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("Y", SpeakerPosition.Position.Y.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("Z", SpeakerPosition.Position.Z.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("X", SpeakerPosition.Position.X.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append(VoiceGateway.MakeXML("Y", SpeakerPosition.Position.Y.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append(VoiceGateway.MakeXML("Z", SpeakerPosition.Position.Z.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append("</Position>");
|
||||
sb.Append("<Velocity>");
|
||||
sb.Append(VoiceGateway.MakeXML("X", SpeakerPosition.Velocity.X.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("Y", SpeakerPosition.Velocity.Y.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("Z", SpeakerPosition.Velocity.Z.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("X", SpeakerPosition.Velocity.X.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append(VoiceGateway.MakeXML("Y", SpeakerPosition.Velocity.Y.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append(VoiceGateway.MakeXML("Z", SpeakerPosition.Velocity.Z.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append("</Velocity>");
|
||||
sb.Append("<AtOrientation>");
|
||||
sb.Append(VoiceGateway.MakeXML("X", SpeakerPosition.AtOrientation.X.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("Y", SpeakerPosition.AtOrientation.Y.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("Z", SpeakerPosition.AtOrientation.Z.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("X", SpeakerPosition.AtOrientation.X.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append(VoiceGateway.MakeXML("Y", SpeakerPosition.AtOrientation.Y.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append(VoiceGateway.MakeXML("Z", SpeakerPosition.AtOrientation.Z.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append("</AtOrientation>");
|
||||
sb.Append("<UpOrientation>");
|
||||
sb.Append(VoiceGateway.MakeXML("X", SpeakerPosition.UpOrientation.X.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("Y", SpeakerPosition.UpOrientation.Y.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("Z", SpeakerPosition.UpOrientation.Z.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("X", SpeakerPosition.UpOrientation.X.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append(VoiceGateway.MakeXML("Y", SpeakerPosition.UpOrientation.Y.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append(VoiceGateway.MakeXML("Z", SpeakerPosition.UpOrientation.Z.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append("</UpOrientation>");
|
||||
sb.Append("<LeftOrientation>");
|
||||
sb.Append(VoiceGateway.MakeXML("X", SpeakerPosition.LeftOrientation.X.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("Y", SpeakerPosition.LeftOrientation.Y.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("Z", SpeakerPosition.LeftOrientation.Z.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("X", SpeakerPosition.LeftOrientation.X.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append(VoiceGateway.MakeXML("Y", SpeakerPosition.LeftOrientation.Y.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append(VoiceGateway.MakeXML("Z", SpeakerPosition.LeftOrientation.Z.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append("</LeftOrientation>");
|
||||
sb.Append("</SpeakerPosition>");
|
||||
sb.Append("<ListenerPosition>");
|
||||
sb.Append("<Position>");
|
||||
sb.Append(VoiceGateway.MakeXML("X", ListenerPosition.Position.X.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("Y", ListenerPosition.Position.Y.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("Z", ListenerPosition.Position.Z.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("X", ListenerPosition.Position.X.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append(VoiceGateway.MakeXML("Y", ListenerPosition.Position.Y.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append(VoiceGateway.MakeXML("Z", ListenerPosition.Position.Z.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append("</Position>");
|
||||
sb.Append("<Velocity>");
|
||||
sb.Append(VoiceGateway.MakeXML("X", ListenerPosition.Velocity.X.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("Y", ListenerPosition.Velocity.Y.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("Z", ListenerPosition.Velocity.Z.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("X", ListenerPosition.Velocity.X.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append(VoiceGateway.MakeXML("Y", ListenerPosition.Velocity.Y.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append(VoiceGateway.MakeXML("Z", ListenerPosition.Velocity.Z.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append("</Velocity>");
|
||||
sb.Append("<AtOrientation>");
|
||||
sb.Append(VoiceGateway.MakeXML("X", ListenerPosition.AtOrientation.X.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("Y", ListenerPosition.AtOrientation.Y.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("Z", ListenerPosition.AtOrientation.Z.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("X", ListenerPosition.AtOrientation.X.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append(VoiceGateway.MakeXML("Y", ListenerPosition.AtOrientation.Y.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append(VoiceGateway.MakeXML("Z", ListenerPosition.AtOrientation.Z.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append("</AtOrientation>");
|
||||
sb.Append("<UpOrientation>");
|
||||
sb.Append(VoiceGateway.MakeXML("X", ListenerPosition.UpOrientation.X.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("Y", ListenerPosition.UpOrientation.Y.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("Z", ListenerPosition.UpOrientation.Z.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("X", ListenerPosition.UpOrientation.X.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append(VoiceGateway.MakeXML("Y", ListenerPosition.UpOrientation.Y.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append(VoiceGateway.MakeXML("Z", ListenerPosition.UpOrientation.Z.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append("</UpOrientation>");
|
||||
sb.Append("<LeftOrientation>");
|
||||
sb.Append(VoiceGateway.MakeXML("X", ListenerPosition.LeftOrientation.X.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("Y", ListenerPosition.LeftOrientation.Y.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("Z", ListenerPosition.LeftOrientation.Z.ToString()));
|
||||
sb.Append(VoiceGateway.MakeXML("X", ListenerPosition.LeftOrientation.X.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append(VoiceGateway.MakeXML("Y", ListenerPosition.LeftOrientation.Y.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append(VoiceGateway.MakeXML("Z", ListenerPosition.LeftOrientation.Z.ToString(CultureInfo.InvariantCulture)));
|
||||
sb.Append("</LeftOrientation>");
|
||||
sb.Append("</ListenerPosition>");
|
||||
return Request("Session.Set3DPosition.1", sb.ToString());
|
||||
|
||||
@@ -25,8 +25,6 @@
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Text;
|
||||
using OpenMetaverse;
|
||||
|
||||
namespace OpenMetaverse
|
||||
{
|
||||
@@ -76692,7 +76690,7 @@ namespace OpenMetaverse.Packets
|
||||
if (TextureEntry != null) { length += Math.Min(TextureEntry.Length, 65535); }
|
||||
if (TextureAnim != null) { length += (byte)TextureAnim.Length; }
|
||||
if (NameValue != null) { length += Math.Min(NameValue.Length, 65535); }
|
||||
if (Data != null) { length += Math.Min(Data.Length, 65535); ; }
|
||||
if (Data != null) { length += Math.Min(Data.Length, 65535); }
|
||||
if (Text != null) { length += (byte)Text.Length; }
|
||||
if (MediaURL != null) { length += (byte)MediaURL.Length; }
|
||||
if (PSBlock != null) { length += (byte)PSBlock.Length; }
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,33 @@
|
||||
fileFormatVersion: 2
|
||||
guid: afe79d3aa99f00f4786a041144e1381c
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Windows Store Apps: WindowsStoreApps
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Binary file not shown.
@@ -0,0 +1,33 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b40d6b883361a0d40921720d88966596
|
||||
PluginImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
iconMap: {}
|
||||
executionOrder: {}
|
||||
defineConstraints: []
|
||||
isPreloaded: 0
|
||||
isOverridable: 0
|
||||
isExplicitlyReferenced: 0
|
||||
validateReferences: 1
|
||||
platformData:
|
||||
- first:
|
||||
Any:
|
||||
second:
|
||||
enabled: 1
|
||||
settings: {}
|
||||
- first:
|
||||
Editor: Editor
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
DefaultValueInitialized: true
|
||||
- first:
|
||||
Windows Store Apps: WindowsStoreApps
|
||||
second:
|
||||
enabled: 0
|
||||
settings:
|
||||
CPU: AnyCPU
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user