a few more test changes and cosmetics

This commit is contained in:
UbitUmarov
2023-03-12 20:26:27 +00:00
parent 6d22429329
commit 77d8bb9968
6 changed files with 392 additions and 242 deletions

View File

@@ -26,21 +26,12 @@
*/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Net;
using System.Reflection;
using System.Text;
using log4net;
using Nini.Config;
using Mono.Addins;
using OpenMetaverse;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
using OpenSim.Framework.Servers.HttpServer;
using OpenSim.Region.Framework.Interfaces;
using OpenSim.Region.Framework.Scenes;
using Caps=OpenSim.Framework.Capabilities.Caps;
namespace OpenSim.Region.ClientStack.Linden
{
@@ -185,7 +176,7 @@ namespace OpenSim.Region.ClientStack.Linden
Vector3 position, uint ttl, UUID transactionID, bool fromGroup, byte[] binaryBucket,
bool checkEstate, int godLevel, bool limitedToEstate)
{
osUTF8 sb = new osUTF8(512);
osUTF8 sb = new(512);
LLSDxmlEncode2.AddMap("instantmessage", sb);
LLSDxmlEncode2.AddMap("message_params", sb); //messageParams
LLSDxmlEncode2.AddElem("type", dialog, sb);
@@ -346,7 +337,7 @@ namespace OpenSim.Region.ClientStack.Linden
public void PlacesQueryReply(UUID avatarID, UUID queryID, UUID transactionID, PlacesReplyData[] replyDataArray)
{
osUTF8 sb = new osUTF8(256);
osUTF8 sb = new(256);
LLSDxmlEncode2.AddMap(sb);
LLSDxmlEncode2.AddElem("message", "PlacesReplyMessage", sb);
LLSDxmlEncode2.AddMap("QueryData[]", sb); LLSDxmlEncode2.AddArray(sb);
@@ -476,7 +467,7 @@ namespace OpenSim.Region.ClientStack.Linden
public static string KeepAliveEvent()
{
osUTF8 sb = new osUTF8(256);
osUTF8 sb = new(256);
LLSDxmlEncode2.AddMap(sb);
LLSDxmlEncode2.AddElem("message", "FAKEEVENT", sb);
LLSDxmlEncode2.AddMap("body", sb);
@@ -485,9 +476,63 @@ namespace OpenSim.Region.ClientStack.Linden
return sb.ToString();
}
public void SendLargeGenericMessage(UUID avatarID, UUID? transationID, UUID? sessionID,
string method, UUID invoice, List<string> message)
{
osUTF8 sb = StartEvent("LargeGenericMessage");
LLSDxmlEncode2.AddArrayAndMap("AgentData", sb);
LLSDxmlEncode2.AddElem("AgentID", avatarID, sb);
if (transationID.HasValue)
LLSDxmlEncode2.AddElem("TransactionID", transationID.Value, sb);
if (sessionID.HasValue)
LLSDxmlEncode2.AddElem("SessionID", sessionID.Value, sb);
LLSDxmlEncode2.AddEndMapAndArray(sb);
LLSDxmlEncode2.AddArrayAndMap("MethodData", sb);
LLSDxmlEncode2.AddElem("Method", method, sb);
LLSDxmlEncode2.AddElem("Invoice", invoice, sb);
LLSDxmlEncode2.AddEndMapAndArray(sb);
LLSDxmlEncode2.AddArrayAndMap("ParamList", sb);
foreach (string s in message)
LLSDxmlEncode2.AddElem("Parameter", s, sb);
LLSDxmlEncode2.AddEndMapAndArray(sb);
Enqueue(EndEventToBytes(sb), avatarID);
}
public void SendLargeGenericMessage(UUID avatarID, UUID? transationID, UUID? sessionID,
string method, UUID invoice, List<byte[]> message)
{
osUTF8 sb = StartEvent("LargeGenericMessage");
LLSDxmlEncode2.AddArrayAndMap("AgentData", sb);
LLSDxmlEncode2.AddElem("AgentID", avatarID, sb);
if (transationID.HasValue)
LLSDxmlEncode2.AddElem("TransactionID", transationID.Value, sb);
if (sessionID.HasValue)
LLSDxmlEncode2.AddElem("SessionID", sessionID.Value, sb);
LLSDxmlEncode2.AddEndMapAndArray(sb);
LLSDxmlEncode2.AddArrayAndMap("MethodData", sb);
LLSDxmlEncode2.AddElem("Method", method, sb);
LLSDxmlEncode2.AddElem("Invoice", invoice, sb);
LLSDxmlEncode2.AddEndMapAndArray(sb);
LLSDxmlEncode2.AddArrayAndMap("ParamList", sb);
foreach (byte[] b in message)
{
LLSDxmlEncode2.AddLLSD("<key>Parameter</key><string>", sb);
sb.Append(b);
LLSDxmlEncode2.AddLLSD("</string>", sb);
}
LLSDxmlEncode2.AddEndMapAndArray(sb);
Enqueue(EndEventToBytes(sb), avatarID);
}
public byte[] BuildEvent(string eventName, OSD eventBody)
{
OSDMap llsdEvent = new OSDMap(2);
OSDMap llsdEvent = new(2);
llsdEvent.Add("message", new OSDString(eventName));
llsdEvent.Add("body", eventBody);

View File

@@ -27,6 +27,8 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Runtime;
@@ -4767,6 +4769,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
List<EntityUpdate> compressedUpdates = null;
List<EntityUpdate> terseUpdates = null;
List<SceneObjectPart> ObjectAnimationUpdates = null;
List<SceneObjectPart> needMaterials = null;
// Check to see if this is a flush
if (maxUpdatesBytes <= 0)
@@ -4821,6 +4824,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
useCompressUpdate = false;
bool istree = false;
bool hasMaterialOverride = false;
if (update.Entity is SceneObjectPart part)
{
@@ -4965,6 +4969,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
useCompressUpdate = grp.IsViewerCachable;
istree = (part.Shape.PCode == (byte)PCode.Grass || part.Shape.PCode == (byte)PCode.NewTree || part.Shape.PCode == (byte)PCode.Tree);
if(!istree && part.Shape.RenderMaterials is not null &&
part.Shape.ReflectionProbe is null &&
part.Shape.RenderMaterials.overrides is not null &&
part.Shape.RenderMaterials.overrides.Length > 0)
hasMaterialOverride = true;
}
else if (update.Entity is ScenePresence presence)
{
@@ -5076,6 +5085,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
objectUpdates.Add(update);
}
if(hasMaterialOverride)
{
needMaterials ??= new List<SceneObjectPart>(16);
needMaterials.Add((SceneObjectPart)update.Entity);
}
}
}
@@ -5090,8 +5104,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
return;
timeDilation = Utils.FloatZeroOneToushort(m_scene.TimeDilation);
if(objectUpdates is not null)
if (objectUpdates is not null)
{
//List<EntityUpdate> tau = new List<EntityUpdate>(30);
@@ -5183,71 +5196,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
}
/* no zero encode compressed updates
if(compressedUpdates != null)
{
List<EntityUpdate> tau = new List<EntityUpdate>(30);
UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
byte[] data = buf.Data;
Buffer.BlockCopy(CompressedObjectHeader, 0, data , 0, 7);
Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, data, 7); // 15
Utils.UInt16ToBytes(timeDilation, data, 15); // 17
int countposition = 17; // blocks count position
int pos = 18;
int lastpos = 0;
int count = 0;
foreach (EntityUpdate eu in compressedUpdates)
{
SceneObjectPart sop = (SceneObjectPart)eu.Entity;
if (sop.ParentGroup is null || sop.ParentGroup.IsDeleted)
continue;
lastpos = pos;
CreateCompressedUpdateBlock(sop, mysp, data, ref pos);
if (pos < LLUDPServer.MAXPAYLOAD)
{
tau.Add(eu);
++count;
}
else
{
// we need more packets
UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint);
Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, countposition); // start is the same
buf.Data[countposition] = (byte)count;
buf.DataLength = lastpos;
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
buf = newbuf;
data = buf.Data;
pos = 18;
// im lazy now, just do last again
CreateCompressedUpdateBlock(sop, mysp, data, ref pos);
tau = new List<EntityUpdate>(30);
tau.Add(eu);
count = 1;
}
}
if (count > 0)
{
buf.Data[countposition] = (byte)count;
buf.DataLength = pos;
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
}
}
*/
if (compressedUpdates is not null)
{
//List<EntityUpdate> tau = new List<EntityUpdate>(30);
@@ -5545,6 +5493,70 @@ namespace OpenSim.Region.ClientStack.LindenUDP
}
}
IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
if (needMaterials is not null && eq is not null)
{
Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out uint regionX, out uint regionY);
foreach (SceneObjectPart sop in needMaterials)
{
Primitive.RenderMaterials.RenderMaterialOverrideEntry[] overrides = sop.Shape.RenderMaterials.overrides;
/*
osUTF8 sbinner = LLSDxmlEncode2.Start();
LLSDxmlEncode2.AddArray(sbinner);
LLSDxmlEncode2.AddMap(sbinner);
LLSDxmlEncode2.AddElem("object_id", sop.UUID, sbinner);
LLSDxmlEncode2.AddElem("region_handle_low", (int)regionX, sbinner);
LLSDxmlEncode2.AddElem("region_handle_high", (int)regionY, sbinner);
LLSDxmlEncode2.AddArray("sides", sbinner);
foreach (Primitive.RenderMaterials.RenderMaterialOverrideEntry ovr in overrides)
LLSDxmlEncode2.AddElem(ovr.te_index, sbinner);
LLSDxmlEncode2.AddEndArray(sbinner);
LLSDxmlEncode2.AddArray("gltf_json", sbinner);
foreach (Primitive.RenderMaterials.RenderMaterialOverrideEntry ovr in overrides)
{
LLSDxmlEncode2.AddElem(ovr.data, sbinner);
}
LLSDxmlEncode2.AddEndArray(sbinner);
LLSDxmlEncode2.AddEndMapAndArray(sbinner);
LLSDxmlEncode2.AddEnd(sbinner);
*/
OSDMap data = new OSDMap();
data["object_id"] = sop.UUID;
//data["region_handle_low"]= (int)regionX;
//data["region_handle_high"]= (int)regionY;
OSDArray sides = new OSDArray();
foreach (Primitive.RenderMaterials.RenderMaterialOverrideEntry ovr in overrides)
sides.Add(ovr.te_index);
data["sides"] = sides;
OSDArray gltf = new OSDArray();
foreach (Primitive.RenderMaterials.RenderMaterialOverrideEntry ovr in overrides)
gltf.Add(ovr.data);
data["gltf_json"] = gltf;
string inner = OSDParser.SerializeLLSDNotationFull(data);
osUTF8 sb = eq.StartEvent("LargeGenericMessage");
LLSDxmlEncode2.AddArrayAndMap("AgentData", sb);
LLSDxmlEncode2.AddElem("AgentID", AgentId, sb);
//LLSDxmlEncode2.AddElem("TransactionID", transationID.Value, sb);
//LLSDxmlEncode2.AddElem("SessionID", sessionID.Value, sb);
LLSDxmlEncode2.AddEndMapAndArray(sb);
LLSDxmlEncode2.AddArrayAndMap("MethodData", sb);
LLSDxmlEncode2.AddElem("Method", "GLTFMaterialOverride", sb);
LLSDxmlEncode2.AddElem("Invoice", UUID.Zero, sb);
LLSDxmlEncode2.AddEndMapAndArray(sb);
LLSDxmlEncode2.AddArrayAndMap("ParamList", sb);
//LLSDxmlEncode2.AddElem("Parameter", sbinner, sb);
LLSDxmlEncode2.AddElem("Parameter", inner, sb);
LLSDxmlEncode2.AddEndMapAndArray(sb);
//OSUTF8Cached.Release(sbinner);
eq.Enqueue(eq.EndEventToBytes(sb), AgentId);
}
}
#endregion Packet Sending
#region Handle deleted objects

