we should be able to zeroencode compressedupdates
parent
b32b104996
commit
5035de053a
|
@ -4857,6 +4857,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
}
|
}
|
||||||
|
|
||||||
useCompressUpdate = false;
|
useCompressUpdate = false;
|
||||||
|
bool istree = false;
|
||||||
|
|
||||||
if (update.Entity is SceneObjectPart)
|
if (update.Entity is SceneObjectPart)
|
||||||
{
|
{
|
||||||
|
@ -4973,8 +4974,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
maxUpdatesBytes -= 20 * part.Animations.Count + 24;
|
maxUpdatesBytes -= 20 * part.Animations.Count + 24;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(viewerCache)
|
if(viewerCache)
|
||||||
useCompressUpdate = grp.IsViewerCachable;
|
useCompressUpdate = grp.IsViewerCachable;
|
||||||
|
|
||||||
|
istree = (part.Shape.PCode == (byte)PCode.Grass || part.Shape.PCode == (byte)PCode.NewTree || part.Shape.PCode == (byte)PCode.Tree);
|
||||||
}
|
}
|
||||||
else if (update.Entity is ScenePresence)
|
else if (update.Entity is ScenePresence)
|
||||||
{
|
{
|
||||||
|
@ -5049,7 +5053,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
{
|
{
|
||||||
if (useCompressUpdate)
|
if (useCompressUpdate)
|
||||||
{
|
{
|
||||||
maxUpdatesBytes -= 150; // crude estimation
|
if (istree)
|
||||||
|
maxUpdatesBytes -= 64;
|
||||||
|
else
|
||||||
|
maxUpdatesBytes -= 100; // crude estimation
|
||||||
|
|
||||||
if (compressedUpdates == null)
|
if (compressedUpdates == null)
|
||||||
{
|
{
|
||||||
|
@ -5060,6 +5067,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
if (istree)
|
||||||
|
maxUpdatesBytes -= 70;
|
||||||
|
else
|
||||||
maxUpdatesBytes -= 150; // crude estimation
|
maxUpdatesBytes -= 150; // crude estimation
|
||||||
|
|
||||||
if (objectUpdates == null)
|
if (objectUpdates == null)
|
||||||
|
@ -5164,6 +5174,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* no zero encode compressed updates
|
||||||
if(compressedUpdates != null)
|
if(compressedUpdates != null)
|
||||||
{
|
{
|
||||||
List<EntityUpdate> tau = new List<EntityUpdate>(30);
|
List<EntityUpdate> tau = new List<EntityUpdate>(30);
|
||||||
|
@ -5211,7 +5222,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
|
|
||||||
pos = 18;
|
pos = 18;
|
||||||
// im lazy now, just do last again
|
// im lazy now, just do last again
|
||||||
CreateCompressedUpdateBlock((SceneObjectPart)eu.Entity, mysp, data, ref pos);
|
CreateCompressedUpdateBlock(sop, mysp, data, ref pos);
|
||||||
tau = new List<EntityUpdate>(30);
|
tau = new List<EntityUpdate>(30);
|
||||||
tau.Add(eu);
|
tau.Add(eu);
|
||||||
count = 1;
|
count = 1;
|
||||||
|
@ -5226,6 +5237,88 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
|
delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
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);
|
||||||
|
data[0] |= Helpers.MSG_ZEROCODED;
|
||||||
|
|
||||||
|
LLUDPZeroEncoder zc = new LLUDPZeroEncoder(buf.Data);
|
||||||
|
zc.Position = 7;
|
||||||
|
|
||||||
|
zc.AddUInt64(m_scene.RegionInfo.RegionHandle);
|
||||||
|
zc.AddUInt16(timeDilation);
|
||||||
|
|
||||||
|
zc.AddByte(1); // tmp block count
|
||||||
|
|
||||||
|
int countposition = zc.Position - 1;
|
||||||
|
|
||||||
|
int lastpos = 0;
|
||||||
|
int lastzc = 0;
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
foreach (EntityUpdate eu in compressedUpdates)
|
||||||
|
{
|
||||||
|
SceneObjectPart sop = (SceneObjectPart)eu.Entity;
|
||||||
|
if (sop.ParentGroup == null || sop.ParentGroup.IsDeleted)
|
||||||
|
continue;
|
||||||
|
lastpos = zc.Position;
|
||||||
|
lastzc = zc.ZeroCount;
|
||||||
|
|
||||||
|
CreateCompressedUpdateBlockZC(sop, mysp, zc);
|
||||||
|
if (zc.Position < 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;
|
||||||
|
// get pending zeros at cut point
|
||||||
|
if (lastzc > 0)
|
||||||
|
{
|
||||||
|
buf.Data[lastpos++] = 0;
|
||||||
|
buf.Data[lastpos++] = (byte)lastzc;
|
||||||
|
}
|
||||||
|
buf.DataLength = lastpos;
|
||||||
|
|
||||||
|
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
|
||||||
|
delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
|
||||||
|
|
||||||
|
buf = newbuf;
|
||||||
|
zc.Data = buf.Data;
|
||||||
|
|
||||||
|
data[0] |= Helpers.MSG_ZEROCODED;
|
||||||
|
|
||||||
|
zc.ZeroCount = 0;
|
||||||
|
zc.Position = countposition + 1;
|
||||||
|
|
||||||
|
// im lazy now, just do last again
|
||||||
|
CreateCompressedUpdateBlockZC(sop, mysp, zc);
|
||||||
|
tau = new List<EntityUpdate>(30);
|
||||||
|
tau.Add(eu);
|
||||||
|
count = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count > 0)
|
||||||
|
{
|
||||||
|
buf.Data[countposition] = (byte)count;
|
||||||
|
buf.DataLength = zc.Finish();
|
||||||
|
m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task,
|
||||||
|
delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (objectUpdateProbes != null)
|
if (objectUpdateProbes != null)
|
||||||
{
|
{
|
||||||
|
@ -7174,9 +7267,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
HasParticlesNew = 0x400
|
HasParticlesNew = 0x400
|
||||||
}
|
}
|
||||||
|
|
||||||
///**** temp hack
|
/*
|
||||||
private static Random rnd = new Random();
|
|
||||||
|
|
||||||
protected void CreateCompressedUpdateBlock(SceneObjectPart part, ScenePresence sp, byte[] dest, ref int pos)
|
protected void CreateCompressedUpdateBlock(SceneObjectPart part, ScenePresence sp, byte[] dest, ref int pos)
|
||||||
{
|
{
|
||||||
// prepare data
|
// prepare data
|
||||||
|
@ -7197,13 +7288,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// first is primFlags
|
|
||||||
Utils.UIntToBytesSafepos((uint)primflags, dest, pos); pos += 4;
|
|
||||||
|
|
||||||
// datablock len to fill later
|
|
||||||
int lenpos = pos;
|
|
||||||
pos += 2;
|
|
||||||
|
|
||||||
byte state = part.Shape.State;
|
byte state = part.Shape.State;
|
||||||
PCode pcode = (PCode)part.Shape.PCode;
|
PCode pcode = (PCode)part.Shape.PCode;
|
||||||
|
|
||||||
|
@ -7278,12 +7362,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
pathScaleY = 150;
|
pathScaleY = 150;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// first is primFlags
|
||||||
|
Utils.UIntToBytesSafepos((uint)primflags, dest, pos); pos += 4;
|
||||||
|
|
||||||
|
// datablock len to fill later
|
||||||
|
int lenpos = pos;
|
||||||
|
pos += 2;
|
||||||
|
|
||||||
|
// data block
|
||||||
part.UUID.ToBytes(dest, pos); pos += 16;
|
part.UUID.ToBytes(dest, pos); pos += 16;
|
||||||
Utils.UIntToBytesSafepos(part.LocalId, dest, pos); pos += 4;
|
Utils.UIntToBytesSafepos(part.LocalId, dest, pos); pos += 4;
|
||||||
dest[pos++] = (byte)pcode;
|
dest[pos++] = (byte)pcode;
|
||||||
dest[pos++] = state;
|
dest[pos++] = state;
|
||||||
|
|
||||||
///**** temp hack
|
|
||||||
Utils.UIntToBytesSafepos((uint)part.ParentGroup.PseudoCRC, dest, pos); pos += 4;
|
Utils.UIntToBytesSafepos((uint)part.ParentGroup.PseudoCRC, dest, pos); pos += 4;
|
||||||
dest[pos++] = part.Material;
|
dest[pos++] = part.Material;
|
||||||
dest[pos++] = part.ClickAction;
|
dest[pos++] = part.ClickAction;
|
||||||
|
@ -7393,15 +7484,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
if (hastexanim)
|
if (hastexanim)
|
||||||
{
|
{
|
||||||
byte[] ta = part.TextureAnimation;
|
byte[] ta = part.TextureAnimation;
|
||||||
if (ta == null)
|
|
||||||
{
|
|
||||||
dest[pos++] = 0;
|
|
||||||
dest[pos++] = 0;
|
|
||||||
dest[pos++] = 0;
|
|
||||||
dest[pos++] = 0;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
int len = ta.Length & 0x7fff;
|
int len = ta.Length & 0x7fff;
|
||||||
dest[pos++] = (byte)len;
|
dest[pos++] = (byte)len;
|
||||||
dest[pos++] = (byte)(len >> 8);
|
dest[pos++] = (byte)(len >> 8);
|
||||||
|
@ -7410,7 +7492,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
Buffer.BlockCopy(ta, 0, dest, pos, len);
|
Buffer.BlockCopy(ta, 0, dest, pos, len);
|
||||||
pos += len;
|
pos += len;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (haspsnew)
|
if (haspsnew)
|
||||||
{
|
{
|
||||||
|
@ -7422,6 +7503,319 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
||||||
dest[lenpos++] = (byte)totlen;
|
dest[lenpos++] = (byte)totlen;
|
||||||
dest[lenpos++] = (byte)(totlen >> 8);
|
dest[lenpos++] = (byte)(totlen >> 8);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
protected void CreateCompressedUpdateBlockZC(SceneObjectPart part, ScenePresence sp, LLUDPZeroEncoder zc)
|
||||||
|
{
|
||||||
|
// prepare data
|
||||||
|
CompressedFlags cflags = CompressedFlags.None;
|
||||||
|
|
||||||
|
// prim/update flags
|
||||||
|
|
||||||
|
PrimFlags primflags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(part, sp);
|
||||||
|
// Don't send the CreateSelected flag to everyone
|
||||||
|
primflags &= ~PrimFlags.CreateSelected;
|
||||||
|
if (sp.UUID == part.OwnerID)
|
||||||
|
{
|
||||||
|
if (part.CreateSelected)
|
||||||
|
{
|
||||||
|
// Only send this flag once, then unset it
|
||||||
|
primflags |= PrimFlags.CreateSelected;
|
||||||
|
part.CreateSelected = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
byte state = part.Shape.State;
|
||||||
|
PCode pcode = (PCode)part.Shape.PCode;
|
||||||
|
|
||||||
|
// trees and grass are a lot more compact
|
||||||
|
if (pcode == PCode.Grass || pcode == PCode.Tree || pcode == PCode.NewTree)
|
||||||
|
{
|
||||||
|
// first is primFlags
|
||||||
|
zc.AddUInt((uint)primflags);
|
||||||
|
|
||||||
|
// datablock len
|
||||||
|
zc.AddByte(113);
|
||||||
|
zc.AddZeros(1);
|
||||||
|
|
||||||
|
// data block
|
||||||
|
zc.AddUUID(part.UUID);
|
||||||
|
zc.AddUInt(part.LocalId);
|
||||||
|
zc.AddByte((byte)pcode);
|
||||||
|
zc.AddByte(state);
|
||||||
|
|
||||||
|
zc.AddUInt((uint)part.ParentGroup.PseudoCRC);
|
||||||
|
|
||||||
|
zc.AddZeros(2); // material and click action
|
||||||
|
|
||||||
|
zc.AddVector3(part.Shape.Scale);
|
||||||
|
zc.AddVector3(part.RelativePosition);
|
||||||
|
if (pcode == PCode.Grass)
|
||||||
|
zc.AddZeros(12);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Quaternion rotation = part.RotationOffset;
|
||||||
|
rotation.Normalize();
|
||||||
|
zc.AddNormQuat(rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
zc.AddUInt((uint)CompressedFlags.Tree); // cflags
|
||||||
|
|
||||||
|
zc.AddZeros(16); // owner id
|
||||||
|
|
||||||
|
zc.AddByte(state); // tree parameter
|
||||||
|
|
||||||
|
zc.AddZeros(28); //extraparameters 1, pbs 23, texture 4
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//NameValue and state
|
||||||
|
byte[] nv = null;
|
||||||
|
if (part.ParentGroup.IsAttachment)
|
||||||
|
{
|
||||||
|
if (part.IsRoot)
|
||||||
|
nv = Util.StringToBytes256("AttachItemID STRING RW SV " + part.ParentGroup.FromItemID);
|
||||||
|
|
||||||
|
int st = (int)part.ParentGroup.AttachmentPoint;
|
||||||
|
state = (byte)(((st & 0xf0) >> 4) + ((st & 0x0f) << 4)); ;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool hastext = false;
|
||||||
|
bool hassound = false;
|
||||||
|
bool hasps = false;
|
||||||
|
bool hastexanim = false;
|
||||||
|
bool hasangvel = false;
|
||||||
|
bool hasmediaurl = false;
|
||||||
|
bool haspsnew = false;
|
||||||
|
|
||||||
|
int BlockLengh = 111;
|
||||||
|
|
||||||
|
byte[] extraParamBytes = part.Shape.ExtraParams;
|
||||||
|
if (extraParamBytes == null || extraParamBytes.Length < 2)
|
||||||
|
{
|
||||||
|
++BlockLengh;
|
||||||
|
extraParamBytes = null;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
BlockLengh += extraParamBytes.Length;
|
||||||
|
|
||||||
|
byte[] hoverText = null;
|
||||||
|
byte[] hoverTextColor = null;
|
||||||
|
if (part.Text != null && part.Text.Length > 0)
|
||||||
|
{
|
||||||
|
cflags |= CompressedFlags.HasText;
|
||||||
|
hoverText = Util.StringToBytes256(part.Text);
|
||||||
|
BlockLengh += hoverText.Length;
|
||||||
|
hoverTextColor = part.GetTextColor().GetBytes(false);
|
||||||
|
BlockLengh += hoverTextColor.Length;
|
||||||
|
hastext = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (part.ParticleSystem != null && part.ParticleSystem.Length > 1)
|
||||||
|
{
|
||||||
|
BlockLengh += part.ParticleSystem.Length;
|
||||||
|
if (part.ParticleSystem.Length > 86)
|
||||||
|
{
|
||||||
|
hasps = false;
|
||||||
|
cflags |= CompressedFlags.HasParticlesNew;
|
||||||
|
haspsnew = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cflags |= CompressedFlags.HasParticlesLegacy;
|
||||||
|
hasps = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (part.Sound != UUID.Zero || part.SoundFlags != 0)
|
||||||
|
{
|
||||||
|
BlockLengh += 25;
|
||||||
|
cflags |= CompressedFlags.HasSound;
|
||||||
|
hassound = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (part.ParentID != 0)
|
||||||
|
{
|
||||||
|
BlockLengh += 4;
|
||||||
|
cflags |= CompressedFlags.HasParent;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (part.TextureAnimation != null && part.TextureAnimation.Length > 0)
|
||||||
|
{
|
||||||
|
BlockLengh += part.TextureAnimation.Length + 4;
|
||||||
|
cflags |= CompressedFlags.TextureAnimation;
|
||||||
|
hastexanim = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (part.AngularVelocity.LengthSquared() > 1e-8f)
|
||||||
|
{
|
||||||
|
BlockLengh += 12;
|
||||||
|
cflags |= CompressedFlags.HasAngularVelocity;
|
||||||
|
hasangvel = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] mediaURLBytes = null;
|
||||||
|
if (part.MediaUrl != null && part.MediaUrl.Length > 1)
|
||||||
|
{
|
||||||
|
mediaURLBytes = Util.StringToBytes256(part.MediaUrl); // must be null term
|
||||||
|
BlockLengh += mediaURLBytes.Length;
|
||||||
|
cflags |= CompressedFlags.MediaURL;
|
||||||
|
hasmediaurl = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nv != null)
|
||||||
|
{
|
||||||
|
BlockLengh += nv.Length;
|
||||||
|
cflags |= CompressedFlags.HasNameValues;
|
||||||
|
}
|
||||||
|
|
||||||
|
byte[] textureEntry = part.Shape.TextureEntry;
|
||||||
|
if(textureEntry != null)
|
||||||
|
BlockLengh += textureEntry.Length;
|
||||||
|
|
||||||
|
// filter out mesh faces hack
|
||||||
|
ushort profileBegin = part.Shape.ProfileBegin;
|
||||||
|
ushort profileHollow = part.Shape.ProfileHollow;
|
||||||
|
byte profileCurve = part.Shape.ProfileCurve;
|
||||||
|
byte pathScaleY = part.Shape.PathScaleY;
|
||||||
|
|
||||||
|
if (part.Shape.SculptType == (byte)SculptType.Mesh) // filter out hack
|
||||||
|
{
|
||||||
|
profileCurve = (byte)(part.Shape.ProfileCurve & 0x0f);
|
||||||
|
// fix old values that confused viewers
|
||||||
|
if (profileBegin == 1)
|
||||||
|
profileBegin = 9375;
|
||||||
|
if (profileHollow == 1)
|
||||||
|
profileHollow = 27500;
|
||||||
|
// fix torus hole size Y that also confuse some viewers
|
||||||
|
if (profileCurve == (byte)ProfileShape.Circle && pathScaleY < 150)
|
||||||
|
pathScaleY = 150;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// first is primFlags
|
||||||
|
zc.AddUInt((uint)primflags);
|
||||||
|
|
||||||
|
// datablock len
|
||||||
|
zc.AddByte((byte)BlockLengh);
|
||||||
|
zc.AddByte((byte)(BlockLengh >> 8));
|
||||||
|
|
||||||
|
// data block
|
||||||
|
zc.AddUUID(part.UUID);
|
||||||
|
zc.AddUInt(part.LocalId);
|
||||||
|
zc.AddByte((byte)pcode);
|
||||||
|
zc.AddByte(state);
|
||||||
|
|
||||||
|
zc.AddUInt((uint)part.ParentGroup.PseudoCRC);
|
||||||
|
|
||||||
|
zc.AddByte(part.Material);
|
||||||
|
zc.AddByte(part.ClickAction);
|
||||||
|
zc.AddVector3(part.Shape.Scale);
|
||||||
|
zc.AddVector3(part.RelativePosition);
|
||||||
|
if (pcode == PCode.Grass)
|
||||||
|
zc.AddZeros(12);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Quaternion rotation = part.RotationOffset;
|
||||||
|
rotation.Normalize();
|
||||||
|
zc.AddNormQuat(rotation);
|
||||||
|
}
|
||||||
|
|
||||||
|
zc.AddUInt((uint)cflags);
|
||||||
|
|
||||||
|
if (hasps || haspsnew || hassound)
|
||||||
|
zc.AddUUID(part.OwnerID);
|
||||||
|
else
|
||||||
|
zc.AddZeros(16);
|
||||||
|
|
||||||
|
if (hasangvel)
|
||||||
|
{
|
||||||
|
zc.AddVector3(part.AngularVelocity);
|
||||||
|
}
|
||||||
|
if (part.ParentID != 0)
|
||||||
|
{
|
||||||
|
zc.AddUInt(part.ParentID);
|
||||||
|
}
|
||||||
|
if (hastext)
|
||||||
|
{
|
||||||
|
zc.AddBytes(hoverText, hoverText.Length);
|
||||||
|
zc.AddBytes(hoverTextColor, hoverTextColor.Length);
|
||||||
|
}
|
||||||
|
if (hasmediaurl)
|
||||||
|
{
|
||||||
|
zc.AddBytes(mediaURLBytes, mediaURLBytes.Length);
|
||||||
|
}
|
||||||
|
if (hasps)
|
||||||
|
{
|
||||||
|
byte[] ps = part.ParticleSystem;
|
||||||
|
zc.AddBytes(ps, ps.Length);
|
||||||
|
}
|
||||||
|
if (extraParamBytes == null)
|
||||||
|
zc.AddZeros(1);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
zc.AddBytes(extraParamBytes, extraParamBytes.Length);
|
||||||
|
}
|
||||||
|
if (hassound)
|
||||||
|
{
|
||||||
|
zc.AddUUID(part.Sound);
|
||||||
|
zc.AddFloat((float)part.SoundGain);
|
||||||
|
zc.AddByte(part.SoundFlags);
|
||||||
|
zc.AddFloat((float)part.SoundRadius);
|
||||||
|
}
|
||||||
|
if (nv != null)
|
||||||
|
{
|
||||||
|
zc.AddBytes(nv, nv.Length);
|
||||||
|
}
|
||||||
|
|
||||||
|
zc.AddByte(part.Shape.PathCurve);
|
||||||
|
zc.AddUInt16(part.Shape.PathBegin);
|
||||||
|
zc.AddUInt16(part.Shape.PathEnd);
|
||||||
|
zc.AddByte(part.Shape.PathScaleX);
|
||||||
|
zc.AddByte(pathScaleY);
|
||||||
|
zc.AddByte(part.Shape.PathShearX);
|
||||||
|
zc.AddByte(part.Shape.PathShearY);
|
||||||
|
zc.AddByte((byte)part.Shape.PathTwist);
|
||||||
|
zc.AddByte((byte)part.Shape.PathTwistBegin);
|
||||||
|
zc.AddByte((byte)part.Shape.PathRadiusOffset);
|
||||||
|
zc.AddByte((byte)part.Shape.PathTaperX);
|
||||||
|
zc.AddByte((byte)part.Shape.PathTaperY);
|
||||||
|
zc.AddByte(part.Shape.PathRevolutions);
|
||||||
|
zc.AddByte((byte)part.Shape.PathSkew);
|
||||||
|
zc.AddByte(profileCurve);
|
||||||
|
zc.AddUInt16(profileBegin);
|
||||||
|
zc.AddUInt16(part.Shape.ProfileEnd);
|
||||||
|
zc.AddUInt16(profileHollow);
|
||||||
|
|
||||||
|
if (textureEntry == null)
|
||||||
|
{
|
||||||
|
zc.AddZeros(4);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int len = textureEntry.Length;
|
||||||
|
zc.AddByte((byte)len);
|
||||||
|
zc.AddByte((byte)(len >> 8));
|
||||||
|
zc.AddZeros(2);
|
||||||
|
zc.AddBytes(textureEntry, len);
|
||||||
|
}
|
||||||
|
if (hastexanim)
|
||||||
|
{
|
||||||
|
byte[] ta = part.TextureAnimation;
|
||||||
|
int len = ta.Length;
|
||||||
|
zc.AddByte((byte)len);
|
||||||
|
zc.AddByte((byte)(len >> 8));
|
||||||
|
zc.AddZeros(2);
|
||||||
|
zc.AddBytes(ta, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (haspsnew)
|
||||||
|
{
|
||||||
|
byte[] ps = part.ParticleSystem;
|
||||||
|
zc.AddBytes(ps, ps.Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void SendNameReply(UUID profileId, string firstname, string lastname)
|
public void SendNameReply(UUID profileId, string firstname, string lastname)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue