aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/OpenSim.Region/World/World.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/OpenSim.Region/World/World.cs')
-rw-r--r--OpenSim/OpenSim.Region/World/World.cs634
1 files changed, 634 insertions, 0 deletions
diff --git a/OpenSim/OpenSim.Region/World/World.cs b/OpenSim/OpenSim.Region/World/World.cs
new file mode 100644
index 0000000..c5c554d
--- /dev/null
+++ b/OpenSim/OpenSim.Region/World/World.cs
@@ -0,0 +1,634 @@
1using System;
2using libsecondlife;
3using libsecondlife.Packets;
4using System.Collections.Generic;
5using System.Text;
6using System.Reflection;
7using System.IO;
8using System.Threading;
9using System.Timers;
10using OpenSim.Physics.Manager;
11using OpenSim.Framework.Interfaces;
12using OpenSim.Framework.Types;
13using OpenSim.Framework.Inventory;
14using OpenSim.Framework;
15using OpenSim.Region.Scripting;
16using OpenSim.Terrain;
17using OpenGrid.Framework.Communications;
18using OpenSim.Region.Estate;
19
20
21namespace OpenSim.Region
22{
23 public partial class World : WorldBase, ILocalStorageReceiver, IScriptAPI
24 {
25 protected System.Timers.Timer m_heartbeatTimer = new System.Timers.Timer();
26 protected Dictionary<libsecondlife.LLUUID, Avatar> Avatars;
27 protected Dictionary<libsecondlife.LLUUID, Primitive> Prims;
28 private PhysicsScene phyScene;
29 private float timeStep = 0.1f;
30 public ILocalStorage localStorage;
31 private Random Rand = new Random();
32 private uint _primCount = 702000;
33 private int storageCount;
34 private Dictionary<LLUUID, ScriptHandler> m_scriptHandlers;
35 private Dictionary<string, ScriptFactory> m_scripts;
36 private Mutex updateLock;
37 public string m_datastore;
38 protected AuthenticateSessionsBase authenticateHandler;
39 protected RegionCommsHostBase regionCommsHost;
40 protected RegionServerCommsManager commsManager;
41
42 public ParcelManager parcelManager;
43 public EstateManager estateManager;
44
45 #region Properties
46 /// <summary>
47 ///
48 /// </summary>
49 public PhysicsScene PhysScene
50 {
51 set
52 {
53 this.phyScene = value;
54 }
55 get
56 {
57 return (this.phyScene);
58 }
59 }
60
61 #endregion
62
63 #region Constructors
64 /// <summary>
65 /// Creates a new World class, and a region to go with it.
66 /// </summary>
67 /// <param name="clientThreads">Dictionary to contain client threads</param>
68 /// <param name="regionHandle">Region Handle for this region</param>
69 /// <param name="regionName">Region Name for this region</param>
70 public World(Dictionary<uint, IClientAPI> clientThreads, RegionInfo regInfo, AuthenticateSessionsBase authen, RegionServerCommsManager commsMan)
71 {
72 try
73 {
74 updateLock = new Mutex(false);
75 this.authenticateHandler = authen;
76 this.commsManager = commsMan;
77 m_clientThreads = clientThreads;
78 m_regInfo = regInfo;
79 m_regionHandle = m_regInfo.RegionHandle;
80 m_regionName = m_regInfo.RegionName;
81 this.m_datastore = m_regInfo.DataStore;
82 this.RegisterRegionWithComms();
83
84 parcelManager = new ParcelManager(this, this.m_regInfo);
85 estateManager = new EstateManager(this, this.m_regInfo);
86
87 m_scriptHandlers = new Dictionary<LLUUID, ScriptHandler>();
88 m_scripts = new Dictionary<string, ScriptFactory>();
89
90 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.LOW, "World.cs - creating new entitities instance");
91 Entities = new Dictionary<libsecondlife.LLUUID, Entity>();
92 Avatars = new Dictionary<LLUUID, Avatar>();
93 Prims = new Dictionary<LLUUID, Primitive>();
94
95 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.LOW, "World.cs - creating LandMap");
96 TerrainManager = new TerrainManager(new SecondLife());
97 Terrain = new TerrainEngine();
98 Avatar.SetupTemplate("avatar-texture.dat");
99
100 Avatar.LoadAnims();
101
102 //this.SetDefaultScripts();
103 //this.LoadScriptEngines();
104
105
106 }
107 catch (Exception e)
108 {
109 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.CRITICAL, "World.cs: Constructor failed with exception " + e.ToString());
110 }
111 }
112 #endregion
113
114 /// <summary>
115 ///
116 /// </summary>
117 public void StartTimer()
118 {
119 m_heartbeatTimer.Enabled = true;
120 m_heartbeatTimer.Interval = 100;
121 m_heartbeatTimer.Elapsed += new ElapsedEventHandler(this.Heartbeat);
122 }
123
124
125 #region Update Methods
126
127
128 /// <summary>
129 /// Performs per-frame updates regularly
130 /// </summary>
131 /// <param name="sender"></param>
132 /// <param name="e"></param>
133 void Heartbeat(object sender, System.EventArgs e)
134 {
135 this.Update();
136 }
137
138 /// <summary>
139 /// Performs per-frame updates on the world, this should be the central world loop
140 /// </summary>
141 public override void Update()
142 {
143 updateLock.WaitOne();
144 try
145 {
146 if (this.phyScene.IsThreaded)
147 {
148 this.phyScene.GetResults();
149
150 }
151
152 foreach (libsecondlife.LLUUID UUID in Entities.Keys)
153 {
154 Entities[UUID].addForces();
155 }
156
157 lock (this.m_syncRoot)
158 {
159 this.phyScene.Simulate(timeStep);
160 }
161
162 foreach (libsecondlife.LLUUID UUID in Entities.Keys)
163 {
164 Entities[UUID].update();
165 }
166
167 foreach (ScriptHandler scriptHandler in m_scriptHandlers.Values)
168 {
169 scriptHandler.OnFrame();
170 }
171 foreach (IScriptEngine scripteng in this.scriptEngines.Values)
172 {
173 scripteng.OnFrame();
174 }
175 //backup world data
176 this.storageCount++;
177 if (storageCount > 1200) //set to how often you want to backup
178 {
179 this.Backup();
180 storageCount = 0;
181 }
182 }
183 catch (Exception e)
184 {
185 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.MEDIUM, "World.cs: Update() - Failed with exception " + e.ToString());
186 }
187 updateLock.ReleaseMutex();
188 }
189
190 /// <summary>
191 ///
192 /// </summary>
193 /// <returns></returns>
194 public bool Backup()
195 {
196 try
197 {
198 // Terrain backup routines
199 if (Terrain.tainted > 0)
200 {
201 Terrain.tainted = 0;
202 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.LOW, "World.cs: Backup() - Terrain tainted, saving.");
203 localStorage.SaveMap(Terrain.getHeights1D());
204 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.LOW, "World.cs: Backup() - Terrain saved, informing Physics.");
205 lock (this.m_syncRoot)
206 {
207 phyScene.SetTerrain(Terrain.getHeights1D());
208 }
209 }
210
211 // Primitive backup routines
212 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.LOW, "World.cs: Backup() - Backing up Primitives");
213 foreach (libsecondlife.LLUUID UUID in Entities.Keys)
214 {
215 Entities[UUID].BackUp();
216 }
217
218 //Parcel backup routines
219 ParcelData[] parcels = new ParcelData[parcelManager.parcelList.Count];
220 int i = 0;
221 foreach (OpenSim.Region.Parcel parcel in parcelManager.parcelList.Values)
222 {
223 parcels[i] = parcel.parcelData;
224 i++;
225 }
226 localStorage.SaveParcels(parcels);
227
228 // Backup successful
229 return true;
230 }
231 catch (Exception e)
232 {
233 // Backup failed
234 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.HIGH, "World.cs: Backup() - Backup Failed with exception " + e.ToString());
235 return false;
236 }
237 }
238 #endregion
239
240 #region Setup Methods
241 /// <summary>
242 /// Loads a new storage subsystem from a named library
243 /// </summary>
244 /// <param name="dllName">Storage Library</param>
245 /// <returns>Successful or not</returns>
246 public bool LoadStorageDLL(string dllName)
247 {
248 try
249 {
250 Assembly pluginAssembly = Assembly.LoadFrom(dllName);
251 ILocalStorage store = null;
252
253 foreach (Type pluginType in pluginAssembly.GetTypes())
254 {
255 if (pluginType.IsPublic)
256 {
257 if (!pluginType.IsAbstract)
258 {
259 Type typeInterface = pluginType.GetInterface("ILocalStorage", true);
260
261 if (typeInterface != null)
262 {
263 ILocalStorage plug = (ILocalStorage)Activator.CreateInstance(pluginAssembly.GetType(pluginType.ToString()));
264 store = plug;
265
266 store.Initialise(this.m_datastore);
267 break;
268 }
269
270 typeInterface = null;
271 }
272 }
273 }
274 pluginAssembly = null;
275 this.localStorage = store;
276 return (store == null);
277 }
278 catch (Exception e)
279 {
280 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.MEDIUM, "World.cs: LoadStorageDLL() - Failed with exception " + e.ToString());
281 return false;
282 }
283 }
284
285 #endregion
286
287
288 #region Regenerate Terrain
289
290 /// <summary>
291 /// Rebuilds the terrain using a procedural algorithm
292 /// </summary>
293 public void RegenerateTerrain()
294 {
295 try
296 {
297 Terrain.hills();
298
299 lock (this.m_syncRoot)
300 {
301 this.phyScene.SetTerrain(Terrain.getHeights1D());
302 }
303 this.localStorage.SaveMap(this.Terrain.getHeights1D());
304
305 foreach (IClientAPI client in m_clientThreads.Values)
306 {
307 this.SendLayerData(client);
308 }
309
310 foreach (libsecondlife.LLUUID UUID in Entities.Keys)
311 {
312 Entities[UUID].LandRenegerated();
313 }
314 }
315 catch (Exception e)
316 {
317 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.MEDIUM, "World.cs: RegenerateTerrain() - Failed with exception " + e.ToString());
318 }
319 }
320
321 /// <summary>
322 /// Rebuilds the terrain using a 2D float array
323 /// </summary>
324 /// <param name="newMap">256,256 float array containing heights</param>
325 public void RegenerateTerrain(float[,] newMap)
326 {
327 try
328 {
329 this.Terrain.setHeights2D(newMap);
330 lock (this.m_syncRoot)
331 {
332 this.phyScene.SetTerrain(this.Terrain.getHeights1D());
333 }
334 this.localStorage.SaveMap(this.Terrain.getHeights1D());
335
336 foreach (IClientAPI client in m_clientThreads.Values)
337 {
338 this.SendLayerData(client);
339 }
340
341 foreach (libsecondlife.LLUUID UUID in Entities.Keys)
342 {
343 Entities[UUID].LandRenegerated();
344 }
345 }
346 catch (Exception e)
347 {
348 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.MEDIUM, "World.cs: RegenerateTerrain() - Failed with exception " + e.ToString());
349 }
350 }
351
352 /// <summary>
353 /// Rebuilds the terrain assuming changes occured at a specified point[?]
354 /// </summary>
355 /// <param name="changes">???</param>
356 /// <param name="pointx">???</param>
357 /// <param name="pointy">???</param>
358 public void RegenerateTerrain(bool changes, int pointx, int pointy)
359 {
360 try
361 {
362 if (changes)
363 {
364 /* Dont save here, rely on tainting system instead */
365
366 foreach (IClientAPI client in m_clientThreads.Values)
367 {
368 this.SendLayerData(pointx, pointy, client);
369 }
370 }
371 }
372 catch (Exception e)
373 {
374 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.MEDIUM, "World.cs: RegenerateTerrain() - Failed with exception " + e.ToString());
375 }
376 }
377
378 #endregion
379
380 #region Load Terrain
381 /// <summary>
382 /// Loads the World heightmap
383 /// </summary>
384 public override void LoadWorldMap()
385 {
386 try
387 {
388 float[] map = this.localStorage.LoadWorld();
389 if (map == null)
390 {
391 Console.WriteLine("creating new terrain");
392 this.Terrain.hills();
393
394 this.localStorage.SaveMap(this.Terrain.getHeights1D());
395 }
396 else
397 {
398 this.Terrain.setHeights1D(map);
399 }
400 }
401 catch (Exception e)
402 {
403 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.MEDIUM, "World.cs: LoadWorldMap() - Failed with exception " + e.ToString());
404 }
405 }
406 #endregion
407
408 #region Primitives Methods
409
410
411 /// <summary>
412 /// Loads the World's objects
413 /// </summary>
414 public void LoadPrimsFromStorage()
415 {
416 try
417 {
418 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.LOW, "World.cs: LoadPrimsFromStorage() - Loading primitives");
419 this.localStorage.LoadPrimitives(this);
420 }
421 catch (Exception e)
422 {
423 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.MEDIUM, "World.cs: LoadPrimsFromStorage() - Failed with exception " + e.ToString());
424 }
425 }
426
427 /// <summary>
428 /// Loads a specific object from storage
429 /// </summary>
430 /// <param name="prim">The object to load</param>
431 public void PrimFromStorage(PrimData prim)
432 {
433
434 }
435
436 /// <summary>
437 ///
438 /// </summary>
439 /// <param name="addPacket"></param>
440 /// <param name="agentClient"></param>
441 public void AddNewPrim(Packet addPacket, IClientAPI agentClient)
442 {
443 AddNewPrim((ObjectAddPacket)addPacket, agentClient.AgentId);
444 }
445
446 /// <summary>
447 ///
448 /// </summary>
449 /// <param name="addPacket"></param>
450 /// <param name="ownerID"></param>
451 public void AddNewPrim(ObjectAddPacket addPacket, LLUUID ownerID)
452 {
453
454 }
455
456 #endregion
457
458 #region Add/Remove Avatar Methods
459
460 /// <summary>
461 ///
462 /// </summary>
463 /// <param name="remoteClient"></param
464 /// <param name="agentID"></param>
465 /// <param name="child"></param>
466 public override void AddNewAvatar(IClientAPI remoteClient, LLUUID agentID, bool child)
467 {
468 remoteClient.OnRegionHandShakeReply += new GenericCall(this.SendLayerData);
469 //remoteClient.OnRequestWearables += new GenericCall(this.GetInitialPrims);
470 remoteClient.OnChatFromViewer += new ChatFromViewer(this.SimChat);
471 remoteClient.OnRequestWearables += new GenericCall(this.InformClientOfNeighbours);
472
473 Avatar newAvatar = null;
474 try
475 {
476 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.LOW, "World.cs:AddViewerAgent() - Creating new avatar for remote viewer agent");
477 newAvatar = new Avatar(remoteClient, this, m_clientThreads, this.m_regInfo);
478 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.LOW, "World.cs:AddViewerAgent() - Adding new avatar to world");
479 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.LOW, "World.cs:AddViewerAgent() - Starting RegionHandshake ");
480
481 //newAvatar.SendRegionHandshake();
482 this.estateManager.sendRegionHandshake(remoteClient);
483
484 PhysicsVector pVec = new PhysicsVector(newAvatar.Pos.X, newAvatar.Pos.Y, newAvatar.Pos.Z);
485 lock (this.m_syncRoot)
486 {
487 newAvatar.PhysActor = this.phyScene.AddAvatar(pVec);
488 }
489
490 lock (Entities)
491 {
492 if (!Entities.ContainsKey(agentID))
493 {
494 this.Entities.Add(agentID, newAvatar);
495 }
496 else
497 {
498 Entities[agentID] = newAvatar;
499 }
500 }
501 lock (Avatars)
502 {
503 if (Avatars.ContainsKey(agentID))
504 {
505 Avatars[agentID] = newAvatar;
506 }
507 else
508 {
509 this.Avatars.Add(agentID, newAvatar);
510 }
511 }
512 }
513 catch (Exception e)
514 {
515 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.MEDIUM, "World.cs: AddViewerAgent() - Failed with exception " + e.ToString());
516 }
517 return;
518 }
519
520 /// <summary>
521 ///
522 /// </summary>
523 protected void InformClientOfNeighbours(IClientAPI remoteClient)
524 {
525 // Console.WriteLine("informing client of neighbouring regions");
526 List<RegionInfo> neighbours = this.commsManager.RequestNeighbours(this.m_regInfo);
527
528 //Console.WriteLine("we have " + neighbours.Count + " neighbouring regions");
529 if (neighbours != null)
530 {
531 for (int i = 0; i < neighbours.Count; i++)
532 {
533 // Console.WriteLine("sending neighbours data");
534 AgentCircuitData agent = remoteClient.RequestClientInfo();
535 agent.BaseFolder = LLUUID.Zero;
536 agent.InventoryFolder = LLUUID.Zero;
537 agent.startpos = new LLVector3(128, 128, 70);
538 this.commsManager.InformNeighbourOfChildAgent(neighbours[i].RegionHandle, agent);
539 remoteClient.InformClientOfNeighbour(neighbours[i].RegionHandle, System.Net.IPAddress.Parse(neighbours[i].IPListenAddr), (ushort)neighbours[i].IPListenPort);
540 }
541 }
542 }
543
544 /// <summary>
545 ///
546 /// </summary>
547 /// <param name="agentID"></param>
548 public override void RemoveAvatar(LLUUID agentID)
549 {
550 return;
551 }
552 #endregion
553
554 #region Request Avatars List Methods
555 //The idea is to have a group of method that return a list of avatars meeting some requirement
556 // ie it could be all Avatars within a certain range of the calling prim/avatar.
557
558 /// <summary>
559 /// Request a List of all Avatars in this World
560 /// </summary>
561 /// <returns></returns>
562 public List<Avatar> RequestAvatarList()
563 {
564 List<Avatar> result = new List<Avatar>();
565
566 foreach (Avatar avatar in Avatars.Values)
567 {
568 result.Add(avatar);
569 }
570
571 return result;
572 }
573 #endregion
574
575 #region ShutDown
576 /// <summary>
577 /// Tidy before shutdown
578 /// </summary>
579 public override void Close()
580 {
581 try
582 {
583 this.localStorage.ShutDown();
584 }
585 catch (Exception e)
586 {
587 OpenSim.Framework.Console.MainConsole.Instance.WriteLine(OpenSim.Framework.Console.LogPriority.HIGH, "World.cs: Close() - Failed with exception " + e.ToString());
588 }
589 }
590 #endregion
591
592 #region RegionCommsHost
593
594 /// <summary>
595 ///
596 /// </summary>
597 public void RegisterRegionWithComms()
598 {
599 this.regionCommsHost = this.commsManager.RegisterRegion(this.m_regInfo);
600 if (this.regionCommsHost != null)
601 {
602 this.regionCommsHost.OnExpectUser += new ExpectUserDelegate(this.NewUserConnection);
603 }
604 }
605
606 /// <summary>
607 ///
608 /// </summary>
609 /// <param name="regionHandle"></param>
610 /// <param name="agent"></param>
611 public void NewUserConnection(ulong regionHandle, AgentCircuitData agent)
612 {
613 // Console.WriteLine("World.cs - add new user connection");
614 //should just check that its meant for this region
615 if (regionHandle == this.m_regInfo.RegionHandle)
616 {
617 this.authenticateHandler.AddNewCircuit(agent.circuitcode, agent);
618 }
619 }
620
621 #endregion
622
623 /// <summary>
624 ///
625 /// </summary>
626 /// <param name="px"></param>
627 /// <param name="py"></param>
628 /// <param name="RemoteClient"></param>
629 public override void SendLayerData(int px, int py, IClientAPI RemoteClient)
630 {
631 RemoteClient.SendLayerData( Terrain.getHeights1D() );
632 }
633 }
634}