we should be able to zeroencode compressedupdates
parent
b32b104996
commit
5035de053a
|
@ -4857,6 +4857,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
}
|
||||
|
||||
useCompressUpdate = false;
|
||||
bool istree = false;
|
||||
|
||||
if (update.Entity is SceneObjectPart)
|
||||
{
|
||||
|
@ -4973,8 +4974,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
maxUpdatesBytes -= 20 * part.Animations.Count + 24;
|
||||
}
|
||||
}
|
||||
|
||||
if(viewerCache)
|
||||
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)
|
||||
{
|
||||
|
@ -5049,7 +5053,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
{
|
||||
if (useCompressUpdate)
|
||||
{
|
||||
maxUpdatesBytes -= 150; // crude estimation
|
||||
if (istree)
|
||||
maxUpdatesBytes -= 64;
|
||||
else
|
||||
maxUpdatesBytes -= 100; // crude estimation
|
||||
|
||||
if (compressedUpdates == null)
|
||||
{
|
||||
|
@ -5060,6 +5067,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
}
|
||||
else
|
||||
{
|
||||
if (istree)
|
||||
maxUpdatesBytes -= 70;
|
||||
else
|
||||
maxUpdatesBytes -= 150; // crude estimation
|
||||
|
||||
if (objectUpdates == null)
|
||||
|
@ -5164,6 +5174,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
}
|
||||
}
|
||||
|
||||
/* no zero encode compressed updates
|
||||
if(compressedUpdates != null)
|
||||
{
|
||||
List<EntityUpdate> tau = new List<EntityUpdate>(30);
|
||||
|
@ -5211,7 +5222,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
|
||||
pos = 18;
|
||||
// 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.Add(eu);
|
||||
count = 1;
|
||||
|
@ -5226,6 +5237,88 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
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)
|
||||
{
|
||||
|
@ -7174,9 +7267,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
HasParticlesNew = 0x400
|
||||
}
|
||||
|
||||
///**** temp hack
|
||||
private static Random rnd = new Random();
|
||||
|
||||
/*
|
||||
protected void CreateCompressedUpdateBlock(SceneObjectPart part, ScenePresence sp, byte[] dest, ref int pos)
|
||||
{
|
||||
// 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;
|
||||
PCode pcode = (PCode)part.Shape.PCode;
|
||||
|
||||
|
@ -7278,12 +7362,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
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;
|
||||
Utils.UIntToBytesSafepos(part.LocalId, dest, pos); pos += 4;
|
||||
dest[pos++] = (byte)pcode;
|
||||
dest[pos++] = state;
|
||||
|
||||
///**** temp hack
|
||||
Utils.UIntToBytesSafepos((uint)part.ParentGroup.PseudoCRC, dest, pos); pos += 4;
|
||||
dest[pos++] = part.Material;
|
||||
dest[pos++] = part.ClickAction;
|
||||
|
@ -7393,15 +7484,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
if (hastexanim)
|
||||
{
|
||||
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;
|
||||
dest[pos++] = (byte)len;
|
||||
dest[pos++] = (byte)(len >> 8);
|
||||
|
@ -7410,7 +7492,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
Buffer.BlockCopy(ta, 0, dest, pos, len);
|
||||
pos += len;
|
||||
}
|
||||
}
|
||||
|
||||
if (haspsnew)
|
||||
{
|
||||
|
@ -7422,6 +7503,319 @@ namespace OpenSim.Region.ClientStack.LindenUDP
|
|||
dest[lenpos++] = (byte)totlen;
|
||||
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)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue