diff options
Diffstat (limited to 'OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs')
-rw-r--r-- | OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs | 226 |
1 files changed, 152 insertions, 74 deletions
diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index d0a5989..2764465 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs | |||
@@ -39,6 +39,7 @@ using OpenSim.Framework.Communications; | |||
39 | using OpenSim.Region.Framework.Interfaces; | 39 | using OpenSim.Region.Framework.Interfaces; |
40 | using OpenSim.Region.Framework.Scenes; | 40 | using OpenSim.Region.Framework.Scenes; |
41 | using OpenSim.Services.Interfaces; | 41 | using OpenSim.Services.Interfaces; |
42 | using System.Text; | ||
42 | using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags; | 43 | using DirFindFlags = OpenMetaverse.DirectoryManager.DirFindFlags; |
43 | 44 | ||
44 | namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | 45 | namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups |
@@ -194,6 +195,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
194 | } | 195 | } |
195 | 196 | ||
196 | scene.EventManager.OnNewClient += OnNewClient; | 197 | scene.EventManager.OnNewClient += OnNewClient; |
198 | scene.EventManager.OnMakeRootAgent += OnMakeRoot; | ||
199 | scene.EventManager.OnMakeChildAgent += OnMakeChild; | ||
197 | scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; | 200 | scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; |
198 | // The InstantMessageModule itself doesn't do this, | 201 | // The InstantMessageModule itself doesn't do this, |
199 | // so lets see if things explode if we don't do it | 202 | // so lets see if things explode if we don't do it |
@@ -244,20 +247,34 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
244 | #endregion | 247 | #endregion |
245 | 248 | ||
246 | #region EventHandlers | 249 | #region EventHandlers |
250 | |||
251 | private void OnMakeRoot(ScenePresence sp) | ||
252 | { | ||
253 | if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); | ||
254 | |||
255 | sp.ControllingClient.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest; | ||
256 | // Used for Notices and Group Invites/Accept/Reject | ||
257 | sp.ControllingClient.OnInstantMessage += OnInstantMessage; | ||
258 | // Send client their groups information. | ||
259 | // SendAgentGroupDataUpdate(sp.ControllingClient, sp.UUID); | ||
260 | // only send data viwer will ask rest later | ||
261 | OnAgentDataUpdateRequest(sp.ControllingClient, sp.UUID, sp.UUID); | ||
262 | } | ||
263 | |||
264 | private void OnMakeChild(ScenePresence sp) | ||
265 | { | ||
266 | if (m_debugEnabled) m_log.DebugFormat("[Groups]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); | ||
267 | |||
268 | sp.ControllingClient.OnUUIDGroupNameRequest -= HandleUUIDGroupNameRequest; | ||
269 | sp.ControllingClient.OnInstantMessage -= OnInstantMessage; | ||
270 | } | ||
271 | |||
247 | private void OnNewClient(IClientAPI client) | 272 | private void OnNewClient(IClientAPI client) |
248 | { | 273 | { |
249 | if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); | 274 | if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); |
250 | 275 | ||
251 | client.OnUUIDGroupNameRequest += HandleUUIDGroupNameRequest; | ||
252 | client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest; | 276 | client.OnAgentDataUpdateRequest += OnAgentDataUpdateRequest; |
253 | client.OnDirFindQuery += OnDirFindQuery; | ||
254 | client.OnRequestAvatarProperties += OnRequestAvatarProperties; | 277 | client.OnRequestAvatarProperties += OnRequestAvatarProperties; |
255 | |||
256 | // Used for Notices and Group Invites/Accept/Reject | ||
257 | client.OnInstantMessage += OnInstantMessage; | ||
258 | |||
259 | // Send client their groups information. | ||
260 | SendAgentGroupDataUpdate(client, client.AgentId); | ||
261 | } | 278 | } |
262 | 279 | ||
263 | private void OnRequestAvatarProperties(IClientAPI remoteClient, UUID avatarID) | 280 | private void OnRequestAvatarProperties(IClientAPI remoteClient, UUID avatarID) |
@@ -303,21 +320,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
303 | } | 320 | } |
304 | */ | 321 | */ |
305 | 322 | ||
306 | void OnDirFindQuery(IClientAPI remoteClient, UUID queryID, string queryText, uint queryFlags, int queryStart) | ||
307 | { | ||
308 | if (((DirFindFlags)queryFlags & DirFindFlags.Groups) == DirFindFlags.Groups) | ||
309 | { | ||
310 | if (m_debugEnabled) | ||
311 | m_log.DebugFormat( | ||
312 | "[GROUPS]: {0} called with queryText({1}) queryFlags({2}) queryStart({3})", | ||
313 | System.Reflection.MethodBase.GetCurrentMethod().Name, queryText, (DirFindFlags)queryFlags, queryStart); | ||
314 | |||
315 | // TODO: This currently ignores pretty much all the query flags including Mature and sort order | ||
316 | remoteClient.SendDirGroupsReply(queryID, m_groupData.FindGroups(GetRequestingAgentID(remoteClient), queryText).ToArray()); | ||
317 | } | ||
318 | |||
319 | } | ||
320 | |||
321 | private void OnAgentDataUpdateRequest(IClientAPI remoteClient, UUID dataForAgentID, UUID sessionID) | 323 | private void OnAgentDataUpdateRequest(IClientAPI remoteClient, UUID dataForAgentID, UUID sessionID) |
322 | { | 324 | { |
323 | if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); | 325 | if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); |
@@ -437,44 +439,75 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
437 | string Subject = im.message.Substring(0, im.message.IndexOf('|')); | 439 | string Subject = im.message.Substring(0, im.message.IndexOf('|')); |
438 | string Message = im.message.Substring(Subject.Length + 1); | 440 | string Message = im.message.Substring(Subject.Length + 1); |
439 | 441 | ||
442 | InventoryItemBase item = null; | ||
443 | bool hasAttachment = false; | ||
444 | UUID itemID = UUID.Zero; //Assignment to quiet compiler | ||
445 | UUID ownerID = UUID.Zero; //Assignment to quiet compiler | ||
440 | byte[] bucket; | 446 | byte[] bucket; |
441 | 447 | ||
442 | if ((im.binaryBucket.Length == 1) && (im.binaryBucket[0] == 0)) | 448 | if (im.binaryBucket.Length >= 1 && im.binaryBucket[0] > 0) |
443 | { | ||
444 | bucket = new byte[19]; | ||
445 | bucket[0] = 0; //dunno | ||
446 | bucket[1] = 0; //dunno | ||
447 | GroupID.ToBytes(bucket, 2); | ||
448 | bucket[18] = 0; //dunno | ||
449 | } | ||
450 | else | ||
451 | { | 449 | { |
452 | string binBucket = OpenMetaverse.Utils.BytesToString(im.binaryBucket); | 450 | string binBucket = OpenMetaverse.Utils.BytesToString(im.binaryBucket); |
453 | binBucket = binBucket.Remove(0, 14).Trim(); | 451 | binBucket = binBucket.Remove(0, 14).Trim(); |
454 | if (m_debugEnabled) | 452 | |
453 | OSDMap binBucketOSD = (OSDMap)OSDParser.DeserializeLLSDXml(binBucket); | ||
454 | if (binBucketOSD is OSD) | ||
455 | { | 455 | { |
456 | m_log.WarnFormat("I don't understand a group notice binary bucket of: {0}", binBucket); | 456 | OSDMap binBucketMap = (OSDMap)binBucketOSD; |
457 | |||
458 | itemID = binBucketMap["item_id"].AsUUID(); | ||
459 | ownerID = binBucketMap["owner_id"].AsUUID(); | ||
457 | 460 | ||
458 | OSDMap binBucketOSD = (OSDMap)OSDParser.DeserializeLLSDXml(binBucket); | 461 | //Attempt to get the details of the attached item. |
459 | 462 | //If sender doesn't own the attachment, the item | |
460 | foreach (string key in binBucketOSD.Keys) | 463 | //variable will be set to null and attachment will |
464 | //not be included with the group notice. | ||
465 | Scene scene = (Scene)remoteClient.Scene; | ||
466 | item = new InventoryItemBase(itemID, ownerID); | ||
467 | item = scene.InventoryService.GetItem(item); | ||
468 | |||
469 | if (item != null) | ||
461 | { | 470 | { |
462 | if (binBucketOSD.ContainsKey(key)) | 471 | //Got item details so include the attachment. |
463 | { | 472 | hasAttachment = true; |
464 | m_log.WarnFormat("{0}: {1}", key, binBucketOSD[key].ToString()); | ||
465 | } | ||
466 | } | 473 | } |
467 | } | 474 | } |
468 | 475 | else | |
469 | // treat as if no attachment | 476 | { |
477 | m_log.DebugFormat("[Groups]: Received OSD with unexpected type: {0}", binBucketOSD.GetType()); | ||
478 | } | ||
479 | } | ||
480 | |||
481 | if (hasAttachment) | ||
482 | { | ||
483 | //Bucket contains information about attachment. | ||
484 | // | ||
485 | //Byte offset and description of bucket data: | ||
486 | //0: 1 byte indicating if attachment is present | ||
487 | //1: 1 byte indicating the type of attachment | ||
488 | //2: 16 bytes - Group UUID | ||
489 | //18: 16 bytes - UUID of the attachment owner | ||
490 | //34: 16 bytes - UUID of the attachment | ||
491 | //50: variable - Name of the attachment | ||
492 | //??: NUL byte to terminate the attachment name | ||
493 | byte[] name = Encoding.UTF8.GetBytes(item.Name); | ||
494 | bucket = new byte[51 + name.Length];//3 bytes, 3 UUIDs, and name | ||
495 | bucket[0] = 1; //Has attachment flag | ||
496 | bucket[1] = (byte)item.InvType; //Type of Attachment | ||
497 | GroupID.ToBytes(bucket, 2); | ||
498 | ownerID.ToBytes(bucket, 18); | ||
499 | itemID.ToBytes(bucket, 34); | ||
500 | name.CopyTo(bucket, 50); | ||
501 | } | ||
502 | else | ||
503 | { | ||
470 | bucket = new byte[19]; | 504 | bucket = new byte[19]; |
471 | bucket[0] = 0; //dunno | 505 | bucket[0] = 0; //Has attachment flag |
472 | bucket[1] = 0; //dunno | 506 | bucket[1] = 0; //Type of attachment |
473 | GroupID.ToBytes(bucket, 2); | 507 | GroupID.ToBytes(bucket, 2); |
474 | bucket[18] = 0; //dunno | 508 | bucket[18] = 0; //NUL terminate name of attachment |
475 | } | 509 | } |
476 | 510 | ||
477 | |||
478 | m_groupData.AddGroupNotice(GetRequestingAgentID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket); | 511 | m_groupData.AddGroupNotice(GetRequestingAgentID(remoteClient), GroupID, NoticeID, im.fromAgentName, Subject, Message, bucket); |
479 | if (OnNewGroupNotice != null) | 512 | if (OnNewGroupNotice != null) |
480 | { | 513 | { |
@@ -499,7 +532,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
499 | 532 | ||
500 | if (member.AcceptNotices) | 533 | if (member.AcceptNotices) |
501 | { | 534 | { |
502 | // Build notice IIM | 535 | // Build notice IM |
503 | GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice); | 536 | GridInstantMessage msg = CreateGroupNoticeIM(UUID.Zero, NoticeID, (byte)OpenMetaverse.InstantMessageDialog.GroupNotice); |
504 | 537 | ||
505 | msg.toAgentID = member.AgentID.Guid; | 538 | msg.toAgentID = member.AgentID.Guid; |
@@ -508,10 +541,40 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
508 | } | 541 | } |
509 | } | 542 | } |
510 | } | 543 | } |
511 | 544 | ||
545 | if (im.dialog == (byte)InstantMessageDialog.GroupNoticeInventoryAccepted) | ||
546 | { | ||
547 | //Is bucket large enough to hold UUID of the attachment? | ||
548 | if (im.binaryBucket.Length < 16) | ||
549 | return; | ||
550 | |||
551 | UUID noticeID = new UUID(im.imSessionID); | ||
552 | |||
553 | GroupNoticeInfo notice = m_groupData.GetGroupNotice(GetRequestingAgentID(remoteClient), noticeID); | ||
554 | if (notice != null) | ||
555 | { | ||
556 | UUID giver = new UUID(notice.BinaryBucket, 18); | ||
557 | UUID attachmentUUID = new UUID(notice.BinaryBucket, 34); | ||
558 | |||
559 | if (m_debugEnabled) | ||
560 | m_log.DebugFormat("[Groups]: Giving inventory from {0} to {1}", giver, remoteClient.AgentId); | ||
561 | |||
562 | InventoryItemBase itemCopy = ((Scene)(remoteClient.Scene)).GiveInventoryItem(remoteClient.AgentId, | ||
563 | giver, attachmentUUID); | ||
564 | |||
565 | if (itemCopy == null) | ||
566 | { | ||
567 | remoteClient.SendAgentAlertMessage("Can't find item to give. Nothing given.", false); | ||
568 | return; | ||
569 | } | ||
570 | |||
571 | remoteClient.SendInventoryItemCreateUpdate(itemCopy, 0); | ||
572 | } | ||
573 | } | ||
574 | |||
512 | // Interop, received special 210 code for ejecting a group member | 575 | // Interop, received special 210 code for ejecting a group member |
513 | // this only works within the comms servers domain, and won't work hypergrid | 576 | // this only works within the comms servers domain, and won't work hypergrid |
514 | // TODO:FIXME: Use a presense server of some kind to find out where the | 577 | // TODO:FIXME: Use a presence server of some kind to find out where the |
515 | // client actually is, and try contacting that region directly to notify them, | 578 | // client actually is, and try contacting that region directly to notify them, |
516 | // or provide the notification via xmlrpc update queue | 579 | // or provide the notification via xmlrpc update queue |
517 | if ((im.dialog == 210)) | 580 | if ((im.dialog == 210)) |
@@ -889,26 +952,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
889 | 952 | ||
890 | if (data != null) | 953 | if (data != null) |
891 | { | 954 | { |
892 | GroupRecord groupInfo = m_groupData.GetGroupRecord(GetRequestingAgentID(remoteClient), data.GroupID, null); | 955 | GridInstantMessage msg = CreateGroupNoticeIM(remoteClient.AgentId, groupNoticeID, (byte)InstantMessageDialog.GroupNoticeRequested); |
893 | |||
894 | GridInstantMessage msg = new GridInstantMessage(); | ||
895 | msg.imSessionID = UUID.Zero.Guid; | ||
896 | msg.fromAgentID = data.GroupID.Guid; | ||
897 | msg.toAgentID = GetRequestingAgentID(remoteClient).Guid; | ||
898 | msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); | ||
899 | msg.fromAgentName = "Group Notice : " + groupInfo == null ? "Unknown" : groupInfo.GroupName; | ||
900 | msg.message = data.noticeData.Subject + "|" + data.Message; | ||
901 | msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNoticeRequested; | ||
902 | msg.fromGroup = true; | ||
903 | msg.offline = (byte)0; | ||
904 | msg.ParentEstateID = 0; | ||
905 | msg.Position = Vector3.Zero; | ||
906 | msg.RegionID = UUID.Zero.Guid; | ||
907 | msg.binaryBucket = data.BinaryBucket; | ||
908 | 956 | ||
909 | OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient)); | 957 | OutgoingInstantMessage(msg, GetRequestingAgentID(remoteClient)); |
910 | } | 958 | } |
911 | |||
912 | } | 959 | } |
913 | 960 | ||
914 | public GridInstantMessage CreateGroupNoticeIM(UUID agentID, UUID groupNoticeID, byte dialog) | 961 | public GridInstantMessage CreateGroupNoticeIM(UUID agentID, UUID groupNoticeID, byte dialog) |
@@ -916,10 +963,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
916 | if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); | 963 | if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: {0} called", System.Reflection.MethodBase.GetCurrentMethod().Name); |
917 | 964 | ||
918 | GridInstantMessage msg = new GridInstantMessage(); | 965 | GridInstantMessage msg = new GridInstantMessage(); |
919 | msg.imSessionID = UUID.Zero.Guid; | 966 | byte[] bucket; |
967 | |||
968 | msg.imSessionID = groupNoticeID.Guid; | ||
920 | msg.toAgentID = agentID.Guid; | 969 | msg.toAgentID = agentID.Guid; |
921 | msg.dialog = dialog; | 970 | msg.dialog = dialog; |
922 | // msg.dialog = (byte)OpenMetaverse.InstantMessageDialog.GroupNotice; | ||
923 | msg.fromGroup = true; | 971 | msg.fromGroup = true; |
924 | msg.offline = (byte)1; // Allow this message to be stored for offline use | 972 | msg.offline = (byte)1; // Allow this message to be stored for offline use |
925 | msg.ParentEstateID = 0; | 973 | msg.ParentEstateID = 0; |
@@ -933,13 +981,38 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
933 | msg.timestamp = info.noticeData.Timestamp; | 981 | msg.timestamp = info.noticeData.Timestamp; |
934 | msg.fromAgentName = info.noticeData.FromName; | 982 | msg.fromAgentName = info.noticeData.FromName; |
935 | msg.message = info.noticeData.Subject + "|" + info.Message; | 983 | msg.message = info.noticeData.Subject + "|" + info.Message; |
936 | msg.binaryBucket = info.BinaryBucket; | 984 | |
985 | if (info.BinaryBucket[0] > 0) | ||
986 | { | ||
987 | //32 is due to not needing space for two of the UUIDs. | ||
988 | //(Don't need UUID of attachment or its owner in IM) | ||
989 | //50 offset gets us to start of attachment name. | ||
990 | //We are skipping the attachment flag, type, and | ||
991 | //the three UUID fields at the start of the bucket. | ||
992 | bucket = new byte[info.BinaryBucket.Length-32]; | ||
993 | bucket[0] = 1; //Has attachment | ||
994 | bucket[1] = info.BinaryBucket[1]; | ||
995 | Array.Copy(info.BinaryBucket, 50, | ||
996 | bucket, 18, info.BinaryBucket.Length-50); | ||
997 | } | ||
998 | else | ||
999 | { | ||
1000 | bucket = new byte[19]; | ||
1001 | bucket[0] = 0; //No attachment | ||
1002 | bucket[1] = 0; //Attachment type | ||
1003 | bucket[18] = 0; //NUL terminate name | ||
1004 | } | ||
1005 | |||
1006 | info.GroupID.ToBytes(bucket, 2); | ||
1007 | msg.binaryBucket = bucket; | ||
937 | } | 1008 | } |
938 | else | 1009 | else |
939 | { | 1010 | { |
940 | if (m_debugEnabled) m_log.DebugFormat("[GROUPS]: Group Notice {0} not found, composing empty message.", groupNoticeID); | 1011 | if (m_debugEnabled) |
1012 | m_log.DebugFormat("[GROUPS]: Group Notice {0} not found, composing empty message.", groupNoticeID); | ||
1013 | |||
941 | msg.fromAgentID = UUID.Zero.Guid; | 1014 | msg.fromAgentID = UUID.Zero.Guid; |
942 | msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); ; | 1015 | msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); |
943 | msg.fromAgentName = string.Empty; | 1016 | msg.fromAgentName = string.Empty; |
944 | msg.message = string.Empty; | 1017 | msg.message = string.Empty; |
945 | msg.binaryBucket = new byte[0]; | 1018 | msg.binaryBucket = new byte[0]; |
@@ -1063,7 +1136,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
1063 | // Message to ejector | 1136 | // Message to ejector |
1064 | // Interop, received special 210 code for ejecting a group member | 1137 | // Interop, received special 210 code for ejecting a group member |
1065 | // this only works within the comms servers domain, and won't work hypergrid | 1138 | // this only works within the comms servers domain, and won't work hypergrid |
1066 | // TODO:FIXME: Use a presense server of some kind to find out where the | 1139 | // TODO:FIXME: Use a presence server of some kind to find out where the |
1067 | // client actually is, and try contacting that region directly to notify them, | 1140 | // client actually is, and try contacting that region directly to notify them, |
1068 | // or provide the notification via xmlrpc update queue | 1141 | // or provide the notification via xmlrpc update queue |
1069 | 1142 | ||
@@ -1178,6 +1251,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
1178 | } | 1251 | } |
1179 | } | 1252 | } |
1180 | 1253 | ||
1254 | public List<DirGroupsReplyData> FindGroups(IClientAPI remoteClient, string query) | ||
1255 | { | ||
1256 | return m_groupData.FindGroups(GetRequestingAgentID(remoteClient), query); | ||
1257 | } | ||
1258 | |||
1259 | |||
1181 | #endregion | 1260 | #endregion |
1182 | 1261 | ||
1183 | #region Client/Update Tools | 1262 | #region Client/Update Tools |
@@ -1222,7 +1301,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups | |||
1222 | AgentDataMap.Add("AgentID", OSD.FromUUID(dataForAgentID)); | 1301 | AgentDataMap.Add("AgentID", OSD.FromUUID(dataForAgentID)); |
1223 | AgentData.Add(AgentDataMap); | 1302 | AgentData.Add(AgentDataMap); |
1224 | 1303 | ||
1225 | |||
1226 | OSDArray GroupData = new OSDArray(data.Length); | 1304 | OSDArray GroupData = new OSDArray(data.Length); |
1227 | OSDArray NewGroupData = new OSDArray(data.Length); | 1305 | OSDArray NewGroupData = new OSDArray(data.Length); |
1228 | 1306 | ||