View File

@@ -109,6 +109,10 @@ namespace OpenSim.Region.Framework.Interfaces
void SendBulkUpdateInventoryItem(InventoryItemBase item, UUID avatarID, UUID? transationID = null);
osUTF8 StartEvent(string eventName);
osUTF8 StartEvent(string eventName, int cap);
void SendLargeGenericMessage(UUID avatarID, UUID? transationID, UUID? sessionID,
string method, UUID invoice, List<byte[]> message);
void SendLargeGenericMessage(UUID avatarID, UUID? transationID, UUID? sessionID,
string method, UUID invoice, List<string> message);
byte[] EndEventToBytes(osUTF8 sb);
}
}

View File

@@ -5287,7 +5287,7 @@ namespace OpenSim.Region.Framework.Scenes
linknumber -= (m_parts.Count + 1);
lock (m_sittingAvatars)
{
if (linknumber >= 0 && linknumber < m_sittingAvatars.Count)
if (linknumber < m_sittingAvatars.Count && linknumber >= 0)
return m_sittingAvatars[linknumber];
}
return null;

View File

@@ -5755,7 +5755,7 @@ namespace OpenSim.Region.Framework.Scenes
int pos = 2;
while(--count >= 0)
{
UUID id = new UUID(data, pos);
UUID id = new(data, pos);
if(id.IsZero())
break;
pos += 16;

View File

@@ -36,6 +36,8 @@ using Mono.Addins;
using Nini.Config;
using OpenMetaverse;
using static OpenMetaverse.Primitive;
using static OpenMetaverse.Primitive.RenderMaterials;
using OpenMetaverse.StructuredData;
using OpenSim.Framework;
@@ -61,23 +63,23 @@ namespace OpenSim.Region.OptionalModules.Materials
private Scene m_scene = null;
private bool m_enabled = false;
private int m_maxMaterialsPerTransaction = 50;
private object materialslock = new object();
private readonly object materialslock = new();
public Dictionary<UUID, FaceMaterial> m_Materials = new Dictionary<UUID, FaceMaterial>();
public Dictionary<UUID, int> m_MaterialsRefCount = new Dictionary<UUID, int>();
public Dictionary<UUID, FaceMaterial> m_Materials = new();
public Dictionary<UUID, int> m_MaterialsRefCount = new();
private Dictionary<FaceMaterial, double> m_changed = new Dictionary<FaceMaterial, double>();
private Queue<UUID> delayedDelete = new Queue<UUID>();
private readonly Dictionary<FaceMaterial, double> m_changed = new();
private readonly Queue<UUID> delayedDelete = new();
private bool m_storeBusy;
private static byte[] GetPutEmptyResponseBytes = osUTF8.GetASCIIBytes("<llsd><map><key>Zipped</key><binary>eNqLZgCCWAAChQC5</binary></map></llsd>");
private static readonly byte[] GetPutEmptyResponseBytes = osUTF8.GetASCIIBytes("<llsd><map><key>Zipped</key><binary>eNqLZgCCWAAChQC5</binary></map></llsd>");
public void Initialise(IConfigSource source)
{
m_enabled = true; // default is enabled
IConfig config = source.Configs["Materials"];
if (config != null)
if (config is not null)
{
m_enabled = config.GetBoolean("enable_materials", m_enabled);
m_maxMaterialsPerTransaction = config.GetInt("MaxMaterialsPerTransaction", m_maxMaterialsPerTransaction);
@@ -124,7 +126,7 @@ namespace OpenSim.Region.OptionalModules.Materials
m_cache = scene.RequestModuleInterface<IAssetCache>();
ISimulatorFeaturesModule featuresModule = scene.RequestModuleInterface<ISimulatorFeaturesModule>();
if (featuresModule != null)
if (featuresModule is not null)
{
featuresModule.AddOpenSimExtraFeature("MaxMaterialsPerTransaction", m_maxMaterialsPerTransaction);
featuresModule.AddOpenSimExtraFeature("RenderMaterialsCapability", 3.0f);
@@ -217,15 +219,17 @@ namespace OpenSim.Region.OptionalModules.Materials
private void EventManager_OnObjectAddedToScene(SceneObjectGroup obj)
{
foreach (var part in obj.Parts)
if (part != null)
{
if (part is not null)
GetStoredMaterialsInPart(part);
}
}
private void EventManager_OnObjectDeleteFromScene(SceneObjectGroup obj)
{
foreach (var part in obj.Parts)
{
if (part != null)
if (part is not null)
RemoveMaterialsInPart(part);
}
}
@@ -271,12 +275,11 @@ namespace OpenSim.Region.OptionalModules.Materials
/// <param name="part"></param>
private bool GetLegacyStoredMaterialsInPart(SceneObjectPart part)
{
if (part.DynAttrs == null)
if (part.DynAttrs is null)
return false;
OSD OSMaterials = null;
OSDArray matsArr = null;
OSDArray matsArr;
bool partchanged = false;
lock (part.DynAttrs)
@@ -284,8 +287,7 @@ namespace OpenSim.Region.OptionalModules.Materials
if (part.DynAttrs.ContainsStore("OpenSim", "Materials"))
{
OSDMap materialsStore = part.DynAttrs.GetStore("OpenSim", "Materials");
if (materialsStore == null)
if (materialsStore is null)
return false;
materialsStore.TryGetValue("Materials", out OSMaterials);
@@ -293,42 +295,37 @@ namespace OpenSim.Region.OptionalModules.Materials
partchanged = true;
}
if (OSMaterials != null && OSMaterials is OSDArray)
matsArr = OSMaterials as OSDArray;
else
if (OSMaterials is not OSDArray)
return partchanged;
matsArr = (OSDArray)OSMaterials;
}
if (matsArr == null)
if (matsArr is null)
return partchanged;
foreach (OSD elemOsd in matsArr)
{
if (elemOsd != null && elemOsd is OSDMap)
if (elemOsd is OSDMap matMap)
{
OSDMap matMap = elemOsd as OSDMap;
OSD OSDID;
OSD OSDMaterial;
if (matMap.TryGetValue("ID", out OSDID) && matMap.TryGetValue("Material", out OSDMaterial) && OSDMaterial is OSDMap)
if (matMap.TryGetValue("ID", out OSD OSDID) &&
matMap.TryGetValue("Material", out OSD OSDMaterial) && OSDMaterial is OSDMap theMatMap)
{
try
{
lock (materialslock)
{
UUID id = OSDID.AsUUID();
if(m_Materials.ContainsKey(id))
if (m_Materials.ContainsKey(id))
continue;
OSDMap theMatMap = (OSDMap)OSDMaterial;
FaceMaterial fmat = new FaceMaterial(theMatMap);
if(fmat == null ||
( fmat.DiffuseAlphaMode == 1
FaceMaterial fmat = new(theMatMap);
if (fmat is null ||
(fmat.DiffuseAlphaMode == 1
&& fmat.NormalMapID.IsZero()
&& fmat.SpecularMapID.IsZero()))
continue;
fmat.ID = id;
fmat.ID = id;
m_Materials[id] = fmat;
m_MaterialsRefCount[id] = 0;
}
@@ -348,18 +345,17 @@ namespace OpenSim.Region.OptionalModules.Materials
/// </summary>
private void GetStoredMaterialsInPart(SceneObjectPart part)
{
if (part.Shape == null)
if (part.Shape is null)
return;
bool partchanged = false;
bool facechanged = false;
var te = new Primitive.TextureEntry(part.Shape.TextureEntry, 0, part.Shape.TextureEntry.Length);
if (te == null)
if (te is null)
return;
partchanged = GetLegacyStoredMaterialsInPart(part);
bool partchanged = GetLegacyStoredMaterialsInPart(part);
bool facechanged = false;
if (te.DefaultTexture != null)
if (te.DefaultTexture is not null)
facechanged = GetStoredMaterialInFace(part, te.DefaultTexture);
else
m_log.WarnFormat(
@@ -368,7 +364,7 @@ namespace OpenSim.Region.OptionalModules.Materials
foreach (Primitive.TextureEntryFace face in te.FaceTextures)
{
if (face != null)
if (face is not null)
facechanged |= GetStoredMaterialInFace(part, face);
}
@@ -377,7 +373,7 @@ namespace OpenSim.Region.OptionalModules.Materials
if(facechanged || partchanged)
{
if (part.ParentGroup != null && !part.ParentGroup.IsDeleted)
if (part.ParentGroup is not null && !part.ParentGroup.IsDeleted)
part.ParentGroup.HasGroupChanged = true;
}
}
@@ -401,7 +397,7 @@ namespace OpenSim.Region.OptionalModules.Materials
}
AssetBase matAsset = m_scene.AssetService.Get(id.ToString());
if (matAsset == null || matAsset.Data == null || matAsset.Data.Length == 0 )
if (matAsset is null || matAsset.Data is null || matAsset.Data.Length == 0 )
{
// grid may just be down...
return false;
@@ -420,9 +416,8 @@ namespace OpenSim.Region.OptionalModules.Materials
return false;
}
FaceMaterial fmat = new FaceMaterial(mat);
if(fmat == null ||
FaceMaterial fmat = new(mat);
if(fmat is null ||
(fmat.DiffuseAlphaMode == 1
&& fmat.NormalMapID.IsZero()
&& fmat.SpecularMapID.IsZero()))
@@ -448,19 +443,19 @@ namespace OpenSim.Region.OptionalModules.Materials
private void RemoveMaterialsInPart(SceneObjectPart part)
{
if (part.Shape == null)
if (part.Shape is null)
return;
var te = new Primitive.TextureEntry(part.Shape.TextureEntry, 0, part.Shape.TextureEntry.Length);
if (te == null)
if (te is null)
return;
if (te.DefaultTexture != null)
if (te.DefaultTexture is not null)
RemoveMaterialInFace(te.DefaultTexture);
foreach (Primitive.TextureEntryFace face in te.FaceTextures)
{
if(face != null)
if(face is not null)
RemoveMaterialInFace(face);
}
}
@@ -495,34 +490,33 @@ namespace OpenSim.Region.OptionalModules.Materials
return;
}
OSDArray respArr = new OSDArray();
OSD tmpOSD;
OSDArray respArr = new();
if (req.TryGetValue("Zipped", out tmpOSD))
if (req.TryGetValue("Zipped", out OSD tmpOSD))
{
OSD osd = null;
OSD osd;
byte[] inBytes = tmpOSD.AsBinary();
try
{
osd = ZDecompressBytesToOsd(inBytes);
if (osd != null && osd is OSDArray)
if (osd is OSDArray OSDArrayosd)
{
foreach (OSD elem in (OSDArray)osd)
foreach (OSD elem in OSDArrayosd)
{
try
{
UUID id = new UUID(elem.AsBinary(), 0);
UUID id = new(elem.AsBinary(), 0);
lock (materialslock)
{
if (m_Materials.ContainsKey(id))
{
OSDMap matMap = new OSDMap();
matMap["ID"] = OSD.FromBinary(id.GetBytes());
matMap["Material"] = m_Materials[id].toOSD();
OSDMap matMap = new()
{
["ID"] = OSD.FromBinary(id.GetBytes()),
["Material"] = m_Materials[id].toOSD()
};
respArr.Add(matMap);
}
else
@@ -552,8 +546,10 @@ namespace OpenSim.Region.OptionalModules.Materials
}
}
OSDMap resp = new OSDMap();
resp["Zipped"] = ZCompressOSD(respArr, false);
OSDMap resp = new()
{
["Zipped"] = ZCompressOSD(respArr, false)
};
response.RawBuffer = Encoding.UTF8.GetBytes(OSDParser.SerializeLLSDXmlString(resp));
//m_log.Debug("[Materials]: cap request: " + request);
@@ -574,22 +570,19 @@ namespace OpenSim.Region.OptionalModules.Materials
return;
}
OSD tmpOSD;
if (req.TryGetValue("Zipped", out tmpOSD))
if (req.TryGetValue("Zipped", out OSD tmpOSD))
{
try
{
byte[] inBytes = tmpOSD.AsBinary();
OSD osd = ZDecompressBytesToOsd(inBytes);
if (osd != null && osd is OSDMap)
if (osd is OSDMap materialsFromViewer)
{
OSDMap materialsFromViewer = osd as OSDMap;
if (materialsFromViewer.TryGetValue("FullMaterialsPerFace", out tmpOSD) && (tmpOSD is OSDArray))
{
Dictionary<uint, SceneObjectPart> parts = new Dictionary<uint, SceneObjectPart>();
HashSet<uint> errorReported = new HashSet<uint>();
Dictionary<uint, SceneObjectPart> parts = new();
HashSet<uint> errorReported = new();
OSDArray matsArr = tmpOSD as OSDArray;
try
{
@@ -607,7 +600,7 @@ namespace OpenSim.Region.OptionalModules.Materials
}
SceneObjectPart sop = m_scene.GetSceneObjectPart(primLocalID);
if (sop == null)
if (sop is null)
{
m_log.WarnFormat("[Materials]: SOP not found for localId: {0}", primLocalID.ToString());
continue;
@@ -634,8 +627,8 @@ namespace OpenSim.Region.OptionalModules.Materials
continue;
}
Primitive.TextureEntry te = new Primitive.TextureEntry(sop.Shape.TextureEntry, 0, sop.Shape.TextureEntry.Length);
if (te == null)
Primitive.TextureEntry te = new(sop.Shape.TextureEntry, 0, sop.Shape.TextureEntry.Length);
if (te is null)
{
m_log.WarnFormat("[Materials]: Error in TextureEntry for SOP {0} {1}", sop.Name, sop.UUID);
continue;
@@ -652,12 +645,12 @@ namespace OpenSim.Region.OptionalModules.Materials
else
faceEntry = te.DefaultTexture;
if (faceEntry == null)
if (faceEntry is null)
continue;
UUID id;
FaceMaterial newFaceMat = null;
if (mat == null)
if (mat is null)
{
// This happens then the user removes a material from a prim
id = UUID.Zero;
@@ -665,7 +658,7 @@ namespace OpenSim.Region.OptionalModules.Materials
else
{
newFaceMat = new FaceMaterial(mat);
if(newFaceMat.DiffuseAlphaMode == 1
if (newFaceMat.DiffuseAlphaMode == 1
&& newFaceMat.NormalMapID.IsZero()
&& newFaceMat.SpecularMapID.IsZero())
id = UUID.Zero;
@@ -678,10 +671,10 @@ namespace OpenSim.Region.OptionalModules.Materials
oldid = faceEntry.MaterialID;
if(oldid == id)
if (oldid == id)
continue;
if (faceEntry != null)
if (faceEntry is not null)
{
faceEntry.MaterialID = id;
//m_log.DebugFormat("[Materials]: in \"{0}\" {1}, setting material ID for face {2} to {3}", sop.Name, sop.UUID, face, id);
@@ -689,12 +682,12 @@ namespace OpenSim.Region.OptionalModules.Materials
sop.Shape.TextureEntry = te.GetBytes(9);
}
if(!oldid.IsZero())
if (!oldid.IsZero())
RemoveMaterial(oldid);
lock(materialslock)
lock (materialslock)
{
if(!id.IsZero())
if (id.IsNotZero())
{
if (m_Materials.ContainsKey(id))
m_MaterialsRefCount[id]++;
@@ -707,13 +700,12 @@ namespace OpenSim.Region.OptionalModules.Materials
}
}
if(!parts.ContainsKey(primLocalID))
parts[primLocalID] = sop;
parts[primLocalID] = sop;
}
foreach(SceneObjectPart sop in parts.Values)
foreach (SceneObjectPart sop in parts.Values)
{
if (sop.ParentGroup != null && !sop.ParentGroup.IsDeleted)
if (sop.ParentGroup is not null && !sop.ParentGroup.IsDeleted)
{
sop.TriggerScriptChangedEvent(Changed.TEXTURE);
sop.ScheduleFullUpdate();
@@ -749,27 +741,26 @@ namespace OpenSim.Region.OptionalModules.Materials
private AssetBase MakeAsset(FaceMaterial fm, bool local)
{
// this are not true assets, should had never been...
AssetBase asset = null;
byte[] data = fm.toLLSDxml();
asset = new AssetBase(fm.ID, "llmaterial", (sbyte)OpenSimAssetType.Material, "00000000-0000-0000-0000-000000000000");
asset.Data = data;
asset.Local = local;
AssetBase asset = new(fm.ID, "llmaterial", (sbyte)OpenSimAssetType.Material, "00000000-0000-0000-0000-000000000000")
{
Data = data,
Local = local
};
return asset;
}
private byte[] CacheGet = null;
private object CacheGetLock = new object();
private readonly object CacheGetLock = new();
private double CacheGetTime = 0;
public void RenderMaterialsGetCap(IOSHttpRequest request, IOSHttpResponse response)
{
lock(CacheGetLock)
{
OSDArray allOsd = new OSDArray();
OSDArray allOsd = new();
double now = Util.GetTimeStamp();
if(CacheGet == null || now - CacheGetTime > 30)
if(CacheGet is null || now - CacheGetTime > 30)
{
CacheGetTime = now;
@@ -777,7 +768,7 @@ namespace OpenSim.Region.OptionalModules.Materials
{
foreach (KeyValuePair<UUID, FaceMaterial> kvp in m_Materials)
{
OSDMap matMap = new OSDMap
OSDMap matMap = new()
{
["ID"] = OSD.FromBinary(kvp.Key.GetBytes()),
["Material"] = kvp.Value.toOSD()
@@ -786,7 +777,7 @@ namespace OpenSim.Region.OptionalModules.Materials
}
}
OSDMap resp = new OSDMap
OSDMap resp = new()
{
["Zipped"] = ZCompressOSD(allOsd, false)
};
@@ -811,11 +802,8 @@ namespace OpenSim.Region.OptionalModules.Materials
public static OSD ZCompressOSD(OSD inOsd, bool useHeader)
{
OSD osd = null;
byte[] data = OSDParser.SerializeLLSDBinary(inOsd, useHeader);
using (MemoryStream msSinkCompressed = new MemoryStream())
using (MemoryStream msSinkCompressed = new())
{
using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkCompressed,
Ionic.Zlib.CompressionMode.Compress, CompressionLevel.BestCompression, true))
@@ -824,42 +812,34 @@ namespace OpenSim.Region.OptionalModules.Materials
}
msSinkCompressed.Seek(0L, SeekOrigin.Begin);
osd = OSD.FromBinary(msSinkCompressed.ToArray());
return OSD.FromBinary(msSinkCompressed.ToArray());
}
return osd;
}
public static OSD ZDecompressBytesToOsd(byte[] input)
{
OSD osd = null;
using (MemoryStream msSinkUnCompressed = new MemoryStream())
using (MemoryStream msSinkUnCompressed = new())
{
using (Ionic.Zlib.ZlibStream zOut = new Ionic.Zlib.ZlibStream(msSinkUnCompressed, CompressionMode.Decompress, true))
using (Ionic.Zlib.ZlibStream zOut = new(msSinkUnCompressed, CompressionMode.Decompress, true))
{
zOut.Write(input, 0, input.Length);
}
msSinkUnCompressed.Seek(0L, SeekOrigin.Begin);
osd = OSDParser.DeserializeLLSDBinary(msSinkUnCompressed.ToArray());
return OSDParser.DeserializeLLSDBinary(msSinkUnCompressed.ToArray());
}
return osd;
}
public FaceMaterial GetMaterial(UUID ID)
{
FaceMaterial fm = null;
if(m_Materials.TryGetValue(ID, out fm))
if(m_Materials.TryGetValue(ID, out FaceMaterial fm))
return fm;
return null;
}
public FaceMaterial GetMaterialCopy(UUID ID)
{
FaceMaterial fm = null;
if(m_Materials.TryGetValue(ID, out fm))
if(m_Materials.TryGetValue(ID, out FaceMaterial fm))
return new FaceMaterial(fm);
return null;
}
@@ -915,10 +895,10 @@ namespace OpenSim.Region.OptionalModules.Materials
httpResponse.StatusCode = (int)HttpStatusCode.NotFound;
return;
}
OSDArray req;
try
{
req = (OSDArray)OSDParser.DeserializeLLSDXml(httpRequest.InputStream);
OSDArray req = (OSDArray)OSDParser.DeserializeLLSDXml(httpRequest.InputStream);
httpRequest.InputStream.Dispose();
OSD tmp;
@@ -940,86 +920,195 @@ namespace OpenSim.Region.OptionalModules.Materials
if (pbs is null)
continue;
if (!m_scene.Permissions.CanEditObject(sop.UUID, agentID))
continue;
if (!map.TryGetValue("side", out tmp))
continue;
int side = tmp.AsInteger();
UUID assetID;
if (map.TryGetValue("asset_id", out tmp))
assetID = tmp.AsUUID();
else
assetID = UUID.Zero;
string overridedata;
if (map.TryGetValue("gltf_json", out tmp))
overridedata = tmp.AsString().TrimEnd('\n');
else
overridedata = string.Empty;
if (map.TryGetValue("asset_id", out tmp))
{
string assetdata = tmp.AsString();
if (!string.IsNullOrEmpty(assetdata))
UUID assetID = tmp.AsUUID();
if (assetID.IsNotZero())
{
if (pbs.RenderMaterials is not null)
if (pbs.RenderMaterials is null)
{
int sideIndex = 0;
while (sideIndex < pbs.RenderMaterials.entries.Length)
var entries = new Primitive.RenderMaterials.RenderMaterialEntry[1];
entries[0].te_index = (byte)side;
entries[0].id = assetID;
pbs.RenderMaterials = new Primitive.RenderMaterials { entries = entries };
}
else
{
if (pbs.RenderMaterials.entries is null)
{
if (pbs.RenderMaterials.entries[sideIndex].te_index == side)
break;
sideIndex++;
var entries = new Primitive.RenderMaterials.RenderMaterialEntry[1];
entries[0].te_index = (byte)side;
entries[0].id = assetID;
pbs.RenderMaterials.entries = entries;
}
if (sideIndex < pbs.RenderMaterials.entries.Length)
else
{
changedSOPs.Add(sop);
int indx = 0;
while (indx < pbs.RenderMaterials.entries.Length)
{
if (pbs.RenderMaterials.entries[indx].te_index == side)
{
pbs.RenderMaterials.entries[indx].id = assetID;
break;
}
indx++;
}
if (indx == pbs.RenderMaterials.entries.Length)
{
Array.Resize(ref pbs.RenderMaterials.entries, indx + 1);
pbs.RenderMaterials.entries[indx].te_index = (byte)side;
pbs.RenderMaterials.entries[indx].id = assetID;
}
}
}
if (string.IsNullOrEmpty(overridedata))
RemoveMaterialOverride(ref pbs.RenderMaterials.overrides, side);
else
AddMaterialOverride(ref pbs.RenderMaterials.overrides, overridedata, side);
changedSOPs.Add(sop);
}
else if(pbs.RenderMaterials is not null)
{
bool changed = RemoveMaterialEntry(ref pbs.RenderMaterials.entries, side);
changed |= RemoveMaterialOverride(ref pbs.RenderMaterials.overrides, side);
if(pbs.RenderMaterials.entries is null && pbs.RenderMaterials.overrides is null)
pbs.RenderMaterials = null;
if(changed)
changedSOPs.Add(sop);
}
}
if (assetID.IsNotZero())
else if (pbs.RenderMaterials is not null)
{
if (pbs.RenderMaterials is null)
if (string.IsNullOrEmpty(overridedata))
{
var entries = new Primitive.RenderMaterials.RenderMaterialEntry[1];
entries[0].te_index = (byte)side;
entries[0].id = assetID;
pbs.RenderMaterials = new Primitive.RenderMaterials
{
entries = entries
};
}
else
{
int i = 0;
while(i < pbs.RenderMaterials.entries.Length)
{
if (pbs.RenderMaterials.entries[i].te_index == side)
{
pbs.RenderMaterials.entries[i].id = assetID;
break;
}
i++;
}
if (i == pbs.RenderMaterials.entries.Length)
{
Array.Resize(ref pbs.RenderMaterials.entries, i + 1);
pbs.RenderMaterials.entries[i].te_index = (byte)side;
pbs.RenderMaterials.entries[i].id = assetID;
}
if(AddMaterialOverride(ref pbs.RenderMaterials.overrides, overridedata, side))
changedSOPs.Add(sop);
}
changedSOPs.Add(sop);
}
}
foreach(SceneObjectPart sop in changedSOPs)
foreach (SceneObjectPart sop in changedSOPs)
{
sop.ParentGroup.HasGroupChanged = true;
sop.ScheduleFullUpdate();
}
httpResponse.RawBuffer = XMLkeyMaterialSucess;
httpResponse.StatusCode = (int)HttpStatusCode.OK;
}
catch
{
httpResponse.StatusCode = (int)HttpStatusCode.BadRequest;
httpResponse.RawBuffer = XMLkeyMaterialFail;
}
}
public static readonly byte[] XMLkeyMaterialSucess = osUTF8.GetASCIIBytes("<llsd><map><key>success</key><integer>1</integer></map></llsd>\r\n");
public static readonly byte[] XMLkeyMaterialFail = osUTF8.GetASCIIBytes("<llsd><map><key>success</key><integer>0</integer></map></llsd>\r\n");
private static bool RemoveMaterialEntry(ref RenderMaterialEntry[] entries, int side)
{
if (entries is null || entries.Length == 0)
return false;
int indx = 0;
while (entries[indx].te_index != side && indx < entries.Length)
indx++;
if (indx >= entries.Length)
return false;
if (entries.Length == 1)
entries = null;
else
{
var newentries = new Primitive.RenderMaterials.RenderMaterialEntry[entries.Length - 1];
if (indx > 0)
Array.Copy(entries, newentries, indx);
int left = newentries.Length - indx;
if (left > 0)
Array.Copy(entries, indx + 1, newentries, indx, left);
entries = newentries;
}
return true;
}
private static bool RemoveMaterialOverride(ref RenderMaterialOverrideEntry[] overrides, int side)
{
if (overrides is null || overrides.Length == 0)
return false;
int indx = 0;
while(overrides[indx].te_index != side && indx < overrides.Length)
indx++;
if (indx >= overrides.Length)
return false;
if (overrides.Length == 1)
overrides = null;
else
{
var entries = new Primitive.RenderMaterials.RenderMaterialOverrideEntry[overrides.Length - 1];
if (indx > 0)
Array.Copy(overrides, entries, indx);
int left = entries.Length - indx;
if (left > 0)
Array.Copy(overrides, indx + 1, entries, indx, left);
overrides = entries;
}
return true;
}
private static bool AddMaterialOverride(ref RenderMaterials.RenderMaterialOverrideEntry[] overrides, string data, int side)
{
if (overrides is null)
{
var entries = new RenderMaterials.RenderMaterialOverrideEntry[1];
entries[0].te_index = (byte)side;
entries[0].data = data;
overrides = entries;
return true;
}
int indx = 0;
while (indx < overrides.Length)
{
if (overrides[indx].te_index == side)
{
overrides[indx].data = data;
return true;
}
indx++;
}
if (indx == overrides.Length)
{
Array.Resize(ref overrides, indx + 1);
overrides[indx].te_index = (byte)side;
if(overrides[indx].data != data)
{
overrides[indx].data = data;
return true;
}
}
return false;
}
}
}