aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorUbitUmarov2016-07-06 16:10:44 +0100
committerUbitUmarov2016-07-06 16:13:27 +0100
commitc02fe98b7da0ef62fe67fb45652878181e4a297d (patch)
treeff2423ad3d7acd614528ed24873613b48869866c /OpenSim/Region
parentadd EngineName also to the others (diff)
downloadopensim-SC-c02fe98b7da0ef62fe67fb45652878181e4a297d.zip
opensim-SC-c02fe98b7da0ef62fe67fb45652878181e4a297d.tar.gz
opensim-SC-c02fe98b7da0ef62fe67fb45652878181e4a297d.tar.bz2
opensim-SC-c02fe98b7da0ef62fe67fb45652878181e4a297d.tar.xz
add test option ObjectsCullingByDistance. In future, if true, it may
prevent sending objects outside view range to viewers. DO NOT SET TRUE unless testing it. Code still not completei!!!
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs128
-rwxr-xr-xOpenSim/Region/Framework/Scenes/Scene.cs23
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs62
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs20
-rw-r--r--OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs10
5 files changed, 182 insertions, 61 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 4a48a80..cddafc5 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -340,6 +340,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
340 private Prioritizer m_prioritizer; 340 private Prioritizer m_prioritizer;
341 private bool m_disableFacelights = false; 341 private bool m_disableFacelights = false;
342 342
343 // needs optimazation
344 private HashSet<SceneObjectGroup> GroupsInView = new HashSet<SceneObjectGroup>();
345
343 private bool m_VelocityInterpolate = false; 346 private bool m_VelocityInterpolate = false;
344 private const uint MaxTransferBytesPerPacket = 600; 347 private const uint MaxTransferBytesPerPacket = 600;
345 348
@@ -3978,7 +3981,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3978// float avgTimeDilation = 0.0f; 3981// float avgTimeDilation = 0.0f;
3979 IEntityUpdate iupdate; 3982 IEntityUpdate iupdate;
3980 Int32 timeinqueue; // this is just debugging code & can be dropped later 3983 Int32 timeinqueue; // this is just debugging code & can be dropped later
3981 3984
3985 bool doCulling = m_scene.ObjectsCullingByDistance;
3986 float cullingrange = 64.0f;
3987 HashSet<SceneObjectGroup> GroupsNeedFullUpdate = new HashSet<SceneObjectGroup>();
3988 Vector3 mycamera = Vector3.Zero;
3989 Vector3 mypos = Vector3.Zero;
3990 ScenePresence mysp = (ScenePresence)SceneAgent;
3991 if(mysp != null && !mysp.IsDeleted)
3992 {
3993 cullingrange = mysp.DrawDistance + m_scene.ReprioritizationDistance +16f;
3994 mycamera = mysp.CameraPosition;
3995 mypos = mysp.AbsolutePosition;
3996 }
3997 else
3998 doCulling = false;
3999
3982 while (updatesThisCall < maxUpdates) 4000 while (updatesThisCall < maxUpdates)
3983 { 4001 {
3984 lock (m_entityUpdates.SyncRoot) 4002 lock (m_entityUpdates.SyncRoot)
@@ -4059,6 +4077,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4059 } 4077 }
4060 } 4078 }
4061 4079
4080 if(doCulling && !part.ParentGroup.IsAttachment)
4081 {
4082 lock(GroupsInView)
4083 {
4084 if(!GroupsInView.Contains(part.ParentGroup))
4085 {
4086 Vector3 partpos = part.ParentGroup.AbsolutePosition;
4087 float dcam = (partpos - mycamera).LengthSquared();
4088 float dpos = (partpos - mypos).LengthSquared();
4089 if(dcam < dpos)
4090 dpos = dcam;
4091 dpos = (float)Math.Sqrt(dpos) + part.ParentGroup.GetBoundsRadius();
4092 if(dpos > cullingrange)
4093 continue;
4094
4095 if(!GroupsNeedFullUpdate.Contains(part.ParentGroup))
4096 GroupsNeedFullUpdate.Add(part.ParentGroup);
4097 continue;
4098 }
4099 }
4100 }
4101
4062 if (part.Shape != null && (part.Shape.SculptType == (byte)SculptType.Mesh)) 4102 if (part.Shape != null && (part.Shape.SculptType == (byte)SculptType.Mesh))
4063 { 4103 {
4064 // Ensure that mesh has at least 8 valid faces 4104 // Ensure that mesh has at least 8 valid faces
@@ -4247,8 +4287,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4247 SendKillObject(m_killRecord); 4287 SendKillObject(m_killRecord);
4248 m_killRecord.Clear(); 4288 m_killRecord.Clear();
4249 } 4289 }
4250 #endregion
4251 4290
4291 lock(GroupsNeedFullUpdate)
4292 {
4293 if(GroupsNeedFullUpdate.Count > 0)
4294 {
4295 foreach(SceneObjectGroup grp in GroupsNeedFullUpdate)
4296 {
4297 grp.ScheduleGroupForFullUpdate();
4298 lock(GroupsInView)
4299 GroupsInView.Add(grp);
4300 }
4301 GroupsNeedFullUpdate.Clear();
4302 }
4303 }
4304 #endregion
4252 4305
4253 } 4306 }
4254 4307
@@ -4282,10 +4335,81 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4282 4335
4283 public void ReprioritizeUpdates() 4336 public void ReprioritizeUpdates()
4284 { 4337 {
4338 CheckGroupsInView();
4285 lock (m_entityUpdates.SyncRoot) 4339 lock (m_entityUpdates.SyncRoot)
4286 m_entityUpdates.Reprioritize(UpdatePriorityHandler); 4340 m_entityUpdates.Reprioritize(UpdatePriorityHandler);
4287 } 4341 }
4288 4342
4343 public void CheckGroupsInView()
4344 {
4345 bool doCulling = m_scene.ObjectsCullingByDistance;
4346 if(!doCulling)
4347 return;
4348 float cullingrange = 64.0f;
4349 Vector3 mycamera = Vector3.Zero;
4350 Vector3 mypos = Vector3.Zero;
4351 ScenePresence mysp = (ScenePresence)SceneAgent;
4352 if(mysp != null && !mysp.IsDeleted)
4353 {
4354 cullingrange = mysp.DrawDistance + m_scene.ReprioritizationDistance + 16f;
4355 mycamera = mysp.CameraPosition;
4356 mypos = mysp.AbsolutePosition;
4357 }
4358 else
4359 return;
4360
4361 HashSet<SceneObjectGroup> NewGroupsInView = new HashSet<SceneObjectGroup>();
4362 HashSet<SceneObjectGroup> GroupsNeedFullUpdate = new HashSet<SceneObjectGroup>();
4363
4364 lock(GroupsInView)
4365 {
4366 EntityBase[] entities = m_scene.Entities.GetEntities();
4367 foreach (EntityBase e in entities)
4368 {
4369 if (e != null && e is SceneObjectGroup && !((SceneObjectGroup)e).IsAttachment)
4370 {
4371 SceneObjectGroup grp = (SceneObjectGroup)e;
4372 Vector3 grppos = grp.AbsolutePosition;
4373 float dcam = (grppos - mycamera).LengthSquared();
4374 float dpos = (grppos - mypos).LengthSquared();
4375 if(dcam < dpos)
4376 dpos = dcam;
4377 dpos = (float)Math.Sqrt(dpos) + grp.GetBoundsRadius();
4378 if(dpos > cullingrange)
4379 {
4380 if(GroupsInView.Contains(grp))
4381 {
4382 GroupsInView.Remove(grp);
4383 if (!m_killRecord.Contains(grp.LocalId))
4384 m_killRecord.Add(grp.LocalId);
4385 }
4386 }
4387 else
4388 {
4389 if(!GroupsInView.Contains(grp) && !GroupsNeedFullUpdate.Contains(grp))
4390 GroupsNeedFullUpdate.Add(grp);
4391 NewGroupsInView.Add(grp);
4392 }
4393 }
4394 }
4395 }
4396
4397 GroupsInView = NewGroupsInView;
4398
4399 if (m_killRecord.Count > 0)
4400 {
4401 SendKillObject(m_killRecord);
4402 m_killRecord.Clear();
4403 }
4404
4405 if(GroupsNeedFullUpdate.Count > 0)
4406 {
4407 foreach(SceneObjectGroup grp in GroupsNeedFullUpdate)
4408 grp.ScheduleGroupForFullUpdate();
4409 }
4410 GroupsNeedFullUpdate.Clear();
4411 }
4412
4289 private bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity) 4413 private bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity)
4290 { 4414 {
4291 if (entity != null) 4415 if (entity != null)
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 0d19e94..3c5630e 100755
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -803,9 +803,9 @@ namespace OpenSim.Region.Framework.Scenes
803 public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get; set; } 803 public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get; set; }
804 public bool IsReprioritizationEnabled { get; set; } 804 public bool IsReprioritizationEnabled { get; set; }
805 public float ReprioritizationInterval { get; set; } 805 public float ReprioritizationInterval { get; set; }
806 public float RootReprioritizationDistance { get; set; } 806 public float ReprioritizationDistance { get; set; }
807 public float ChildReprioritizationDistance { get; set; }
808 private float m_minReprioritizationDistance = 32f; 807 private float m_minReprioritizationDistance = 32f;
808 public bool ObjectsCullingByDistance = false;
809 809
810 public AgentCircuitManager AuthenticateHandler 810 public AgentCircuitManager AuthenticateHandler
811 { 811 {
@@ -1185,15 +1185,15 @@ namespace OpenSim.Region.Framework.Scenes
1185 = interestConfig.GetBoolean("ReprioritizationEnabled", IsReprioritizationEnabled); 1185 = interestConfig.GetBoolean("ReprioritizationEnabled", IsReprioritizationEnabled);
1186 ReprioritizationInterval 1186 ReprioritizationInterval
1187 = interestConfig.GetFloat("ReprioritizationInterval", ReprioritizationInterval); 1187 = interestConfig.GetFloat("ReprioritizationInterval", ReprioritizationInterval);
1188 RootReprioritizationDistance 1188 ReprioritizationDistance
1189 = interestConfig.GetFloat("RootReprioritizationDistance", RootReprioritizationDistance); 1189 = interestConfig.GetFloat("RootReprioritizationDistance", ReprioritizationDistance);
1190 ChildReprioritizationDistance 1190
1191 = interestConfig.GetFloat("ChildReprioritizationDistance", ChildReprioritizationDistance); 1191 if(ReprioritizationDistance < m_minReprioritizationDistance)
1192 ReprioritizationDistance = m_minReprioritizationDistance;
1193
1194 ObjectsCullingByDistance
1195 = interestConfig.GetBoolean("ObjectsCullingByDistance", ObjectsCullingByDistance);
1192 1196
1193 if(RootReprioritizationDistance < m_minReprioritizationDistance)
1194 RootReprioritizationDistance = m_minReprioritizationDistance;
1195 if(ChildReprioritizationDistance < m_minReprioritizationDistance)
1196 ChildReprioritizationDistance = m_minReprioritizationDistance;
1197 1197
1198 RootTerseUpdatePeriod = interestConfig.GetInt("RootTerseUpdatePeriod", RootTerseUpdatePeriod); 1198 RootTerseUpdatePeriod = interestConfig.GetInt("RootTerseUpdatePeriod", RootTerseUpdatePeriod);
1199 ChildTerseUpdatePeriod = interestConfig.GetInt("ChildTerseUpdatePeriod", ChildTerseUpdatePeriod); 1199 ChildTerseUpdatePeriod = interestConfig.GetInt("ChildTerseUpdatePeriod", ChildTerseUpdatePeriod);
@@ -1252,8 +1252,7 @@ namespace OpenSim.Region.Framework.Scenes
1252 RootRotationUpdateTolerance = 0.1f; 1252 RootRotationUpdateTolerance = 0.1f;
1253 RootVelocityUpdateTolerance = 0.001f; 1253 RootVelocityUpdateTolerance = 0.001f;
1254 RootPositionUpdateTolerance = 0.05f; 1254 RootPositionUpdateTolerance = 0.05f;
1255 RootReprioritizationDistance = m_minReprioritizationDistance; 1255 ReprioritizationDistance = m_minReprioritizationDistance;
1256 ChildReprioritizationDistance = m_minReprioritizationDistance;
1257 1256
1258 m_eventManager = new EventManager(); 1257 m_eventManager = new EventManager();
1259 1258
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index cb1bf55..4e87014 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -1567,6 +1567,39 @@ namespace OpenSim.Region.Framework.Scenes
1567 1567
1568 #endregion 1568 #endregion
1569 1569
1570 private float? m_boundsRadius = null;
1571
1572 public float GetBoundsRadius()
1573 {
1574 // this may need more threading work
1575 if(m_boundsRadius == null)
1576 {
1577 float res = 0;
1578 SceneObjectPart p;
1579 SceneObjectPart[] parts;
1580 float partR;
1581 lock (m_parts)
1582 {
1583 parts = m_parts.GetArray();
1584 }
1585
1586 int nparts = parts.Length;
1587 for (int i = 0; i < nparts; i++)
1588 {
1589 p = parts[i];
1590 partR = p.Scale.Length();
1591 if(p != RootPart)
1592 partR += p.OffsetPosition.Length();
1593 if(partR > res)
1594 res = partR;
1595 }
1596 m_boundsRadius = res;
1597 return res;
1598 }
1599
1600 return m_boundsRadius.Value;
1601 }
1602
1570 public void GetResourcesCosts(SceneObjectPart apart, 1603 public void GetResourcesCosts(SceneObjectPart apart,
1571 out float linksetResCost, out float linksetPhysCost, out float partCost, out float partPhysCost) 1604 out float linksetResCost, out float linksetPhysCost, out float partCost, out float partPhysCost)
1572 { 1605 {
@@ -4596,14 +4629,11 @@ namespace OpenSim.Region.Framework.Scenes
4596 if (nparts <= 1) 4629 if (nparts <= 1)
4597 return gc; 4630 return gc;
4598 4631
4599 Quaternion parentRot = RootPart.RotationOffset;
4600 Vector3 pPos; 4632 Vector3 pPos;
4601 4633
4602 // average all parts positions 4634 // average all parts positions
4603 for (int i = 0; i < nparts; i++) 4635 for (int i = 0; i < nparts; i++)
4604 { 4636 {
4605 // do it directly
4606 // gc += parts[i].GetWorldPosition();
4607 if (parts[i] != RootPart) 4637 if (parts[i] != RootPart)
4608 { 4638 {
4609 pPos = parts[i].OffsetPosition; 4639 pPos = parts[i].OffsetPosition;
@@ -4613,8 +4643,6 @@ namespace OpenSim.Region.Framework.Scenes
4613 } 4643 }
4614 gc /= nparts; 4644 gc /= nparts;
4615 4645
4616 // relative to root:
4617// gc -= AbsolutePosition;
4618 return gc; 4646 return gc;
4619 } 4647 }
4620 4648
@@ -4662,30 +4690,6 @@ namespace OpenSim.Region.Framework.Scenes
4662 } 4690 }
4663 4691
4664 /// <summary> 4692 /// <summary>
4665 /// If the object is a sculpt/mesh, retrieve the mesh data for each part and reinsert it into each shape so that
4666 /// the physics engine can use it.
4667 /// </summary>
4668 /// <remarks>
4669 /// When the physics engine has finished with it, the sculpt data is discarded to save memory.
4670 /// </remarks>
4671/*
4672 public void CheckSculptAndLoad()
4673 {
4674 if (IsDeleted)
4675 return;
4676
4677 if ((RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.Phantom) != 0)
4678 return;
4679
4680// m_log.Debug("Processing CheckSculptAndLoad for {0} {1}", Name, LocalId);
4681
4682 SceneObjectPart[] parts = m_parts.GetArray();
4683
4684 for (int i = 0; i < parts.Length; i++)
4685 parts[i].CheckSculptAndLoad();
4686 }
4687*/
4688 /// <summary>
4689 /// Set the user group to which this scene object belongs. 4693 /// Set the user group to which this scene object belongs.
4690 /// </summary> 4694 /// </summary>
4691 /// <param name="GroupID"></param> 4695 /// <param name="GroupID"></param>
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 4775b1f..817ed43 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -350,6 +350,7 @@ namespace OpenSim.Region.Framework.Scenes
350 protected int m_reprioritizationLastTime; 350 protected int m_reprioritizationLastTime;
351 protected bool m_reprioritizationBusy; 351 protected bool m_reprioritizationBusy;
352 protected Vector3 m_reprioritizationLastPosition; 352 protected Vector3 m_reprioritizationLastPosition;
353 protected float m_reprioritizationLastDrawDistance;
353 354
354 private Quaternion m_headrotation = Quaternion.Identity; 355 private Quaternion m_headrotation = Quaternion.Identity;
355 356
@@ -1047,6 +1048,8 @@ namespace OpenSim.Region.Framework.Scenes
1047 AbsolutePosition = posLastMove = posLastSignificantMove = CameraPosition = 1048 AbsolutePosition = posLastMove = posLastSignificantMove = CameraPosition =
1048 m_reprioritizationLastPosition = ControllingClient.StartPos; 1049 m_reprioritizationLastPosition = ControllingClient.StartPos;
1049 1050
1051 m_reprioritizationLastDrawDistance = DrawDistance;
1052
1050 // disable updates workjobs for now 1053 // disable updates workjobs for now
1051 childUpdatesBusy = true; 1054 childUpdatesBusy = true;
1052 m_reprioritizationBusy = true; 1055 m_reprioritizationBusy = true;
@@ -2130,6 +2133,7 @@ namespace OpenSim.Region.Framework.Scenes
2130 2133
2131 // priority uses avatar position only 2134 // priority uses avatar position only
2132 m_reprioritizationLastPosition = AbsolutePosition; 2135 m_reprioritizationLastPosition = AbsolutePosition;
2136 m_reprioritizationLastDrawDistance = DrawDistance;
2133 m_reprioritizationLastTime = Util.EnvironmentTickCount() + 15000; // delay it 2137 m_reprioritizationLastTime = Util.EnvironmentTickCount() + 15000; // delay it
2134 m_reprioritizationBusy = false; 2138 m_reprioritizationBusy = false;
2135 2139
@@ -3986,24 +3990,24 @@ namespace OpenSim.Region.Framework.Scenes
3986 if(m_reprioritizationBusy) 3990 if(m_reprioritizationBusy)
3987 return; 3991 return;
3988 3992
3993 float limit = Scene.ReprioritizationDistance;
3994 bool byDrawdistance = Scene.ObjectsCullingByDistance;
3995 if(byDrawdistance)
3996 byDrawdistance = (Math.Abs(DrawDistance-m_reprioritizationLastDrawDistance) > 0.5f * limit);
3997
3989 int tdiff = Util.EnvironmentTickCountSubtract(m_reprioritizationLastTime); 3998 int tdiff = Util.EnvironmentTickCountSubtract(m_reprioritizationLastTime);
3990 if(tdiff < Scene.ReprioritizationInterval) 3999 if(!byDrawdistance && tdiff < Scene.ReprioritizationInterval)
3991 return; 4000 return;
3992 // priority uses avatar position 4001 // priority uses avatar position
3993 Vector3 pos = AbsolutePosition; 4002 Vector3 pos = AbsolutePosition;
3994 Vector3 diff = pos - m_reprioritizationLastPosition; 4003 Vector3 diff = pos - m_reprioritizationLastPosition;
3995 float limit;
3996 if(IsChildAgent)
3997 limit = (float)Scene.ChildReprioritizationDistance;
3998 else
3999 limit = (float)Scene.RootReprioritizationDistance;
4000
4001 limit *= limit; 4004 limit *= limit;
4002 if (diff.LengthSquared() < limit) 4005 if (!byDrawdistance && diff.LengthSquared() < limit)
4003 return; 4006 return;
4004 4007
4005 m_reprioritizationBusy = true; 4008 m_reprioritizationBusy = true;
4006 m_reprioritizationLastPosition = pos; 4009 m_reprioritizationLastPosition = pos;
4010 m_reprioritizationLastDrawDistance = DrawDistance;
4007 4011
4008 Util.FireAndForget( 4012 Util.FireAndForget(
4009 o => 4013 o =>
diff --git a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
index db5c7eb..cbb79d0 100644
--- a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
+++ b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs
@@ -156,7 +156,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
156 cdl.AddRow("active", m_scene.Active); 156 cdl.AddRow("active", m_scene.Active);
157 cdl.AddRow("animations", m_scene.DebugAnimations); 157 cdl.AddRow("animations", m_scene.DebugAnimations);
158 cdl.AddRow("appear-refresh", m_scene.SendPeriodicAppearanceUpdates); 158 cdl.AddRow("appear-refresh", m_scene.SendPeriodicAppearanceUpdates);
159 cdl.AddRow("child-repri", m_scene.ChildReprioritizationDistance);
160 cdl.AddRow("client-pos-upd", m_scene.RootPositionUpdateTolerance); 159 cdl.AddRow("client-pos-upd", m_scene.RootPositionUpdateTolerance);
161 cdl.AddRow("client-rot-upd", m_scene.RootRotationUpdateTolerance); 160 cdl.AddRow("client-rot-upd", m_scene.RootRotationUpdateTolerance);
162 cdl.AddRow("client-vel-upd", m_scene.RootVelocityUpdateTolerance); 161 cdl.AddRow("client-vel-upd", m_scene.RootVelocityUpdateTolerance);
@@ -219,15 +218,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments
219 m_scene.SendPeriodicAppearanceUpdates = newValue; 218 m_scene.SendPeriodicAppearanceUpdates = newValue;
220 } 219 }
221 220
222 if (options.ContainsKey("child-repri"))
223 {
224 double newValue;
225
226 // FIXME: This can only come from the console at the moment but might not always be true.
227 if (ConsoleUtil.TryParseConsoleDouble(MainConsole.Instance, options["child-repri"], out newValue))
228 m_scene.ChildReprioritizationDistance = (float)newValue;
229 }
230
231 if (options.ContainsKey("client-pos-upd")) 221 if (options.ContainsKey("client-pos-upd"))
232 { 222 {
233 float newValue; 223 float newValue;