diff --git a/LibreMetaverse.StructuredData/LibreMetaverse.StructuredData.csproj b/LibreMetaverse.StructuredData/LibreMetaverse.StructuredData.csproj
index 4c70caa..0a5147c 100644
--- a/LibreMetaverse.StructuredData/LibreMetaverse.StructuredData.csproj
+++ b/LibreMetaverse.StructuredData/LibreMetaverse.StructuredData.csproj
@@ -3,7 +3,7 @@
LibreMetaverse.StructuredData
LibreMetaverse structured data library
LibreMetaverse.StructuredData
- net48;netstandard2.1;net6.0;net7.0
+ net7.0
Library
LibreMetaverse.StructuredData
true
diff --git a/LibreMetaverse.Types/LibreMetaverse.Types.csproj b/LibreMetaverse.Types/LibreMetaverse.Types.csproj
index a78282b..10954f2 100644
--- a/LibreMetaverse.Types/LibreMetaverse.Types.csproj
+++ b/LibreMetaverse.Types/LibreMetaverse.Types.csproj
@@ -3,7 +3,7 @@
LibreMetaverse.Types
LibreMetaverse.Types
LibreMetaverse type library
- net48;netstandard2.1;net6.0;net7.0
+ net7.0
Library
LibreMetaverse
true
diff --git a/LibreMetaverse.Types/Utils.cs b/LibreMetaverse.Types/Utils.cs
index 14443d1..2c5ea4a 100644
--- a/LibreMetaverse.Types/Utils.cs
+++ b/LibreMetaverse.Types/Utils.cs
@@ -366,7 +366,7 @@ namespace OpenMetaverse
public static string MD5(string str)
{
StringBuilder digest = new StringBuilder(32);
- byte[] hash = MD5(Encoding.Default.GetBytes(str));
+ byte[] hash = MD5(Encoding.UTF8.GetBytes(str));
// Convert the hash to a hex string
foreach (byte b in hash)
@@ -399,7 +399,7 @@ namespace OpenMetaverse
/// The PBKDF2 hash of the supplied string
public static string PBKDF2(string str)
{
- var derivebytes = new Rfc2898DeriveBytes(str, 32) {IterationCount = 10000};
+ var derivebytes = new Rfc2898DeriveBytes(str, 32, 10000, HashAlgorithmName.SHA1);
byte[] hash = derivebytes.GetBytes(20);
byte[] salt = derivebytes.Salt;
return Convert.ToBase64String(salt) + "|" + Convert.ToBase64String(hash);
diff --git a/LibreMetaverse/AgentManager.cs b/LibreMetaverse/AgentManager.cs
index f71b509..27e6555 100644
--- a/LibreMetaverse/AgentManager.cs
+++ b/LibreMetaverse/AgentManager.cs
@@ -910,7 +910,7 @@ namespace OpenMetaverse
/// Thread sync lock object
private readonly object m_InstantMessageLock = new object();
- /// Raised when an ImprovedInstantMessage packet is recieved from the simulator, this is used for everything from
+ /// Raised when an ImprovedInstantMessage packet is received from the simulator, this is used for everything from
/// private messaging to friendship offers. The Dialog field defines what type of message has arrived
public event EventHandler IM
{
@@ -1104,8 +1104,7 @@ namespace OpenMetaverse
protected virtual void OnCameraConstraint(CameraConstraintEventArgs e)
{
EventHandler handler = m_CameraConstraint;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -1128,8 +1127,7 @@ namespace OpenMetaverse
protected virtual void OnScriptSensorReply(ScriptSensorReplyEventArgs e)
{
EventHandler handler = m_ScriptSensorReply;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -1151,8 +1149,7 @@ namespace OpenMetaverse
protected virtual void OnAvatarSitResponse(AvatarSitResponseEventArgs e)
{
EventHandler handler = m_AvatarSitResponse;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -1478,7 +1475,7 @@ namespace OpenMetaverse
private HomeInfo home;
private string fullName;
- private TeleportStatus teleportStat = TeleportStatus.None;
+ private TeleportStatus teleportStatus = TeleportStatus.None;
private ManualResetEvent teleportEvent = new ManualResetEvent(false);
private uint heightWidthGenCounter;
private Dictionary gestureCache = new Dictionary();
@@ -2966,7 +2963,13 @@ namespace OpenMetaverse
/// true on success, false on failure
public bool Teleport(UUID landmark)
{
- teleportStat = TeleportStatus.None;
+ if (teleportStatus == TeleportStatus.Progress)
+ {
+ Logger.Log("Teleport already in progress while attempting to teleport.", Helpers.LogLevel.Info, Client);
+ return false;
+ }
+
+ teleportStatus = TeleportStatus.None;
teleportEvent.Reset();
TeleportLandmarkRequestPacket p = new TeleportLandmarkRequestPacket
{
@@ -2981,15 +2984,15 @@ namespace OpenMetaverse
teleportEvent.WaitOne(Client.Settings.TELEPORT_TIMEOUT, false);
- if (teleportStat == TeleportStatus.None ||
- teleportStat == TeleportStatus.Start ||
- teleportStat == TeleportStatus.Progress)
+ if (teleportStatus == TeleportStatus.None ||
+ teleportStatus == TeleportStatus.Start ||
+ teleportStatus == TeleportStatus.Progress)
{
TeleportMessage = "Teleport timed out.";
- teleportStat = TeleportStatus.Failed;
+ teleportStatus = TeleportStatus.Failed;
}
- return (teleportStat == TeleportStatus.Finished);
+ return (teleportStatus == TeleportStatus.Finished);
}
///
@@ -3018,7 +3021,14 @@ namespace OpenMetaverse
{
if (Client.Network.CurrentSim == null) { return false; }
- teleportStat = TeleportStatus.None;
+ if (teleportStatus == TeleportStatus.Progress)
+ {
+ Logger.Log($"Teleport already in progress while attempting to teleport to {simName}.",
+ Helpers.LogLevel.Info, Client);
+ return false;
+ }
+
+ teleportStatus = TeleportStatus.None;
if (simName != Client.Network.CurrentSim.Name)
{
@@ -3030,7 +3040,7 @@ namespace OpenMetaverse
else
{
TeleportMessage = $"Unable to resolve simulator named: {simName}";
- teleportStat = TeleportStatus.Failed;
+ teleportStatus = TeleportStatus.Failed;
return false;
}
}
@@ -3063,40 +3073,46 @@ namespace OpenMetaverse
/// This call is blocking
public bool Teleport(ulong regionHandle, Vector3 position, Vector3 lookAt)
{
+ if (teleportStatus == TeleportStatus.Progress)
+ {
+ Logger.Log("Teleport already in progress while attempting to teleport.",
+ Helpers.LogLevel.Info, Client);
+ return false;
+ }
+
if (Client.Network.CurrentSim == null ||
Client.Network.CurrentSim.Caps == null ||
!Client.Network.CurrentSim.Caps.IsEventQueueRunning)
{
// Wait a bit to see if the event queue comes online
AutoResetEvent queueEvent = new AutoResetEvent(false);
- EventHandler queueCallback =
- delegate(object sender, EventQueueRunningEventArgs e)
- {
- if (e.Simulator == Client.Network.CurrentSim)
- queueEvent.Set();
- };
- Client.Network.EventQueueRunning += queueCallback;
+ void QueueCallback(object sender, EventQueueRunningEventArgs e)
+ {
+ if (e.Simulator == Client.Network.CurrentSim) { queueEvent.Set(); }
+ }
+
+ Client.Network.EventQueueRunning += QueueCallback;
queueEvent.WaitOne(10 * 1000, false);
- Client.Network.EventQueueRunning -= queueCallback;
+ Client.Network.EventQueueRunning -= QueueCallback;
}
- teleportStat = TeleportStatus.None;
+ teleportStatus = TeleportStatus.None;
teleportEvent.Reset();
RequestTeleport(regionHandle, position, lookAt);
teleportEvent.WaitOne(Client.Settings.TELEPORT_TIMEOUT, false);
- if (teleportStat == TeleportStatus.None ||
- teleportStat == TeleportStatus.Start ||
- teleportStat == TeleportStatus.Progress)
+ if (teleportStatus == TeleportStatus.None ||
+ teleportStatus == TeleportStatus.Start ||
+ teleportStatus == TeleportStatus.Progress)
{
TeleportMessage = "Teleport timed out.";
- teleportStat = TeleportStatus.Failed;
+ teleportStatus = TeleportStatus.Failed;
}
- return (teleportStat == TeleportStatus.Finished);
+ return (teleportStatus == TeleportStatus.Finished);
}
///
@@ -3117,8 +3133,7 @@ namespace OpenMetaverse
/// direction in destination sim agent will look at
public void RequestTeleport(ulong regionHandle, Vector3 position, Vector3 lookAt)
{
- if (Client.Network.CurrentSim != null &&
- Client.Network.CurrentSim.Caps != null &&
+ if (Client.Network?.CurrentSim?.Caps != null &&
Client.Network.CurrentSim.Caps.IsEventQueueRunning)
{
TeleportLocationRequestPacket teleport = new TeleportLocationRequestPacket
@@ -3144,7 +3159,7 @@ namespace OpenMetaverse
{
TeleportMessage = "CAPS event queue is not running";
teleportEvent.Set();
- teleportStat = TeleportStatus.Failed;
+ teleportStatus = TeleportStatus.Failed;
}
}
@@ -3251,7 +3266,7 @@ namespace OpenMetaverse
}
public void SendTeleportLureRequest(UUID targetID)
{
- SendTeleportLureRequest(targetID, "Hi there I would like to teleport to you");
+ SendTeleportLureRequest(targetID, "Let me join you in your location");
}
#endregion Teleporting
@@ -4302,7 +4317,9 @@ namespace OpenMetaverse
SimAccess = (byte) msg.SimAccess,
SimIP = Utils.IPToUInt(msg.IP),
SimPort = (ushort) msg.Port,
- TeleportFlags = (uint) msg.Flags
+ TeleportFlags = (uint) msg.Flags,
+ RegionSizeX = msg.RegionSizeX,
+ RegionSizeY = msg.RegionSizeY
}
};
// FIXME: Check This
@@ -4328,7 +4345,7 @@ namespace OpenMetaverse
TeleportMessage = "Teleport started";
flags = (TeleportFlags)start.Info.TeleportFlags;
- teleportStat = TeleportStatus.Start;
+ teleportStatus = TeleportStatus.Start;
Logger.DebugLog($"TeleportStart received, Flags: {flags}", Client);
}
@@ -4338,7 +4355,7 @@ namespace OpenMetaverse
TeleportMessage = Utils.BytesToString(progress.Info.Message);
flags = (TeleportFlags)progress.Info.TeleportFlags;
- teleportStat = TeleportStatus.Progress;
+ teleportStatus = TeleportStatus.Progress;
Logger.DebugLog($"TeleportProgress received, Message: {TeleportMessage}, Flags: {flags}", Client);
}
@@ -4347,7 +4364,7 @@ namespace OpenMetaverse
TeleportFailedPacket failed = (TeleportFailedPacket)packet;
TeleportMessage = Utils.BytesToString(failed.Info.Reason);
- teleportStat = TeleportStatus.Failed;
+ teleportStatus = TeleportStatus.Failed;
finished = true;
Logger.DebugLog($"TeleportFailed received, Reason: {TeleportMessage}", Client);
@@ -4365,19 +4382,20 @@ namespace OpenMetaverse
// Connect to the new sim
Client.Network.CurrentSim.AgentMovementComplete = false; // we're not there anymore
Simulator newSimulator = Client.Network.Connect(new IPAddress(finish.Info.SimIP),
- finish.Info.SimPort, finish.Info.RegionHandle, true, seedcaps);
+ finish.Info.SimPort, finish.Info.RegionHandle, true, seedcaps,
+ finish.Info.RegionSizeX, finish.Info.RegionSizeY);
if (newSimulator != null)
{
TeleportMessage = "Teleport finished";
- teleportStat = TeleportStatus.Finished;
+ teleportStatus = TeleportStatus.Finished;
- Logger.Log($"Moved to new sim {newSimulator}", Helpers.LogLevel.Info, Client);
+ Logger.Log($"Moved to {newSimulator}", Helpers.LogLevel.Info, Client);
}
else
{
- TeleportMessage = "Failed to connect to the new sim after a teleport";
- teleportStat = TeleportStatus.Failed;
+ TeleportMessage = $"Failed to connect to {newSimulator} after teleport";
+ teleportStatus = TeleportStatus.Failed;
// We're going to get disconnected now
Logger.Log(TeleportMessage, Helpers.LogLevel.Error, Client);
@@ -4388,7 +4406,7 @@ namespace OpenMetaverse
//TeleportCancelPacket cancel = (TeleportCancelPacket)packet;
TeleportMessage = "Cancelled";
- teleportStat = TeleportStatus.Cancelled;
+ teleportStatus = TeleportStatus.Cancelled;
finished = true;
Logger.DebugLog($"TeleportCancel received from {simulator}", Client);
@@ -4399,7 +4417,7 @@ namespace OpenMetaverse
TeleportMessage = "Teleport finished";
flags = (TeleportFlags)local.Info.TeleportFlags;
- teleportStat = TeleportStatus.Finished;
+ teleportStatus = TeleportStatus.Finished;
relativePosition = local.Info.Position;
Movement.Camera.LookDirection(local.Info.LookAt);
// This field is apparently not used for anything
@@ -4411,7 +4429,7 @@ namespace OpenMetaverse
if (m_Teleport != null)
{
- OnTeleport(new TeleportEventArgs(TeleportMessage, teleportStat, flags));
+ OnTeleport(new TeleportEventArgs(TeleportMessage, teleportStatus, flags));
}
if (finished) { teleportEvent.Set(); }
@@ -4541,7 +4559,8 @@ namespace OpenMetaverse
Logger.DebugLog($"Crossed in to new region area, attempting to connect to {endPoint}", Client);
Simulator oldSim = Client.Network.CurrentSim;
- Simulator newSim = Client.Network.Connect(endPoint, crossed.RegionHandle, true, crossed.SeedCapability);
+ Simulator newSim = Client.Network.Connect(endPoint, crossed.RegionHandle, true, crossed.SeedCapability,
+ crossed.RegionSizeX, crossed.RegionSizeY);
if (newSim != null)
{
diff --git a/LibreMetaverse/AgentManagerMovement.cs b/LibreMetaverse/AgentManagerMovement.cs
index d16f227..08bc45c 100644
--- a/LibreMetaverse/AgentManagerMovement.cs
+++ b/LibreMetaverse/AgentManagerMovement.cs
@@ -393,18 +393,12 @@ namespace OpenMetaverse
{
if (value > 0)
{
- if (updateTimer != null)
- {
- updateTimer.Change(value, value);
- }
+ updateTimer?.Change(value, value);
updateInterval = value;
}
else
{
- if (updateTimer != null)
- {
- updateTimer.Change(Timeout.Infinite, Timeout.Infinite);
- }
+ updateTimer?.Change(Timeout.Infinite, Timeout.Infinite);
updateInterval = 0;
}
}
diff --git a/LibreMetaverse/AssetCache.cs b/LibreMetaverse/AssetCache.cs
index 9c19fd8..731aebf 100644
--- a/LibreMetaverse/AssetCache.cs
+++ b/LibreMetaverse/AssetCache.cs
@@ -219,7 +219,7 @@ namespace OpenMetaverse
///
/// UUID of the asset
/// Raw bytes the asset consists of
- /// Weather the operation was successfull
+ /// Whether the operation was successful
public bool SaveAssetToCache(UUID assetID, byte[] assetData)
{
if (!Operational())
diff --git a/LibreMetaverse/AssetManager.cs b/LibreMetaverse/AssetManager.cs
index 4d287a2..f0c7ca1 100644
--- a/LibreMetaverse/AssetManager.cs
+++ b/LibreMetaverse/AssetManager.cs
@@ -319,8 +319,7 @@ namespace OpenMetaverse
protected virtual void OnXferReceived(XferReceivedEventArgs e)
{
EventHandler handler = m_XferReceivedEvent;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -344,8 +343,7 @@ namespace OpenMetaverse
protected virtual void OnAssetUploaded(AssetUploadEventArgs e)
{
EventHandler handler = m_AssetUploadedEvent;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -369,8 +367,7 @@ namespace OpenMetaverse
protected virtual void OnUploadProgress(AssetUploadEventArgs e)
{
EventHandler handler = m_UploadProgressEvent;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -394,8 +391,7 @@ namespace OpenMetaverse
protected virtual void OnInitiateDownload(InitiateDownloadEventArgs e)
{
EventHandler handler = m_InitiateDownloadEvent;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -419,8 +415,7 @@ namespace OpenMetaverse
protected virtual void OnImageReceiveProgress(ImageReceiveProgressEventArgs e)
{
EventHandler handler = m_ImageReceiveProgressEvent;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -640,8 +635,7 @@ namespace OpenMetaverse
}
// If ViewerAsset capability exists, use that, if not, fallback to UDP (which is obsoleted on Second Life.)
- if (Client.Network.CurrentSim.Caps != null
- && Client.Network.CurrentSim.Caps.CapabilityURI("ViewerAsset") != null)
+ if (Client.Network.CurrentSim?.Caps?.CapabilityURI("ViewerAsset") != null)
{
RequestAssetHTTP(assetID, transfer, callback);
}
@@ -827,10 +821,20 @@ namespace OpenMetaverse
}
// If ViewerAsset capability exists, use that, if not, fallback to UDP
- if (Client.Network.CurrentSim.Caps != null
- && Client.Network.CurrentSim.Caps.CapabilityURI("ViewerAsset") != null)
+ if (Client.Network.CurrentSim?.Caps?.CapabilityURI("ViewerAsset") != null)
{
- RequestInventoryAssetHTTP(assetID, transfer, callback);
+ RequestInventoryAssetHTTP(assetID, transfer,
+ (AssetDownload transferResult, Asset assetResult) =>
+ {
+ if (transferResult.Success == false)
+ {
+ Logger.Log($"HTTP transfer has failed trying UDP", Helpers.LogLevel.Warning, Client);
+ RequestInventoryAssetUDP(assetID, itemID, taskID, ownerID, transfer, callback);
+ return;
+ }
+ callback(transferResult, assetResult);
+ }
+ );
}
else
{
@@ -849,6 +853,7 @@ namespace OpenMetaverse
///
private void RequestInventoryAssetHTTP(UUID assetID, AssetDownload transfer, AssetReceivedCallback callback)
{
+ int attempts = 0;
DownloadRequest req = new DownloadRequest(
BuildFetchRequestUri(transfer.AssetType, assetID),
null,
@@ -873,6 +878,7 @@ namespace OpenMetaverse
}
else // download failed
{
+ attempts++;
Logger.Log($"Failed to fetch asset {assetID}: {((error == null) ? "" : error.Message)}",
Helpers.LogLevel.Warning, Client);
if (callback != null)
@@ -880,6 +886,10 @@ namespace OpenMetaverse
transfer.Success = false;
transfer.Status = StatusCode.Error;
}
+ if (attempts == 5)
+ {
+ callback(transfer, null);
+ }
}
}
@@ -1213,8 +1223,7 @@ namespace OpenMetaverse
if (meshID == UUID.Zero || callback == null)
return;
- if (Client.Network.CurrentSim.Caps != null &&
- Client.Network.CurrentSim.Caps.GetMeshCapURI() != null)
+ if (Client.Network.CurrentSim?.Caps?.GetMeshCapURI() != null)
{
// Do we have this mesh asset in the cache?
if (Client.Assets.Cache.HasAsset(meshID))
@@ -1329,8 +1338,7 @@ namespace OpenMetaverse
uint packetStart, TextureDownloadCallback callback, bool progress)
{
if (Client.Settings.USE_HTTP_TEXTURES
- && Client.Network.CurrentSim.Caps != null
- && Client.Network.CurrentSim.Caps.GetTextureCapURI() != null)
+ && Client.Network.CurrentSim?.Caps?.GetTextureCapURI() != null)
{
HttpRequestTexture(textureID, imageType, priority, discardLevel, packetStart, callback, progress);
}
diff --git a/LibreMetaverse/Assets/Archiving/OarFile.cs b/LibreMetaverse/Assets/Archiving/OarFile.cs
index 99eb2a5..fc8d57f 100644
--- a/LibreMetaverse/Assets/Archiving/OarFile.cs
+++ b/LibreMetaverse/Assets/Archiving/OarFile.cs
@@ -206,6 +206,7 @@ namespace OpenMetaverse.Assets
private static bool LoadTerrain(string filePath, byte[] data, TerrainLoadedCallback terrainCallback, long bytesRead, long totalBytes)
{
+ // TODO: This needs to be re-written to read data from a saved varregion (sizeX != 256)
float[,] terrain = new float[256, 256];
bool loaded = false;
@@ -350,10 +351,10 @@ namespace OpenMetaverse.Assets
BinaryWriter bs = new BinaryWriter(s);
int y;
- for (y = 0; y < 256; y++)
+ for (y = 0; y < sim.SizeY; y++)
{
int x;
- for (x = 0; x < 256; x++)
+ for (x = 0; x < sim.SizeX; x++)
{
float height;
sim.TerrainHeightAtPoint(x, y, out height);
diff --git a/LibreMetaverse/AvatarManager.cs b/LibreMetaverse/AvatarManager.cs
index d7d5b16..f0bfeaa 100644
--- a/LibreMetaverse/AvatarManager.cs
+++ b/LibreMetaverse/AvatarManager.cs
@@ -689,9 +689,7 @@ namespace OpenMetaverse
/// True if Display name functionality is available
public bool DisplayNamesAvailable()
{
- return (Client.Network.CurrentSim != null
- && Client.Network.CurrentSim.Caps != null)
- && Client.Network.CurrentSim.Caps.CapabilityURI("GetDisplayNames") != null;
+ return Client.Network.CurrentSim?.Caps?.CapabilityURI("GetDisplayNames") != null;
}
///
diff --git a/LibreMetaverse/Capabilities/CapsBase.cs b/LibreMetaverse/Capabilities/CapsBase.cs
index c83649e..61b079b 100644
--- a/LibreMetaverse/Capabilities/CapsBase.cs
+++ b/LibreMetaverse/Capabilities/CapsBase.cs
@@ -296,8 +296,7 @@ namespace OpenMetaverse.Http
}
// Fire the download progress callback for each chunk of received data
- if (state.DownloadProgressCallback != null)
- state.DownloadProgressCallback(state.Request, response, totalBytesRead, totalSize);
+ state.DownloadProgressCallback?.Invoke(state.Request, response, totalBytesRead, totalSize);
}
if (nolength)
diff --git a/LibreMetaverse/Capabilities/EventQueueClient.cs b/LibreMetaverse/Capabilities/EventQueueClient.cs
index 72114fe..1dd3553 100644
--- a/LibreMetaverse/Capabilities/EventQueueClient.cs
+++ b/LibreMetaverse/Capabilities/EventQueueClient.cs
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2006-2016, openmetaverse.co
- * Copyright (c) 2022, Sjofn LLC.
+ * Copyright (c) 2022-2023, Sjofn LLC.
* All rights reserved.
*
* - Redistribution and use in source and binary forms, with or without
@@ -38,9 +38,9 @@ namespace OpenMetaverse.Http
public class EventQueueClient
{
/// For exponential backoff on error.
- public const int REQUEST_BACKOFF_SECONDS = 15 * 1000; // 15 seconds start
- public const int REQUEST_BACKOFF_SECONDS_INC = 5 * 1000; // 5 seconds increase
- public const int REQUEST_BACKOFF_SECONDS_MAX = 5 * 60 * 1000; // 5 minutes
+ private const int REQUEST_BACKOFF_SECONDS = 15 * 1000; // 15 seconds start
+ private const int REQUEST_BACKOFF_SECONDS_INC = 5 * 1000; // 5 seconds increase
+ private const int REQUEST_BACKOFF_SECONDS_MAX = 5 * 60 * 1000; // 5 minutes
public delegate void ConnectedCallback();
public delegate void EventCallback(string eventName, OSDMap body);
@@ -48,13 +48,14 @@ namespace OpenMetaverse.Http
public ConnectedCallback OnConnected;
public EventCallback OnEvent;
- public bool Running => _Running;
+ public bool Running { get; private set; }
+
+ private readonly Uri _Address;
+ private readonly Simulator _Simulator;
+ private readonly CancellationTokenSource _queueCts;
+ private bool _Dead;
+ private OSD _AckPayload;
- protected readonly Uri _Address;
- protected readonly Simulator _Simulator;
- protected bool _Dead;
- protected bool _Running;
- private CancellationTokenSource _HttpCts;
/// Number of times we've received an unknown CAPS exception in series.
private int _errorCount;
@@ -63,19 +64,71 @@ namespace OpenMetaverse.Http
{
_Address = eventQueueLocation;
_Simulator = sim;
+ _queueCts = new CancellationTokenSource();
}
public void Start()
{
_Dead = false;
- _Running = true;
+ Running = true;
- // Create an EventQueueGet request
- OSDMap payload = new OSDMap {["ack"] = new OSD(), ["done"] = OSD.FromBoolean(false)};
+ Task.Factory.StartNew(() =>
+ {
+ // Initial request
+ _AckPayload = new OSDMap { ["ack"] = new OSD(), ["done"] = OSD.FromBoolean(false) };
+ var initialTimeoutCts = CancellationTokenSource.CreateLinkedTokenSource(_queueCts.Token);
+ initialTimeoutCts.CancelAfter(TimeSpan.FromSeconds(30));
+
+ Task initialReq = _Simulator.Client.HttpCapsClient.PostRequestAsync(_Address, OSDFormat.Xml, _AckPayload,
+ initialTimeoutCts.Token, RequestCompletedHandler, null, ConnectedResponseHandler);
+
+ initialReq.Wait(initialTimeoutCts.Token);
+ initialTimeoutCts.Dispose();
+
+ while (Running && !_queueCts.Token.IsCancellationRequested)
+ {
+ if (_errorCount > 0)
+ { // Exponentially back off, so we don't hammer the CPU
+ while (!_queueCts.Token.IsCancellationRequested)
+ {
+ _queueCts.Token.WaitHandle.WaitOne(
+ Math.Min(REQUEST_BACKOFF_SECONDS + _errorCount * REQUEST_BACKOFF_SECONDS_INC,
+ REQUEST_BACKOFF_SECONDS_MAX));
+ }
+ }
+ // Resume the connection.
+ if (!_queueCts.Token.IsCancellationRequested)
+ {
+ using (CancellationTokenSource timeoutCts =
+ CancellationTokenSource.CreateLinkedTokenSource(_queueCts.Token))
+ {
+ timeoutCts.CancelAfter(TimeSpan.FromSeconds(30));
+
+ try
+ {
+ Task req = _Simulator.Client.HttpCapsClient.PostRequestAsync(_Address, OSDFormat.Xml,
+ _AckPayload, timeoutCts.Token, RequestCompletedHandler);
+ req.Wait(timeoutCts.Token);
+ }
+ catch (OperationCanceledException)
+ {
+ /*no-op*/
+ }
+ }
+ }
+
+
+ // If the event queue is dead at this point, turn it off since
+ // that was the last thing we want to do
+ if (_Dead)
+ {
+ Running = false;
+ Logger.DebugLog($"Sent event queue shutdown message for {_Simulator}");
+ }
+ }
+
+ }, _queueCts.Token); // TOOD: TaskCreationOptions.LongRunning?
- _HttpCts = new CancellationTokenSource();
- Task req = _Simulator.Client.HttpCapsClient.PostRequestAsync(_Address, OSDFormat.Xml, payload, _HttpCts.Token,
- RequestCompletedHandler, null, ConnectedResponseHandler);
}
public void Stop(bool immediate)
@@ -84,17 +137,17 @@ namespace OpenMetaverse.Http
if (immediate)
{
- _Running = false;
+ Running = false;
}
- _HttpCts.Cancel();
+ _queueCts.Cancel();
}
void ConnectedResponseHandler(HttpResponseMessage response)
{
if (!response.IsSuccessStatusCode) { return; }
- _Running = true;
+ Running = true;
// The event queue is starting up for the first time
if (OnConnected != null)
@@ -120,11 +173,11 @@ namespace OpenMetaverse.Http
}
else
{
- Logger.Log($"Got an unparseable response from {_Simulator} event queue: \"" +
+ Logger.Log($"Received an invalid response from {_Simulator} event queue: \"" +
System.Text.Encoding.UTF8.GetString(responseData) + "\"", Helpers.LogLevel.Warning);
}
}
- else if (error != null)
+ else if (response != null && error != null)
{
#region Error handling
@@ -132,30 +185,31 @@ namespace OpenMetaverse.Http
{
case HttpStatusCode.NotFound:
case HttpStatusCode.Gone:
- Logger.Log($"Closing event queue at {_Simulator} due to missing caps URI", Helpers.LogLevel.Info);
+ Logger.Log($"Closing event queue at {_Simulator} due to missing caps URI", Helpers.LogLevel.Info, _Simulator.Client);
- _Running = false;
+ Running = false;
_Dead = true;
break;
case (HttpStatusCode)499: // weird error returned occasionally, ignore for now
// I believe this is the timeout error invented by LL for LSL HTTP-out requests (gwyneth 20220413)
- Logger.Log($"Possible HTTP-out timeout error from {_Simulator}, no need to continue", Helpers.LogLevel.Debug);
+ Logger.Log($"Possible HTTP-out timeout error from {_Simulator}, no need to continue", Helpers.LogLevel.Debug, _Simulator.Client);
- _Running = false;
+ Running = false;
_Dead = true;
break;
case HttpStatusCode.InternalServerError:
// As per LL's instructions, we ought to consider this a
// 'request to close client' (gwyneth 20220413)
- Logger.Log($"Grid sent a {response.StatusCode} at {_Simulator}, closing connection", Helpers.LogLevel.Debug);
+ Logger.Log($"Grid sent a {response.StatusCode} at {_Simulator}, closing connection", Helpers.LogLevel.Debug, _Simulator.Client);
// ... but do we happen to have an InnerException? Log it!
if (error.InnerException != null)
{
// unravel the whole inner error message, so we finally figure out what it is!
// (gwyneth 20220414)
- Logger.Log($"Unrecognized internal caps exception from {_Simulator}: '{error.InnerException.Message}'", Helpers.LogLevel.Warning);
- Logger.Log($"\nMessage ---\n{error.Message}", Helpers.LogLevel.Warning);
+ Logger.Log($"Unrecognized internal caps exception from {_Simulator}: '{error.InnerException.Message}'",
+ Helpers.LogLevel.Warning, _Simulator.Client);
+ Logger.Log($"\nMessage ---\n{error.Message}", Helpers.LogLevel.Warning, _Simulator.Client);
if (error.Data.Count > 0)
{
Logger.Log(" Extra details:", Helpers.LogLevel.Warning);
@@ -163,13 +217,13 @@ namespace OpenMetaverse.Http
{
Logger.Log(String.Format(" Key: {0,-20} Value: '{1}'",
de.Key, de.Value),
- Helpers.LogLevel.Warning);
+ Helpers.LogLevel.Warning, _Simulator.Client);
}
}
// but we'll nevertheless close this connection (gwyneth 20220414)
}
- _Running = false;
+ Running = false;
_Dead = true;
break;
case HttpStatusCode.BadGateway:
@@ -182,7 +236,8 @@ namespace OpenMetaverse.Http
// Note: if this condition persists, it _might_ be the grid trying to request
// that the client closes the connection, as per LL's specs (gwyneth 20220414)
Logger.Log($"Grid sent a Bad Gateway Error at {_Simulator}; " +
- $"probably a time-out from the grid's EventQueue server (normal) -- ignoring and continuing", Helpers.LogLevel.Debug);
+ $"probably a time-out from the grid's EventQueue server (normal) -- ignoring and continuing",
+ Helpers.LogLevel.Debug, _Simulator.Client);
break;
default:
++_errorCount;
@@ -191,71 +246,55 @@ namespace OpenMetaverse.Http
if (response.StatusCode != HttpStatusCode.OK)
{
Logger.Log($"Unrecognized caps connection problem from {_Simulator}: {response.StatusCode} {response.ReasonPhrase}",
- Helpers.LogLevel.Warning);
+ Helpers.LogLevel.Warning, _Simulator.Client);
}
else if (error.InnerException != null)
{
// see comment above (gwyneth 20220414)
- Logger.Log($"Unrecognized internal caps exception from {_Simulator}: '{error.InnerException.Message}'", Helpers.LogLevel.Warning);
- Logger.Log($"Message ---\n{error.Message}", Helpers.LogLevel.Warning);
+ Logger.Log($"Unrecognized internal caps exception from {_Simulator}: '{error.InnerException.Message}'",
+ Helpers.LogLevel.Warning, _Simulator.Client);
+ Logger.Log($"Message ---\n{error.Message}", Helpers.LogLevel.Warning, _Simulator.Client);
if (error.Data.Count > 0)
{
- Logger.Log(" Extra details:", Helpers.LogLevel.Warning);
+ Logger.Log(" Extra details:", Helpers.LogLevel.Warning, _Simulator.Client);
foreach (DictionaryEntry de in error.Data)
{
Logger.Log(string.Format(" Key: {0,-20} Value: {1}",
"'" + de.Key + "'", de.Value),
- Helpers.LogLevel.Warning);
+ Helpers.LogLevel.Warning, _Simulator.Client);
}
}
}
else
{
Logger.Log($"Unrecognized caps exception from {_Simulator}: {error.Message}",
- Helpers.LogLevel.Warning);
+ Helpers.LogLevel.Warning, _Simulator.Client);
}
break;
} // end switch
#endregion Error handling
}
+ else if (error != null)
+ {
+ ++_errorCount;
+ Logger.Log($"Exception thrown from {_Simulator} event queue: " +
+ $"{(error.InnerException != null ? error.InnerException.Message : error.Message)}", Helpers.LogLevel.Warning, _Simulator.Client);
+ }
else
{
++_errorCount;
-
- Logger.Log($"No response from {_Simulator} event queue but no reported error either", Helpers.LogLevel.Warning);
+ Logger.Log($"No response from {_Simulator} event queue with no reported error", Helpers.LogLevel.Warning, _Simulator.Client);
}
-
-#pragma warning disable CS0164 // This label has not been referenced
- HandlingDone:
-
- #region Resume the connection
-
- if (_Running)
+
+ if (Running)
{
OSDMap payload = new OSDMap();
if (ack != 0) { payload["ack"] = OSD.FromInteger(ack); }
else { payload["ack"] = new OSD(); }
payload["done"] = OSD.FromBoolean(_Dead);
-
- if (_errorCount > 0) { // Exponentially back off, so we don't hammer the CPU
- Thread.Sleep(Math.Min(REQUEST_BACKOFF_SECONDS + _errorCount * REQUEST_BACKOFF_SECONDS_INC, REQUEST_BACKOFF_SECONDS_MAX));
- }
- // Resume the connection.
- Task req = _Simulator.Client.HttpCapsClient.PostRequestAsync(_Address, OSDFormat.Xml, payload, _HttpCts.Token,
- RequestCompletedHandler);
-
- // If the event queue is dead at this point, turn it off since
- // that was the last thing we want to do
- if (_Dead)
- {
- _Running = false;
- Logger.DebugLog($"Sent event queue shutdown message for {_Simulator}");
- }
+ _AckPayload = payload;
}
-#pragma warning restore CS0164 // This label has not been referenced
-
- #endregion Resume the connection
#region Handle incoming events
diff --git a/LibreMetaverse/Capabilities/HttpCapsClient.cs b/LibreMetaverse/Capabilities/HttpCapsClient.cs
index ff55fd7..9f31663 100644
--- a/LibreMetaverse/Capabilities/HttpCapsClient.cs
+++ b/LibreMetaverse/Capabilities/HttpCapsClient.cs
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2022, Sjofn, LLC.
+ * Copyright (c) 2022-2023, Sjofn, LLC.
* All rights reserved.
*
* - Redistribution and use in source and binary forms, with or without
@@ -234,19 +234,26 @@ namespace LibreMetaverse
private async Task SendRequestAsync(HttpRequestMessage request, CancellationToken? cancellationToken,
DownloadCompleteHandler completeHandler, DownloadProgressHandler progressHandler, ConnectedHandler connectedHandler)
{
- using (var response = (cancellationToken.HasValue)
- ? await SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken.Value)
- : await SendAsync(request, HttpCompletionOption.ResponseHeadersRead))
+ try
{
- if (!response.IsSuccessStatusCode)
+ using (var response = (cancellationToken.HasValue)
+ ? await SendAsync(request, HttpCompletionOption.ResponseHeadersRead, cancellationToken.Value)
+ : await SendAsync(request, HttpCompletionOption.ResponseHeadersRead))
{
- completeHandler?.Invoke(response, null,
- new HttpRequestException(response.StatusCode + " " + response.ReasonPhrase));
+ if (!response.IsSuccessStatusCode)
+ {
+ completeHandler?.Invoke(response, null,
+ new HttpRequestException(response.StatusCode + " " + response.ReasonPhrase));
+ }
+
+ connectedHandler?.Invoke(response);
+
+ await ProcessResponseAsync(response, cancellationToken, completeHandler, progressHandler);
}
-
- connectedHandler?.Invoke(response);
-
- await ProcessResponseAsync(response, cancellationToken, completeHandler, progressHandler);
+ }
+ catch (HttpRequestException ex)
+ {
+ completeHandler?.Invoke(null, null, ex);
}
}
diff --git a/LibreMetaverse/Caps.cs b/LibreMetaverse/Caps.cs
index c7fa081..53bc460 100644
--- a/LibreMetaverse/Caps.cs
+++ b/LibreMetaverse/Caps.cs
@@ -307,6 +307,7 @@ namespace OpenMetaverse
private void EventQueueConnectedHandler()
{
Logger.DebugLog($"Event queue for {Simulator} is connected", Simulator.Client);
+ Simulator.DisconnectCandidate = false;
Simulator.Client.Network.RaiseConnectedEvent(Simulator);
}
@@ -333,7 +334,7 @@ namespace OpenMetaverse
{
Logger.Log($"No Message handler exists for event {eventName}. Unable to decode. Will try Generic Handler next",
Helpers.LogLevel.Warning);
- Logger.Log("Please report this information at https://radegast.life/bugs/issue-entry/: " + Environment.NewLine + body,
+ Logger.Log("Please report this information at https://github.com/cinderblocks/libremetaverse/issues: " + Environment.NewLine + body,
Helpers.LogLevel.Debug);
// try generic decoder next which takes a caps event and tries to match it to an existing packet
diff --git a/LibreMetaverse/DirectoryManager.cs b/LibreMetaverse/DirectoryManager.cs
index b6eb2dd..665a79f 100644
--- a/LibreMetaverse/DirectoryManager.cs
+++ b/LibreMetaverse/DirectoryManager.cs
@@ -1029,7 +1029,7 @@ namespace OpenMetaverse
///
/// Searches Places for land owned by the specified group
///
- /// ID of the group you want to recieve land list for (You must be a member of the group)
+ /// ID of the group you want to receive land list for (You must be a member of the group)
/// Transaction (Query) ID which can be associated with results from your request.
public UUID StartPlacesSearch(UUID groupID)
{
@@ -1055,7 +1055,7 @@ namespace OpenMetaverse
/// One of the values from the SearchCategory Struct, ie: Any, Linden, Newcomer
/// A string containing a list of keywords to search for separated by a space character
/// String Simulator Name to search in
- /// LLUID of group you want to recieve results for
+ /// LLUID of group you want to receive results for
/// Transaction (Query) ID which can be associated with results from your request.
/// Transaction (Query) ID which can be associated with results from your request.
public UUID StartPlacesSearch(DirFindFlags findFlags, ParcelCategory searchCategory, string searchText, string simulatorName,
diff --git a/LibreMetaverse/EstateTools.cs b/LibreMetaverse/EstateTools.cs
index 3969982..06d49f4 100644
--- a/LibreMetaverse/EstateTools.cs
+++ b/LibreMetaverse/EstateTools.cs
@@ -167,8 +167,7 @@ namespace OpenMetaverse
protected virtual void OnTopCollidersReply(TopCollidersReplyEventArgs e)
{
EventHandler handler = m_TopCollidersReply;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -190,8 +189,7 @@ namespace OpenMetaverse
protected virtual void OnTopScriptsReply(TopScriptsReplyEventArgs e)
{
EventHandler handler = m_TopScriptsReply;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -214,8 +212,7 @@ namespace OpenMetaverse
protected virtual void OnEstateUsersReply(EstateUsersReplyEventArgs e)
{
EventHandler handler = m_EstateUsersReply;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -238,8 +235,7 @@ namespace OpenMetaverse
protected virtual void OnEstateGroupsReply(EstateGroupsReplyEventArgs e)
{
EventHandler handler = m_EstateGroupsReply;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -261,8 +257,7 @@ namespace OpenMetaverse
protected virtual void OnEstateManagersReply(EstateManagersReplyEventArgs e)
{
EventHandler handler = m_EstateManagersReply;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -284,8 +279,7 @@ namespace OpenMetaverse
protected virtual void OnEstateBansReply(EstateBansReplyEventArgs e)
{
EventHandler handler = m_EstateBansReply;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -307,8 +301,7 @@ namespace OpenMetaverse
protected virtual void OnEstateCovenantReply(EstateCovenantReplyEventArgs e)
{
EventHandler handler = m_EstateCovenantReply;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -331,8 +324,7 @@ namespace OpenMetaverse
protected virtual void OnEstateUpdateInfoReply(EstateUpdateInfoReplyEventArgs e)
{
EventHandler handler = m_EstateUpdateInfoReply;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
diff --git a/LibreMetaverse/FriendsManager.cs b/LibreMetaverse/FriendsManager.cs
index f9ddfd9..5d2e565 100644
--- a/LibreMetaverse/FriendsManager.cs
+++ b/LibreMetaverse/FriendsManager.cs
@@ -218,8 +218,7 @@ namespace OpenMetaverse
protected virtual void OnfriendsListReady(FriendsReadyEventArgs e)
{
EventHandler handler = m_FriendsListReadyResponse;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -240,8 +239,7 @@ namespace OpenMetaverse
protected virtual void OnFriendOnline(FriendInfoEventArgs e)
{
EventHandler handler = m_FriendOnline;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -263,8 +261,7 @@ namespace OpenMetaverse
protected virtual void OnFriendOffline(FriendInfoEventArgs e)
{
EventHandler handler = m_FriendOffline;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -286,8 +283,7 @@ namespace OpenMetaverse
protected virtual void OnFriendRights(FriendInfoEventArgs e)
{
EventHandler handler = m_FriendRights;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -309,8 +305,7 @@ namespace OpenMetaverse
protected virtual void OnFriendNames(FriendNamesEventArgs e)
{
EventHandler handler = m_FriendNames;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -332,8 +327,7 @@ namespace OpenMetaverse
protected virtual void OnFriendshipOffered(FriendshipOfferedEventArgs e)
{
EventHandler handler = m_FriendshipOffered;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -355,8 +349,7 @@ namespace OpenMetaverse
protected virtual void OnFriendshipResponse(FriendshipResponseEventArgs e)
{
EventHandler handler = m_FriendshipResponse;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -378,8 +371,7 @@ namespace OpenMetaverse
protected virtual void OnFriendshipTerminated(FriendshipTerminatedEventArgs e)
{
EventHandler handler = m_FriendshipTerminated;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -402,8 +394,7 @@ namespace OpenMetaverse
protected virtual void OnFriendFoundReply(FriendFoundReplyEventArgs e)
{
EventHandler handler = m_FriendFound;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
diff --git a/LibreMetaverse/GridClient.cs b/LibreMetaverse/GridClient.cs
index b7c83e1..28b14ad 100644
--- a/LibreMetaverse/GridClient.cs
+++ b/LibreMetaverse/GridClient.cs
@@ -145,7 +145,6 @@ namespace OpenMetaverse
{
AllowAutoRedirect = true,
AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip,
- MaxConnectionsPerServer = Settings.MAX_HTTP_CONNECTIONS,
ServerCertificateCustomValidationCallback = (message, cert, chain, sslPolicyErrors) =>
{
if (sslPolicyErrors == SslPolicyErrors.None)
@@ -157,6 +156,10 @@ namespace OpenMetaverse
return true;
}
};
+
+ if (Utils.GetRunningRuntime() != Utils.Runtime.Mono)
+ handler.MaxConnectionsPerServer = Settings.MAX_HTTP_CONNECTIONS;
+
HttpCapsClient client = new HttpCapsClient(handler);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("User-Agent", $"{Settings.USER_AGENT}");
diff --git a/LibreMetaverse/GridManager.cs b/LibreMetaverse/GridManager.cs
index e273a07..03f75a4 100644
--- a/LibreMetaverse/GridManager.cs
+++ b/LibreMetaverse/GridManager.cs
@@ -158,14 +158,15 @@ namespace OpenMetaverse
public uint GlobalY;
/// Get the Local X position of the item
- public uint LocalX { get { return GlobalX % 256; } }
+ public uint LocalX { get { return GlobalX % Simulator.DefaultRegionSizeX; } }
/// Get the Local Y position of the item
- public uint LocalY { get { return GlobalY % 256; } }
+ public uint LocalY { get { return GlobalY % Simulator.DefaultRegionSizeY; } }
/// Get the Handle of the region
public ulong RegionHandle
{
- get { return Utils.UIntsToLong((uint)(GlobalX - (GlobalX % 256)), (uint)(GlobalY - (GlobalY % 256))); }
+ get { return Utils.UIntsToLong((uint)(GlobalX - (GlobalX % Simulator.DefaultRegionSizeX)),
+ (uint)(GlobalY - (GlobalY % Simulator.DefaultRegionSizeY))); }
}
}
diff --git a/LibreMetaverse/GroupManager.cs b/LibreMetaverse/GroupManager.cs
index 8ef83dd..ad72bfb 100644
--- a/LibreMetaverse/GroupManager.cs
+++ b/LibreMetaverse/GroupManager.cs
@@ -1047,9 +1047,7 @@ namespace OpenMetaverse
UUID requestID = UUID.Random();
Uri cap = null;
- if (Client.Network.CurrentSim != null
- && Client.Network.CurrentSim.Caps != null
- && (cap = Client.Network.CurrentSim.Caps.CapabilityURI("GroupMemberData")) != null)
+ if ((cap = Client.Network.CurrentSim?.Caps?.CapabilityURI("GroupMemberData")) != null)
{
OSDMap payload = new OSDMap(1) { ["group_id"] = @group };
Task req = Client.HttpCapsClient.PostRequestAsync(cap, OSDFormat.Xml, payload, CancellationToken.None,
@@ -1630,11 +1628,9 @@ namespace OpenMetaverse
{
Uri ret = null;
- if (Client.Network.Connected
- && Client.Network.CurrentSim != null
- && Client.Network.CurrentSim.Caps != null)
+ if (Client.Network.Connected)
{
- ret = Client.Network.CurrentSim.Caps.CapabilityURI("GroupAPIv1");
+ ret = Client.Network.CurrentSim?.Caps?.CapabilityURI("GroupAPIv1");
if (ret != null)
{
ret = new Uri($"{ret}?group_id={groupID.ToString()}");
diff --git a/LibreMetaverse/Helpers.cs b/LibreMetaverse/Helpers.cs
index 9f3b09b..45c6076 100644
--- a/LibreMetaverse/Helpers.cs
+++ b/LibreMetaverse/Helpers.cs
@@ -149,6 +149,11 @@ namespace OpenMetaverse
/// Given an X/Y location in absolute (grid-relative) terms, a region
/// handle is returned along with the local X/Y location in that region
///
+ ///
+ /// NOTE: this does not work for varregions -- the region handle is correct but
+ /// the local X,Y are wrong. TODO: create new function
+ /// that takes a reference to the region and thus can calculate region local address.
+ ///
/// The absolute X location, a number such as
/// 255360.35
/// The absolute Y location, a number such as
@@ -160,8 +165,8 @@ namespace OpenMetaverse
/// A 64-bit region handle that can be used to teleport to
public static ulong GlobalPosToRegionHandle(float globalX, float globalY, out float localX, out float localY)
{
- uint x = ((uint)globalX / 256) * 256;
- uint y = ((uint)globalY / 256) * 256;
+ uint x = ((uint)globalX / Simulator.DefaultRegionSizeX) * Simulator.DefaultRegionSizeX;
+ uint y = ((uint)globalY / Simulator.DefaultRegionSizeY) * Simulator.DefaultRegionSizeY;
localX = globalX - (float)x;
localY = globalY - (float)y;
return Utils.UIntsToLong(x, y);
diff --git a/LibreMetaverse/ImportExport/ModelUploader.cs b/LibreMetaverse/ImportExport/ModelUploader.cs
index a487448..9ea6569 100644
--- a/LibreMetaverse/ImportExport/ModelUploader.cs
+++ b/LibreMetaverse/ImportExport/ModelUploader.cs
@@ -196,7 +196,8 @@ namespace OpenMetaverse.ImportExport
Client.Inventory.RequestFetchInventory(reply["new_inventory_item"].AsUUID(), Client.Self.AgentID);
}
}
- if (callback != null) callback(contents);
+
+ callback?.Invoke(contents);
}));
}
}));
diff --git a/LibreMetaverse/InventoryAISClient.cs b/LibreMetaverse/InventoryAISClient.cs
index 4e3e341..cb3cf1c 100644
--- a/LibreMetaverse/InventoryAISClient.cs
+++ b/LibreMetaverse/InventoryAISClient.cs
@@ -48,8 +48,7 @@ namespace LibreMetaverse
Client = client;
}
- public bool IsAvailable => (Client.Network.CurrentSim.Caps != null &&
- Client.Network.CurrentSim.Caps.CapabilityURI(INVENTORY_CAP_NAME) != null);
+ public bool IsAvailable => (Client.Network.CurrentSim.Caps?.CapabilityURI(INVENTORY_CAP_NAME) != null);
public async Task CreateInventory(UUID parentUuid, OSD newInventory, bool createLink, InventoryManager.ItemCreatedCallback callback)
{
diff --git a/LibreMetaverse/InventoryManager.cs b/LibreMetaverse/InventoryManager.cs
index 7113422..5bc8b49 100644
--- a/LibreMetaverse/InventoryManager.cs
+++ b/LibreMetaverse/InventoryManager.cs
@@ -582,8 +582,7 @@ namespace OpenMetaverse
}
Uri cap;
- if (Client.Network.CurrentSim.Caps != null &&
- (cap = Client.Network.CurrentSim.Caps.CapabilityURI("FetchInventory2")) != null)
+ if ((cap = Client.Network.CurrentSim?.Caps?.CapabilityURI("FetchInventory2")) != null)
{
OSDMap payload = new OSDMap { ["agent_id"] = Client.Self.AgentID };
diff --git a/LibreMetaverse/LibreMetaverse.csproj b/LibreMetaverse/LibreMetaverse.csproj
index afe5cde..f42f7a4 100644
--- a/LibreMetaverse/LibreMetaverse.csproj
+++ b/LibreMetaverse/LibreMetaverse.csproj
@@ -11,7 +11,7 @@
true
snupkg
0419,1574,1591
- net48;netstandard2.1;net6.0;net7.0
+ net7.0
x64;x86;AnyCPU
..\bin\
@@ -44,8 +44,8 @@
-
-
+
+
diff --git a/LibreMetaverse/Login.cs b/LibreMetaverse/Login.cs
index de2d593..bc1abdd 100644
--- a/LibreMetaverse/Login.cs
+++ b/LibreMetaverse/Login.cs
@@ -369,6 +369,8 @@ namespace OpenMetaverse
public int CircuitCode;
public uint RegionX;
public uint RegionY;
+ public uint RegionSizeX;
+ public uint RegionSizeY;
public ushort SimPort;
public IPAddress SimIP;
public string SeedCapability;
@@ -488,6 +490,9 @@ namespace OpenMetaverse
CircuitCode = (int)ParseUInt("circuit_code", reply);
RegionX = ParseUInt("region_x", reply);
RegionY = ParseUInt("region_y", reply);
+ // Region size is returned by OpenSimulator derived systems but not SL
+ RegionSizeX = reply.ContainsKey("region_size_x") ? ParseUInt("region_size_x", reply) : Simulator.DefaultRegionSizeX;
+ RegionSizeY = reply.ContainsKey("region_size_y") ? ParseUInt("region_size_y", reply) : Simulator.DefaultRegionSizeY;
SimPort = (ushort)ParseUInt("sim_port", reply);
var simIP = ParseString("sim_ip", reply);
IPAddress.TryParse(simIP, out SimIP);
@@ -693,6 +698,9 @@ namespace OpenMetaverse
CircuitCode = (int)ParseUInt("circuit_code", reply);
RegionX = ParseUInt("region_x", reply);
RegionY = ParseUInt("region_y", reply);
+ // Region size is returned by OpenSimulator derived systems but not SL
+ RegionSizeX = reply.ContainsKey("region_size_x") ? ParseUInt("region_size_x", reply) : Simulator.DefaultRegionSizeX;
+ RegionSizeY = reply.ContainsKey("region_size_y") ? ParseUInt("region_size_y", reply) : Simulator.DefaultRegionSizeY;
SimPort = (ushort)ParseUInt("sim_port", reply);
var simIP = ParseString("sim_ip", reply);
IPAddress.TryParse(simIP, out SimIP);
@@ -1691,7 +1699,7 @@ namespace OpenMetaverse
var handle = Utils.UIntsToLong(regionX, regionY);
// Connect to the sim given in the login reply
- if (Connect(reply.SimIP, simPort, handle, true, LoginSeedCapability) != null)
+ if (Connect(reply.SimIP, simPort, handle, true, LoginSeedCapability, reply.RegionSizeX, reply.RegionSizeY) != null)
{
// Request the economy data right after login
SendPacket(new EconomyDataRequestPacket());
diff --git a/LibreMetaverse/Messages/LindenMessages.cs b/LibreMetaverse/Messages/LindenMessages.cs
index be2565f..f6f1025 100644
--- a/LibreMetaverse/Messages/LindenMessages.cs
+++ b/LibreMetaverse/Messages/LindenMessages.cs
@@ -1,4 +1,4 @@
-/*
+/*
* Copyright (c) 2006-2016, openmetaverse.co
* Copyright (c) 2021-2022, Sjofn LLC
* All rights reserved.
@@ -61,6 +61,10 @@ namespace OpenMetaverse.Messages.Linden
/// Status flags indicating the state of the Agent upon arrival, Flying, etc.
public TeleportFlags Flags;
+ /// The size of the region teleporting into
+ public uint RegionSizeX;
+ public uint RegionSizeY;
+
///
/// Serialize the object
///
@@ -71,7 +75,7 @@ namespace OpenMetaverse.Messages.Linden
OSDArray infoArray = new OSDArray(1);
- OSDMap info = new OSDMap(8)
+ OSDMap info = new OSDMap(10)
{
{"AgentID", OSD.FromUUID(AgentID)},
{"LocationID", OSD.FromInteger(LocationID)},
@@ -80,7 +84,9 @@ namespace OpenMetaverse.Messages.Linden
{"SimAccess", OSD.FromInteger((byte) SimAccess)},
{"SimIP", MessageUtils.FromIP(IP)},
{"SimPort", OSD.FromInteger(Port)},
- {"TeleportFlags", OSD.FromUInteger((uint) Flags)}
+ {"TeleportFlags", OSD.FromUInteger((uint) Flags)},
+ {"RegionSizeX", OSD.FromUInteger((uint) RegionSizeX)},
+ {"RegionSizeY", OSD.FromUInteger((uint) RegionSizeY)}
};
// Unused by the client
@@ -108,6 +114,8 @@ namespace OpenMetaverse.Messages.Linden
IP = MessageUtils.ToIP(blockMap["SimIP"]);
Port = blockMap["SimPort"].AsInteger();
Flags = (TeleportFlags)blockMap["TeleportFlags"].AsUInteger();
+ RegionSizeX = blockMap.ContainsKey("RegionSizeX") ? blockMap["RegionSizeX"].AsUInteger() : Simulator.DefaultRegionSizeX;
+ RegionSizeY = blockMap.ContainsKey("RegionSizeY") ? blockMap["RegionSizeY"].AsUInteger() : Simulator.DefaultRegionSizeY;
}
}
@@ -162,6 +170,8 @@ namespace OpenMetaverse.Messages.Linden
public Uri SeedCapability;
public IPAddress IP;
public int Port;
+ public uint RegionSizeX;
+ public uint RegionSizeY;
///
/// Serialize the object
@@ -190,12 +200,14 @@ namespace OpenMetaverse.Messages.Linden
map["AgentData"] = agentDataArray;
OSDArray regionDataArray = new OSDArray(1);
- OSDMap regionDataMap = new OSDMap(4)
+ OSDMap regionDataMap = new OSDMap(6)
{
["RegionHandle"] = OSD.FromULong(RegionHandle),
["SeedCapability"] = OSD.FromUri(SeedCapability),
["SimIP"] = MessageUtils.FromIP(IP),
- ["SimPort"] = OSD.FromInteger(Port)
+ ["SimPort"] = OSD.FromInteger(Port),
+ ["RegionSizeX"] = OSD.FromUInteger(RegionSizeX),
+ ["RegionSizeY"] = OSD.FromUInteger(RegionSizeY)
};
regionDataArray.Add(regionDataMap);
map["RegionData"] = regionDataArray;
@@ -222,6 +234,8 @@ namespace OpenMetaverse.Messages.Linden
SeedCapability = regionDataMap["SeedCapability"].AsUri();
IP = MessageUtils.ToIP(regionDataMap["SimIP"]);
Port = regionDataMap["SimPort"].AsInteger();
+ RegionSizeX = regionDataMap.ContainsKey("RegionSizeX") ? regionDataMap["RegionSizeX"].AsUInteger() : Simulator.DefaultRegionSizeX;
+ RegionSizeY = regionDataMap.ContainsKey("RegionSizeY") ? regionDataMap["RegionSizeY"].AsUInteger() : Simulator.DefaultRegionSizeY;
}
}
@@ -232,6 +246,8 @@ namespace OpenMetaverse.Messages.Linden
public ulong RegionHandle;
public IPAddress IP;
public int Port;
+ public uint RegionSizeX;
+ public uint RegionSizeY;
}
public SimulatorInfoBlock[] Simulators;
@@ -247,11 +263,13 @@ namespace OpenMetaverse.Messages.Linden
OSDArray array = new OSDArray(Simulators.Length);
foreach (SimulatorInfoBlock block in Simulators)
{
- OSDMap blockMap = new OSDMap(3)
+ OSDMap blockMap = new OSDMap(5)
{
["Handle"] = OSD.FromULong(block.RegionHandle),
["IP"] = MessageUtils.FromIP(block.IP),
- ["Port"] = OSD.FromInteger(block.Port)
+ ["Port"] = OSD.FromInteger(block.Port),
+ ["RegionSizeX"] = OSD.FromUInteger(block.RegionSizeX),
+ ["RegionSizeY"] = OSD.FromUInteger(block.RegionSizeY),
};
array.Add(blockMap);
}
@@ -277,7 +295,9 @@ namespace OpenMetaverse.Messages.Linden
{
RegionHandle = blockMap["Handle"].AsULong(),
IP = MessageUtils.ToIP(blockMap["IP"]),
- Port = blockMap["Port"].AsInteger()
+ Port = blockMap["Port"].AsInteger(),
+ RegionSizeX = blockMap.ContainsKey("RegionSizeX") ? blockMap["RegionSizeX"].AsUInteger() : Simulator.DefaultRegionSizeX,
+ RegionSizeY = blockMap.ContainsKey("RegionSizeY") ? blockMap["RegionSizeY"].AsUInteger() : Simulator.DefaultRegionSizeY,
};
Simulators[i] = block;
}
@@ -5395,7 +5415,7 @@ namespace OpenMetaverse.Messages.Linden
}
///
- /// Message recieved in response to request to change display name
+ /// Message received in response to request to change display name
///
public class SetDisplayNameReplyMessage : IMessage
{
@@ -5434,7 +5454,7 @@ namespace OpenMetaverse.Messages.Linden
}
///
- /// Message recieved when someone nearby changes their display name
+ /// Message received when someone nearby changes their display name
///
public class DisplayNameUpdateMessage : IMessage
{
diff --git a/LibreMetaverse/NetworkManager.cs b/LibreMetaverse/NetworkManager.cs
index f8794a3..c182693 100644
--- a/LibreMetaverse/NetworkManager.cs
+++ b/LibreMetaverse/NetworkManager.cs
@@ -36,7 +36,7 @@ using OpenMetaverse.Interfaces;
using OpenMetaverse.Messages.Linden;
namespace OpenMetaverse
-{
+{
///
/// NetworkManager is responsible for managing the network layer of
/// OpenMetaverse. It tracks all the server connections, serializes
@@ -463,14 +463,14 @@ namespace OpenMetaverse
{
Logger.DebugLog("simulator object was null, using first found connected simulator", Client);
simulator = Client.Network.Simulators[0];
- }
+ }
if (simulator != null)
{
simulator.SendPacket(packet);
}
- else
- {
- NetworkInvaildWarning("simulator", "SendPacket");
+ else
+ {
+ NetworkInvaildWarning("simulator", "SendPacket");
}
}
@@ -479,34 +479,34 @@ namespace OpenMetaverse
///
/// Incoming packet to process
public void EnqueueIncoming(IncomingPacket packet)
- {
- if (_packetInbox != null)
- {
- if (_packetInbox.Writer.TryWrite(packet))
- Interlocked.Increment(ref _packetInboxCount);
- }
- else
- {
- NetworkInvaildWarning("_packetInbox", "EnqueueIncoming");
+ {
+ if (_packetInbox != null)
+ {
+ if (_packetInbox.Writer.TryWrite(packet))
+ Interlocked.Increment(ref _packetInboxCount);
}
- }
-
+ else
+ {
+ NetworkInvaildWarning("_packetInbox", "EnqueueIncoming");
+ }
+ }
+
///
/// adds a debug message when you try to access a network item
/// while they are still null
///
/// what
/// where
- protected void NetworkInvaildWarning(string source,string function)
- {
- long now = DateTimeOffset.Now.ToUnixTimeSeconds();
- long dif = lastpacketwarning - now;
- if (dif > 10)
- {
- lastpacketwarning = now;
- Logger.Log(source+" is null (Are we disconnected?) - from: "+ function,
- Helpers.LogLevel.Debug);
- }
+ protected void NetworkInvaildWarning(string source,string function)
+ {
+ long now = DateTimeOffset.Now.ToUnixTimeSeconds();
+ long dif = lastpacketwarning - now;
+ if (dif > 10)
+ {
+ lastpacketwarning = now;
+ Logger.Log(source+" is null (Are we disconnected?) - from: " + function,
+ Helpers.LogLevel.Debug);
+ }
}
///
@@ -515,17 +515,30 @@ namespace OpenMetaverse
/// Incoming packet to process
public void EnqueueOutgoing(OutgoingPacket packet)
{
- if (_packetOutbox != null)
- {
- if (_packetOutbox.Writer.TryWrite(packet))
+ if (_packetOutbox != null)
+ {
+ if (_packetOutbox.Writer.TryWrite(packet))
Interlocked.Increment(ref _packetOutboxCount);
- }
- else
- {
- NetworkInvaildWarning("_packetOutbox", "EnqueueOutgoing");
+ }
+ else
+ {
+ NetworkInvaildWarning("_packetOutbox", "EnqueueOutgoing");
}
}
+ ///
+ /// Connect to simulator assuming legacy region size
+ ///
+ /// IP address to connect to
+ /// Port to connect to
+ ///
+ ///
+ ///
+ ///
+ public Simulator Connect(IPAddress ip, ushort port, ulong handle, bool setDefault, Uri seedcaps)
+ {
+ return Connect(ip, port, handle, setDefault, seedcaps, Simulator.DefaultRegionSizeX, Simulator.DefaultRegionSizeY);
+ }
///
/// Connect to a simulator
///
@@ -537,13 +550,26 @@ namespace OpenMetaverse
/// connection, use this if the avatar is moving in to this simulator
/// URL of the capabilities server to use for
/// this sim connection
+ /// Size of the region in X meters
+ /// Size of the region in Y meters
/// A Simulator object on success, otherwise null
- public Simulator Connect(IPAddress ip, ushort port, ulong handle, bool setDefault, Uri seedcaps)
+ public Simulator Connect(IPAddress ip, ushort port, ulong handle, bool setDefault, Uri seedcaps, uint sizeX, uint sizeY)
{
IPEndPoint endPoint = new IPEndPoint(ip, port);
- return Connect(endPoint, handle, setDefault, seedcaps);
+ return Connect(endPoint, handle, setDefault, seedcaps, sizeX, sizeY);
}
+ ///
+ /// Connect to simulator assuming legacy region size
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ public Simulator Connect(IPEndPoint endPoint, ulong handle, bool setDefault, Uri seedcaps) {
+ return Connect(endPoint, handle, setDefault, seedcaps, Simulator.DefaultRegionSizeX, Simulator.DefaultRegionSizeY);
+ }
///
/// Connect to a simulator
///
@@ -554,15 +580,17 @@ namespace OpenMetaverse
/// connection, use this if the avatar is moving in to this simulator
/// URL of the capabilities server to use for
/// this sim connection
+ /// Size of the region in X meters
+ /// Size of the region in Y meters
/// A Simulator object on success, otherwise null
- public Simulator Connect(IPEndPoint endPoint, ulong handle, bool setDefault, Uri seedcaps)
+ public Simulator Connect(IPEndPoint endPoint, ulong handle, bool setDefault, Uri seedcaps, uint sizeX, uint sizeY)
{
Simulator simulator = FindSimulator(endPoint);
if (simulator == null)
{
// We're not tracking this sim, create a new Simulator object
- simulator = new Simulator(Client, endPoint, handle);
+ simulator = new Simulator(Client, endPoint, handle, sizeX, sizeY);
// Immediately add this simulator to the list of current sims. It will be removed if the
// connection fails
@@ -639,7 +667,7 @@ namespace OpenMetaverse
lock (Simulators)
{
Simulators.Remove(simulator);
- }
+ }
return null;
}
@@ -682,13 +710,13 @@ namespace OpenMetaverse
// Otherwise we fire it manually with a NetworkTimeout type after LOGOUT_TIMEOUT
System.Timers.Timer timeout = new System.Timers.Timer();
- EventHandler callback = delegate
+ void Callback(object sender, LoggedOutEventArgs e)
{
Shutdown(DisconnectType.ClientInitiated);
timeout.Stop();
- };
+ }
- LoggedOut += callback;
+ LoggedOut += Callback;
timeout.Interval = Client.Settings.LOGOUT_TIMEOUT;
timeout.Elapsed += delegate
@@ -702,7 +730,7 @@ namespace OpenMetaverse
// Send the packet requesting a clean logout
RequestLogout();
- LoggedOut -= callback;
+ LoggedOut -= Callback;
}
///
@@ -713,9 +741,13 @@ namespace OpenMetaverse
public void Logout()
{
AutoResetEvent logoutEvent = new AutoResetEvent(false);
- EventHandler callback = delegate { logoutEvent.Set(); };
- LoggedOut += callback;
+ void Callback(object sender, LoggedOutEventArgs e)
+ {
+ logoutEvent.Set();
+ }
+
+ LoggedOut += Callback;
// Send the packet requesting a clean logout
RequestLogout();
@@ -724,9 +756,11 @@ namespace OpenMetaverse
// will be fired in the callback. Otherwise we fire it manually with
// a NetworkTimeout type
if (!logoutEvent.WaitOne(Client.Settings.LOGOUT_TIMEOUT, false))
+ {
Shutdown(DisconnectType.NetworkTimeout);
+ }
- LoggedOut -= callback;
+ LoggedOut -= Callback;
}
///
@@ -787,20 +821,26 @@ namespace OpenMetaverse
simulatorsCount = Simulators.Count;
}
- if (simulatorsCount == 0) Shutdown(DisconnectType.SimShutdown);
+ if (simulatorsCount == 0)
+ {
+ Shutdown(DisconnectType.SimShutdown, $"You have disconnected from {simulator.Name}.");
+ }
}
- else
- {
- NetworkInvaildWarning("simulator", "DisconnectSim");
+ else
+ {
+ NetworkInvaildWarning("simulator", "DisconnectSim");
}
}
///
- /// Shutdown will disconnect all the sims except for the current sim
- /// first, and then kill the connection to CurrentSim. This should only
- /// be called if the logout process times out on RequestLogout
+ /// This method disconnects Client from all simulators leaving CurrentSim
+ /// last to disconnect.
///
+ ///
+ /// This should only be called if the logout process times out on
+ /// RequestLogout
+ ///
/// Type of shutdown
public void Shutdown(DisconnectType type)
{
@@ -808,10 +848,13 @@ namespace OpenMetaverse
}
///
- /// Shutdown will disconnect all the sims except for the current sim
- /// first, and then kill the connection to CurrentSim. This should only
- /// be called if the logout process times out on RequestLogout
+ /// This method disconnects Client from all simulators leaving CurrentSim
+ /// last to disconnect.
///
+ ///
+ /// This should only be called if the logout process times out on
+ /// RequestLogout
+ ///
/// Type of shutdown
/// Shutdown message
public void Shutdown(DisconnectType type, string message)
@@ -824,17 +867,14 @@ namespace OpenMetaverse
lock (Simulators)
{
// Disconnect all simulators except the current one
- foreach (Simulator t in Simulators)
+ foreach (var sim in Simulators.Where(t => t != null && t != CurrentSim))
{
- if (t != null && t != CurrentSim)
- {
- t.Disconnect(sendCloseCircuit);
+ sim.Disconnect(sendCloseCircuit);
- // Fire the SimDisconnected event if a handler is registered
- if (m_SimDisconnected != null)
- {
- OnSimDisconnected(new SimDisconnectedEventArgs(t, type));
- }
+ // Fire the SimDisconnected event if a handler is registered
+ if (m_SimDisconnected != null)
+ {
+ OnSimDisconnected(new SimDisconnectedEventArgs(sim, type));
}
}
@@ -843,7 +883,7 @@ namespace OpenMetaverse
if (CurrentSim != null)
{
- // Kill the connection to the curent simulator
+ // Kill the connection to the current simulator
CurrentSim.Disconnect(sendCloseCircuit);
// Fire the SimDisconnected event if a handler is registered
@@ -881,10 +921,9 @@ namespace OpenMetaverse
{
lock (Simulators)
{
- foreach (Simulator t in Simulators)
+ foreach (var sim in Simulators.Where(t => t.IPEndPoint.Equals(endPoint)))
{
- if (t.IPEndPoint.Equals(endPoint))
- return t;
+ return sim;
}
}
@@ -913,73 +952,73 @@ namespace OpenMetaverse
private async Task OutgoingPacketHandler()
{
- if (_packetOutbox != null)
- {
- var reader = _packetOutbox.Reader;
-
- // 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 (reader.TryRead(out var outgoingPacket))
- {
- Interlocked.Decrement(ref _packetOutboxCount);
-
- var simulator = outgoingPacket.Simulator;
-
- stopwatch.Stop();
- if (stopwatch.ElapsedMilliseconds < 10)
- {
- //Logger.DebugLog(String.Format("Rate limiting, last packet was {0}ms ago", ms));
- Thread.Sleep(10 - (int)stopwatch.ElapsedMilliseconds);
- }
-
- simulator.SendPacketFinal(outgoingPacket);
- stopwatch.Start();
- }
+ if (_packetOutbox != null)
+ {
+ var reader = _packetOutbox.Reader;
+
+ // 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 (reader.TryRead(out var outgoingPacket))
+ {
+ Interlocked.Decrement(ref _packetOutboxCount);
+
+ var simulator = outgoingPacket.Simulator;
+
+ stopwatch.Stop();
+ if (stopwatch.ElapsedMilliseconds < 10)
+ {
+ //Logger.DebugLog(String.Format("Rate limiting, last packet was {0}ms ago", ms));
+ Thread.Sleep(10 - (int)stopwatch.ElapsedMilliseconds);
+ }
+
+ simulator.SendPacketFinal(outgoingPacket);
+ stopwatch.Start();
+ }
}
- }
- else
- {
- NetworkInvaildWarning("_packetOutbox", "OutgoingPacketHandler");
+ }
+ else
+ {
+ NetworkInvaildWarning("_packetOutbox", "OutgoingPacketHandler");
}
}
private async Task IncomingPacketHandler()
{
- if (_packetInbox != null)
- {
- var reader = _packetInbox.Reader;
-
- while (await reader.WaitToReadAsync() && Connected)
- {
- while (reader.TryRead(out var incomingPacket))
- {
- Interlocked.Decrement(ref _packetInboxCount);
-
- var packet = incomingPacket.Packet;
- var simulator = incomingPacket.Simulator;
-
- if (packet == null) continue;
-
- // Skip blacklisted packets
- if (UDPBlacklist.Contains(packet.Type.ToString()))
- {
- Logger.Log($"Discarding Blacklisted packet {packet.Type} from {simulator.IPEndPoint}",
- Helpers.LogLevel.Warning);
- return;
- }
-
- // Fire the callback(s), if any
- PacketEvents.RaiseEvent(packet.Type, packet, simulator);
- }
+ if (_packetInbox != null)
+ {
+ var reader = _packetInbox.Reader;
+
+ while (await reader.WaitToReadAsync() && Connected)
+ {
+ while (reader.TryRead(out var incomingPacket))
+ {
+ Interlocked.Decrement(ref _packetInboxCount);
+
+ var packet = incomingPacket.Packet;
+ var simulator = incomingPacket.Simulator;
+
+ if (packet == null) continue;
+
+ // Skip blacklisted packets
+ if (UDPBlacklist.Contains(packet.Type.ToString()))
+ {
+ Logger.Log($"Discarding Blacklisted packet {packet.Type} from {simulator.IPEndPoint}",
+ Helpers.LogLevel.Warning);
+ return;
+ }
+
+ // Fire the callback(s), if any
+ PacketEvents.RaiseEvent(packet.Type, packet, simulator);
+ }
}
- }
- else
- {
- NetworkInvaildWarning("_packetInbox", "IncomingPacketHandler");
+ }
+ else
+ {
+ NetworkInvaildWarning("_packetInbox", "IncomingPacketHandler");
}
}
@@ -1277,10 +1316,10 @@ namespace OpenMetaverse
if (FindSimulator(endPoint) != null) return;
- if (Connect(ip, port, handle, false, null) == null)
+ if (Connect(ip, port, handle, false, null, t.RegionSizeX, t.RegionSizeY) == null)
{
Logger.Log($"Unable to connect to new sim {ip}:{port}",
- Helpers.LogLevel.Error, Client);
+ Helpers.LogLevel.Error, Client);
}
}
}
diff --git a/LibreMetaverse/ObjectManager.cs b/LibreMetaverse/ObjectManager.cs
index e7470a8..d7df9cc 100644
--- a/LibreMetaverse/ObjectManager.cs
+++ b/LibreMetaverse/ObjectManager.cs
@@ -198,8 +198,7 @@ namespace OpenMetaverse
protected virtual void OnObjectProperties(ObjectPropertiesEventArgs e)
{
EventHandler handler = m_ObjectProperties;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -224,8 +223,7 @@ namespace OpenMetaverse
protected virtual void OnObjectPropertiesUpdated(ObjectPropertiesUpdatedEventArgs e)
{
EventHandler handler = m_ObjectPropertiesUpdated;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -250,8 +248,7 @@ namespace OpenMetaverse
protected virtual void OnObjectPropertiesFamily(ObjectPropertiesFamilyEventArgs e)
{
EventHandler handler = m_ObjectPropertiesFamily;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -278,8 +275,7 @@ namespace OpenMetaverse
protected virtual void OnAvatarUpdate(AvatarUpdateEventArgs e)
{
EventHandler handler = m_AvatarUpdate;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
///
/// Raises the ParticleUpdate Event
@@ -288,8 +284,7 @@ namespace OpenMetaverse
/// the data sent from the simulator
protected virtual void OnParticleUpdate(ParticleUpdateEventArgs e) {
EventHandler handler = m_ParticleUpdate;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -337,8 +332,7 @@ namespace OpenMetaverse
protected virtual void OnObjectDataBlockUpdate(ObjectDataBlockUpdateEventArgs e)
{
EventHandler handler = m_ObjectDataBlockUpdate;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -363,8 +357,7 @@ namespace OpenMetaverse
protected virtual void OnKillObject(KillObjectEventArgs e)
{
EventHandler handler = m_KillObject;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -389,8 +382,7 @@ namespace OpenMetaverse
protected virtual void OnKillObjects(KillObjectsEventArgs e)
{
EventHandler handler = m_KillObjects;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -415,8 +407,7 @@ namespace OpenMetaverse
protected virtual void OnAvatarSitChanged(AvatarSitChangedEventArgs e)
{
EventHandler handler = m_AvatarSitChanged;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -441,8 +432,7 @@ namespace OpenMetaverse
protected virtual void OnPayPriceReply(PayPriceReplyEventArgs e)
{
EventHandler handler = m_PayPriceReply;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -475,8 +465,7 @@ namespace OpenMetaverse
protected virtual void OnPhysicsProperties(PhysicsPropertiesEventArgs e)
{
EventHandler handler = m_PhysicsProperties;
- if (handler != null)
- handler(this, e);
+ handler?.Invoke(this, e);
}
/// Thread sync lock object
@@ -2611,8 +2600,7 @@ namespace OpenMetaverse
#region Raise Events
EventHandler handler = m_ObjectUpdate;
- if (handler != null)
- handler(this, new PrimEventArgs(simulator, prim, update.RegionData.TimeDilation, isNew, prim.IsAttachment));
+ handler?.Invoke(this, new PrimEventArgs(simulator, prim, update.RegionData.TimeDilation, isNew, prim.IsAttachment));
#endregion
}
@@ -3310,10 +3298,7 @@ namespace OpenMetaverse
// Start the timer again. Use a minimum of a 50ms pause in between calculations
int delay = Math.Max(50, Settings.INTERPOLATION_INTERVAL - elapsed);
- if (InterpolationTimer != null)
- {
- InterpolationTimer.Change(delay, Timeout.Infinite);
- }
+ InterpolationTimer?.Change(delay, Timeout.Infinite);
}
}
diff --git a/LibreMetaverse/ParcelManager.cs b/LibreMetaverse/ParcelManager.cs
index d6f064f..d105099 100644
--- a/LibreMetaverse/ParcelManager.cs
+++ b/LibreMetaverse/ParcelManager.cs
@@ -606,13 +606,12 @@ namespace OpenMetaverse
Media = new ParcelMedia();
}
- ///
- /// Update the parcel (in the current sim)
- ///
- /// Client message originates from
- /// Whether we want the simulator to confirm
- /// the update with a reply packet or not [default false]
- public void Update(GridClient client, bool wantReply = false)
+ public void Update(GridClient client)
+ {
+ Update(client, client.Network.CurrentSim, false);
+ }
+
+ public void Update(GridClient client, bool wantReply)
{
Update(client, client.Network.CurrentSim, wantReply);
}
@@ -1688,7 +1687,17 @@ namespace OpenMetaverse
{
OSD res = null;
await Client.HttpCapsClient.PostRequestAsync(cap, OSDFormat.Xml, msg.Serialize(), CancellationToken.None,
- (response, data, error) => res = OSDParser.Deserialize(data));
+ (response, data, error) =>
+ {
+ if (data != null)
+ {
+ res = OSDParser.Deserialize(data);
+ }
+ else if (error != null)
+ {
+ Logger.Log("Did not receive response from RemoteParcelRequest: " + error.Message, Helpers.LogLevel.Warning, Client);
+ }
+ });
if (res is OSDMap result)
{
diff --git a/LibreMetaverse/Primitives/TextureEntry.cs b/LibreMetaverse/Primitives/TextureEntry.cs
index 5359703..3cf9f51 100644
--- a/LibreMetaverse/Primitives/TextureEntry.cs
+++ b/LibreMetaverse/Primitives/TextureEntry.cs
@@ -768,16 +768,11 @@ namespace OpenMetaverse
private void FromBytes(byte[] data, int pos, int length)
{
+ DefaultTexture = new TextureEntryFace(null);
+
if (length < 16)
- {
// No TextureEntry to process
- DefaultTexture = null;
return;
- }
- else
- {
- DefaultTexture = new TextureEntryFace(null);
- }
uint bitfieldSize = 0;
uint faceBits = 0;
diff --git a/LibreMetaverse/Settings.cs b/LibreMetaverse/Settings.cs
index aec56ab..748ae9e 100644
--- a/LibreMetaverse/Settings.cs
+++ b/LibreMetaverse/Settings.cs
@@ -217,10 +217,6 @@ namespace OpenMetaverse
/// server the full object info will automatically be requested
public bool ALWAYS_REQUEST_OBJECTS = true;
- /// Whether to establish connections to HTTP capabilities
- /// servers for simulators
- public bool ENABLE_CAPS = true;
-
/// Whether to decode sim stats
public bool ENABLE_SIMSTATS = true;
@@ -342,11 +338,7 @@ namespace OpenMetaverse
/// You will get no output on the console. This behavior can be overriden by creating
/// a logger configuration file for log4net
///
-#if DEBUG
- public static Helpers.LogLevel LOG_LEVEL = Helpers.LogLevel.Debug;
-#else
public static Helpers.LogLevel LOG_LEVEL = Helpers.LogLevel.None;
-#endif
/// Attach avatar names to log messages
public bool LOG_NAMES = true;
diff --git a/LibreMetaverse/Simulator.cs b/LibreMetaverse/Simulator.cs
index 6d74060..2f82738 100644
--- a/LibreMetaverse/Simulator.cs
+++ b/LibreMetaverse/Simulator.cs
@@ -171,7 +171,7 @@ namespace OpenMetaverse
public int ConnectTime;
/// Total number of packets that have been resent
public int ResentPackets;
- /// Total number of resent packets recieved
+ /// Total number of resent packets received
public int ReceivedResends;
/// Total number of pings sent to this simulator by this agent
public int SentPings;
@@ -180,7 +180,7 @@ namespace OpenMetaverse
///
/// Incoming bytes per second
///
- /// It would be nice to have this claculated on the fly, but
+ /// It would be nice to have this calculated on the fly, but
/// this is far, far easier
public int IncomingBPS;
///
@@ -252,6 +252,11 @@ namespace OpenMetaverse
#endregion Structs
#region Public Members
+
+ // Default legacy simulator/region size
+ public const uint DefaultRegionSizeX = 256;
+ public const uint DefaultRegionSizeY = 256;
+
/// A public reference to the client that this Simulator object is attached to
public GridClient Client;
/// A Unique Cache identifier for this simulator
@@ -260,6 +265,10 @@ namespace OpenMetaverse
public Caps Caps;
/// Unique identified for this region generated via it's coordinates on the world map
public ulong Handle;
+ /// Simulator land size in X direction in meters
+ public uint SizeX;
+ /// Simulator land size in Y direction in meters
+ public uint SizeY;
/// The current version of software this simulator is running
public string SimVersion = String.Empty;
/// Human readable name given to the simulator
@@ -497,10 +506,7 @@ namespace OpenMetaverse
public readonly SimulatorDataPool DataPool;
internal bool DownloadingParcelMap
{
- get
- {
- return Client.Settings.POOL_PARCEL_DATA ? DataPool.DownloadingParcelMap : _DownloadingParcelMap;
- }
+ get => Client.Settings.POOL_PARCEL_DATA ? DataPool.DownloadingParcelMap : _DownloadingParcelMap;
set
{
if (Client.Settings.POOL_PARCEL_DATA) DataPool.DownloadingParcelMap = value;
@@ -520,7 +526,7 @@ namespace OpenMetaverse
/// Reference to the object
/// IPEndPoint of the simulator
/// Region handle for the simulator
- public Simulator(GridClient client, IPEndPoint address, ulong handle)
+ public Simulator(GridClient client, IPEndPoint address, ulong handle, uint sizeX = DefaultRegionSizeX, uint sizeY = DefaultRegionSizeY)
: base(address)
{
Client = client;
@@ -532,14 +538,16 @@ namespace OpenMetaverse
Handle = handle;
Network = Client.Network;
+ SizeX = sizeX;
+ SizeY = sizeY;
PacketArchive = new IncomingPacketIDCollection(Settings.PACKET_ARCHIVE_SIZE);
InBytes = new Queue(Client.Settings.STATS_QUEUE_SIZE);
OutBytes = new Queue(Client.Settings.STATS_QUEUE_SIZE);
if (client.Settings.STORE_LAND_PATCHES)
{
- Terrain = new TerrainPatch[16 * 16];
- WindSpeeds = new Vector2[16 * 16];
+ Terrain = new TerrainPatch[sizeX/16 * sizeY/16];
+ WindSpeeds = new Vector2[sizeX/16 * sizeY/16];
}
}
@@ -648,7 +656,7 @@ namespace OpenMetaverse
///
/// Initiates connection to the simulator
///
- /// Should we block until ack for this packet is recieved
+ /// Should we block until ack for this packet is received
public void UseCircuitCode(bool waitForAck)
{
// Send the UseCircuitCode packet to initiate the connection
@@ -690,17 +698,14 @@ namespace OpenMetaverse
Caps = null;
}
- if (Client.Settings.ENABLE_CAPS)
+ // Connect to the CAPS system
+ if (seedcaps != null)
{
- // Connect to the new CAPS system
- if (seedcaps != null)
- {
- Caps = new Caps(this, seedcaps);
- }
- else
- {
- Logger.Log("Setting up a sim without a valid capabilities server!", Helpers.LogLevel.Error, Client);
- }
+ Caps = new Caps(this, seedcaps);
+ }
+ else
+ {
+ Logger.Log("Setting up a sim without valid http capabilities", Helpers.LogLevel.Error, Client);
}
}
@@ -709,6 +714,8 @@ namespace OpenMetaverse
///
public void Disconnect(bool sendCloseCircuit)
{
+ DisconnectCandidate = false;
+
if (!connected) return;
connected = false;
@@ -795,7 +802,7 @@ namespace OpenMetaverse
/// True if the lookup was successful, otherwise false
public bool TerrainHeightAtPoint(int x, int y, out float height)
{
- if (Terrain != null && x >= 0 && x < 256 && y >= 0 && y < 256)
+ if (Terrain != null && x >= 0 && x < SizeX && y >= 0 && y < SizeY)
{
int patchX = x / 16;
int patchY = y / 16;
@@ -1002,7 +1009,7 @@ namespace OpenMetaverse
///
/// Returns Simulator Name as a String
///
- ///
+ /// Simulator name as String
public override string ToString()
{
return !String.IsNullOrEmpty(Name)
@@ -1059,8 +1066,8 @@ namespace OpenMetaverse
// Check if this packet came from the server we expected it to come from
if (!remoteEndPoint.Address.Equals(((IPEndPoint)buffer.RemoteEndPoint).Address))
{
- Logger.Log("Received " + buffer.DataLength + " bytes of data from unrecognized source " +
- ((IPEndPoint)buffer.RemoteEndPoint), Helpers.LogLevel.Warning, Client);
+ Logger.Log($"Received {buffer.DataLength} bytes of data from unrecognized source {(IPEndPoint)buffer.RemoteEndPoint}",
+ Helpers.LogLevel.Warning, Client);
return;
}
@@ -1201,7 +1208,7 @@ namespace OpenMetaverse
///
- /// Sends out pending acknowledgements
+ /// Sends out pending acknowledgments
///
/// Number of ACKs sent
private int SendAcks()
diff --git a/LibreMetaverse/TerrainCompressor.cs b/LibreMetaverse/TerrainCompressor.cs
index 43ffd4a..7677b76 100644
--- a/LibreMetaverse/TerrainCompressor.cs
+++ b/LibreMetaverse/TerrainCompressor.cs
@@ -61,16 +61,27 @@ namespace OpenMetaverse
public int PatchIDs;
public uint WordBits;
+ // true if PatchIDs are 32 bits and not 10
+ public bool LargeRegion { get; set; }
+
public int X
{
- get { return PatchIDs >> 5; }
- set { PatchIDs += (value << 5); }
+ get { return PatchIDs >> (LargeRegion ? 16 : 5); }
+ set { PatchIDs += (value << (LargeRegion ? 16 : 5)); }
}
public int Y
{
- get { return PatchIDs & 0x1F; }
- set { PatchIDs |= value & 0x1F; }
+ get { return PatchIDs & (LargeRegion ? 0xffff : 0x1F); }
+ set { PatchIDs |= value & (LargeRegion ? 0xffff : 0x1F); }
+ }
+
+ public int setPatchIDs(int xx, int yy) {
+ if (LargeRegion)
+ PatchIDs = (xx << 16) | (yy & 0xffff);
+ else
+ PatchIDs = (xx << 5) | (yy & 0x1f);
+ return PatchIDs;
}
}
@@ -148,14 +159,18 @@ namespace OpenMetaverse
/// simulator heightmap and an array of indices of patches to compress
///
/// A 256 * 256 array of floating point values
- /// specifying the height at each meter in the simulator
+ /// specifying the height at each meter in the simulator.
+ /// This can be larger if it is a varregion.
/// Array of indexes in the 16x16 grid of patches
/// for this simulator. For example if 1 and 17 are specified, patches
/// x=1,y=0 and x=1,y=1 are sent
///
public static LayerDataPacket CreateLandPacket(float[] heightmap, int[] patches)
{
- LayerDataPacket layer = new LayerDataPacket {LayerID = {Type = (byte) TerrainPatch.LayerType.Land}};
+ var layerType = TerrainPatch.LayerType.Land;
+ if (heightmap.Length > Simulator.DefaultRegionSizeY * Simulator.DefaultRegionSizeY)
+ layerType = TerrainPatch.LayerType.LandExtended;
+ LayerDataPacket layer = new LayerDataPacket {LayerID = {Type = (byte) layerType}};
TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader
{
@@ -235,15 +250,19 @@ namespace OpenMetaverse
return layer;
}
- public static void CreatePatch(BitPack output, float[] patchData, int x, int y)
+ private static void CreatePatch(BitPack output, float[] patchData, int x, int y)
+ {
+ CreatePatch(output, patchData, x, y, false);
+ }
+ private static void CreatePatch(BitPack output, float[] patchData, int x, int y, bool largeRegion)
{
if (patchData.Length != 16 * 16)
throw new ArgumentException("Patch data must be a 16x16 array");
TerrainPatch.Header header = PrescanPatch(patchData);
+ header.LargeRegion = largeRegion;
header.QuantWBits = 136;
- header.PatchIDs = (y & 0x1F);
- header.PatchIDs += (x << 5);
+ header.setPatchIDs(x, y);
// NOTE: No idea what prequant and postquant should be or what they do
int[] patch = CompressPatch(patchData, header, 10);
@@ -252,14 +271,18 @@ namespace OpenMetaverse
}
public static void CreatePatch(BitPack output, float[,] patchData, int x, int y)
+ {
+ CreatePatch(output, patchData, x, y, false);
+ }
+ public static void CreatePatch(BitPack output, float[,] patchData, int x, int y, bool largeRegion)
{
if (patchData.Length != 16 * 16)
throw new ArgumentException("Patch data must be a 16x16 array");
var header = PrescanPatch(patchData);
+ header.LargeRegion = largeRegion;
header.QuantWBits = 136;
- header.PatchIDs = (y & 0x1F);
- header.PatchIDs += (x << 5);
+ header.setPatchIDs(x, y);
// NOTE: No idea what prequant and postquant should be or what they do
int[] patch = CompressPatch(patchData, header, 10);
@@ -278,6 +301,10 @@ namespace OpenMetaverse
/// Y offset of the patch to create, valid values are
/// from 0 to 15
public static void CreatePatchFromHeightmap(BitPack output, float[] heightmap, int x, int y)
+ {
+ CreatePatchFromHeightmap(output, heightmap, x, y, false);
+ }
+ public static void CreatePatchFromHeightmap(BitPack output, float[] heightmap, int x, int y, bool largeRegion)
{
if (heightmap.Length != 256 * 256)
throw new ArgumentException("Heightmap data must be 256x256");
@@ -286,9 +313,9 @@ namespace OpenMetaverse
throw new ArgumentException("X and Y patch offsets must be from 0 to 15");
var header = PrescanPatch(heightmap, x, y);
+ header.LargeRegion = largeRegion;
header.QuantWBits = 136;
- header.PatchIDs = (y & 0x1F);
- header.PatchIDs += (x << 5);
+ header.setPatchIDs(x, y);
// NOTE: No idea what prequant and postquant should be or what they do
int[] patch = CompressPatch(heightmap, x, y, header, 10);
@@ -296,6 +323,8 @@ namespace OpenMetaverse
EncodePatch(output, patch, 0, wbits);
}
+ // Scan the height map to get the range of values so the values can be compressed.
+ // Returns a TerrainPatch.Header with the range information filled in.
private static TerrainPatch.Header PrescanPatch(float[] patch)
{
TerrainPatch.Header header = new TerrainPatch.Header();
@@ -318,6 +347,8 @@ namespace OpenMetaverse
return header;
}
+ // Scan the height map to get the range of values so the values can be compressed.
+ // Returns a TerrainPatch.Header with the range information filled in.
private static TerrainPatch.Header PrescanPatch(float[,] patch)
{
TerrainPatch.Header header = new TerrainPatch.Header();
@@ -340,6 +371,8 @@ namespace OpenMetaverse
return header;
}
+ // Scan the height map to get the range of values so the values can be compressed.
+ // Returns a TerrainPatch.Header with the range information filled in.
private static TerrainPatch.Header PrescanPatch(float[] heightmap, int patchX, int patchY)
{
TerrainPatch.Header header = new TerrainPatch.Header();
@@ -363,6 +396,11 @@ namespace OpenMetaverse
}
public static TerrainPatch.Header DecodePatchHeader(BitPack bitpack)
+ {
+ return DecodePatchHeader(bitpack, false);
+
+ }
+ public static TerrainPatch.Header DecodePatchHeader(BitPack bitpack, bool largeRegion)
{
TerrainPatch.Header header = new TerrainPatch.Header {QuantWBits = bitpack.UnpackBits(8)};
@@ -377,7 +415,9 @@ namespace OpenMetaverse
header.Range = bitpack.UnpackBits(16);
// Patch IDs (10 bits)
- header.PatchIDs = bitpack.UnpackBits(10);
+
+ header.LargeRegion = largeRegion;
+ header.PatchIDs = bitpack.UnpackBits(largeRegion ? 32 : 10);
// Word bits
header.WordBits = (uint)((header.QuantWBits & 0x0f) + 2);
@@ -428,7 +468,7 @@ namespace OpenMetaverse
output.PackBits(header.QuantWBits, 8);
output.PackFloat(header.DCOffset);
output.PackBits(header.Range, 16);
- output.PackBits(header.PatchIDs, 10);
+ output.PackBits(header.PatchIDs, header.LargeRegion ? 32 : 10); // the IDs are larger for large regions
return wbits;
}
diff --git a/LibreMetaverse/TerrainManager.cs b/LibreMetaverse/TerrainManager.cs
index 8a112e9..71183ea 100644
--- a/LibreMetaverse/TerrainManager.cs
+++ b/LibreMetaverse/TerrainManager.cs
@@ -67,7 +67,7 @@ namespace OpenMetaverse
Client.Network.RegisterCallback(PacketType.LayerData, LayerDataHandler);
}
- private void DecompressLand(Simulator simulator, BitPack bitpack, TerrainPatch.GroupHeader group)
+ private void DecompressLand(Simulator simulator, BitPack bitpack, TerrainPatch.GroupHeader group, bool largeRegion = false)
{
int x;
int y;
@@ -76,7 +76,7 @@ namespace OpenMetaverse
while (true)
{
- TerrainPatch.Header header = TerrainCompressor.DecodePatchHeader(bitpack);
+ TerrainPatch.Header header = TerrainCompressor.DecodePatchHeader(bitpack, largeRegion);
if (header.QuantWBits == TerrainCompressor.END_OF_PATCHES)
break;
@@ -84,7 +84,7 @@ namespace OpenMetaverse
x = header.X;
y = header.Y;
- if (x >= TerrainCompressor.PATCHES_PER_EDGE || y >= TerrainCompressor.PATCHES_PER_EDGE)
+ if (!largeRegion && (x >= TerrainCompressor.PATCHES_PER_EDGE || y >= TerrainCompressor.PATCHES_PER_EDGE))
{
Logger.Log(String.Format(
"Invalid LayerData land packet, x={0}, y={1}, dc_offset={2}, range={3}, quant_wbits={4}, patchids={5}, count={6}",
@@ -117,7 +117,7 @@ namespace OpenMetaverse
}
}
- private void DecompressWind(Simulator simulator, BitPack bitpack, TerrainPatch.GroupHeader group)
+ private void DecompressWind(Simulator simulator, BitPack bitpack, TerrainPatch.GroupHeader group, bool largeRegion = false)
{
int[] patches = new int[32 * 32];
@@ -131,12 +131,12 @@ namespace OpenMetaverse
// wind_direction = vec2(x,y)
// X values
- TerrainPatch.Header header = TerrainCompressor.DecodePatchHeader(bitpack);
+ TerrainPatch.Header header = TerrainCompressor.DecodePatchHeader(bitpack, largeRegion);
TerrainCompressor.DecodePatch(patches, bitpack, header, group.PatchSize);
float[] xvalues = TerrainCompressor.DecompressPatch(patches, header, group);
// Y values
- header = TerrainCompressor.DecodePatchHeader(bitpack);
+ header = TerrainCompressor.DecodePatchHeader(bitpack, largeRegion);
TerrainCompressor.DecodePatch(patches, bitpack, header, group.PatchSize);
float[] yvalues = TerrainCompressor.DecompressPatch(patches, header, group);
@@ -172,6 +172,10 @@ namespace OpenMetaverse
if (m_LandPatchReceivedEvent != null || Client.Settings.STORE_LAND_PATCHES)
DecompressLand(e.Simulator, bitpack, header);
break;
+ case TerrainPatch.LayerType.LandExtended:
+ if (m_LandPatchReceivedEvent != null || Client.Settings.STORE_LAND_PATCHES)
+ DecompressLand(e.Simulator, bitpack, header, true);
+ break;
case TerrainPatch.LayerType.Water:
Logger.Log("Got a Water LayerData packet, implement me!", Helpers.LogLevel.Error, Client);
break;
diff --git a/LibreMetaverse/UDPBase.cs b/LibreMetaverse/UDPBase.cs
index cda79fc..212749c 100644
--- a/LibreMetaverse/UDPBase.cs
+++ b/LibreMetaverse/UDPBase.cs
@@ -119,7 +119,7 @@ namespace OpenMetaverse
// kick off an async receive. The Start() method will return, the
// actual receives will occur asynchronously and will be caught in
- // AsyncEndRecieve().
+ // AsyncEndReceive().
AsyncBeginReceive();
}
diff --git a/LibreMetaverse/_Packets_.cs b/LibreMetaverse/_Packets_.cs
index 096c5f3..4c90716 100644
--- a/LibreMetaverse/_Packets_.cs
+++ b/LibreMetaverse/_Packets_.cs
@@ -10023,6 +10023,9 @@ namespace OpenMetaverse.Packets
public byte[] SeedCapability;
public byte SimAccess;
public uint TeleportFlags;
+ // Sim/region size information sent in TeleportFinishMesssage
+ public uint RegionSizeX = Simulator.DefaultRegionSizeX;
+ public uint RegionSizeY = Simulator.DefaultRegionSizeY;
public override int Length
{
@@ -10075,6 +10078,7 @@ namespace OpenMetaverse.Packets
Buffer.BlockCopy(SeedCapability, 0, bytes, i, SeedCapability.Length); i += SeedCapability.Length;
bytes[i++] = SimAccess;
Utils.UIntToBytes(TeleportFlags, bytes, i); i += 4;
+ // size information is not sent in the UDP packet
}
}
diff --git a/SecondBotEvents/Commands/Group.cs b/SecondBotEvents/Commands/Group.cs
index 1ca61d3..3e456de 100644
--- a/SecondBotEvents/Commands/Group.cs
+++ b/SecondBotEvents/Commands/Group.cs
@@ -66,7 +66,7 @@ namespace SecondBotEvents.Commands
return Failure("Unknown group", new[] { group, avatar, state });
}
ProcessAvatar(avatar);
- if(avataruuid == null)
+ if(avataruuid == UUID.Zero)
{
return Failure("Unknown avatar", new[] { group, avatar, state });
}
@@ -75,8 +75,10 @@ namespace SecondBotEvents.Commands
{
Action = GroupBanAction.Unban;
}
- List avatarstoaction = new List();
- avatarstoaction.Add(avataruuid);
+ List avatarstoaction = new()
+ {
+ avataruuid
+ };
GetClient().Groups.RequestBanAction(groupuuid, Action, avatarstoaction.ToArray());
return BasicReply("Accepted");
}
@@ -104,7 +106,7 @@ namespace SecondBotEvents.Commands
return Failure("Unknown group", new[] { group, avatar });
}
ProcessAvatar(avatar);
- if (avataruuid == null)
+ if (avataruuid == UUID.Zero)
{
return Failure("Unknown avatar", new[] { group, avatar});
}
@@ -172,12 +174,13 @@ namespace SecondBotEvents.Commands
{
return Failure("avatar lookup", new [] { group, avatar, role });
}
- List roles = new List();
- roles.Add(UUID.Zero);
- if(role != "everyone")
+ List roles = new()
{
- UUID roleuuid = UUID.Zero;
- if (UUID.TryParse(role, out roleuuid) == false)
+ UUID.Zero
+ };
+ if (role != "everyone")
+ {
+ if (UUID.TryParse(role, out UUID roleuuid) == false)
{
return Failure("Unable to process role UUID", new[] { group, avatar, role });
}
@@ -215,10 +218,12 @@ namespace SecondBotEvents.Commands
{
return Failure("Message empty", new [] { group, title, message });
}
- GroupNotice NewNotice = new GroupNotice();
- NewNotice.Subject = title;
- NewNotice.Message = message;
- NewNotice.OwnerID = GetClient().Self.AgentID;
+ GroupNotice NewNotice = new()
+ {
+ Subject = title,
+ Message = message,
+ OwnerID = GetClient().Self.AgentID
+ };
GetClient().Groups.SendGroupNotice(groupuuid, NewNotice);
return BasicReply("Sending notice", new [] { group, title, message });
}
@@ -301,11 +306,13 @@ namespace SecondBotEvents.Commands
{
return Failure("Message empty", new [] { group, title, message, attachment });
}
- GroupNotice NewNotice = new GroupNotice();
- NewNotice.Subject = title;
- NewNotice.Message = message;
- NewNotice.OwnerID = GetClient().Self.AgentID;
- NewNotice.AttachmentID = inventoryuuid;
+ GroupNotice NewNotice = new()
+ {
+ Subject = title,
+ Message = message,
+ OwnerID = GetClient().Self.AgentID,
+ AttachmentID = inventoryuuid
+ };
GetClient().Groups.SendGroupNotice(groupuuid, NewNotice);
return BasicReply("Sending notice with attachment", new [] { group, title, message, attachment });
}
@@ -351,8 +358,7 @@ namespace SecondBotEvents.Commands
[ArgHints("group", "the UUID of the group")]
public object GroupchatGroupHasUnread(string group)
{
- UUID groupUUID = UUID.Zero;
- if(UUID.TryParse(group,out groupUUID) == false)
+ if(UUID.TryParse(group,out UUID groupUUID) == false)
{
return Failure("group value is invaild", new [] { group });
}
@@ -400,8 +406,7 @@ namespace SecondBotEvents.Commands
[ReturnHintsFailure("Unknown group")]
public object Groupchat(string group, string message)
{
- UUID groupUUID = UUID.Zero;
- if (UUID.TryParse(group, out groupUUID) == false)
+ if (UUID.TryParse(group, out UUID groupUUID) == false)
{
return Failure("group value is invaild", new [] { group, message });
}
diff --git a/SecondBotEvents/Commands/Inventory.cs b/SecondBotEvents/Commands/Inventory.cs
index f571e09..5caab79 100644
--- a/SecondBotEvents/Commands/Inventory.cs
+++ b/SecondBotEvents/Commands/Inventory.cs
@@ -44,8 +44,10 @@ namespace SecondBotEvents.Commands
break;
}
}
- AssetSound S = new AssetSound();
- S.AssetData = audioData;
+ AssetSound S = new()
+ {
+ AssetData = audioData
+ };
S.Encode();
GetClient().Inventory.RequestCreateItemFromAsset(S.AssetData, inventoryName, "", AssetType.Sound, InventoryType.Sound, AA.UUID, null);
@@ -204,7 +206,7 @@ namespace SecondBotEvents.Commands
return Failure("Cant find target folder", new [] { name });
}
List contents = GetClient().Inventory.FolderContents(AA.UUID, GetClient().Self.AgentID, true, true, InventorySortOrder.ByName, 5 * 1000);
- List wareables = new List();
+ List wareables = new();
if (contents == null)
{
return Failure("target folder is empty or so full I cant get it in 5 secs...", new [] { name });
@@ -241,7 +243,7 @@ namespace SecondBotEvents.Commands
{
return Failure("Unable to find notecard folder");
}
- List purge_notecards = new List();
+ List purge_notecards = new();
List contents = GetClient().Inventory.FolderContents(NotecardFolder.UUID, GetClient().Self.AgentID, true, true, InventorySortOrder.ByDate, 40 * 1000);
foreach (InventoryBase C in contents)
{
@@ -255,7 +257,7 @@ namespace SecondBotEvents.Commands
}
}
}
- if (purge_notecards.Count() > 0)
+ if (purge_notecards.Count > 0)
{
GetClient().Inventory.Remove(purge_notecards, new List());
}
@@ -266,7 +268,7 @@ namespace SecondBotEvents.Commands
[ReturnHints("Asset UUID or UUID zero")]
[ReturnHints("Invaild item uuid")]
[ArgHints("item", "inventory level UUID of item")]
- public object getRealUUID(string item)
+ public object GetRealUUID(string item)
{
if (UUID.TryParse(item, out UUID itemUUID) == false)
{
@@ -364,7 +366,7 @@ namespace SecondBotEvents.Commands
return Failure("Unable to find inventory", new [] { item, objectuuid, running });
}
Dictionary objects_copy = GetClient().Network.CurrentSim.ObjectsPrimitives.Copy();
- KeyValuePair RealObject = new KeyValuePair(0,null);
+ KeyValuePair RealObject = new(0, null);
foreach (KeyValuePair Obj in objects_copy)
{
if (Obj.Value.ID == objectUUID)
@@ -431,7 +433,7 @@ namespace SecondBotEvents.Commands
[ReturnHintsFailure("new folder name is too short, must be longer than 3 characters.")]
[ArgHints("parentFolder", "UUID of folder to create a subfolder in")]
[ArgHints("folderName", "name of the new folder")]
- public object CreateInventoryFolder(string parentFolder, string folderName, string token)
+ public object CreateInventoryFolder(string parentFolder, string folderName)
{
if (UUID.TryParse(parentFolder, out UUID parentFolderUUID) == false)
{
diff --git a/SecondBotEvents/Commands/ParcelCommands.cs b/SecondBotEvents/Commands/ParcelCommands.cs
index 84f76fa..ab43b86 100644
--- a/SecondBotEvents/Commands/ParcelCommands.cs
+++ b/SecondBotEvents/Commands/ParcelCommands.cs
@@ -49,8 +49,8 @@ namespace SecondBotEvents.Commands
}
targetparcel.SalePrice = amountvalue;
targetparcel.AuthBuyerID = avataruuid;
- parcel_static.ParcelSetFlag(ParcelFlags.ForSale, targetparcel, true);
- parcel_static.ParcelSetFlag(ParcelFlags.ForSaleObjects, targetparcel, false);
+ ParcelStatic.ParcelSetFlag(ParcelFlags.ForSale, targetparcel, true);
+ ParcelStatic.ParcelSetFlag(ParcelFlags.ForSaleObjects, targetparcel, false);
targetparcel.Update(GetClient());
return Failure("ok", new [] { amount, avatar });
}
@@ -167,8 +167,8 @@ namespace SecondBotEvents.Commands
{
return Failure(tests.Value);
}
- Dictionary flags = parcel_static.get_flags_list();
- Dictionary collection = new Dictionary();
+ Dictionary flags = ParcelStatic.GetFlagsList();
+ Dictionary collection = new();
foreach (ParcelFlags cfg in flags.Values)
{
collection.Add(cfg.ToString(), targetparcel.Flags.HasFlag(cfg).ToString());
@@ -237,10 +237,12 @@ namespace SecondBotEvents.Commands
{
return BasicReply("Avatar is in the blacklist", new [] { avatar });
}
- ParcelAccessEntry entry = new ParcelAccessEntry();
- entry.AgentID = avataruuid;
- entry.Flags = AccessList.Ban;
- entry.Time = new System.DateTime(3030, 03, 03);
+ ParcelAccessEntry entry = new()
+ {
+ AgentID = avataruuid,
+ Flags = AccessList.Ban,
+ Time = new System.DateTime(3030, 03, 03)
+ };
targetparcel.AccessBlackList.Add(entry);
targetparcel.Update(GetClient());
return BasicReply("ok", new [] { avatar });
@@ -266,7 +268,7 @@ namespace SecondBotEvents.Commands
return Failure("Invaild avatar", new [] { avatar });
}
bool alreadyBanned = false;
- ParcelAccessEntry removeentry = new ParcelAccessEntry();
+ ParcelAccessEntry removeentry = new();
foreach (ParcelAccessEntry E in targetparcel.AccessBlackList)
{
if (E.AgentID == avataruuid)
@@ -298,7 +300,7 @@ namespace SecondBotEvents.Commands
{
return Failure(tests.Value, new [] { musicurl });
}
- bool status = parcel_static.set_parcel_music(GetClient(), targetparcel, musicurl);
+ bool status = ParcelStatic.SetParcelMusic(GetClient(), targetparcel, musicurl);
return BasicReply(status.ToString(), new [] { musicurl });
}
@@ -319,11 +321,11 @@ namespace SecondBotEvents.Commands
{
return Failure(tests.Value, new [] { escapedflagdata });
}
- List acceptablewords = new List();
- Dictionary flags = parcel_static.get_flags_list();
+ List acceptablewords = new();
+ Dictionary flags = ParcelStatic.GetFlagsList();
acceptablewords.AddRange(new[] { "True", "False" });
- Dictionary setflags = new Dictionary();
+ Dictionary setflags = new();
string[] args = escapedflagdata.Split(":::");
foreach (string a in args)
{
@@ -348,7 +350,7 @@ namespace SecondBotEvents.Commands
{
return Failure("No accepted flags", new [] { escapedflagdata });
}
- if (parcel_static.has_parcel_perm(targetparcel, GetClient()) == false)
+ if (ParcelStatic.HasParcelPerm(targetparcel, GetClient()) == false)
{
return Failure("Incorrect perms to control parcel", new [] { escapedflagdata });
}
@@ -356,7 +358,7 @@ namespace SecondBotEvents.Commands
{
if (flags.ContainsKey(cfg.Key) == true)
{
- parcel_static.ParcelSetFlag(flags[cfg.Key], targetparcel, cfg.Value);
+ ParcelStatic.ParcelSetFlag(flags[cfg.Key], targetparcel, cfg.Value);
}
}
targetparcel.Update(GetClient());
@@ -494,7 +496,7 @@ namespace SecondBotEvents.Commands
{
return Failure(tests.Value);
}
- GetParcelBanlistObject reply = new GetParcelBanlistObject();
+ GetParcelBanlistObject reply = new();
int delays = 0;
bool haslookup = true;
while ((haslookup == true) && (delays < 3))
@@ -582,7 +584,7 @@ namespace SecondBotEvents.Commands
{
if (bits[0] == "MediaType")
{
- UpdateParcel_MediaType(targetparcel, bits[1]);
+ UpdateParcelMediaType(targetparcel, bits[1]);
}
else if ((bits[0] == "MediaWidth") || (bits[0] == "MediaHeight"))
{
@@ -636,7 +638,7 @@ namespace SecondBotEvents.Commands
return BasicReply("ok", new [] { escapedflagdata });
}
- protected bool UpdateParcel_MediaType(Parcel targetparcel, string value)
+ protected static bool UpdateParcelMediaType(Parcel targetparcel, string value)
{
if (value == "IMG-PNG")
{
@@ -670,7 +672,7 @@ namespace SecondBotEvents.Commands
public class GetParcelBanlistObject
{
- public Dictionary entrys = new Dictionary();
+ public Dictionary entrys = new();
public string parcelName = "";
public string regionName = "";
public int delay = 0;
diff --git a/SecondBotEvents/SecondBotEvents.csproj b/SecondBotEvents/SecondBotEvents.csproj
index 2033c41..13fb8d0 100644
--- a/SecondBotEvents/SecondBotEvents.csproj
+++ b/SecondBotEvents/SecondBotEvents.csproj
@@ -1,28 +1,25 @@
-
-
+
Exe
- net6.0
+ net7.0
SecondBotEvents.Startup
- git rev-parse --short HEAD
- False
- False
+ git rev-parse --short HEAD
+ False
+ False
-
-
-
-
+
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
+
+
-
-
-
+
\ No newline at end of file
diff --git a/SecondBotEvents/Services/BotClientService.cs b/SecondBotEvents/Services/BotClientService.cs
index f8b4b2d..93a7f6e 100644
--- a/SecondBotEvents/Services/BotClientService.cs
+++ b/SecondBotEvents/Services/BotClientService.cs
@@ -1,6 +1,7 @@
using OpenMetaverse;
using OpenMetaverse.Assets;
using SecondBotEvents.Config;
+using Swan;
using System;
using System.Collections.Generic;
using System.Text;
@@ -200,7 +201,9 @@ namespace SecondBotEvents.Services
{
return "No sim";
}
- return client.Network.CurrentSim.Name + " " + client.Self.SimPosition.ToString();
+ Vector3 pos = client.Self.SimPosition;
+ string loc = "" + Math.Round(pos.X).ToString() + "," + Math.Round(pos.Y).ToString() + "," + Math.Round(pos.Z).ToString();
+ return client.Network.CurrentSim.Name + " " + loc;
}
}
}
diff --git a/SecondBotEvents/Services/DataStoreService.cs b/SecondBotEvents/Services/DataStoreService.cs
index 739123b..5b659c1 100644
--- a/SecondBotEvents/Services/DataStoreService.cs
+++ b/SecondBotEvents/Services/DataStoreService.cs
@@ -18,25 +18,25 @@ namespace SecondBotEvents.Services
myConfig = new DataStoreConfig(master.fromEnv,master.fromFolder);
}
- protected Dictionary avatarsName2Key = new Dictionary();
- protected Dictionary avatarLastUsed = new Dictionary();
+ protected Dictionary avatarsName2Key = new();
+ protected Dictionary avatarLastUsed = new();
- protected Dictionary groupsKey2Name = new Dictionary();
+ protected Dictionary groupsKey2Name = new();
- protected Dictionary> groupMembers = new Dictionary>();
- protected Dictionary> groupRoles = new Dictionary>();
+ protected Dictionary> groupMembers = new();
+ protected Dictionary> groupRoles = new();
- protected List localChatHistory = new List();
+ protected List localChatHistory = new();
- protected Dictionary> chatWindows = new Dictionary>(); // sess, list chat
- protected Dictionary chatWindowsUnread = new Dictionary(); // sess, bool
- protected Dictionary chatWindowsIsGroup = new Dictionary(); // sess, bool
- protected Dictionary chatWindowsOwner = new Dictionary(); // sess, owner id
+ protected Dictionary> chatWindows = new(); // sess, list chat
+ protected Dictionary chatWindowsUnread = new(); // sess, bool
+ protected Dictionary chatWindowsIsGroup = new(); // sess, bool
+ protected Dictionary chatWindowsOwner = new(); // sess, owner id
- protected Dictionary KeyValueStore = new Dictionary();
- protected Dictionary KeyValueStoreLastUsed = new Dictionary();
+ protected Dictionary KeyValueStore = new();
+ protected Dictionary KeyValueStoreLastUsed = new();
- protected List commandHistories = new List();
+ protected List commandHistories = new();
protected long lastCleanupKeyValueStore = 0;
protected long lastCleanupAvatarStore = 0;
@@ -53,7 +53,7 @@ namespace SecondBotEvents.Services
return groupsKey2Name[group];
}
string reply = "lookup";
- AutoResetEvent fetchEvent = new AutoResetEvent(false);
+ AutoResetEvent fetchEvent = new(false);
void callback(object sender, CurrentGroupsEventArgs e)
{
foreach(KeyValuePair entry in e.Groups)
@@ -91,7 +91,7 @@ namespace SecondBotEvents.Services
if (dif > 125)
{
lastCleanupKeyValueStore = unixtime;
- List clearentrys = new List();
+ List clearentrys = new();
foreach (KeyValuePair entry in KeyValueStoreLastUsed)
{
dif = unixtime - entry.Value;
@@ -121,7 +121,7 @@ namespace SecondBotEvents.Services
if (dif > 75)
{
lastCleanupAvatarStore = unixtime;
- Dictionary clearLinks = new Dictionary();
+ Dictionary clearLinks = new();
foreach (KeyValuePair entry in avatarsName2Key)
{
dif = unixtime - avatarLastUsed[entry.Value];
@@ -141,10 +141,10 @@ namespace SecondBotEvents.Services
}
}
}
- int sum = commandHistories.Count() + KeyValueStoreLastUsed.Count() + KeyValueStore.Count() +
- chatWindowsOwner.Count() + chatWindowsIsGroup.Count() + chatWindowsUnread.Count() +
- chatWindows.Count() + localChatHistory.Count() + groupRoles.Count() +
- groupMembers.Count() + groupsKey2Name.Count() + avatarsName2Key.Count();
+ int sum = commandHistories.Count + KeyValueStoreLastUsed.Count + KeyValueStore.Count +
+ chatWindowsOwner.Count + chatWindowsIsGroup.Count + chatWindowsUnread.Count +
+ chatWindows.Count + localChatHistory.Count + groupRoles.Count +
+ groupMembers.Count + groupsKey2Name.Count + avatarsName2Key.Count;
return sum.ToString();
}
@@ -152,7 +152,7 @@ namespace SecondBotEvents.Services
{
lock (commandHistories)
{
- CommandHistory A = new CommandHistory(status, command, args, SecondbotHelpers.UnixTimeNow());
+ CommandHistory A = new(status, command, args, SecondbotHelpers.UnixTimeNow());
commandHistories.Add(A);
int c = commandHistories.Count;
while (c > myConfig.GetCommandHistoryLimit())
@@ -226,7 +226,7 @@ namespace SecondBotEvents.Services
public List GetAllGroupsChatWithUnread()
{
- List reply = new List();
+ List reply = new();
foreach(KeyValuePair windowState in chatWindowsUnread)
{
if(windowState.Value == false)
@@ -299,11 +299,11 @@ namespace SecondBotEvents.Services
public Dictionary GetGroupRoles(UUID group)
{
- Dictionary reply = new Dictionary();
+ Dictionary reply = new();
if (groupRoles.ContainsKey(group) == false)
{
- AutoResetEvent fetchEvent = new AutoResetEvent(false);
+ AutoResetEvent fetchEvent = new(false);
void callback(object sender, GroupRolesDataReplyEventArgs e)
{
if (e.GroupID == group)
@@ -341,7 +341,7 @@ namespace SecondBotEvents.Services
if (groupMembers[group].Contains(avatar) == false)
{
reply = false;
- AutoResetEvent fetchEvent = new AutoResetEvent(false);
+ AutoResetEvent fetchEvent = new(false);
void callback(object sender, GroupMembersReplyEventArgs e)
{
if (e.GroupID == group)
@@ -395,7 +395,7 @@ namespace SecondBotEvents.Services
{
purgeLen = myConfig.GetGroupChatHistoryLimitPerGroup();
}
- int counter = chatWindows[sessionID].Count();
+ int counter = chatWindows[sessionID].Count;
while (counter > purgeLen)
{
chatWindows[sessionID].RemoveAt(0);
@@ -471,7 +471,7 @@ namespace SecondBotEvents.Services
}
- protected Dictionary> notecardDataStore = new Dictionary>();
+ protected Dictionary> notecardDataStore = new();
public List GetLocalChat()
{
@@ -532,7 +532,7 @@ namespace SecondBotEvents.Services
if(avatarsName2Key.ContainsValue(avatarId) == false)
{
bool hasReply = false;
- AutoResetEvent fetchEvent = new AutoResetEvent(false);
+ AutoResetEvent fetchEvent = new(false);
void callback(object sender, UUIDNameReplyEventArgs e)
{
foreach (KeyValuePair av in e.Names)
@@ -563,7 +563,7 @@ namespace SecondBotEvents.Services
UUID wantedReplyID = UUID.SecureRandom();
bool hasReply = false;
- AutoResetEvent fetchEvent = new AutoResetEvent(false);
+ AutoResetEvent fetchEvent = new(false);
void callback(object sender, AvatarPickerReplyEventArgs e)
{
if (e.QueryID == wantedReplyID)
@@ -590,7 +590,7 @@ namespace SecondBotEvents.Services
public void GetAvatarNames(List avatars)
{
- List lookup = new List();
+ List lookup = new();
foreach (UUID id in avatars)
{
if (avatarsName2Key.ContainsValue(id) == false)
@@ -664,7 +664,7 @@ namespace SecondBotEvents.Services
public Dictionary GetAvatarImWindows()
{
- Dictionary windows = new Dictionary();
+ Dictionary windows = new();
foreach (KeyValuePair links in chatWindowsIsGroup)
{
if(links.Value == true)
@@ -728,7 +728,7 @@ namespace SecondBotEvents.Services
public List GetAvatarImWindowsUnread()
{
- List windows = new List();
+ List windows = new();
foreach (KeyValuePair links in chatWindowsIsGroup)
{
if (links.Value == true)
@@ -834,8 +834,8 @@ namespace SecondBotEvents.Services
{
if (estateBanlist == null)
{
- List reply = new List();
- AutoResetEvent fetchEvent = new AutoResetEvent(false);
+ List reply = new();
+ AutoResetEvent fetchEvent = new(false);
void callback(object sender, EstateBansReplyEventArgs e)
{
reply = e.Banned;
@@ -1077,7 +1077,7 @@ namespace SecondBotEvents.Services
public class CommandHistory
{
public string Command = "";
- public string[] Args = new string[] { };
+ public string[] Args = Array.Empty();
public long Unixtime = 0;
public bool status = false;
diff --git a/SecondBotEvents/Services/HomeboundService.cs b/SecondBotEvents/Services/HomeboundService.cs
index 218695d..0702de8 100644
--- a/SecondBotEvents/Services/HomeboundService.cs
+++ b/SecondBotEvents/Services/HomeboundService.cs
@@ -46,11 +46,11 @@ namespace SecondBotEvents.Services
protected bool attemptedTeleportBackup = false;
protected long teleportActionLockout = 0;
- public void GoHome()
+ public bool GoHome()
{
attemptedTeleportHome = true;
LogFormater.Info("Teleporting to home sim");
- GetClient().Self.Teleport(home.name, new Vector3(home.x, home.y, home.z), new Vector3(0, 0, 0));
+ return GetClient().Self.Teleport(home.name, new Vector3(home.x, home.y, home.z), new Vector3(0, 0, 0));
}
protected void Tick()
{
@@ -85,8 +85,14 @@ namespace SecondBotEvents.Services
}
if (simNickname == "")
{
- simNickname = "Someplace # ";
- return;
+ if (GetClient().Network.CurrentSim != null)
+ {
+ simNickname = ""+ GetClient().Network.CurrentSim.Name+" # ";
+ }
+ else
+ {
+ simNickname = "Someplace # ";
+ }
}
long dif = SecondbotHelpers.UnixTimeNow() - teleportActionLockout;
if(dif < 30)
@@ -96,7 +102,10 @@ namespace SecondBotEvents.Services
teleportActionLockout = SecondbotHelpers.UnixTimeNow();
if (attemptedTeleportHome == false)
{
- GoHome();
+ if(GoHome() == false)
+ {
+ LogFormater.Warn("Unable to teleport to home sim");
+ }
return;
}
else if(attemptedTeleportBackup == false)
@@ -104,7 +113,10 @@ namespace SecondBotEvents.Services
attemptedTeleportBackup = true;
LogFormater.Info("Teleporting to backup sim");
teleportActionLockout = SecondbotHelpers.UnixTimeNow();
- GetClient().Self.Teleport(backup.name, new Vector3(backup.x, backup.y, backup.z), new Vector3(0, 0, 0));
+ if(GetClient().Self.Teleport(backup.name, new Vector3(backup.x, backup.y, backup.z), new Vector3(0, 0, 0)) == false)
+ {
+ LogFormater.Warn("Unable to teleport to backup sim");
+ }
return;
}
attemptedTeleportHome = false;
diff --git a/SecondBotEvents/Services/HttpService.cs b/SecondBotEvents/Services/HttpService.cs
index aa9ce6d..6b8f35f 100644
--- a/SecondBotEvents/Services/HttpService.cs
+++ b/SecondBotEvents/Services/HttpService.cs
@@ -161,13 +161,16 @@ namespace SecondBotEvents.Services
string UUIDfetch = master.DataStoreService.GetAvatarUUID(avatar);
if (UUIDfetch != "lookup")
{
- UUID.TryParse(UUIDfetch, out avataruuid);
+ if(UUID.TryParse(UUIDfetch, out avataruuid) == false)
+ {
+ avataruuid = UUID.Zero;
+ }
}
}
protected object BasicReply(string input)
{
- return BasicReply(input, new string[] { }, GetCallingCommand());
+ return BasicReply(input, Array.Empty(), GetCallingCommand());
}
protected object BasicReply(string input, string[] args)
@@ -178,13 +181,13 @@ namespace SecondBotEvents.Services
protected object BasicReply(string input, string[] args, string command)
{
master.DataStoreService.AddCommandToHistory(true, command, args);
- return new { command = command, args = args, reply = input, status = true };
+ return new { command, args, reply = input, status = true };
}
protected object Failure(string input, string command, string[] args, string whyfailed)
{
master.DataStoreService.AddCommandToHistory(false, command, args);
- return new { command = command, args = args, reply = input, status = false, whyfailed = whyfailed };
+ return new { command, args, reply = input, status = false, whyfailed };
}
protected object Failure(string input, string[] args)
@@ -194,10 +197,10 @@ namespace SecondBotEvents.Services
protected object Failure(string input)
{
- return Failure(input, GetCallingCommand(), new string[] { }, null);
+ return Failure(input, GetCallingCommand(), Array.Empty(), null);
}
- protected string GetCallingCommand()
+ protected static string GetCallingCommand()
{
return (new System.Diagnostics.StackTrace()).GetFrame(2).GetMethod().Name;
}
@@ -272,7 +275,7 @@ namespace SecondBotEvents.Services
public string Run([FormField] string commandName, [FormField] string args, [FormField] string signing, [FormField] string unixtime)
{
- string[] myArgs = new string[] { };
+ string[] myArgs = Array.Empty();
if(args != null)
{
myArgs = args.Split("~#~", StringSplitOptions.RemoveEmptyEntries);
@@ -285,7 +288,7 @@ namespace SecondBotEvents.Services
{
return "No bot connected yet";
}
- SignedCommand C = new SignedCommand(commandName, signing, myArgs, cmdUnixtime, null, true, 5, master.CommandsService.myConfig.GetSharedSecret());
+ SignedCommand C = new(commandName, signing, myArgs, cmdUnixtime, null, true, 5, master.CommandsService.myConfig.GetSharedSecret());
if(C.accepted == false)
{
return "Command request rejected";
diff --git a/SecondBotEvents/Services/RelayService.cs b/SecondBotEvents/Services/RelayService.cs
index f46a856..0cfa83e 100644
--- a/SecondBotEvents/Services/RelayService.cs
+++ b/SecondBotEvents/Services/RelayService.cs
@@ -13,7 +13,7 @@ namespace SecondBotEvents.Services
{
protected RelayConfig myConfig;
protected bool botConnected = false;
- protected List Relays = new List();
+ protected List Relays = new();
public RelayService(EventsSecondBot setMaster) : base(setMaster)
{
myConfig = new RelayConfig(master.fromEnv, master.fromFolder);
@@ -348,7 +348,7 @@ namespace SecondBotEvents.Services
readonly string[] vaildToOptions = new[] { "avatar", "group", "localchat", "discord", "http" };
readonly
- protected HttpClient HTTPclient = new HttpClient();
+ protected HttpClient HTTPclient = new();
public void TriggerWith(string sourceType, string message, string filterOption1, string filterOption2=null, string filterOption3 = null)
{
// avatarim, {message}, avatarUUID
@@ -414,7 +414,7 @@ namespace SecondBotEvents.Services
case "http":
{
long unixtime = SecondbotHelpers.UnixTimeNow();
- Dictionary values = new Dictionary
+ Dictionary values = new()
{
{ "fromType", fromType },
{ "fromOption", fromOption },
diff --git a/SecondBotEvents/Static/parcel.cs b/SecondBotEvents/Static/parcel.cs
index 94bed34..c4649a5 100644
--- a/SecondBotEvents/Static/parcel.cs
+++ b/SecondBotEvents/Static/parcel.cs
@@ -5,9 +5,9 @@ using System.Text;
namespace SecondBotEvents
{
- public static class parcel_static
+ public static class ParcelStatic
{
- public static bool set_parcel_music(GridClient bot, Parcel p, string url)
+ public static bool SetParcelMusic(GridClient bot, Parcel p, string url)
{
if (p.MusicURL != url)
{
@@ -27,7 +27,7 @@ namespace SecondBotEvents
p.Flags |= F;
}
}
- public static bool has_parcel_perm(Parcel P, GridClient bot)
+ public static bool HasParcelPerm(Parcel P, GridClient bot)
{
bool has_perm = true;
if (P.OwnerID != bot.Self.AgentID)
@@ -54,30 +54,32 @@ namespace SecondBotEvents
return has_perm;
}
- public static string[] get_flag_names()
+ public static string[] GetFlagNames()
{
System.Type enumType = typeof(ParcelFlags);
- List flagnames = new List(System.Enum.GetNames(enumType));
+ List flagnames = new(System.Enum.GetNames(enumType));
flagnames.Remove("None");
return flagnames.ToArray();
}
- public static Dictionary get_media_list()
+ public static Dictionary GetMediaList()
{
- Dictionary flags = new Dictionary();
- flags.Add("MediaAutoScale", "Bool (True|False)");
- flags.Add("MediaLoop", "Bool (True|False)");
- flags.Add("MediaID", "UUID (Texture)");
- flags.Add("MediaURL", "String");
- flags.Add("MediaDesc", "String");
- flags.Add("MediaHeight", "Int (256 to 1024)");
- flags.Add("MediaWidth", "Int (256 to 1024)");
- flags.Add("MediaType", "String [\"IMG-PNG\",\"IMG-JPG\",\"VID-MP4\",\"VID-AVI\" or \"Custom-MIME_TYPE_CODE\"]");
+ Dictionary flags = new()
+ {
+ { "MediaAutoScale", "Bool (True|False)" },
+ { "MediaLoop", "Bool (True|False)" },
+ { "MediaID", "UUID (Texture)" },
+ { "MediaURL", "String" },
+ { "MediaDesc", "String" },
+ { "MediaHeight", "Int (256 to 1024)" },
+ { "MediaWidth", "Int (256 to 1024)" },
+ { "MediaType", "String [\"IMG-PNG\",\"IMG-JPG\",\"VID-MP4\",\"VID-AVI\" or \"Custom-MIME_TYPE_CODE\"]" }
+ };
return flags;
}
- public static Dictionary get_flags_list()
+ public static Dictionary GetFlagsList()
{
- Dictionary flags = new Dictionary();
+ Dictionary flags = new();
Type enumType = typeof(ParcelFlags);
Array enumValues = Enum.GetValues(enumType);
Array enumNames = Enum.GetNames(enumType);