we should be able to zeroencode compressedupdates

0.9.1.0-post-fixes
UbitUmarov 2019-03-25 17:51:38 +00:00
parent b32b104996
commit 5035de053a
1 changed files with 425 additions and 31 deletions

View File

@ -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)
{ {