From f0581ff1ff6123523c3983a7edbc4e63369ef4ce Mon Sep 17 00:00:00 2001 From: UbitUmarov Date: Sun, 31 May 2020 01:35:03 +0100 Subject: [PATCH] and more changes on uuid gatherer and libomv --- .../Region/Framework/Scenes/UuidGatherer.cs | 302 +++++++++++++++--- bin/OpenMetaverse.Rendering.Meshmerizer.dll | Bin 20480 -> 20480 bytes bin/OpenMetaverse.StructuredData.dll | Bin 110592 -> 110592 bytes bin/OpenMetaverse.dll | Bin 2191360 -> 2191360 bytes bin/OpenMetaverseTypes.dll | Bin 126976 -> 126976 bytes 5 files changed, 261 insertions(+), 41 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index c410f35889..974caacf38 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs @@ -435,6 +435,19 @@ namespace OpenSim.Region.Framework.Scenes AddForInspection(tii.AssetID, (sbyte)tii.Type); } + if(part.Animations != null && part.Animations.Count > 0) + { + foreach(UUID id in part.Animations.Keys) + { + if(id != UUID.Zero && + !ToSkip.Contains(id) && + !FailedUUIDs.Contains(id)) + { + GatheredUuids[id] = (sbyte)AssetType.Animation; + } + } + } + RecordMaterialsUuids(part); } catch (Exception e) @@ -588,6 +601,10 @@ namespace OpenSim.Region.Framework.Scenes { RecordSceneObjectAssetUuids(assetBase); } + else if ((sbyte)AssetType.Settings == assetType) + { + RecordEmbeddedAssetDataUuids(assetBase); // BAD to do + } } catch (Exception e) { @@ -647,8 +664,13 @@ namespace OpenSim.Region.Framework.Scenes /// private void RecordTextureEntryAssetUuids(Primitive.TextureEntryFace texture) { - if (texture.TextureID != UUID.Zero) - GatheredUuids[texture.TextureID] = (sbyte)AssetType.Texture; + UUID teid = texture.TextureID; + if (teid != UUID.Zero && + !ToSkip.Contains(teid) && + !FailedUUIDs.Contains(teid)) + { + GatheredUuids[teid] = (sbyte)AssetType.Texture; + } if (texture.MaterialID != UUID.Zero) AddForInspection(texture.MaterialID); @@ -843,7 +865,7 @@ namespace OpenSim.Region.Framework.Scenes } } - private int getxmlheader(osUTF8 data, out osUTF8 h) + private int getxmlNode(ref osUTF8 data, out osUTF8 h) { h = data; int st = -1; @@ -868,9 +890,83 @@ namespace OpenSim.Region.Framework.Scenes h = data.osUTF8SubString(st, ed - st); h.SelfTrim(); - return ed + 1; + ++ed; + data.osUTF8SubStringSelf(ed); + return ed; } + private bool TryGetxmlUUIDValue(ref osUTF8 data, out UUID id) + { + id = UUID.Zero; + if(getxmlNode(ref data, out osUTF8 h) < 0) + return false; + + if (h.StartsWith(UUIDB)) + { + if (h.EndsWith((byte)'/')) + return true; + int indx = data.IndexOf((byte)'<'); + if (indx < 0) + return false; + osUTF8 tmp = data.osUTF8SubString(0, indx); + tmp.SelfTrim(); + data.osUTF8SubStringSelf(indx + 1); + return UUID.TryParse(tmp.ToString(), out id); + } + + if (h.StartsWith(uuidB)) + { + if (h.EndsWith((byte)'/')) + return true; + int indx = data.IndexOf((byte)'<'); + if (indx < 0) + return false; + osUTF8 tmp = data.osUTF8SubString(0, indx); + tmp.SelfTrim(); + return UUID.TryParse(tmp.ToString(), out id); + } + + return false; + } + + private bool TryGetXMLBinary(ref osUTF8 data, out byte[] te) + { + te = null; + int indx = data.IndexOf((byte)'<'); + if(indx <= 0) + return false; + + osUTF8 tmp = data.osUTF8SubString(0, indx); + data.osUTF8SubStringSelf(indx + 1); + + tmp.SelfTrim(); + if(tmp.Lenght == 0) + return false; + try + { + te = Convert.FromBase64String(tmp.ToString()); // need to replace + return true; + } + catch { } + + return false; + } + + + // bad ugly and ulgy + private static osUTF8 UUIDB = new osUTF8("UUID"); + private static osUTF8 uuidB = new osUTF8("uuid"); + private static osUTF8 SOPAnimsB = new osUTF8("SOPAnims"); + private static osUTF8 CollisionSoundB = new osUTF8("CollisionSound"); + private static osUTF8 SoundIDB = new osUTF8("SoundID"); + private static osUTF8 SculptTextureB = new osUTF8("SculptTexture"); + private static osUTF8 ExtraParamsB = new osUTF8("ExtraParams"); + private static osUTF8 ParticleSystemB = new osUTF8("ParticleSystem"); + private static osUTF8 TextureEntryB = new osUTF8("TextureEntry"); + private static osUTF8 TaskInventoryB = new osUTF8("TaskInventory"); + private static osUTF8 endTaskInventoryB = new osUTF8("/TaskInventory"); + private static osUTF8 AssetIDB = new osUTF8("AssetID"); + /// /// Get all the asset uuids associated with a given object. This includes both those directly associated with /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained @@ -879,46 +975,170 @@ namespace OpenSim.Region.Framework.Scenes /// private void RecordSceneObjectAssetUuids(AssetBase sceneObjectAsset) { - string xml = Utils.BytesToString(sceneObjectAsset.Data); + osUTF8 data = new osUTF8(sceneObjectAsset.Data); - CoalescedSceneObjects coa; - if (CoalescedSceneObjectsSerializer.TryFromXml(xml, out coa)) + int next; + osUTF8 nodeName; + while ((next = getxmlNode(ref data, out nodeName)) > 0) { - foreach (SceneObjectGroup sog in coa.Objects) + if (nodeName.StartsWith((byte)'/')) + continue; + if (nodeName.StartsWith(SOPAnimsB)) { - sog.TemporaryInstance = true; - AddForInspection(sog); - } - } - else - { - SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlFormat(xml); - if (null != sog) - { - sog.TemporaryInstance = true; - AddForInspection(sog); - } - } + if (nodeName.EndsWith((byte)'/')) + continue; - /* - if (CoalescedSceneObjectsSerializer.TryFromXmlData(sceneObjectAsset.Data, out CoalescedSceneObjects coa)) - { - foreach (SceneObjectGroup sog in coa.Objects) + if (TryGetXMLBinary(ref data, out byte[] abytes) && abytes != null && abytes.Length > 16) + { + try + { + int count = Utils.BytesToUInt16(abytes, 0); + if (count >0) + { + int pos = 2; + while (--count >= 0) + { + UUID id = new UUID(abytes, pos); + if (id == UUID.Zero) + break; + if (!ToSkip.Contains(id) && + !FailedUUIDs.Contains(id)) + { + GatheredUuids[id] = (sbyte)AssetType.Animation; + } + pos += 16; + int strlen = data[pos++]; + pos += strlen; + } + } + abytes = null; + } + catch { } + } + } + else if (nodeName.StartsWith(CollisionSoundB)) { - sog.TemporaryInstance = true; - AddForInspection(sog); + if (!nodeName.EndsWith((byte)'d')) + continue; + if (TryGetxmlUUIDValue(ref data, out UUID id) && id != UUID.Zero) + GatheredUuids[id] = (sbyte)AssetType.Sound; + } + else if (nodeName.StartsWith(SoundIDB)) + { + if (nodeName.EndsWith((byte)'/')) + continue; + if (TryGetxmlUUIDValue(ref data, out UUID id) && id != UUID.Zero) + GatheredUuids[id] = (sbyte)AssetType.Sound; + } + else if (nodeName.StartsWith(SculptTextureB)) + { + if (nodeName.EndsWith((byte)'/')) + continue; + if (TryGetxmlUUIDValue(ref data, out UUID id) && id != UUID.Zero) + GatheredUuids[id] = (sbyte)AssetType.Texture; // can be mesh but no prob + } + else if (nodeName.StartsWith(ExtraParamsB)) + { + if (nodeName.EndsWith((byte)'/')) + continue; + + if (TryGetXMLBinary(ref data, out byte[] exbytes) && exbytes != null && exbytes.Length > 16) + { + try + { + PrimitiveBaseShape ps = new PrimitiveBaseShape(); + ps.ReadInExtraParamsBytes(exbytes); + UUID teid = ps.ProjectionTextureUUID; + if (teid != UUID.Zero && + !ToSkip.Contains(teid) && + !FailedUUIDs.Contains(teid)) + { + GatheredUuids[teid] = (sbyte)AssetType.Texture; + } + /* multiple store + teid = ps.SculptTexture; //?? + if (teid != UUID.Zero && + !ToSkip.Contains(teid) && + !FailedUUIDs.Contains(teid)) + { + GatheredUuids[teid] = (sbyte)AssetType.Texture; + } + */ + ps = null; + exbytes = null; + } + catch { } + } + } + else if (nodeName.StartsWith(ParticleSystemB)) + { + if (nodeName.EndsWith((byte)'/')) + continue; + + if (TryGetXMLBinary(ref data, out byte[] psbytes) && psbytes != null && psbytes.Length > 16) + { + try + { + Primitive.ParticleSystem ps = new Primitive.ParticleSystem(psbytes, 0); + UUID teid = ps.Texture; + if (teid != UUID.Zero && + !ToSkip.Contains(teid) && + !FailedUUIDs.Contains(teid)) + { + GatheredUuids[teid] = (sbyte)AssetType.Texture; + } + psbytes = null; + } + catch { } + } + } + else if (nodeName.StartsWith(TextureEntryB)) + { + if (nodeName.EndsWith((byte)'/')) + continue; + + if (TryGetXMLBinary(ref data, out byte[] tebytes) && tebytes != null && tebytes.Length > 16) + { + try + { + Primitive.TextureEntry te = new Primitive.TextureEntry(tebytes, 0, tebytes.Length); + if (te != null) + { + // Get the prim's default texture. This will be used for faces which don't have their own texture + if (te.DefaultTexture != null) + RecordTextureEntryAssetUuids(te.DefaultTexture); + + if (te.FaceTextures != null) + { + // Loop through the rest of the texture faces (a non-null face means the face is different from DefaultTexture) + foreach (Primitive.TextureEntryFace texture in te.FaceTextures) + { + if (texture != null) + RecordTextureEntryAssetUuids(texture); + } + } + } + te = null; + } + catch { } + } + } + else if (nodeName.StartsWith(TaskInventoryB)) + { + if (nodeName.EndsWith((byte)'/')) + continue; + while ((next = getxmlNode(ref data, out nodeName)) > 0) + { + if (nodeName.StartsWith(AssetIDB)) + { + if (TryGetxmlUUIDValue(ref data, out UUID id) && id != UUID.Zero) + AddForInspection(id); + } + else if (nodeName.StartsWith(endTaskInventoryB)) + break; + } } } - else - { - SceneObjectGroup sog = SceneObjectSerializer.FromOriginalXmlData(sceneObjectAsset.Data); - if (null != sog) - { - sog.TemporaryInstance = true; - AddForInspection(sog); - } - } - */ } /// @@ -990,12 +1210,12 @@ namespace OpenSim.Region.Framework.Scenes { osUTF8 data = new osUTF8(materialAsset.Data); int next; - while ((next = getxmlheader(data, out osUTF8 header)) > 0) + while ((next = getxmlNode(ref data, out osUTF8 header)) > 0) { - data.osUTF8SubStringSelf(next); - if (header.StartsWith("/")) + + if (header.StartsWith((byte)'/')) continue; - if (header.StartsWith("uuid")) + if (header.StartsWith(uuidB)) { if(header.EndsWith((byte)'/')) continue; diff --git a/bin/OpenMetaverse.Rendering.Meshmerizer.dll b/bin/OpenMetaverse.Rendering.Meshmerizer.dll index 11236d97dde4aea03334289e952bebc1960a6d4e..3cde6ae7e678aaeee0757ba58e17d585781cb01a 100755 GIT binary patch delta 45 zcmV+|0Mh?}paFoO0g#9StJkrLaw7uVp|k!Yss|AF?MT@*?tV^@4ZG*f)YFUskRc-R|S8xI=)`gu#%(gu$4> RZ1YFPFWlQ16BPgR0{~!zQVak9 delta 222 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 bY)l0%iY#kVh3`d@f}}F}BEA`!mlX0pd@9QM delta 10401 zcmZA730xIb-v{us3~&Lj+?hKwcjkr{L=;?eU&>r?iBi$jl+s5qH8shlEH#&_rD%pJ zhGdEcMrmq>g<`Ih=woT_85t@Tp`s!#^q673=gj%vdEWQ+^RZ7~e`lFFbIzQZf%)Yj z^UFh4EFqq~nM-|mY3Ap{apw;(jtfF3FpB)(Hg5633pft1_<8~M*O${yV#NO>vcCic zA@sHEniVpTcxhYQI4$(uGT2Jg{U{)^}DMLN(4EZUUjuaIku`@ z?NGHJ_%Ld}t37&PtHjj-Ia-Ql_BXoc>WK1f)ww#O9<2gdko*KXZ>zrC72N~v3D@Or zXlQFuvLrl@bVqaAaAl+0jT*?^QEXd3XQuH?q${{5>fDwq-RKnA9QQ;+Y+;muCff=| zz0eX%C1|*dt59TUoR{k!D8|W^*v@Jb4UKpi_d?IvYAp9csqGN&Kb?g`aBoy@hb`nj zD7C$)I5MI>ej05B_0WUaC9e^3M2F;&MD#Z(EG~~_w1ZX8@v^0GA$CfbW$kUXm!Co9 zOsxNO>$smq{X71*!)MV+5I^pIXk;gmoo~W5p|d5{Xg9eZ%D2^59*8D%31ms~5R`9g zm^=*qW-CR05vfnGl73W)pEbwHBhU&?b}$jXBzYw2^JGB7l_bB6rgs%>&Slv|RBFkej(SJTlqVraHxZun1*1u*)KWHj zDrgSN%DVF`8#VJTlqaLkJ-7~|0m|oS8d_;79qpI7N+2tY$|2LxWlNQ~FzS8zHFOKI zv7veBbrjtbu|L^&{4qj2ATl!89DL{R02Bc$&qKF=me{x12@f)XQNq` z!~~v;iY)O79E|3o!$Rnw^Zn4d=!UIHu6d|gFWyR~;pa1d0qSc}R9t|j*urQ5$`L{v zfUS$yXiz^Zw1#aJ8e_|aR-w5`%YE&+SI)w!L(Hi9H&%5XAAVyh(dRr2gVl6r% z#0Gz>v=*fe5NEL=c!#tep(LUG&aF}&T4-yBl#d((MaBnzBbozx7}bSrL|28ZOX1&y z?gMYB@yaGtFi2E9AJK(;juM{}`Y>V)*^H#YLI<5+%3IMcTU(`VXyK4RwnN&EdJGjB zYPM1eQS$R#3()=0G-)T=I?T!(1KG`MmmlpEv<80{x?rm+WETn=ZWU$Oy`XPUgsn$G zyHN`v$6M?MwHIv#@#(b}71||(nJR=3zmx7o$;nom=(&iF%0A>TvY3hVpn<{rQHcm0 zqoSTtzC{;66Qg=D(HF#VPiNV8C=#@QW#6F$P$J6?q7k4WEIWu63bB)TRw+UCUksem zDCI1Q_S+n%{ETXZkRx`cT#9o3C64qN%GG0(5Dn!@1tl~{Q%cc<6p{U?zp4C+az_ir zJLfP}jN!^=Gbls3h}w@6x)!!tDMv$J=KBu|X~PZ5Z)oOtpTxmxJm>K2m~lS8EIpBYw{h#X~Ledw!TZ3@6X$tsF-Do*#~57YOm4BOJGSo5_!| z*$yDP!*OR$rUE7>?gR1}8A=3B0)=|26d4Z#9ra`=3QhrGHZm%nVC#&c<7uEuJwq|@ zTei+9UcAtfKizRleasz+TfD=&Pj}o`W84jJ>_VYiYBP5f9=a%ywRSheS?OG2%ZbIo zi>-{!?!Iy?ZfvWQJ01_UHA-oQOKc^{EiqYQ)$_B8-QBHmdrq8=wng=Ix4|oH4RE)` z7eSHknR0vVdsmcHLb#Ga1K5LDdwdmC${xMiV|A%0S=59pmkXXR+T*V83HkXWMJHSX z(6zAX?w+{9 z);xC~+;)Y?Xu~D$r*Z#){0%eRiMU>-2t(u7xclMil}xOQ;h`z+{n&cjVv$$BJ{hTH4k$CKfLW$0!?tkH2OJc64;C+_(T<_~n#dVPJxjq{AU(M@@ zr=-z%lcjVtiOu}cSo_FolTG}ye)nh`1uSTK);$Kd0Qrm*_c+`E6zZAe9*>^_9rdKR zC*VX7W@q?{I77C6FgwFE+;NTQqEb(BPsZIXi77i3r&!`U>_xYKDxP997`=vP*m5z= zx3wwcb-dKlLRPUL@5%azwbzQY>f-t2hhKStqhBtm0cZ1GJBooQ=z!vebsW zWLhpiv;}Bw>|OUI!g4MTii#)CcXiro<^&OmNNj!)x!Ut?& zvc=r-H2KUc5_4Jon;5kgem7z4*)qYyV3}{PAiju7L1} zqN*8q>?fkpBZ^O5hRZ<Wb0Nph6$QnFkBX2Vs-7zPqAh!Q8PEptWukcMZ7rz2UKXe=p z{sg}T`pbFAk&l<#s&IUY^Fey(kN7iO0J`m*t8T)BHi-^zJJZ!Ka1E%LcY^vA$j{&E zrl>n`9fXJ2vF*YwJ{J`au|wN~(?GEe28Zm&vq2Z528SHL8K5e1+ghbHAm?nY)1t|rpwYg3Er$GKYqQpf zIChC1Hb!sOnh*t~%A2*O#2*Rt`o7XykStrfw3fv6ji~7L6>F_Y8t9eiU0PdGW@rD_ zI*=Z_Makb>Uum64maSb{XL7?q91jhWhs6L^9ph&)PF&zO74IKeEi$6)lN;1o|NQk~WBZwukS3>=x0% zSFH^p+ac`W`&k=G_JOEetqmhb?ChR4ocv^~PJ5AD2F;7Ur;Q}lTto4m2xlm|KAtSG)j*#})P16vzP`qK8tD((sx{VM zB@4LNN$m7B*C&$|knQxf*Iy$?Y(1sFN!0zKm7Tt)_1UE20KEU*YCKq&()1;y%u*(LB4V2UE^&V+O16r4Q(sDYg0{uX z)t8Zxw$k-XlEKCIzqKsPB3mKMjajCzCS{;Hnx(HLVFyK{b#$%1o^%bUL7tvVa&2wa z^GQ&NDA_iAyZ#wz0D38Gm%fQ~0G*3Fpl>FFEV2DBBkr)im8^v@S~;eFLGnR!>z&rO zk#iuYQmTJR%0VyIyQmis5! zX4s1H>?iX{U?WC!SmJjZj6?6>ufr<5GA^`7Tfatd@^{=jpAoVT^cbBR>g+Ti(()NsK|dj*+u ziiG=MS>U)-<`2l-Sztxk~QY+UdDQ$Z6gT|8Tj_Q$-9*`~&_p`8vr3 z@%QVSq!`5CuWyprGgkL#s#N0l+#*|nUn@tLLeBD#zkVKLa)A<^XFN4zD(J`XGS3}S z2pXnc_1q)Hmc*x)d*m#Lf0VgL=uf;&{-Rp#sU^B4@oMV-6GHwOrq=T(>1l=hGfb`L zJ{bgh%3J1n5I8i)M~#ko>PVKAiTA&Uq{I>*(np?$&O8!Kji0&rrHD3y=@VS6 z3w|j=XflXjicq>3#4klC^?wTFA6LTZ_aOdpC7fOb@sBIvv|lN2lz;h%Gs0;a=#JUW zaMC=G9-3gd=ynhZNiY;z1sWb2XQ;H^FQS#XO%e=)4&h?gzL|HJ;idB+ zJ02HjG@u(nBlI{Uik<{XP2-G)^tP@3MkDGtFSqb0Pe-+^&bC}VLcIRT}dn_i-Xh~BcE7s;1kJFu?R_Yw14ZUkgd=+U& zU1hu#KG{s8J&m>`rez1(AH=@^cA(SC;Qfz(7U@90u|hr(mlz%BFQ5XZPGa!c*A1T$ zXLJdip(E5Y#&|MtppK)SIHPM|WY~9*IHOx&WSIIJJpz})QOU+If!47e{Ok-F`y0J! z`~`m8Vm|k!`Ih*69;Ni9du#<6&(PDhRvORJySCOC{b}Sy-U_cbO&&m#Z1qwG(&=0< z^9RwBTzPJoavl4SZRh%b_4dfF17`9;Qy6#d4V z;jgU+jgd4N^j*UuBZcnaV$(|xJ#CDp#~>pir;RaG{aw@>9$I9KqrHXv>?>cHF`m8& zp{vPhVi=lQ)t5q(dY=h$e2b)fTX5H#_RN5TV=)@ zbQ9>5^MNsgmVo>NTn~(yH2x3KVLvA|XVH96qBG2Vi&lV4-EGdHD=S5Zhs;W29z6j% z7E@#_py-NdrC5tH-=X=SR%(>Fh_=5f>J@9v&Be6cHC~df7(cr|ze@*M0#}r+pCTiNj)kmJFEiHD zY%X?a&DhA~(vLwOHR@?@pqngNE6pGL2_1HW7v)RlS@RS6s;!r#&*(y1)8vhGx2;~v z=k#}5YmCh_^rqDcigb^Xw$Nyh62jFM#8=D~nh4q!^_=P7LZ@5gi{u6K3z`ifUnJY; z0T5p!+h`4luaN@Us#8sN$?Pte#qqGCVir{+nT3rciuHBZrU z&>?fVd4@K)D@q=VNj1;WA(q5`P)es-;*)!a`3s!~8UIRto_^v7^4Wc!mRb_C`#g=m zXEn-Z_g?cn9R@03DhmuZo877AMG7auW_ONR9yk~_yHm}}fwN~5IMw_;aP~}#%s<#@ z`$ZR(Y@n{tvCu`OzR0{rH-MV4bGlBqfR;5nY~G}Wmc(9BP5ajJR`>+&D_7HTwoaIL z=rUWK+_iMKtsvt+w6s?2f7WJkpSu4HG*fCmpov_tS^Q0NKqK^0^KYvDM`Xw2O3ga@ zE*Evq^2Z*l&EX@b;bwH(~AifT$TR}+_4k!nEAys=(Y>R%`79gnLuJyJesgkEc!(gTpx zwAOq~>hMsMl$v_I4WyBl*!$lpXB%&nG#|nNt~TCisSI?;jP*8@I{qUn9*e0pW2Nb! zV(kfU6Up^RWW`!vZ@g4tYp}PObQWP2@<;hm-WF0S7D{xE^R|?7EFJb+KQ?__`oMy=Ta z&NrK_kv85=(saoDM?JM>=fFU*Wl?KB5f~^YueWR9!mzu1t=UZ~fQps6*V{w7VM(lm z1nHc_yAS9$OMF!XqXenS(mN;&y^Q~>hA|fZZ_(R!#rmx1Z$+LqxaH$`MNywrJieQ2 zN_W!b%B=o<->I$Ycx*o@FWS2v4~=f&*?W2vzY>J~Wxwl%BKa>39>8euklsTUeLuiV z4XdB@c`td=y6zKxD(ZRwJFqhqeua=%d+WpJit%GOt?1QaoEMSVx?WNJllVad$!J|9 Lm*ZRPUqb!|Ksmac