aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/OptionalModules/World/NPC
diff options
context:
space:
mode:
authorTom2011-09-04 07:06:36 -0700
committerTom2011-09-04 07:06:36 -0700
commit66dec3b8742eff04fbbcc6e3249fe4ba87986500 (patch)
tree76cc708a821d35fac5cdbbce2de304b47064e732 /OpenSim/Region/OptionalModules/World/NPC
parentGuard another nullref (diff)
parentFixed BulletSim config files for Linux *.so libraries. (diff)
downloadopensim-SC-66dec3b8742eff04fbbcc6e3249fe4ba87986500.zip
opensim-SC-66dec3b8742eff04fbbcc6e3249fe4ba87986500.tar.gz
opensim-SC-66dec3b8742eff04fbbcc6e3249fe4ba87986500.tar.bz2
opensim-SC-66dec3b8742eff04fbbcc6e3249fe4ba87986500.tar.xz
Resolve merge commits, stage 1
Diffstat (limited to 'OpenSim/Region/OptionalModules/World/NPC')
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs16
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs187
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs108
3 files changed, 265 insertions, 46 deletions
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index 69d6261..4f831a4 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -37,6 +37,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC
37{ 37{
38 public class NPCAvatar : IClientAPI 38 public class NPCAvatar : IClientAPI
39 { 39 {
40 /// <summary>
41 /// Signal whether the avatar should land when it reaches a move target
42 /// </summary>
43 public bool LandAtTarget { get; set; }
44
40 private readonly string m_firstname; 45 private readonly string m_firstname;
41 private readonly string m_lastname; 46 private readonly string m_lastname;
42 private readonly Vector3 m_startPos; 47 private readonly Vector3 m_startPos;
@@ -99,6 +104,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
99 { 104 {
100 105
101 } 106 }
107
102 public void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot, 108 public void SendSitResponse(UUID TargetID, Vector3 OffsetPos, Quaternion SitOrientation, bool autopilot,
103 Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook) 109 Vector3 CameraAtOffset, Vector3 CameraEyeOffset, bool ForceMouseLook)
104 { 110 {
@@ -189,7 +195,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
189 public event DeRezObject OnDeRezObject; 195 public event DeRezObject OnDeRezObject;
190 public event Action<IClientAPI> OnRegionHandShakeReply; 196 public event Action<IClientAPI> OnRegionHandShakeReply;
191 public event GenericCall1 OnRequestWearables; 197 public event GenericCall1 OnRequestWearables;
192 public event GenericCall1 OnCompleteMovementToRegion; 198 public event Action<IClientAPI, bool> OnCompleteMovementToRegion;
193 public event UpdateAgent OnPreAgentUpdate; 199 public event UpdateAgent OnPreAgentUpdate;
194 public event UpdateAgent OnAgentUpdate; 200 public event UpdateAgent OnAgentUpdate;
195 public event AgentRequestSit OnAgentRequestSit; 201 public event AgentRequestSit OnAgentRequestSit;
@@ -327,7 +333,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
327 public event ScriptReset OnScriptReset; 333 public event ScriptReset OnScriptReset;
328 public event GetScriptRunning OnGetScriptRunning; 334 public event GetScriptRunning OnGetScriptRunning;
329 public event SetScriptRunning OnSetScriptRunning; 335 public event SetScriptRunning OnSetScriptRunning;
330 public event UpdateVector OnAutoPilotGo; 336 public event Action<Vector3, bool> OnAutoPilotGo;
331 337
332 public event TerrainUnacked OnUnackedTerrain; 338 public event TerrainUnacked OnUnackedTerrain;
333 339
@@ -744,12 +750,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC
744 { 750 {
745 OnRegionHandShakeReply(this); 751 OnRegionHandShakeReply(this);
746 } 752 }
747
748 if (OnCompleteMovementToRegion != null)
749 {
750 OnCompleteMovementToRegion(this);
751 }
752 } 753 }
754
753 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) 755 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)
754 { 756 {
755 } 757 }
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
index 3cdd06d..2fdeeab 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs
@@ -44,32 +44,119 @@ namespace OpenSim.Region.OptionalModules.World.NPC
44 { 44 {
45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 45 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
46 46
47 // private const bool m_enabled = false; 47 private Dictionary<UUID, NPCAvatar> m_avatars = new Dictionary<UUID, NPCAvatar>();
48
49 private Dictionary<UUID,NPCAvatar> m_avatars = new Dictionary<UUID, NPCAvatar>();
50 private Dictionary<UUID,AvatarAppearance> m_appearanceCache = new Dictionary<UUID, AvatarAppearance>();
51 48
52 public void Initialise(Scene scene, IConfigSource source) 49 public void Initialise(Scene scene, IConfigSource source)
53 { 50 {
54 scene.RegisterModuleInterface<INPCModule>(this); 51 IConfig config = source.Configs["NPC"];
52
53 if (config != null && config.GetBoolean("Enabled", false))
54 {
55 scene.RegisterModuleInterface<INPCModule>(this);
56 scene.EventManager.OnSignificantClientMovement += HandleOnSignificantClientMovement;
57 }
55 } 58 }
56 59
57 private AvatarAppearance GetAppearance(UUID target, Scene scene) 60 public void HandleOnSignificantClientMovement(ScenePresence presence)
58 { 61 {
59 if (m_appearanceCache.ContainsKey(target)) 62 lock (m_avatars)
60 return m_appearanceCache[target];
61
62 AvatarAppearance appearance = scene.AvatarService.GetAppearance(target);
63 if (appearance != null)
64 { 63 {
65 m_appearanceCache.Add(target, appearance); 64 if (m_avatars.ContainsKey(presence.UUID) && presence.MovingToTarget)
66 return appearance; 65 {
66 double distanceToTarget = Util.GetDistanceTo(presence.AbsolutePosition, presence.MoveToPositionTarget);
67// m_log.DebugFormat(
68// "[NPC MODULE]: Abs pos of {0} is {1}, target {2}, distance {3}",
69// presence.Name, presence.AbsolutePosition, presence.MoveToPositionTarget, distanceToTarget);
70
71 // Check the error term of the current position in relation to the target position
72 if (distanceToTarget <= ScenePresence.SIGNIFICANT_MOVEMENT)
73 {
74 // We are close enough to the target
75 m_log.DebugFormat("[NPC MODULE]: Stopping movement of npc {0}", presence.Name);
76
77 presence.Velocity = Vector3.Zero;
78 presence.AbsolutePosition = presence.MoveToPositionTarget;
79 presence.ResetMoveToTarget();
80
81 if (presence.PhysicsActor.Flying)
82 {
83 // A horrible hack to stop the NPC dead in its tracks rather than having them overshoot
84 // the target if flying.
85 // We really need to be more subtle (slow the avatar as it approaches the target) or at
86 // least be able to set collision status once, rather than 5 times to give it enough
87 // weighting so that that PhysicsActor thinks it really is colliding.
88 for (int i = 0; i < 5; i++)
89 presence.PhysicsActor.IsColliding = true;
90
91// Vector3 targetPos = presence.MoveToPositionTarget;
92 if (m_avatars[presence.UUID].LandAtTarget)
93 presence.PhysicsActor.Flying = false;
94
95// float terrainHeight = (float)presence.Scene.Heightmap[(int)targetPos.X, (int)targetPos.Y];
96// if (targetPos.Z - terrainHeight < 0.2)
97// {
98// presence.PhysicsActor.Flying = false;
99// }
100 }
101
102// m_log.DebugFormat(
103// "[NPC MODULE]: AgentControlFlags {0}, MovementFlag {1} for {2}",
104// presence.AgentControlFlags, presence.MovementFlag, presence.Name);
105 }
106 else
107 {
108// m_log.DebugFormat(
109// "[NPC MODULE]: Updating npc {0} at {1} for next movement to {2}",
110// presence.Name, presence.AbsolutePosition, presence.MoveToPositionTarget);
111
112 Vector3 agent_control_v3 = new Vector3();
113 presence.HandleMoveToTargetUpdate(ref agent_control_v3);
114 presence.AddNewMovement(agent_control_v3);
115 }
116//
117//// presence.DoMoveToPositionUpdate((0, presence.MoveToPositionTarget, null);
118
119//
120//
121
122 }
67 } 123 }
124 }
125
126 public bool IsNPC(UUID agentId, Scene scene)
127 {
128 ScenePresence sp = scene.GetScenePresence(agentId);
129 if (sp == null || sp.IsChildAgent)
130 return false;
68 131
69 return new AvatarAppearance(); 132 lock (m_avatars)
133 return m_avatars.ContainsKey(agentId);
70 } 134 }
71 135
72 public UUID CreateNPC(string firstname, string lastname, Vector3 position, Scene scene, UUID cloneAppearanceFrom) 136 public bool SetNPCAppearance(UUID agentId, AvatarAppearance appearance, Scene scene)
137 {
138 ScenePresence sp = scene.GetScenePresence(agentId);
139 if (sp == null || sp.IsChildAgent)
140 return false;
141
142 lock (m_avatars)
143 if (!m_avatars.ContainsKey(agentId))
144 return false;
145
146 scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, false);
147
148 AvatarAppearance npcAppearance = new AvatarAppearance(appearance, true);
149 sp.Appearance = npcAppearance;
150 scene.AttachmentsModule.RezAttachments(sp);
151
152 IAvatarFactory module = scene.RequestModuleInterface<IAvatarFactory>();
153 module.SendAppearance(sp.UUID);
154
155 return true;
156 }
157
158 public UUID CreateNPC(
159 string firstname, string lastname, Vector3 position, Scene scene, AvatarAppearance appearance)
73 { 160 {
74 NPCAvatar npcAvatar = new NPCAvatar(firstname, lastname, position, scene); 161 NPCAvatar npcAvatar = new NPCAvatar(firstname, lastname, position, scene);
75 npcAvatar.CircuitCode = (uint)Util.RandomClass.Next(0, int.MaxValue); 162 npcAvatar.CircuitCode = (uint)Util.RandomClass.Next(0, int.MaxValue);
@@ -84,12 +171,18 @@ namespace OpenSim.Region.OptionalModules.World.NPC
84 acd.lastname = lastname; 171 acd.lastname = lastname;
85 acd.ServiceURLs = new Dictionary<string, object>(); 172 acd.ServiceURLs = new Dictionary<string, object>();
86 173
87 AvatarAppearance originalAppearance = GetAppearance(cloneAppearanceFrom, scene); 174 AvatarAppearance npcAppearance = new AvatarAppearance(appearance, true);
88 AvatarAppearance npcAppearance = new AvatarAppearance(originalAppearance, true);
89 acd.Appearance = npcAppearance; 175 acd.Appearance = npcAppearance;
90 176
177// for (int i = 0; i < acd.Appearance.Texture.FaceTextures.Length; i++)
178// {
179// m_log.DebugFormat(
180// "[NPC MODULE]: NPC avatar {0} has texture id {1} : {2}",
181// acd.AgentID, i, acd.Appearance.Texture.FaceTextures[i]);
182// }
183
91 scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode, acd); 184 scene.AuthenticateHandler.AddNewCircuit(npcAvatar.CircuitCode, acd);
92 scene.AddNewClient(npcAvatar); 185 scene.AddNewClient(npcAvatar, PresenceType.Npc);
93 186
94 ScenePresence sp; 187 ScenePresence sp;
95 if (scene.TryGetScenePresence(npcAvatar.AgentId, out sp)) 188 if (scene.TryGetScenePresence(npcAvatar.AgentId, out sp))
@@ -97,13 +190,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC
97 m_log.DebugFormat( 190 m_log.DebugFormat(
98 "[NPC MODULE]: Successfully retrieved scene presence for NPC {0} {1}", sp.Name, sp.UUID); 191 "[NPC MODULE]: Successfully retrieved scene presence for NPC {0} {1}", sp.Name, sp.UUID);
99 192
100 // Shouldn't call this - temporary. 193 sp.CompleteMovement(npcAvatar, false);
101 sp.CompleteMovement(npcAvatar);
102
103// sp.SendAppearanceToAllOtherAgents();
104//
105// // Send animations back to the avatar as well
106// sp.Animator.SendAnimPack();
107 } 194 }
108 else 195 else
109 { 196 {
@@ -118,7 +205,30 @@ namespace OpenSim.Region.OptionalModules.World.NPC
118 return npcAvatar.AgentId; 205 return npcAvatar.AgentId;
119 } 206 }
120 207
121 public void Autopilot(UUID agentID, Scene scene, Vector3 pos) 208 public bool MoveToTarget(UUID agentID, Scene scene, Vector3 pos, bool noFly, bool landAtTarget)
209 {
210 lock (m_avatars)
211 {
212 if (m_avatars.ContainsKey(agentID))
213 {
214 ScenePresence sp;
215 scene.TryGetScenePresence(agentID, out sp);
216
217 m_log.DebugFormat(
218 "[NPC MODULE]: Moving {0} to {1} in {2}, noFly {3}, landAtTarget {4}",
219 sp.Name, pos, scene.RegionInfo.RegionName, noFly, landAtTarget);
220
221 m_avatars[agentID].LandAtTarget = landAtTarget;
222 sp.MoveToTarget(pos, noFly);
223
224 return true;
225 }
226 }
227
228 return false;
229 }
230
231 public bool StopMoveToTarget(UUID agentID, Scene scene)
122 { 232 {
123 lock (m_avatars) 233 lock (m_avatars)
124 { 234 {
@@ -126,32 +236,49 @@ namespace OpenSim.Region.OptionalModules.World.NPC
126 { 236 {
127 ScenePresence sp; 237 ScenePresence sp;
128 scene.TryGetScenePresence(agentID, out sp); 238 scene.TryGetScenePresence(agentID, out sp);
129 sp.DoAutoPilot(0, pos, m_avatars[agentID]); 239
240 sp.Velocity = Vector3.Zero;
241 sp.ResetMoveToTarget();
242
243 return true;
130 } 244 }
131 } 245 }
246
247 return false;
132 } 248 }
133 249
134 public void Say(UUID agentID, Scene scene, string text) 250 public bool Say(UUID agentID, Scene scene, string text)
135 { 251 {
136 lock (m_avatars) 252 lock (m_avatars)
137 { 253 {
138 if (m_avatars.ContainsKey(agentID)) 254 if (m_avatars.ContainsKey(agentID))
139 { 255 {
256 ScenePresence sp;
257 scene.TryGetScenePresence(agentID, out sp);
258
140 m_avatars[agentID].Say(text); 259 m_avatars[agentID].Say(text);
260
261 return true;
141 } 262 }
142 } 263 }
264
265 return false;
143 } 266 }
144 267
145 public void DeleteNPC(UUID agentID, Scene scene) 268 public bool DeleteNPC(UUID agentID, Scene scene)
146 { 269 {
147 lock (m_avatars) 270 lock (m_avatars)
148 { 271 {
149 if (m_avatars.ContainsKey(agentID)) 272 if (m_avatars.ContainsKey(agentID))
150 { 273 {
151 scene.RemoveClient(agentID); 274 scene.RemoveClient(agentID, false);
152 m_avatars.Remove(agentID); 275 m_avatars.Remove(agentID);
276
277 return true;
153 } 278 }
154 } 279 }
280
281 return false;
155 } 282 }
156 283
157 public void PostInitialise() 284 public void PostInitialise()
diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
index 899e721..78296a4 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
@@ -27,11 +27,14 @@
27 27
28using System; 28using System;
29using System.Reflection; 29using System.Reflection;
30using log4net;
30using Nini.Config; 31using Nini.Config;
31using NUnit.Framework; 32using NUnit.Framework;
32using OpenMetaverse; 33using OpenMetaverse;
33using OpenSim.Framework; 34using OpenSim.Framework;
34using OpenSim.Framework.Communications; 35using OpenSim.Framework.Communications;
36using OpenSim.Region.CoreModules.Avatar.AvatarFactory;
37using OpenSim.Region.CoreModules.Framework.UserManagement;
35using OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar; 38using OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar;
36using OpenSim.Region.Framework.Interfaces; 39using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes; 40using OpenSim.Region.Framework.Scenes;
@@ -47,25 +50,112 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
47 [Test] 50 [Test]
48 public void TestCreate() 51 public void TestCreate()
49 { 52 {
50 TestHelper.InMethod(); 53 TestHelpers.InMethod();
51// log4net.Config.XmlConfigurator.Configure(); 54// log4net.Config.XmlConfigurator.Configure();
52 55
53 IConfigSource config = new IniConfigSource(); 56 IConfigSource config = new IniConfigSource();
57 config.AddConfig("NPC");
58 config.Configs["NPC"].Set("Enabled", "true");
54 59
55 config.AddConfig("Modules"); 60 AvatarFactoryModule afm = new AvatarFactoryModule();
56 config.Configs["Modules"].Set("AvatarServices", "LocalAvatarServicesConnector"); 61 UserManagementModule umm = new UserManagementModule();
57 config.AddConfig("AvatarService");
58 config.Configs["AvatarService"].Set("LocalServiceModule", "OpenSim.Services.AvatarService.dll:AvatarService");
59 config.Configs["AvatarService"].Set("StorageProvider", "OpenSim.Data.Null.dll");
60 62
61 TestScene scene = SceneSetupHelpers.SetupScene(); 63 TestScene scene = SceneHelpers.SetupScene();
62 SceneSetupHelpers.SetupSceneModules(scene, config, new NPCModule(), new LocalAvatarServicesConnector()); 64 SceneHelpers.SetupSceneModules(scene, config, afm, umm, new NPCModule());
65 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
66// ScenePresence originalAvatar = scene.GetScenePresence(originalClient.AgentId);
67
68 // 8 is the index of the first baked texture in AvatarAppearance
69 UUID originalFace8TextureId = TestHelpers.ParseTail(0x10);
70 Primitive.TextureEntry originalTe = new Primitive.TextureEntry(UUID.Zero);
71 Primitive.TextureEntryFace originalTef = originalTe.CreateFace(8);
72 originalTef.TextureID = originalFace8TextureId;
73
74 // We also need to add the texture to the asset service, otherwise the AvatarFactoryModule will tell
75 // ScenePresence.SendInitialData() to reset our entire appearance.
76 scene.AssetService.Store(AssetHelpers.CreateAsset(originalFace8TextureId));
77
78 afm.SetAppearanceFromClient(sp.ControllingClient, originalTe, null);
63 79
64 INPCModule npcModule = scene.RequestModuleInterface<INPCModule>(); 80 INPCModule npcModule = scene.RequestModuleInterface<INPCModule>();
65 UUID npcId = npcModule.CreateNPC("John", "Smith", new Vector3(128, 128, 30), scene, UUID.Zero); 81 UUID npcId = npcModule.CreateNPC("John", "Smith", new Vector3(128, 128, 30), scene, sp.Appearance);
66 82
67 ScenePresence npc = scene.GetScenePresence(npcId); 83 ScenePresence npc = scene.GetScenePresence(npcId);
84
68 Assert.That(npc, Is.Not.Null); 85 Assert.That(npc, Is.Not.Null);
86 Assert.That(npc.Appearance.Texture.FaceTextures[8].TextureID, Is.EqualTo(originalFace8TextureId));
87 Assert.That(umm.GetUserName(npc.UUID), Is.EqualTo(string.Format("{0} {1}", npc.Firstname, npc.Lastname)));
88 }
89
90 [Test]
91 public void TestMove()
92 {
93 TestHelpers.InMethod();
94// log4net.Config.XmlConfigurator.Configure();
95
96 IConfigSource config = new IniConfigSource();
97
98 config.AddConfig("NPC");
99 config.Configs["NPC"].Set("Enabled", "true");
100
101 TestScene scene = SceneHelpers.SetupScene();
102 SceneHelpers.SetupSceneModules(scene, config, new NPCModule());
103 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
104// ScenePresence originalAvatar = scene.GetScenePresence(originalClient.AgentId);
105
106 Vector3 startPos = new Vector3(128, 128, 30);
107 INPCModule npcModule = scene.RequestModuleInterface<INPCModule>();
108 UUID npcId = npcModule.CreateNPC("John", "Smith", startPos, scene, sp.Appearance);
109
110 ScenePresence npc = scene.GetScenePresence(npcId);
111 Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos));
112
113 // For now, we'll make the scene presence fly to simplify this test, but this needs to change.
114 npc.PhysicsActor.Flying = true;
115
116 scene.Update();
117 Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos));
118
119 Vector3 targetPos = startPos + new Vector3(0, 0, 10);
120 npcModule.MoveToTarget(npc.UUID, scene, targetPos, false, false);
121
122 Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos));
123
124 scene.Update();
125
126 // We should really check the exact figure.
127 Assert.That(npc.AbsolutePosition.X, Is.EqualTo(startPos.X));
128 Assert.That(npc.AbsolutePosition.Y, Is.EqualTo(startPos.Y));
129 Assert.That(npc.AbsolutePosition.Z, Is.GreaterThan(startPos.Z));
130 Assert.That(npc.AbsolutePosition.Z, Is.LessThan(targetPos.Z));
131
132 for (int i = 0; i < 10; i++)
133 scene.Update();
134
135 double distanceToTarget = Util.GetDistanceTo(npc.AbsolutePosition, targetPos);
136 Assert.That(distanceToTarget, Is.LessThan(1), "NPC not within 1 unit of target position on first move");
137 Assert.That(npc.AbsolutePosition, Is.EqualTo(targetPos));
138 Assert.That(npc.AgentControlFlags, Is.EqualTo((uint)AgentManager.ControlFlags.NONE));
139
140 // Try a second movement
141 startPos = npc.AbsolutePosition;
142 targetPos = startPos + new Vector3(10, 0, 0);
143 npcModule.MoveToTarget(npc.UUID, scene, targetPos, false, false);
144
145 scene.Update();
146
147 // We should really check the exact figure.
148 Assert.That(npc.AbsolutePosition.X, Is.GreaterThan(startPos.X));
149 Assert.That(npc.AbsolutePosition.X, Is.LessThan(targetPos.X));
150 Assert.That(npc.AbsolutePosition.Y, Is.EqualTo(startPos.Y));
151 Assert.That(npc.AbsolutePosition.Z, Is.EqualTo(startPos.Z));
152
153 for (int i = 0; i < 10; i++)
154 scene.Update();
155
156 distanceToTarget = Util.GetDistanceTo(npc.AbsolutePosition, targetPos);
157 Assert.That(distanceToTarget, Is.LessThan(1), "NPC not within 1 unit of target position on second move");
158 Assert.That(npc.AbsolutePosition, Is.EqualTo(targetPos));
69 } 159 }
70 } 160 }
71} \ No newline at end of file 161} \ No newline at end of file