diff options
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 407 | ||||
-rwxr-xr-x | OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | 10 |
2 files changed, 363 insertions, 54 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 50bb9ba..662e5ad 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | |||
@@ -4770,6 +4770,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4770 | 30 // ID (high frequency) | 4770 | 30 // ID (high frequency) |
4771 | }; | 4771 | }; |
4772 | 4772 | ||
4773 | static private readonly byte[] CompressedObjectHeader = new byte[] { | ||
4774 | Helpers.MSG_RELIABLE, | ||
4775 | 0, 0, 0, 0, // sequence number | ||
4776 | 0, // extra | ||
4777 | 13 // ID (high frequency) | ||
4778 | }; | ||
4779 | |||
4773 | private void ProcessEntityUpdates(int maxUpdatesBytes) | 4780 | private void ProcessEntityUpdates(int maxUpdatesBytes) |
4774 | { | 4781 | { |
4775 | if (!IsActive) | 4782 | if (!IsActive) |
@@ -4779,9 +4786,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4779 | if (mysp == null) | 4786 | if (mysp == null) |
4780 | return; | 4787 | return; |
4781 | 4788 | ||
4782 | // List<ObjectUpdateCompressedPacket.ObjectDataBlock> compressedUpdateBlocks = null; | ||
4783 | List<EntityUpdate> objectUpdates = null; | 4789 | List<EntityUpdate> objectUpdates = null; |
4784 | // List<EntityUpdate> compressedUpdates = null; | 4790 | //List<EntityUpdate> compressedUpdates = null; |
4785 | List<EntityUpdate> terseUpdates = null; | 4791 | List<EntityUpdate> terseUpdates = null; |
4786 | List<SceneObjectPart> ObjectAnimationUpdates = null; | 4792 | List<SceneObjectPart> ObjectAnimationUpdates = null; |
4787 | 4793 | ||
@@ -4970,17 +4976,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4970 | if(updateFlags == PrimUpdateFlags.None) | 4976 | if(updateFlags == PrimUpdateFlags.None) |
4971 | continue; | 4977 | continue; |
4972 | 4978 | ||
4973 | /* | ||
4974 | const PrimUpdateFlags canNotUseCompressedMask = | ||
4975 | PrimUpdateFlags.Velocity | PrimUpdateFlags.Acceleration | | ||
4976 | PrimUpdateFlags.CollisionPlane | PrimUpdateFlags.Joint; | ||
4977 | |||
4978 | if ((updateFlags & canNotUseCompressedMask) != 0) | ||
4979 | { | ||
4980 | canUseCompressed = false; | ||
4981 | } | ||
4982 | */ | ||
4983 | |||
4984 | const PrimUpdateFlags canNotUseImprovedMask = ~( | 4979 | const PrimUpdateFlags canNotUseImprovedMask = ~( |
4985 | PrimUpdateFlags.AttachmentPoint | | 4980 | PrimUpdateFlags.AttachmentPoint | |
4986 | PrimUpdateFlags.Position | | 4981 | PrimUpdateFlags.Position | |
@@ -4996,19 +4991,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4996 | 4991 | ||
4997 | #region Block Construction | 4992 | #region Block Construction |
4998 | 4993 | ||
4999 | // TODO: Remove this once we can build compressed updates | ||
5000 | /* | ||
5001 | if (canUseCompressed) | ||
5002 | { | ||
5003 | ObjectUpdateCompressedPacket.ObjectDataBlock ablock = | ||
5004 | CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags); | ||
5005 | compressedUpdateBlocks.Add(ablock); | ||
5006 | compressedUpdates.Value.Add(update); | ||
5007 | maxUpdatesBytes -= ablock.Length; | ||
5008 | } | ||
5009 | else if (canUseImproved) | ||
5010 | */ | ||
5011 | |||
5012 | if ((updateFlags & canNotUseImprovedMask) == 0) | 4994 | if ((updateFlags & canNotUseImprovedMask) == 0) |
5013 | { | 4995 | { |
5014 | if (terseUpdates == null) | 4996 | if (terseUpdates == null) |
@@ -5031,16 +5013,47 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5031 | else | 5013 | else |
5032 | { | 5014 | { |
5033 | if (update.Entity is ScenePresence) | 5015 | if (update.Entity is ScenePresence) |
5016 | { | ||
5034 | maxUpdatesBytes -= 150; // crude estimation | 5017 | maxUpdatesBytes -= 150; // crude estimation |
5035 | else | ||
5036 | maxUpdatesBytes -= 300; | ||
5037 | 5018 | ||
5038 | if(objectUpdates == null) | 5019 | if (objectUpdates == null) |
5020 | { | ||
5021 | objectUpdates = new List<EntityUpdate>(); | ||
5022 | maxUpdatesBytes -= 18; | ||
5023 | } | ||
5024 | objectUpdates.Add(update); | ||
5025 | } | ||
5026 | else | ||
5039 | { | 5027 | { |
5040 | objectUpdates = new List<EntityUpdate>(); | 5028 | SceneObjectPart part = (SceneObjectPart)update.Entity; |
5041 | maxUpdatesBytes -= 18; | 5029 | SceneObjectGroup grp = part.ParentGroup; |
5030 | // minimal compress conditions, not enough ? | ||
5031 | //if (grp.UsesPhysics || part.Velocity.LengthSquared() > 1e-8f || part.Acceleration.LengthSquared() > 1e-6f) | ||
5032 | { | ||
5033 | maxUpdatesBytes -= 150; // crude estimation | ||
5034 | |||
5035 | if (objectUpdates == null) | ||
5036 | { | ||
5037 | objectUpdates = new List<EntityUpdate>(); | ||
5038 | maxUpdatesBytes -= 18; | ||
5039 | } | ||
5040 | objectUpdates.Add(update); | ||
5041 | } | ||
5042 | //compress still disabled | ||
5043 | /* | ||
5044 | else | ||
5045 | { | ||
5046 | maxUpdatesBytes -= 150; // crude estimation | ||
5047 | |||
5048 | if (compressedUpdates == null) | ||
5049 | { | ||
5050 | compressedUpdates = new List<EntityUpdate>(); | ||
5051 | maxUpdatesBytes -= 18; | ||
5052 | } | ||
5053 | compressedUpdates.Add(update); | ||
5054 | } | ||
5055 | */ | ||
5042 | } | 5056 | } |
5043 | objectUpdates.Add(update); | ||
5044 | } | 5057 | } |
5045 | 5058 | ||
5046 | #endregion Block Construction | 5059 | #endregion Block Construction |
@@ -5067,7 +5080,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5067 | zc.Position = 7; | 5080 | zc.Position = 7; |
5068 | 5081 | ||
5069 | zc.AddUInt64(m_scene.RegionInfo.RegionHandle); | 5082 | zc.AddUInt64(m_scene.RegionInfo.RegionHandle); |
5070 | zc.AddUInt16(Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f)); | 5083 | zc.AddUInt16(timeDilation); |
5071 | 5084 | ||
5072 | zc.AddByte(1); // tmp block count | 5085 | zc.AddByte(1); // tmp block count |
5073 | 5086 | ||
@@ -5134,19 +5147,67 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5134 | delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); | 5147 | delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); |
5135 | } | 5148 | } |
5136 | } | 5149 | } |
5137 | 5150 | /* | |
5138 | /* | 5151 | if(compressedUpdates != null) |
5139 | if (compressedUpdateBlocks != null) | ||
5140 | { | 5152 | { |
5141 | ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed); | 5153 | List<EntityUpdate> tau = new List<EntityUpdate>(30); |
5142 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; | 5154 | |
5143 | packet.RegionData.TimeDilation = timeDilation; | 5155 | UDPPacketBuffer buf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); |
5144 | packet.ObjectData = compressedUpdateBlocks.ToArray(); | 5156 | byte[] data = buf.Data; |
5145 | compressedUpdateBlocks.Clear(); | 5157 | |
5158 | Buffer.BlockCopy(CompressedObjectHeader, 0, data , 0, 7); | ||
5146 | 5159 | ||
5147 | OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates, oPacket); }); | 5160 | Utils.UInt64ToBytesSafepos(m_scene.RegionInfo.RegionHandle, data, 7); // 15 |
5161 | Utils.UInt16ToBytes(timeDilation, data, 15); // 17 | ||
5162 | |||
5163 | int countposition = 17; // blocks count position | ||
5164 | int pos = 18; | ||
5165 | |||
5166 | int lastpos = 0; | ||
5167 | |||
5168 | int count = 0; | ||
5169 | foreach (EntityUpdate eu in compressedUpdates) | ||
5170 | { | ||
5171 | lastpos = pos; | ||
5172 | CreateCompressedUpdateBlock((SceneObjectPart)eu.Entity, mysp, data, ref pos); | ||
5173 | if (pos < LLUDPServer.MAXPAYLOAD) | ||
5174 | { | ||
5175 | tau.Add(eu); | ||
5176 | ++count; | ||
5177 | } | ||
5178 | else | ||
5179 | { | ||
5180 | // we need more packets | ||
5181 | UDPPacketBuffer newbuf = m_udpServer.GetNewUDPBuffer(m_udpClient.RemoteEndPoint); | ||
5182 | Buffer.BlockCopy(buf.Data, 0, newbuf.Data, 0, countposition); // start is the same | ||
5183 | |||
5184 | buf.Data[countposition] = (byte)count; | ||
5185 | |||
5186 | buf.DataLength = lastpos; | ||
5187 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, | ||
5188 | delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); | ||
5189 | |||
5190 | buf = newbuf; | ||
5191 | data = buf.Data; | ||
5192 | |||
5193 | pos = 18; | ||
5194 | // im lazy now, just do last again | ||
5195 | CreateCompressedUpdateBlock((SceneObjectPart)eu.Entity, mysp, data, ref pos); | ||
5196 | tau = new List<EntityUpdate>(30); | ||
5197 | tau.Add(eu); | ||
5198 | count = 1; | ||
5199 | } | ||
5200 | } | ||
5201 | |||
5202 | if (count > 0) | ||
5203 | { | ||
5204 | buf.Data[countposition] = (byte)count; | ||
5205 | buf.DataLength = pos; | ||
5206 | m_udpServer.SendUDPPacket(m_udpClient, buf, ThrottleOutPacketType.Task, | ||
5207 | delegate (OutgoingPacket oPacket) { ResendPrimUpdates(tau, oPacket); }, false, false); | ||
5208 | } | ||
5148 | } | 5209 | } |
5149 | */ | 5210 | */ |
5150 | if (terseUpdates != null) | 5211 | if (terseUpdates != null) |
5151 | { | 5212 | { |
5152 | int blocks = terseUpdates.Count; | 5213 | int blocks = terseUpdates.Count; |
@@ -5305,7 +5366,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
5305 | // | 5366 | // |
5306 | } | 5367 | } |
5307 | */ | 5368 | */ |
5308 | public void ReprioritizeUpdates() | 5369 | public void ReprioritizeUpdates() |
5309 | { | 5370 | { |
5310 | lock (m_entityUpdates.SyncRoot) | 5371 | lock (m_entityUpdates.SyncRoot) |
5311 | m_entityUpdates.Reprioritize(UpdatePriorityHandler); | 5372 | m_entityUpdates.Reprioritize(UpdatePriorityHandler); |
@@ -6986,10 +7047,262 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
6986 | zc.AddZeros(lastzeros); | 7047 | zc.AddZeros(lastzeros); |
6987 | } | 7048 | } |
6988 | 7049 | ||
6989 | protected ObjectUpdateCompressedPacket.ObjectDataBlock CreateCompressedUpdateBlock(SceneObjectPart part, PrimUpdateFlags updateFlags) | 7050 | [Flags] |
7051 | private enum CompressedFlags : uint | ||
7052 | { | ||
7053 | None = 0x00, | ||
7054 | /// <summary>Unknown</summary> | ||
7055 | ScratchPad = 0x01, | ||
7056 | /// <summary>Whether the object has a TreeSpecies</summary> | ||
7057 | Tree = 0x02, | ||
7058 | /// <summary>Whether the object has floating text ala llSetText</summary> | ||
7059 | HasText = 0x04, | ||
7060 | /// <summary>Whether the object has an active particle system</summary> | ||
7061 | HasParticles = 0x08, | ||
7062 | /// <summary>Whether the object has sound attached to it</summary> | ||
7063 | HasSound = 0x10, | ||
7064 | /// <summary>Whether the object is attached to a root object or not</summary> | ||
7065 | HasParent = 0x20, | ||
7066 | /// <summary>Whether the object has texture animation settings</summary> | ||
7067 | TextureAnimation = 0x40, | ||
7068 | /// <summary>Whether the object has an angular velocity</summary> | ||
7069 | HasAngularVelocity = 0x80, | ||
7070 | /// <summary>Whether the object has a name value pairs string</summary> | ||
7071 | HasNameValues = 0x100, | ||
7072 | /// <summary>Whether the object has a Media URL set</summary> | ||
7073 | MediaURL = 0x200 | ||
7074 | } | ||
7075 | |||
7076 | ///**** temp hack | ||
7077 | private static Random rnd = new Random(); | ||
7078 | |||
7079 | protected void CreateCompressedUpdateBlock(SceneObjectPart part, ScenePresence sp, byte[] dest, ref int pos) | ||
6990 | { | 7080 | { |
6991 | // TODO: Implement this | 7081 | // prepare data |
6992 | return null; | 7082 | CompressedFlags cflags = CompressedFlags.None; |
7083 | |||
7084 | // prim/update flags | ||
7085 | |||
7086 | PrimFlags primflags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(part, sp); | ||
7087 | // Don't send the CreateSelected flag to everyone | ||
7088 | primflags &= ~PrimFlags.CreateSelected; | ||
7089 | if (sp.UUID == part.OwnerID) | ||
7090 | { | ||
7091 | if (part.CreateSelected) | ||
7092 | { | ||
7093 | // Only send this flag once, then unset it | ||
7094 | primflags |= PrimFlags.CreateSelected; | ||
7095 | part.CreateSelected = false; | ||
7096 | } | ||
7097 | } | ||
7098 | |||
7099 | // first is primFlags | ||
7100 | Utils.UIntToBytesSafepos((uint)primflags, dest, pos); pos += 4; | ||
7101 | |||
7102 | // datablock len to fill later | ||
7103 | int lenpos = pos; | ||
7104 | pos += 2; | ||
7105 | |||
7106 | byte state = part.Shape.State; | ||
7107 | PCode pcode = (PCode)part.Shape.PCode; | ||
7108 | |||
7109 | bool hastree = false; | ||
7110 | if (pcode == PCode.Grass || pcode == PCode.Tree || pcode == PCode.NewTree) | ||
7111 | { | ||
7112 | cflags |= CompressedFlags.Tree; | ||
7113 | hastree = true; | ||
7114 | } | ||
7115 | |||
7116 | //NameValue and state | ||
7117 | byte[] nv = null; | ||
7118 | if (part.ParentGroup.IsAttachment) | ||
7119 | { | ||
7120 | if (part.IsRoot) | ||
7121 | nv = Util.StringToBytes256("AttachItemID STRING RW SV " + part.ParentGroup.FromItemID); | ||
7122 | |||
7123 | int st = (int)part.ParentGroup.AttachmentPoint; | ||
7124 | state = (byte)(((st & 0xf0) >> 4) + ((st & 0x0f) << 4)); ; | ||
7125 | } | ||
7126 | |||
7127 | bool hastext = part.Text != null && part.Text.Length > 0; | ||
7128 | bool hassound = part.Sound != UUID.Zero || part.SoundFlags != 0; | ||
7129 | bool hasps = part.ParticleSystem != null && part.ParticleSystem.Length > 1; | ||
7130 | bool hastexanim = part.TextureAnimation != null && part.TextureAnimation.Length > 0; | ||
7131 | bool hasangvel = part.AngularVelocity.LengthSquared() > 1e-8f; | ||
7132 | bool hasmediaurl = part.MediaUrl != null && part.MediaUrl.Length > 1; | ||
7133 | |||
7134 | if (hastext) | ||
7135 | cflags |= CompressedFlags.HasText; | ||
7136 | if (hasps) | ||
7137 | cflags |= CompressedFlags.HasParticles; | ||
7138 | if (hassound) | ||
7139 | cflags |= CompressedFlags.HasSound; | ||
7140 | if (part.ParentID != 0) | ||
7141 | cflags |= CompressedFlags.HasParent; | ||
7142 | if (hastexanim) | ||
7143 | cflags |= CompressedFlags.TextureAnimation; | ||
7144 | if (hasangvel) | ||
7145 | cflags |= CompressedFlags.HasAngularVelocity; | ||
7146 | if (hasmediaurl) | ||
7147 | cflags |= CompressedFlags.MediaURL; | ||
7148 | if (nv != null) | ||
7149 | cflags |= CompressedFlags.HasNameValues; | ||
7150 | |||
7151 | // filter out mesh faces hack | ||
7152 | ushort profileBegin = part.Shape.ProfileBegin; | ||
7153 | ushort profileHollow = part.Shape.ProfileHollow; | ||
7154 | byte profileCurve = part.Shape.ProfileCurve; | ||
7155 | byte pathScaleY = part.Shape.PathScaleY; | ||
7156 | |||
7157 | if (part.Shape.SculptType == (byte)SculptType.Mesh) // filter out hack | ||
7158 | { | ||
7159 | profileCurve = (byte)(part.Shape.ProfileCurve & 0x0f); | ||
7160 | // fix old values that confused viewers | ||
7161 | if (profileBegin == 1) | ||
7162 | profileBegin = 9375; | ||
7163 | if (profileHollow == 1) | ||
7164 | profileHollow = 27500; | ||
7165 | // fix torus hole size Y that also confuse some viewers | ||
7166 | if (profileCurve == (byte)ProfileShape.Circle && pathScaleY < 150) | ||
7167 | pathScaleY = 150; | ||
7168 | } | ||
7169 | |||
7170 | part.UUID.ToBytes(dest, pos); pos += 16; | ||
7171 | Utils.UIntToBytesSafepos(part.LocalId, dest, pos); pos += 4; | ||
7172 | dest[pos++] = (byte)pcode; | ||
7173 | dest[pos++] = state; | ||
7174 | |||
7175 | ///**** temp hack | ||
7176 | Utils.UIntToBytesSafepos((uint)rnd.Next(), dest, pos); pos += 4; //CRC needs fix or things will get crazy for now avoid caching | ||
7177 | dest[pos++] = part.Material; | ||
7178 | dest[pos++] = part.ClickAction; | ||
7179 | part.Shape.Scale.ToBytes(dest, pos); pos += 12; | ||
7180 | part.RelativePosition.ToBytes(dest, pos); pos += 12; | ||
7181 | if(pcode == PCode.Grass) | ||
7182 | Vector3.Zero.ToBytes(dest, pos); | ||
7183 | else | ||
7184 | { | ||
7185 | Quaternion rotation = part.RotationOffset; | ||
7186 | rotation.Normalize(); | ||
7187 | rotation.ToBytes(dest, pos); | ||
7188 | } | ||
7189 | pos += 12; | ||
7190 | |||
7191 | Utils.UIntToBytesSafepos((uint)cflags, dest, pos); pos += 4; | ||
7192 | |||
7193 | if (hasps || hassound) | ||
7194 | part.OwnerID.ToBytes(dest, pos); | ||
7195 | else | ||
7196 | UUID.Zero.ToBytes(dest, pos); | ||
7197 | pos += 16; | ||
7198 | |||
7199 | if (hasangvel) | ||
7200 | { | ||
7201 | part.AngularVelocity.ToBytes(dest, pos); pos += 12; | ||
7202 | } | ||
7203 | if (part.ParentID != 0) | ||
7204 | { | ||
7205 | Utils.UIntToBytesSafepos(part.ParentID, dest, pos); pos += 4; | ||
7206 | } | ||
7207 | if (hastree) | ||
7208 | dest[pos++] = state; | ||
7209 | if (hastext) | ||
7210 | { | ||
7211 | byte[] text = Util.StringToBytes256(part.Text); // must be null term | ||
7212 | Buffer.BlockCopy(text, 0, dest, pos, text.Length); pos += text.Length; | ||
7213 | byte[] tc = part.GetTextColor().GetBytes(false); | ||
7214 | Buffer.BlockCopy(tc, 0, dest, pos, tc.Length); pos += tc.Length; | ||
7215 | } | ||
7216 | if (hasmediaurl) | ||
7217 | { | ||
7218 | byte[] mu = Util.StringToBytes256(part.MediaUrl); // must be null term | ||
7219 | Buffer.BlockCopy(mu, 0, dest, pos, mu.Length); pos += mu.Length; | ||
7220 | } | ||
7221 | if (hasps) | ||
7222 | { | ||
7223 | byte[] ps = part.ParticleSystem; | ||
7224 | Buffer.BlockCopy(ps, 0, dest, pos, ps.Length); pos += ps.Length; | ||
7225 | } | ||
7226 | byte[] ex = part.Shape.ExtraParams; | ||
7227 | if (ex == null || ex.Length < 2) | ||
7228 | dest[pos++] = 0; | ||
7229 | else | ||
7230 | { | ||
7231 | Buffer.BlockCopy(ex, 0, dest, pos, ex.Length); pos += ex.Length; | ||
7232 | } | ||
7233 | if (hassound) | ||
7234 | { | ||
7235 | part.Sound.ToBytes(dest, pos); pos += 16; | ||
7236 | Utils.FloatToBytesSafepos((float)part.SoundGain, dest, pos); pos += 4; | ||
7237 | dest[pos++] = part.SoundFlags; | ||
7238 | Utils.FloatToBytesSafepos((float)part.SoundRadius, dest, pos); pos += 4; | ||
7239 | } | ||
7240 | if (nv != null) | ||
7241 | { | ||
7242 | Buffer.BlockCopy(nv, 0, dest, pos, nv.Length); pos += nv.Length; | ||
7243 | } | ||
7244 | |||
7245 | dest[pos++] = part.Shape.PathCurve; | ||
7246 | Utils.UInt16ToBytes(part.Shape.PathBegin, dest, pos); pos += 2; | ||
7247 | Utils.UInt16ToBytes(part.Shape.PathEnd, dest, pos); pos += 2; | ||
7248 | dest[pos++] = part.Shape.PathScaleX; | ||
7249 | dest[pos++] = pathScaleY; | ||
7250 | dest[pos++] = part.Shape.PathShearX; | ||
7251 | dest[pos++] = part.Shape.PathShearY; | ||
7252 | dest[pos++] = (byte)part.Shape.PathTwist; | ||
7253 | dest[pos++] = (byte)part.Shape.PathTwistBegin; | ||
7254 | dest[pos++] = (byte)part.Shape.PathRadiusOffset; | ||
7255 | dest[pos++] = (byte)part.Shape.PathTaperX; | ||
7256 | dest[pos++] = (byte)part.Shape.PathTaperY; | ||
7257 | dest[pos++] = part.Shape.PathRevolutions; | ||
7258 | dest[pos++] = (byte)part.Shape.PathSkew; | ||
7259 | dest[pos++] = profileCurve; | ||
7260 | Utils.UInt16ToBytes(profileBegin, dest, pos); pos += 2; | ||
7261 | Utils.UInt16ToBytes(part.Shape.ProfileEnd, dest, pos); pos += 2; | ||
7262 | Utils.UInt16ToBytes(profileHollow, dest, pos); pos += 2; | ||
7263 | |||
7264 | byte[] te = part.Shape.TextureEntry; | ||
7265 | if (te == null) | ||
7266 | { | ||
7267 | dest[pos++] = 0; | ||
7268 | dest[pos++] = 0; | ||
7269 | dest[pos++] = 0; | ||
7270 | dest[pos++] = 0; | ||
7271 | } | ||
7272 | else | ||
7273 | { | ||
7274 | int len = te.Length & 0x7fff; | ||
7275 | dest[pos++] = (byte)len; | ||
7276 | dest[pos++] = (byte)(len >> 8); | ||
7277 | dest[pos++] = 0; | ||
7278 | dest[pos++] = 0; | ||
7279 | Buffer.BlockCopy(te, 0, dest, pos, len); | ||
7280 | pos += len; | ||
7281 | } | ||
7282 | if (hastexanim) | ||
7283 | { | ||
7284 | byte[] ta = part.TextureAnimation; | ||
7285 | if (ta == null) | ||
7286 | { | ||
7287 | dest[pos++] = 0; | ||
7288 | dest[pos++] = 0; | ||
7289 | dest[pos++] = 0; | ||
7290 | dest[pos++] = 0; | ||
7291 | } | ||
7292 | else | ||
7293 | { | ||
7294 | int len = ta.Length & 0x7fff; | ||
7295 | dest[pos++] = (byte)len; | ||
7296 | dest[pos++] = (byte)(len >> 8); | ||
7297 | dest[pos++] = 0; | ||
7298 | dest[pos++] = 0; | ||
7299 | Buffer.BlockCopy(ta, 0, dest, pos, len); | ||
7300 | pos += len; | ||
7301 | } | ||
7302 | } | ||
7303 | int totlen = pos - lenpos - 2; | ||
7304 | dest[lenpos++] = (byte)totlen; | ||
7305 | dest[lenpos++] = (byte)(totlen >> 8); | ||
6993 | } | 7306 | } |
6994 | 7307 | ||
6995 | public void SendNameReply(UUID profileId, string firstname, string lastname) | 7308 | public void SendNameReply(UUID profileId, string firstname, string lastname) |
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index c899428..a0b3d21 100755 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs | |||
@@ -466,8 +466,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
466 | Throttle = new TokenBucket(null, sceneThrottleBps, sceneThrottleBps * 10e-3f); | 466 | Throttle = new TokenBucket(null, sceneThrottleBps, sceneThrottleBps * 10e-3f); |
467 | ThrottleRates = new ThrottleRates(configSource); | 467 | ThrottleRates = new ThrottleRates(configSource); |
468 | 468 | ||
469 | Random rnd = new Random(Util.EnvironmentTickCount()); | ||
470 | |||
471 | // if (usePools) | 469 | // if (usePools) |
472 | // EnablePools(); | 470 | // EnablePools(); |
473 | } | 471 | } |
@@ -1359,11 +1357,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1359 | if (packet.Type == PacketType.UseCircuitCode) | 1357 | if (packet.Type == PacketType.UseCircuitCode) |
1360 | { | 1358 | { |
1361 | // And if there is a UseCircuitCode pending, also drop it | 1359 | // And if there is a UseCircuitCode pending, also drop it |
1360 | |||
1362 | lock (m_pendingCache) | 1361 | lock (m_pendingCache) |
1363 | { | 1362 | { |
1364 | if (m_pendingCache.Contains(endPoint)) | 1363 | if (m_pendingCache.Contains(endPoint)) |
1365 | { | 1364 | { |
1366 | FreeUDPBuffer(buffer); | 1365 | FreeUDPBuffer(buffer); |
1366 | SendAckImmediate(endPoint, packet.Header.Sequence); // i hear you shutup | ||
1367 | return; | 1367 | return; |
1368 | } | 1368 | } |
1369 | 1369 | ||
@@ -1372,6 +1372,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1372 | 1372 | ||
1373 | Util.FireAndForget(HandleUseCircuitCode, new object[] { endPoint, packet }); | 1373 | Util.FireAndForget(HandleUseCircuitCode, new object[] { endPoint, packet }); |
1374 | FreeUDPBuffer(buffer); | 1374 | FreeUDPBuffer(buffer); |
1375 | SendAckImmediate(endPoint, packet.Header.Sequence); | ||
1375 | return; | 1376 | return; |
1376 | } | 1377 | } |
1377 | } | 1378 | } |
@@ -1720,11 +1721,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1720 | 1721 | ||
1721 | queue = null; | 1722 | queue = null; |
1722 | 1723 | ||
1723 | // Send ack straight away to let the viewer know that the connection is active. | ||
1724 | // The client will be null if it already exists (e.g. if on a region crossing the client sends a use | ||
1725 | // circuit code to the existing child agent. This is not particularly obvious. | ||
1726 | SendAckImmediate(endPoint, uccp.Header.Sequence); | ||
1727 | |||
1728 | if (client != null) | 1724 | if (client != null) |
1729 | { | 1725 | { |
1730 | client.SendRegionHandshake(); | 1726 | client.SendRegionHandshake(); |