diff --git a/Programs/Simian.Tests/SceneManagerTests.cs b/Programs/Simian.Tests/SceneManagerTests.cs index ffd06761..a685a76d 100644 --- a/Programs/Simian.Tests/SceneManagerTests.cs +++ b/Programs/Simian.Tests/SceneManagerTests.cs @@ -3,17 +3,14 @@ using System.Threading; using OpenMetaverse; using OpenMetaverse.Packets; using ExtensionLoader; -using Simian; -using Simian.Extensions; using NUnit.Framework; -namespace SimianTests +namespace Simian.Tests { [TestFixture(Description = "Simian.Extensions.SceneManager")] public class SceneManagerTest { - Simian.Simian simian; - SceneManager sceneManager; + Simian simian; Random rand = new Random(); Agent agent; Agent observer; @@ -21,25 +18,20 @@ namespace SimianTests [SetUp] public void Start() { - simian = new Simian.Simian(); - simian.UDP = new UDPManager(); - (simian.UDP as IExtension).Start(simian); - sceneManager = new SceneManager(); - simian.Scene = sceneManager; - sceneManager.Start(simian); + simian = new Simian(); + simian.Start(); agent = CreateDummyAgent(); - simian.Scene.AgentAdd(this, agent, PrimFlags.None); + simian.Scenes[0].AgentAdd(this, agent, PrimFlags.None); observer = CreateDummyAgent(); - simian.Scene.AgentAdd(this, observer, PrimFlags.None); + simian.Scenes[0].AgentAdd(this, observer, PrimFlags.None); } [TearDown] public void Stop() { - sceneManager.Stop(); - (simian.UDP as IExtension).Stop(); + simian.Stop(); } [Test] @@ -74,11 +66,11 @@ namespace SimianTests } ); - simian.UDP.OnOutgoingPacket += callback; - sceneManager.AgentAppearance(this, agent, textures, visualParams); + simian.Scenes[0].UDP.OnOutgoingPacket += callback; + simian.Scenes[0].AgentAppearance(this, agent, textures, visualParams); Assert.IsTrue(callbackEvent.WaitOne(1000, false), "Timed out waiting for callback"); - simian.UDP.OnOutgoingPacket -= callback; + simian.Scenes[0].UDP.OnOutgoingPacket -= callback; Assert.That(receivedAgentID == agent.ID, "Agent ID mismatch"); @@ -97,7 +89,11 @@ namespace SimianTests Agent CreateDummyAgent() { - Agent agent = new Agent(new SimulationObject(new Avatar(), simian)); + AgentInfo info = new AgentInfo(); + info.FirstName = "Dummy"; + info.LastName = "Agent"; + + Agent agent = new Agent(new SimulationObject(new Avatar(), simian.Scenes[0]), info); agent.Avatar.Prim.ID = UUID.Random(); agent.SessionID = UUID.Random(); agent.Avatar.Prim.Position = new Vector3(128f, 128f, 40f); diff --git a/Programs/Simian/Agent.cs b/Programs/Simian/Agent.cs index 278bb7eb..99f8baf5 100644 --- a/Programs/Simian/Agent.cs +++ b/Programs/Simian/Agent.cs @@ -7,9 +7,10 @@ using OpenMetaverse.Packets; namespace Simian { - public class Agent + public class AgentInfo { // Account + public UUID ID; public string FirstName; public string LastName; public string PasswordHash; @@ -28,10 +29,6 @@ namespace Simian public ulong HomeRegionHandle; public Vector3 HomePosition; public Vector3 HomeLookAt; - public Vector3 CurrentLookAt; - public UUID RequestedSitTarget; - public Vector3 RequestedSitOffset; - public ulong CurrentRegionHandle; // Profile public UUID PartnerID; @@ -62,32 +59,27 @@ namespace Simian public UUID UndershirtItem; public UUID UnderpantsItem; public UUID SkirtItem; + } - // Temporary - [NonSerialized] + public class Agent + { + public AgentInfo Info; public SimulationObject Avatar; - [NonSerialized] public UUID SessionID; - [NonSerialized] public UUID SecureSessionID; - [NonSerialized] public uint CircuitCode; - [NonSerialized] public bool Running; - [NonSerialized] public int TickFall; - [NonSerialized] public int TickJump; - [NonSerialized] public int TickLastPacketReceived; - [NonSerialized] public AgentManager.ControlFlags ControlFlags = AgentManager.ControlFlags.NONE; - [NonSerialized] public AnimationSet Animations = new AnimationSet(); - [NonSerialized] public AgentState State; - [NonSerialized] public bool HideTitle; + public Uri SeedCapability; + public Vector3 CurrentLookAt; + public UUID RequestedSitTarget; + public Vector3 RequestedSitOffset; public UUID ID { @@ -98,23 +90,24 @@ namespace Simian { get { - bool hasFirst = !String.IsNullOrEmpty(FirstName); - bool hasLast = !String.IsNullOrEmpty(LastName); + bool hasFirst = !String.IsNullOrEmpty(Info.FirstName); + bool hasLast = !String.IsNullOrEmpty(Info.LastName); if (hasFirst && hasLast) - return String.Format("{0} {1}", FirstName, LastName); + return String.Format("{0} {1}", Info.FirstName, Info.LastName); else if (hasFirst) - return FirstName; + return Info.FirstName; else if (hasLast) - return LastName; + return Info.LastName; else return String.Empty; } } - public Agent(SimulationObject avatar) + public Agent(SimulationObject avatar, AgentInfo info) { Avatar = avatar; + Info = info; } } } diff --git a/Programs/Simian/Archiving/OarFile.cs b/Programs/Simian/Archiving/OarFile.cs index e5c6e062..fe45b0d8 100644 --- a/Programs/Simian/Archiving/OarFile.cs +++ b/Programs/Simian/Archiving/OarFile.cs @@ -53,7 +53,7 @@ namespace Simian archive.Close(); } - public static void SavePrims(Simian server, string primsPath, string assetsPath, string textureCacheFolder) + public static void SavePrims(ISceneProvider scene, string primsPath, string assetsPath, string textureCacheFolder) { Dictionary textureList = new Dictionary(); @@ -71,7 +71,7 @@ namespace Simian // Copy the double dictionary to a temporary list for iterating List primList = new List(); - server.Scene.ForEachObject(delegate(SimulationObject prim) + scene.ForEachObject(delegate(SimulationObject prim) { if (!(prim.Prim is Avatar)) primList.Add(prim); diff --git a/Programs/Simian/Extensions/AccountManager.cs b/Programs/Simian/Extensions/AccountManager.cs index fb0e2f6a..1d4c7dc8 100644 --- a/Programs/Simian/Extensions/AccountManager.cs +++ b/Programs/Simian/Extensions/AccountManager.cs @@ -4,49 +4,46 @@ using ExtensionLoader; using OpenMetaverse; using OpenMetaverse.StructuredData; -namespace Simian.Extensions +namespace Simian { public class AccountManager : IExtension, IAccountProvider, IPersistable { Simian server; - DoubleDictionary accounts = new DoubleDictionary(); + DoubleDictionary accounts = new DoubleDictionary(); public AccountManager() { } - public void Start(Simian server) + public bool Start(Simian server) { this.server = server; + return true; } public void Stop() { } - public void AddAccount(Agent agent) + public void AddAccount(AgentInfo agent) { - accounts.Add(agent.FullName, agent.ID, agent); + accounts.Add(agent.FirstName + " " + agent.LastName, agent.ID, agent); } public bool RemoveAccount(UUID agentID) { - Agent agent; + AgentInfo agent; if (accounts.TryGetValue(agentID, out agent)) - return accounts.Remove(agent.FullName, agentID); + return accounts.Remove(agent.FirstName + " " + agent.LastName, agentID); else return false; } - public Agent CreateInstance(UUID agentID) + public AgentInfo CreateInstance(UUID agentID) { - Agent agent; + AgentInfo agent; if (accounts.TryGetValue(agentID, out agent)) { - // Random session IDs - agent.SessionID = UUID.Random(); - agent.SecureSessionID = UUID.Random(); - return agent; } else @@ -57,12 +54,12 @@ namespace Simian.Extensions } } - public bool TryGetAccount(UUID agentID, out Agent agent) + public bool TryGetAccount(UUID agentID, out AgentInfo agent) { return accounts.TryGetValue(agentID, out agent); } - public bool TryGetAccount(string fullName, out Agent agent) + public bool TryGetAccount(string fullName, out AgentInfo agent) { return accounts.TryGetValue(fullName, out agent); } @@ -73,10 +70,9 @@ namespace Simian.Extensions { OSDArray array = new OSDArray(accounts.Count); - accounts.ForEach(delegate(Agent agent) + accounts.ForEach(delegate(AgentInfo agent) { OSDMap agentMap = OSD.SerializeMembers(agent); - agentMap["AgentID"] = OSD.FromUUID(agent.ID); array.Add(agentMap); }); @@ -94,17 +90,14 @@ namespace Simian.Extensions for (int i = 0; i < array.Count; i++) { - Avatar avatar = new Avatar(); - SimulationObject obj = new SimulationObject(avatar, server); - Agent agent = new Agent(obj); - object agentRef = (object)agent; OSDMap map = array[i] as OSDMap; + + AgentInfo agentInfo = new AgentInfo(); + object agentRef = (object)agentInfo; OSD.DeserializeMembers(ref agentRef, map); - agent = (Agent)agentRef; + agentInfo = (AgentInfo)agentRef; - agent.Avatar.Prim.ID = map["AgentID"].AsUUID(); - - accounts.Add(agent.FullName, agent.ID, agent); + accounts.Add(agentInfo.FirstName + " " + agentInfo.LastName, agentInfo.ID, agentInfo); } Logger.Log(String.Format("Deserialized the agent store with {0} entries", accounts.Count), diff --git a/Programs/Simian/Extensions/AssetManager.cs b/Programs/Simian/Extensions/AssetManager.cs index 40496110..4a359057 100644 --- a/Programs/Simian/Extensions/AssetManager.cs +++ b/Programs/Simian/Extensions/AssetManager.cs @@ -5,7 +5,7 @@ using ExtensionLoader; using OpenMetaverse; using OpenMetaverse.Imaging; -namespace Simian.Extensions +namespace Simian { public class AssetManager : IExtension, IAssetProvider { @@ -17,7 +17,7 @@ namespace Simian.Extensions { } - public void Start(Simian server) + public bool Start(Simian server) { this.server = server; @@ -27,16 +27,25 @@ namespace Simian.Extensions if (!Directory.Exists(Simian.DATA_DIR)) { try { Directory.CreateDirectory(Simian.DATA_DIR); } - catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Warning, ex); } + catch (Exception ex) + { + Logger.Log(ex.Message, Helpers.LogLevel.Error, ex); + return false; + } } if (!Directory.Exists(UploadDir)) { try { Directory.CreateDirectory(UploadDir); } - catch (Exception ex) { Logger.Log(ex.Message, Helpers.LogLevel.Warning, ex); } + catch (Exception ex) + { + Logger.Log(ex.Message, Helpers.LogLevel.Error, ex); + return false; + } } LoadAssets(Simian.DATA_DIR); LoadAssets(UploadDir); + return true; } public void Stop() diff --git a/Programs/Simian/Extensions/AuthFreeForAll.cs b/Programs/Simian/Extensions/AuthFreeForAll.cs index a86b38ab..7de961c9 100644 --- a/Programs/Simian/Extensions/AuthFreeForAll.cs +++ b/Programs/Simian/Extensions/AuthFreeForAll.cs @@ -2,7 +2,7 @@ using System; using ExtensionLoader; using OpenMetaverse; -namespace Simian.Extensions +namespace Simian { public class AuthFreeForAll : IExtension, IAuthenticationProvider { @@ -12,9 +12,10 @@ namespace Simian.Extensions { } - public void Start(Simian server) + public bool Start(Simian server) { this.server = server; + return true; } public void Stop() @@ -23,87 +24,83 @@ namespace Simian.Extensions public UUID Authenticate(string firstName, string lastName, string password) { + AgentInfo agentInfo; + ISceneProvider scene = server.Grid.GetDefaultLocalScene(); string fullName = String.Format("{0} {1}", firstName, lastName); - Agent agent; - if (!server.Accounts.TryGetAccount(fullName, out agent)) + if (!server.Accounts.TryGetAccount(fullName, out agentInfo)) { // Account doesn't exist, create it now - Avatar avatar = new Avatar(); - SimulationObject obj = new SimulationObject(avatar, server); - agent = new Agent(obj); - agent.AccessLevel = "M"; - agent.Avatar.Prim.ID = UUID.Random(); - agent.Balance = 1000; - agent.CreationTime = Utils.DateTimeToUnixTime(DateTime.Now); - agent.CurrentLookAt = Vector3.UnitZ; - agent.Avatar.Prim.Position = new Vector3(128f, 128f, 25f); - agent.CurrentRegionHandle = Utils.UIntsToLong(256 * server.Scene.RegionX, 256 * server.Scene.RegionY); - agent.FirstName = firstName; - agent.GodLevel = 0; - agent.HomeLookAt = agent.CurrentLookAt; - agent.HomePosition = agent.Avatar.Prim.Position; - agent.HomeRegionHandle = agent.CurrentRegionHandle; - agent.LastName = lastName; - agent.PasswordHash = password; + agentInfo = new AgentInfo(); + agentInfo.AccessLevel = "M"; + agentInfo.ID = UUID.Random(); + agentInfo.Balance = 1000; + agentInfo.CreationTime = Utils.DateTimeToUnixTime(DateTime.Now); + agentInfo.FirstName = firstName; + agentInfo.GodLevel = 0; + agentInfo.HomeLookAt = scene.DefaultLookAt; + agentInfo.HomePosition = scene.DefaultPosition; + agentInfo.HomeRegionHandle = scene.RegionHandle; + agentInfo.LastName = lastName; + agentInfo.PasswordHash = password; // Create a very basic inventory skeleton UUID rootFolder = UUID.Random(); - server.Inventory.CreateRootFolder(agent.ID, rootFolder, "Inventory", agent.ID); + server.Inventory.CreateRootFolder(agentInfo.ID, rootFolder, "Inventory", agentInfo.ID); UUID libraryRootFolder = UUID.Random(); - server.Inventory.CreateRootFolder(agent.ID, libraryRootFolder, "Library", agent.ID); + server.Inventory.CreateRootFolder(agentInfo.ID, libraryRootFolder, "Library", agentInfo.ID); - agent.InventoryRoot = rootFolder; - agent.InventoryLibraryOwner = agent.ID; - agent.InventoryLibraryRoot = libraryRootFolder; + agentInfo.InventoryRoot = rootFolder; + agentInfo.InventoryLibraryOwner = agentInfo.ID; + agentInfo.InventoryLibraryRoot = libraryRootFolder; // Create some inventory items for appearance UUID clothingFolder = UUID.Random(); - server.Inventory.CreateFolder(agent.ID, clothingFolder, "Clothing", AssetType.Clothing, - agent.InventoryRoot, agent.ID); + server.Inventory.CreateFolder(agentInfo.ID, clothingFolder, "Clothing", AssetType.Clothing, + agentInfo.InventoryRoot, agentInfo.ID); UUID defaultOutfitFolder = UUID.Random(); - server.Inventory.CreateFolder(agent.ID, defaultOutfitFolder, "Default Outfit", AssetType.Unknown, - clothingFolder, agent.ID); + server.Inventory.CreateFolder(agentInfo.ID, defaultOutfitFolder, "Default Outfit", AssetType.Unknown, + clothingFolder, agentInfo.ID); UUID hairAsset = new UUID("dc675529-7ba5-4976-b91d-dcb9e5e36188"); - UUID hairItem = server.Inventory.CreateItem(agent.ID, "Default Hair", "Default Hair", + UUID hairItem = server.Inventory.CreateItem(agentInfo.ID, "Default Hair", "Default Hair", InventoryType.Wearable, AssetType.Bodypart, hairAsset, defaultOutfitFolder, - PermissionMask.All, PermissionMask.All, agent.ID, agent.ID, UUID.Random(), 0, false); + PermissionMask.All, PermissionMask.All, agentInfo.ID, agentInfo.ID, UUID.Random(), 0).ID; UUID pantsAsset = new UUID("3e8ee2d6-4f21-4a55-832d-77daa505edff"); - UUID pantsItem = server.Inventory.CreateItem(agent.ID, "Default Pants", "Default Pants", + UUID pantsItem = server.Inventory.CreateItem(agentInfo.ID, "Default Pants", "Default Pants", InventoryType.Wearable, AssetType.Clothing, pantsAsset, defaultOutfitFolder, - PermissionMask.All, PermissionMask.All, agent.ID, agent.ID, UUID.Random(), 0, false); + PermissionMask.All, PermissionMask.All, agentInfo.ID, agentInfo.ID, UUID.Random(), 0).ID; UUID shapeAsset = new UUID("530a2614-052e-49a2-af0e-534bb3c05af0"); - UUID shapeItem = server.Inventory.CreateItem(agent.ID, "Default Shape", "Default Shape", + UUID shapeItem = server.Inventory.CreateItem(agentInfo.ID, "Default Shape", "Default Shape", InventoryType.Wearable, AssetType.Clothing, shapeAsset, defaultOutfitFolder, - PermissionMask.All, PermissionMask.All, agent.ID, agent.ID, UUID.Random(), 0, false); + PermissionMask.All, PermissionMask.All, agentInfo.ID, agentInfo.ID, UUID.Random(), 0).ID; UUID shirtAsset = new UUID("6a714f37-fe53-4230-b46f-8db384465981"); - UUID shirtItem = server.Inventory.CreateItem(agent.ID, "Default Shirt", "Default Shirt", + UUID shirtItem = server.Inventory.CreateItem(agentInfo.ID, "Default Shirt", "Default Shirt", InventoryType.Wearable, AssetType.Clothing, shirtAsset, defaultOutfitFolder, - PermissionMask.All, PermissionMask.All, agent.ID, agent.ID, UUID.Random(), 0, false); + PermissionMask.All, PermissionMask.All, agentInfo.ID, agentInfo.ID, UUID.Random(), 0).ID; UUID skinAsset = new UUID("5f787f25-f761-4a35-9764-6418ee4774c4"); - UUID skinItem = server.Inventory.CreateItem(agent.ID, "Default Skin", "Default Skin", + UUID skinItem = server.Inventory.CreateItem(agentInfo.ID, "Default Skin", "Default Skin", InventoryType.Wearable, AssetType.Clothing, skinAsset, defaultOutfitFolder, - PermissionMask.All, PermissionMask.All, agent.ID, agent.ID, UUID.Random(), 0, false); + PermissionMask.All, PermissionMask.All, agentInfo.ID, agentInfo.ID, UUID.Random(), 0).ID; UUID eyesAsset = new UUID("78d20332-9b07-44a2-bf74-3b368605f4b5"); - UUID eyesItem = server.Inventory.CreateItem(agent.ID, "Default Eyes", "Default Eyes", + UUID eyesItem = server.Inventory.CreateItem(agentInfo.ID, "Default Eyes", "Default Eyes", InventoryType.Wearable, AssetType.Bodypart, eyesAsset, defaultOutfitFolder, - PermissionMask.All, PermissionMask.All, agent.ID, agent.ID, UUID.Random(), 0, false); + PermissionMask.All, PermissionMask.All, agentInfo.ID, agentInfo.ID, UUID.Random(), 0).ID; - agent.HairItem = hairItem; - agent.PantsItem = pantsItem; - agent.ShapeItem = shapeItem; - agent.ShirtItem = shirtItem; - agent.SkinItem = skinItem; - agent.EyesItem = eyesItem; + agentInfo.HairItem = hairItem; + agentInfo.PantsItem = pantsItem; + agentInfo.ShapeItem = shapeItem; + agentInfo.ShirtItem = shirtItem; + agentInfo.SkinItem = skinItem; + agentInfo.EyesItem = eyesItem; - server.Accounts.AddAccount(agent); + server.Accounts.AddAccount(agentInfo); Logger.Log("Created new account for " + fullName, Helpers.LogLevel.Info); } - if (password == agent.PasswordHash) - return agent.ID; + if (password == agentInfo.PasswordHash) + return agentInfo.ID; else return UUID.Zero; } diff --git a/Programs/Simian/Extensions/CapsManager.cs b/Programs/Simian/Extensions/CapsManager.cs index 3bc79940..9657ff13 100644 --- a/Programs/Simian/Extensions/CapsManager.cs +++ b/Programs/Simian/Extensions/CapsManager.cs @@ -7,7 +7,7 @@ using OpenMetaverse; using OpenMetaverse.Http; using OpenMetaverse.StructuredData; -namespace Simian.Extensions +namespace Simian { public class CapsManager : IExtension, ICapabilitiesProvider { @@ -18,11 +18,12 @@ namespace Simian.Extensions { } - public void Start(Simian server) + public bool Start(Simian server) { this.server = server; capsServer = new CapsServer(server.HttpServer, @"^/caps/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"); capsServer.Start(); + return true; } public void Stop() @@ -34,21 +35,13 @@ namespace Simian.Extensions public Uri CreateCapability(CapsRequestCallback localHandler, bool clientCertRequired, object state) { UUID capID = capsServer.CreateCapability(localHandler, clientCertRequired, state); - return new Uri( - (server.SSL ? "https://" : "http://") + - server.HostName + - (server.HttpPort == 80 ? String.Empty : ":" + server.HttpPort) + - "/caps/" + capID.ToString()); + return new Uri(server.HttpUri, "/caps/" + capID.ToString()); } public Uri CreateCapability(Uri remoteHandler, bool clientCertRequired) { UUID capID = capsServer.CreateCapability(remoteHandler, clientCertRequired); - return new Uri( - (server.SSL ? "https://" : "http://") + - server.HostName + - (server.HttpPort == 80 ? String.Empty : ":" + server.HttpPort) + - "/caps/" + capID.ToString()); + return new Uri(server.HttpUri, "/caps/" + capID.ToString()); } public bool RemoveCapability(Uri cap) diff --git a/Programs/Simian/Extensions/GridLocal.cs b/Programs/Simian/Extensions/GridLocal.cs new file mode 100644 index 00000000..097eeee1 --- /dev/null +++ b/Programs/Simian/Extensions/GridLocal.cs @@ -0,0 +1,70 @@ +using System; +using ExtensionLoader; +using OpenMetaverse; + +namespace Simian +{ + public class GridLocal : IExtension, IGridProvider + { + Simian server; + + public GridLocal() + { + } + + public bool Start(Simian server) + { + this.server = server; + return true; + } + + public void Stop() + { + } + + public bool TryRegisterGridSpace(RegionInfo region, out UUID regionID) + { + regionID = UUID.Zero; + return false; + } + + public bool TryRegisterAnyGridSpace(RegionInfo region, bool isolated, out UUID regionID) + { + regionID = UUID.Zero; + return false; + } + + public bool UnregisterGridSpace(RegionInfo region) + { + return false; + } + + public void RegionUpdate(RegionInfo region) + { + } + + public void RegionHeartbeat(RegionInfo region) + { + } + + public bool TryGetRegion(UUID regionID, out RegionInfo region) + { + region = null; + return false; + } + + public bool TryGetRegion(uint x, uint y, out RegionInfo region) + { + region = null; + return false; + } + + public ISceneProvider GetDefaultLocalScene() + { + if (server.Scenes.Count > 0) + return server.Scenes[0]; + else + return null; + } + } +} diff --git a/Programs/Simian/Extensions/InventoryManager.cs b/Programs/Simian/Extensions/InventoryManager.cs index 1dc07021..65e644af 100644 --- a/Programs/Simian/Extensions/InventoryManager.cs +++ b/Programs/Simian/Extensions/InventoryManager.cs @@ -5,7 +5,7 @@ using OpenMetaverse; using OpenMetaverse.StructuredData; using OpenMetaverse.Packets; -namespace Simian.Extensions +namespace Simian { public class InventoryManager : IExtension, IInventoryProvider, IPersistable { @@ -14,620 +14,23 @@ namespace Simian.Extensions /// is also a dictionary itself Dictionary> Inventory = new Dictionary>(); - /// Global shared inventory for all agent + /// Global shared inventory for all agents Dictionary Library = new Dictionary(); public InventoryManager() { } - public void Start(Simian server) + public bool Start(Simian server) { this.server = server; - - server.UDP.RegisterPacketCallback(PacketType.CreateInventoryItem, new PacketCallback(CreateInventoryItemHandler)); - server.UDP.RegisterPacketCallback(PacketType.CreateInventoryFolder, new PacketCallback(CreateInventoryFolderHandler)); - server.UDP.RegisterPacketCallback(PacketType.UpdateInventoryItem, new PacketCallback(UpdateInventoryItemHandler)); - server.UDP.RegisterPacketCallback(PacketType.FetchInventoryDescendents, new PacketCallback(FetchInventoryDescendentsHandler)); - server.UDP.RegisterPacketCallback(PacketType.FetchInventory, new PacketCallback(FetchInventoryHandler)); - server.UDP.RegisterPacketCallback(PacketType.CopyInventoryItem, new PacketCallback(CopyInventoryItemHandler)); - server.UDP.RegisterPacketCallback(PacketType.MoveInventoryItem, new PacketCallback(MoveInventoryItemHandler)); - server.UDP.RegisterPacketCallback(PacketType.MoveInventoryFolder, new PacketCallback(MoveInventoryFolderHandler)); - server.UDP.RegisterPacketCallback(PacketType.PurgeInventoryDescendents, new PacketCallback(PurgeInventoryDescendentsHandler)); + return true; } public void Stop() { } - Dictionary GetAgentInventory(UUID agentID) - { - Dictionary agentInventory; - if (!Inventory.TryGetValue(agentID, out agentInventory)) - { - Logger.Log("Creating an empty inventory store for agent " + agentID.ToString(), - Helpers.LogLevel.Info); - - agentInventory = new Dictionary(); - lock (Inventory) - Inventory[agentID] = agentInventory; - } - - return agentInventory; - } - - void CreateInventoryItemHandler(Packet packet, Agent agent) - { - CreateInventoryItemPacket create = (CreateInventoryItemPacket)packet; - UUID assetID; - if (create.InventoryBlock.TransactionID != UUID.Zero) - assetID = UUID.Combine(create.InventoryBlock.TransactionID, agent.SecureSessionID); - else - assetID = UUID.Random(); - - UUID parentID = (create.InventoryBlock.FolderID != UUID.Zero) ? create.InventoryBlock.FolderID : agent.InventoryRoot; - AssetType assetType = (AssetType)create.InventoryBlock.Type; - - switch (assetType) - { - case AssetType.Gesture: - Logger.Log("Need to create a default gesture asset!", Helpers.LogLevel.Warning); - break; - } - - if (parentID == UUID.Zero) - parentID = agent.InventoryRoot; - - // Create the inventory item - CreateItem(agent.ID, Utils.BytesToString(create.InventoryBlock.Name), "Created in Simian", - (InventoryType)create.InventoryBlock.InvType, assetType, assetID, parentID, - PermissionMask.All, (PermissionMask)create.InventoryBlock.NextOwnerMask, agent.ID, - agent.ID, create.InventoryBlock.TransactionID, create.InventoryBlock.CallbackID, true); - } - - void CreateInventoryFolderHandler(Packet packet, Agent agent) - { - CreateInventoryFolderPacket create = (CreateInventoryFolderPacket)packet; - - UUID folderID = create.FolderData.FolderID; - if (folderID == UUID.Zero) - folderID = agent.InventoryRoot; - - CreateFolder(agent.ID, folderID, Utils.BytesToString(create.FolderData.Name), - (AssetType)create.FolderData.Type, create.FolderData.ParentID, agent.ID); - } - - void UpdateInventoryItemHandler(Packet packet, Agent agent) - { - UpdateInventoryItemPacket update = (UpdateInventoryItemPacket)packet; - - // No packet is sent back to the client, we just need to update the - // inventory item locally - for (int i = 0; i < update.InventoryData.Length; i++) - { - UpdateInventoryItemPacket.InventoryDataBlock block = update.InventoryData[i]; - Dictionary agentInventory = GetAgentInventory(agent.ID); - - InventoryObject obj; - if (agentInventory.TryGetValue(block.ItemID, out obj) && obj is InventoryItem) - { - InventoryItem item = (InventoryItem)obj; - - //item.Permissions.BaseMask = (PermissionMask)block.BaseMask; - item.Permissions.BaseMask = PermissionMask.All; - //item.Permissions.EveryoneMask = (PermissionMask)block.EveryoneMask; - item.Permissions.EveryoneMask = PermissionMask.All; - //item.Permissions.GroupMask = (PermissionMask)block.GroupMask; - item.Permissions.GroupMask = PermissionMask.All; - //item.Permissions.NextOwnerMask = (PermissionMask)block.NextOwnerMask; - item.Permissions.NextOwnerMask = PermissionMask.All; - //item.Permissions.OwnerMask = (PermissionMask)block.OwnerMask; - item.Permissions.OwnerMask = PermissionMask.All; - - //block.CRC; - item.CreationDate = Utils.UnixTimeToDateTime(block.CreationDate); - item.CreatorID = block.CreatorID; - item.Name = Utils.BytesToString(block.Description); - item.Flags = block.Flags; - item.ParentID = block.FolderID; - item.GroupID = block.GroupID; - item.GroupOwned = block.GroupOwned; - item.InventoryType = (InventoryType)block.InvType; - item.Name = Utils.BytesToString(block.Name); - item.OwnerID = block.OwnerID; - item.SalePrice = block.SalePrice; - item.SaleType = (SaleType)block.SaleType; - item.AssetType = (AssetType)block.Type; - item.AssetID = UUID.Combine(block.TransactionID, agent.SecureSessionID); - - Logger.DebugLog(String.Format( - "UpdateInventoryItem: CallbackID: {0}, TransactionID: {1}", - block.CallbackID, block.TransactionID)); - } - else - { - Logger.Log("Received an UpdateInventoryItem packet for unknown inventory item " + - block.ItemID.ToString(), Helpers.LogLevel.Warning); - } - } - } - - void FetchInventoryDescendentsHandler(Packet packet, Agent agent) - { - // A very safe estimate of the fixed minimum packet size - const int PACKET_OVERHEAD = 96; - - FetchInventoryDescendentsPacket fetch = (FetchInventoryDescendentsPacket)packet; - bool sendFolders = fetch.InventoryData.FetchFolders; - bool sendItems = fetch.InventoryData.FetchItems; - // TODO: Obey SortOrder - //InventorySortOrder order = (InventorySortOrder)fetch.InventoryData.SortOrder; - - Dictionary agentInventory = GetAgentInventory(agent.ID); - - // TODO: Use OwnerID - // TODO: Do we need to obey InventorySortOrder? - InventoryObject invObject; - if (agentInventory.TryGetValue(fetch.InventoryData.FolderID, out invObject) && invObject is InventoryFolder) - { - InventoryFolder folder = (InventoryFolder)invObject; - - int descendCount; - int version; - - List items = new List(); - List folders = new List(); - InventoryDescendentsPacket.FolderDataBlock[] folderBlocks; - InventoryDescendentsPacket.ItemDataBlock[] itemBlocks; - - lock (folder.Children.Dictionary) - { - // These two are coupled to the actual items in the dictionary, - // so they are set inside the lock - descendCount = folder.Children.Count; - version = folder.Version; - - if (sendItems || sendFolders) - { - // Create a list of all of the folders and items under this folder - folder.Children.ForEach( - delegate(InventoryObject obj) - { - if (obj is InventoryItem) - items.Add((InventoryItem)obj); - else - folders.Add((InventoryFolder)obj); - } - ); - } - } - - if (sendFolders) - { - folderBlocks = new InventoryDescendentsPacket.FolderDataBlock[folders.Count]; - for (int i = 0; i < folders.Count; i++) - { - InventoryFolder currentFolder = folders[i]; - - folderBlocks[i] = new InventoryDescendentsPacket.FolderDataBlock(); - folderBlocks[i].FolderID = currentFolder.ID; - folderBlocks[i].Name = Utils.StringToBytes(currentFolder.Name); - folderBlocks[i].ParentID = currentFolder.ParentID; - folderBlocks[i].Type = (sbyte)currentFolder.PreferredType; - } - } - else - { - folderBlocks = new InventoryDescendentsPacket.FolderDataBlock[0]; - } - - if (sendItems) - { - itemBlocks = new InventoryDescendentsPacket.ItemDataBlock[items.Count]; - for (int i = 0; i < items.Count; i++) - { - InventoryItem currentItem = items[i]; - - itemBlocks[i] = new InventoryDescendentsPacket.ItemDataBlock(); - itemBlocks[i].AssetID = currentItem.AssetID; - itemBlocks[i].BaseMask = (uint)currentItem.Permissions.BaseMask; - itemBlocks[i].CRC = currentItem.CRC; - itemBlocks[i].CreationDate = (int)Utils.DateTimeToUnixTime(currentItem.CreationDate); - itemBlocks[i].CreatorID = currentItem.CreatorID; - itemBlocks[i].Description = Utils.StringToBytes(currentItem.Description); - itemBlocks[i].EveryoneMask = (uint)currentItem.Permissions.EveryoneMask; - itemBlocks[i].Flags = currentItem.Flags; - itemBlocks[i].FolderID = currentItem.ParentID; - itemBlocks[i].GroupID = currentItem.GroupID; - itemBlocks[i].GroupMask = (uint)currentItem.Permissions.GroupMask; - itemBlocks[i].GroupOwned = currentItem.GroupOwned; - itemBlocks[i].InvType = (sbyte)currentItem.InventoryType; - itemBlocks[i].ItemID = currentItem.ID; - itemBlocks[i].Name = Utils.StringToBytes(currentItem.Name); - itemBlocks[i].NextOwnerMask = (uint)currentItem.Permissions.NextOwnerMask; - itemBlocks[i].OwnerID = currentItem.OwnerID; - itemBlocks[i].OwnerMask = (uint)currentItem.Permissions.OwnerMask; - itemBlocks[i].SalePrice = currentItem.SalePrice; - itemBlocks[i].SaleType = (byte)currentItem.SaleType; - itemBlocks[i].Type = (sbyte)currentItem.AssetType; - } - } - else - { - itemBlocks = new InventoryDescendentsPacket.ItemDataBlock[0]; - } - - // FolderDataBlock and ItemDataBlock are both variable and possibly very large, - // so we handle the splitting separately. This could be replaced by some custom - // splitting - if (folderBlocks.Length > 0) - { - List splitPoints = Helpers.SplitBlocks(folderBlocks, PACKET_OVERHEAD); - Logger.DebugLog(String.Format("Sending {0} InventoryDescendents packets containing {1} folders", - splitPoints.Count, folderBlocks.Length)); - - for (int i = 0; i < splitPoints.Count; i++) - { - int count = (i != splitPoints.Count - 1) ? splitPoints[i + 1] - splitPoints[i] : - folderBlocks.Length - splitPoints[i]; - - InventoryDescendentsPacket descendents = new InventoryDescendentsPacket(); - descendents.AgentData.AgentID = agent.ID; - descendents.AgentData.FolderID = folder.ID; - descendents.AgentData.OwnerID = folder.OwnerID; - descendents.AgentData.Descendents = descendCount; - descendents.AgentData.Version = version; - descendents.FolderData = new InventoryDescendentsPacket.FolderDataBlock[count]; - descendents.ItemData = new InventoryDescendentsPacket.ItemDataBlock[0]; - - for (int j = 0; j < count; j++) - descendents.FolderData[j] = folderBlocks[splitPoints[i] + j]; - - server.UDP.SendPacket(agent.ID, descendents, PacketCategory.Inventory); - } - } - else - { - Logger.DebugLog("Sending a single InventoryDescendents for folders"); - - InventoryDescendentsPacket descendents = new InventoryDescendentsPacket(); - descendents.AgentData.AgentID = agent.ID; - descendents.AgentData.FolderID = folder.ID; - descendents.AgentData.OwnerID = folder.OwnerID; - descendents.AgentData.Descendents = descendCount; - descendents.AgentData.Version = version; - descendents.FolderData = new InventoryDescendentsPacket.FolderDataBlock[0]; - descendents.ItemData = new InventoryDescendentsPacket.ItemDataBlock[0]; - - server.UDP.SendPacket(agent.ID, descendents, PacketCategory.Inventory); - } - - if (itemBlocks.Length > 0) - { - List splitPoints = Helpers.SplitBlocks(itemBlocks, PACKET_OVERHEAD); - Logger.DebugLog(String.Format("Sending {0} InventoryDescendents packets containing {1} items", - splitPoints.Count, itemBlocks.Length)); - - for (int i = 0; i < splitPoints.Count; i++) - { - int count = (i != splitPoints.Count - 1) ? splitPoints[i + 1] - splitPoints[i] : - itemBlocks.Length - splitPoints[i]; - - InventoryDescendentsPacket descendents = new InventoryDescendentsPacket(); - descendents.AgentData.AgentID = agent.ID; - descendents.AgentData.FolderID = folder.ID; - descendents.AgentData.OwnerID = folder.OwnerID; - descendents.AgentData.Descendents = descendCount; - descendents.AgentData.Version = version; - descendents.FolderData = new InventoryDescendentsPacket.FolderDataBlock[0]; - descendents.ItemData = new InventoryDescendentsPacket.ItemDataBlock[count]; - - for (int j = 0; j < count; j++) - descendents.ItemData[j] = itemBlocks[splitPoints[i] + j]; - - server.UDP.SendPacket(agent.ID, descendents, PacketCategory.Inventory); - } - } - } - else - { - Logger.Log("FetchInventoryDescendents called for an unknown folder " + fetch.InventoryData.FolderID, - Helpers.LogLevel.Warning); - } - } - - void FetchInventoryHandler(Packet packet, Agent agent) - { - // This is probably too large, but better to be on the safe side - const int PACKET_OVERHEAD = 32; - - FetchInventoryPacket fetch = (FetchInventoryPacket)packet; - - // Create all of the blocks first. These will be split up into different packets - FetchInventoryReplyPacket.InventoryDataBlock[] blocks = - new FetchInventoryReplyPacket.InventoryDataBlock[fetch.InventoryData.Length]; - - for (int i = 0; i < fetch.InventoryData.Length; i++) - { - UUID itemID = fetch.InventoryData[i].ItemID; - Dictionary agentInventory = GetAgentInventory(agent.ID); - - blocks[i] = new FetchInventoryReplyPacket.InventoryDataBlock(); - blocks[i].ItemID = itemID; - - InventoryObject obj; - if (agentInventory.TryGetValue(itemID, out obj) && obj is InventoryItem) - { - InventoryItem item = (InventoryItem)obj; - - blocks[i].AssetID = item.AssetID; - blocks[i].BaseMask = (uint)item.Permissions.BaseMask; - blocks[i].CRC = item.CRC; - blocks[i].CreationDate = (int)Utils.DateTimeToUnixTime(item.CreationDate); - blocks[i].CreatorID = item.CreatorID; - blocks[i].Description = Utils.StringToBytes(item.Description); - blocks[i].EveryoneMask = (uint)item.Permissions.EveryoneMask; - blocks[i].Flags = item.Flags; - blocks[i].FolderID = item.ParentID; - blocks[i].GroupID = item.GroupID; - blocks[i].GroupMask = (uint)item.Permissions.GroupMask; - blocks[i].GroupOwned = item.GroupOwned; - blocks[i].InvType = (sbyte)item.InventoryType; - blocks[i].Name = Utils.StringToBytes(item.Name); - blocks[i].NextOwnerMask = (uint)item.Permissions.NextOwnerMask; - blocks[i].OwnerID = item.OwnerID; - blocks[i].OwnerMask = (uint)item.Permissions.OwnerMask; - blocks[i].SalePrice = item.SalePrice; - blocks[i].SaleType = (byte)item.SaleType; - blocks[i].Type = (sbyte)item.AssetType; - } - else - { - Logger.Log("FetchInventory called for an unknown item " + itemID.ToString(), - Helpers.LogLevel.Warning); - - blocks[i].Name = Utils.EmptyBytes; - blocks[i].Description = Utils.EmptyBytes; - } - } - - // Split the blocks up into multiple packets - List splitPoints = Helpers.SplitBlocks(blocks, PACKET_OVERHEAD); - for (int i = 0; i < splitPoints.Count; i++) - { - int count = (i != splitPoints.Count - 1) ? splitPoints[i + 1] - splitPoints[i] : - blocks.Length - splitPoints[i]; - - FetchInventoryReplyPacket reply = new FetchInventoryReplyPacket(); - reply.AgentData.AgentID = agent.ID; - reply.InventoryData = new FetchInventoryReplyPacket.InventoryDataBlock[count]; - - for (int j = 0; j < count; j++) - reply.InventoryData[j] = blocks[splitPoints[i] + j]; - - server.UDP.SendPacket(agent.ID, reply, PacketCategory.Inventory); - } - } - - void CopyInventoryItemHandler(Packet packet, Agent agent) - { - CopyInventoryItemPacket copy = (CopyInventoryItemPacket)packet; - - for (int i = 0; i < copy.InventoryData.Length; i++) - { - CopyInventoryItemPacket.InventoryDataBlock block = copy.InventoryData[i]; - - // TODO: This allows someone to copy objects from another - // agent's inventory. Should we allow that, or do any - // permission checks? - Dictionary agentInventory = GetAgentInventory(block.OldAgentID); - - // Get the original object - InventoryObject obj; - if (agentInventory.TryGetValue(block.OldItemID, out obj) && obj is InventoryItem) - { - InventoryItem item = (InventoryItem)obj; - - // Get the new folder - InventoryObject folderObj; - if (agentInventory.TryGetValue(block.NewFolderID, out folderObj) && folderObj is InventoryFolder) - { - string newName = Utils.BytesToString(block.NewName); - if (String.IsNullOrEmpty(newName)) - newName = item.Name; - - // Create the copy - CreateItem(agent.ID, newName, item.Description, item.InventoryType, item.AssetType, - item.AssetID, folderObj.ID, item.Permissions.OwnerMask, item.Permissions.NextOwnerMask, - agent.ID, item.CreatorID, UUID.Zero, block.CallbackID, true); - } - else - { - Logger.Log("CopyInventoryItem called with an unknown target folder " + block.NewFolderID, - Helpers.LogLevel.Warning); - } - - } - else - { - Logger.Log("CopyInventoryItem called for an unknown item " + block.OldItemID, - Helpers.LogLevel.Warning); - } - } - } - - void MoveInventoryItemHandler(Packet packet, Agent agent) - { - MoveInventoryItemPacket move = (MoveInventoryItemPacket)packet; - // TODO: What is move.AgentData.Stamp for? - - Dictionary agentInventory = GetAgentInventory(agent.ID); - - for (int i = 0; i < move.InventoryData.Length; i++) - { - MoveInventoryItemPacket.InventoryDataBlock block = move.InventoryData[i]; - UUID newFolderID = block.FolderID; - if (newFolderID == UUID.Zero) - newFolderID = agent.InventoryRoot; - MoveInventory(agent, agentInventory, block.ItemID, newFolderID, Utils.BytesToString(block.NewName), - UUID.Zero, 0); - } - } - - void MoveInventoryFolderHandler(Packet packet, Agent agent) - { - MoveInventoryFolderPacket move = (MoveInventoryFolderPacket)packet; - // TODO: What is move.AgentData.Stamp for? - - Dictionary agentInventory = GetAgentInventory(agent.ID); - - for (int i = 0; i < move.InventoryData.Length; i++) - { - MoveInventoryFolderPacket.InventoryDataBlock block = move.InventoryData[i]; - UUID newFolderID = block.ParentID; - if (newFolderID == UUID.Zero) - newFolderID = agent.InventoryRoot; - MoveInventory(agent, agentInventory, block.FolderID, newFolderID, null, UUID.Zero, 0); - } - } - - void SendBulkUpdate(Agent agent, InventoryObject obj, UUID transactionID, uint callbackID) - { - BulkUpdateInventoryPacket update = new BulkUpdateInventoryPacket(); - update.AgentData.AgentID = agent.ID; - update.AgentData.TransactionID = transactionID; - - if (obj is InventoryItem) - { - InventoryItem item = (InventoryItem)obj; - - update.FolderData = new BulkUpdateInventoryPacket.FolderDataBlock[0]; - update.ItemData = new BulkUpdateInventoryPacket.ItemDataBlock[1]; - update.ItemData[0] = new BulkUpdateInventoryPacket.ItemDataBlock(); - update.ItemData[0].AssetID = item.AssetID; - update.ItemData[0].BaseMask = (uint)item.Permissions.BaseMask; - update.ItemData[0].CallbackID = callbackID; - update.ItemData[0].CRC = item.CRC; - update.ItemData[0].CreationDate = (int)Utils.DateTimeToUnixTime(item.CreationDate); - update.ItemData[0].CreatorID = item.CreatorID; - update.ItemData[0].Description = Utils.StringToBytes(item.Description); - update.ItemData[0].EveryoneMask = (uint)item.Permissions.EveryoneMask; - update.ItemData[0].Flags = item.Flags; - update.ItemData[0].FolderID = item.ParentID; - update.ItemData[0].GroupID = item.GroupID; - update.ItemData[0].GroupMask = (uint)item.Permissions.GroupMask; - update.ItemData[0].GroupOwned = item.GroupOwned; - update.ItemData[0].InvType = (sbyte)item.InventoryType; - update.ItemData[0].ItemID = item.ID; - update.ItemData[0].Name = Utils.StringToBytes(item.Name); - update.ItemData[0].NextOwnerMask = (uint)item.Permissions.NextOwnerMask; - update.ItemData[0].OwnerID = item.OwnerID; - update.ItemData[0].OwnerMask = (uint)item.Permissions.OwnerMask; - update.ItemData[0].SalePrice = item.SalePrice; - update.ItemData[0].SaleType = (byte)item.SaleType; - update.ItemData[0].Type = (sbyte)item.InventoryType; - } - else - { - InventoryFolder folder = (InventoryFolder)obj; - - update.ItemData = new BulkUpdateInventoryPacket.ItemDataBlock[0]; - update.FolderData = new BulkUpdateInventoryPacket.FolderDataBlock[1]; - update.FolderData[0] = new BulkUpdateInventoryPacket.FolderDataBlock(); - update.FolderData[0].FolderID = folder.ID; - update.FolderData[0].Name = Utils.StringToBytes(folder.Name); - update.FolderData[0].ParentID = folder.ParentID; - update.FolderData[0].Type = (sbyte)folder.PreferredType; - } - - Logger.DebugLog("Sending bulk update for inventory object " + obj.ID); - - server.UDP.SendPacket(agent.ID, update, PacketCategory.Inventory); - } - - void MoveInventory(Agent agent, Dictionary agentInventory, UUID objectID, - UUID newFolderID, string newName, UUID transactionID, uint callbackID) - { - InventoryObject obj; - if (agentInventory.TryGetValue(objectID, out obj)) - { - lock (agentInventory) - { - InventoryObject newParentObj; - if (agentInventory.TryGetValue(newFolderID, out newParentObj) && newParentObj is InventoryFolder) - { - // Remove this item from the current parent - if (obj.Parent != null) - { - InventoryFolder parent = (InventoryFolder)obj.Parent; - lock (parent.Children.Dictionary) - parent.Children.Dictionary.Remove(obj.ID); - } - - // Update the new parent - InventoryFolder newParent = (InventoryFolder)newParentObj; - newParent.Children.Dictionary[obj.ID] = obj; - - // Update the object - obj.ParentID = newParent.ID; - obj.Parent = newParent; - if (!String.IsNullOrEmpty(newName)) - obj.Name = newName; - } - else - { - Logger.Log("MoveInventory called with an unknown destination folder " + newFolderID, - Helpers.LogLevel.Warning); - } - - SendBulkUpdate(agent, obj, transactionID, callbackID); - } - } - else - { - Logger.Log("MoveInventory called for an unknown object " + objectID, - Helpers.LogLevel.Warning); - } - } - - void PurgeInventoryDescendentsHandler(Packet packet, Agent agent) - { - PurgeInventoryDescendentsPacket purge = (PurgeInventoryDescendentsPacket)packet; - - Dictionary agentInventory = GetAgentInventory(agent.ID); - - InventoryObject obj; - if (agentInventory.TryGetValue(purge.InventoryData.FolderID, out obj) && obj is InventoryFolder) - { - lock (agentInventory) - PurgeFolder(agentInventory, (InventoryFolder)obj); - } - else - { - Logger.Log("PurgeInventoryDescendents called on a missing folder " + purge.InventoryData.FolderID, - Helpers.LogLevel.Warning); - } - } - - void PurgeFolder(Dictionary inventory, InventoryFolder folder) - { - folder.Children.ForEach( - delegate(InventoryObject child) - { - inventory.Remove(child.ID); - - if (child is InventoryFolder) - { - InventoryFolder childFolder = (InventoryFolder)child; - PurgeFolder(inventory, childFolder); - } - } - ); - - lock (folder.Children.Dictionary) - folder.Children.Dictionary.Clear(); - } - public bool CreateRootFolder(UUID agentID, UUID folderID, string name, UUID ownerID) { Dictionary agentInventory = GetAgentInventory(agentID); @@ -710,9 +113,9 @@ namespace Simian.Extensions return false; } - public UUID CreateItem(UUID agentID, string name, string description, InventoryType invType, AssetType type, + public InventoryItem CreateItem(UUID agentID, string name, string description, InventoryType invType, AssetType type, UUID assetID, UUID parentID, PermissionMask ownerMask, PermissionMask nextOwnerMask, UUID ownerID, - UUID creatorID, UUID transactionID, uint callbackID, bool sendPacket) + UUID creatorID, UUID transactionID, uint callbackID) { Dictionary agentInventory = GetAgentInventory(agentID); @@ -752,43 +155,7 @@ namespace Simian.Extensions lock (parentFolder.Children.Dictionary) parentFolder.Children.Dictionary[item.ID] = item; - // Send a success response - UpdateCreateInventoryItemPacket update = new UpdateCreateInventoryItemPacket(); - update.AgentData.AgentID = agentID; - update.AgentData.SimApproved = true; - if (transactionID != UUID.Zero) - update.AgentData.TransactionID = transactionID; - else - update.AgentData.TransactionID = UUID.Random(); - update.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1]; - update.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock(); - update.InventoryData[0].AssetID = assetID; - update.InventoryData[0].BaseMask = (uint)PermissionMask.All; - update.InventoryData[0].CallbackID = callbackID; - update.InventoryData[0].CreationDate = (int)Utils.DateTimeToUnixTime(item.CreationDate); - update.InventoryData[0].CRC = item.CRC; - update.InventoryData[0].CreatorID = item.CreatorID; - update.InventoryData[0].Description = Utils.StringToBytes(item.Description); - update.InventoryData[0].EveryoneMask = (uint)item.Permissions.EveryoneMask; - update.InventoryData[0].Flags = item.Flags; - update.InventoryData[0].FolderID = item.ParentID; - update.InventoryData[0].GroupID = item.GroupID; - update.InventoryData[0].GroupMask = (uint)item.Permissions.GroupMask; - update.InventoryData[0].GroupOwned = item.GroupOwned; - update.InventoryData[0].InvType = (sbyte)item.InventoryType; - update.InventoryData[0].ItemID = item.ID; - update.InventoryData[0].Name = Utils.StringToBytes(item.Name); - update.InventoryData[0].NextOwnerMask = (uint)item.Permissions.NextOwnerMask; - update.InventoryData[0].OwnerID = item.OwnerID; - update.InventoryData[0].OwnerMask = (uint)item.Permissions.OwnerMask; - update.InventoryData[0].SalePrice = item.SalePrice; - update.InventoryData[0].SaleType = (byte)item.SaleType; - update.InventoryData[0].Type = (sbyte)item.AssetType; - - if (sendPacket) - server.UDP.SendPacket(agentID, update, PacketCategory.Inventory); - - return item.ID; + return item; } else { @@ -796,11 +163,87 @@ namespace Simian.Extensions "Cannot create new inventory item, folder {0} does not exist", parentID), Helpers.LogLevel.Warning); - return UUID.Zero; + return null; } } } + public InventoryObject MoveInventory(UUID agentID, UUID objectID, UUID newFolderID, string newName, UUID transactionID, uint callbackID) + { + Dictionary agentInventory = GetAgentInventory(agentID); + + InventoryObject obj; + if (agentInventory.TryGetValue(objectID, out obj)) + { + lock (agentInventory) + { + InventoryObject newParentObj; + if (agentInventory.TryGetValue(newFolderID, out newParentObj) && newParentObj is InventoryFolder) + { + // Remove this item from the current parent + if (obj.Parent != null) + { + InventoryFolder parent = (InventoryFolder)obj.Parent; + lock (parent.Children.Dictionary) + parent.Children.Dictionary.Remove(obj.ID); + } + + // Update the new parent + InventoryFolder newParent = (InventoryFolder)newParentObj; + newParent.Children.Dictionary[obj.ID] = obj; + + // Update the object + obj.ParentID = newParent.ID; + obj.Parent = newParent; + if (!String.IsNullOrEmpty(newName)) + obj.Name = newName; + + return obj; + } + else + { + Logger.Log("MoveInventory called with an unknown destination folder " + newFolderID, + Helpers.LogLevel.Warning); + return null; + } + } + } + else + { + Logger.Log("MoveInventory called for an unknown object " + objectID, + Helpers.LogLevel.Warning); + return null; + } + } + + public void PurgeFolder(UUID agentID, UUID folderID) + { + Dictionary agentInventory = GetAgentInventory(agentID); + + InventoryObject obj; + if (TryGetInventory(agentID, folderID, out obj) && obj is InventoryFolder) + { + InventoryFolder folder = (InventoryFolder)obj; + + folder.Children.ForEach( + delegate(InventoryObject child) + { + agentInventory.Remove(child.ID); + + if (child is InventoryFolder) + PurgeFolder(agentID, child.ID); + } + ); + + lock (folder.Children.Dictionary) + folder.Children.Dictionary.Clear(); + } + else + { + Logger.Log("PurgeFolder called on a missing folder " + folderID, Helpers.LogLevel.Warning); + } + } + public bool TryGetInventory(UUID agentID, UUID objectID, out InventoryObject obj) { Dictionary inventory; @@ -856,6 +299,27 @@ namespace Simian.Extensions } } + public bool InventoryExists(UUID agentID) + { + return Inventory.ContainsKey(agentID); + } + + Dictionary GetAgentInventory(UUID agentID) + { + Dictionary agentInventory; + if (!Inventory.TryGetValue(agentID, out agentInventory)) + { + Logger.Log("Creating an empty inventory store for agent " + agentID.ToString(), + Helpers.LogLevel.Info); + + agentInventory = new Dictionary(); + lock (Inventory) + Inventory[agentID] = agentInventory; + } + + return agentInventory; + } + #region Persistence OSDMap SerializeItem(InventoryItem item) diff --git a/Programs/Simian/Extensions/LindenLogin.cs b/Programs/Simian/Extensions/LindenLogin.cs index 175a93bd..200f858d 100644 --- a/Programs/Simian/Extensions/LindenLogin.cs +++ b/Programs/Simian/Extensions/LindenLogin.cs @@ -7,7 +7,7 @@ using ExtensionLoader; using HttpServer; using OpenMetaverse; -namespace Simian.Extensions +namespace Simian { public class LindenLogin : IExtension { @@ -17,7 +17,7 @@ namespace Simian.Extensions { } - public void Start(Simian server) + public bool Start(Simian server) { this.server = server; @@ -32,7 +32,7 @@ namespace Simian.Extensions // Client LLSD login server.HttpServer.AddHandler("post", "application/xml", "^/$", LoginLLSDPostHandler); - + return true; } public void Stop() @@ -175,61 +175,69 @@ namespace Simian.Extensions LoginResponseData HandleLogin(string firstName, string lastName, string password, string start, string version, string channel) { - LoginResponseData response = new LoginResponseData(); - Agent agent; + ISceneProvider scene = server.Grid.GetDefaultLocalScene(); + LoginResponseData response = new LoginResponseData(); + AgentInfo agentInfo; + + // Attempt to authenticate UUID agentID = server.Authentication.Authenticate(firstName, lastName, password); if (agentID != UUID.Zero) { // Authentication successful, create a login instance of this agent - agent = server.Accounts.CreateInstance(agentID); - - // Create a seed capability for this agent - Uri seedCap = server.Capabilities.CreateCapability(server.Scene.SeedCapabilityHandler, false, agentID); - - if (agent != null) + agentInfo = server.Accounts.CreateInstance(agentID); + if (agentInfo != null) { + Agent agent = new Agent(new SimulationObject(new Avatar(), scene), agentInfo); + + // Set the avatar ID + agent.Avatar.Prim.ID = agentInfo.ID; + + // Random session IDs + agent.SessionID = UUID.Random(); + agent.SecureSessionID = UUID.Random(); + + // Create a seed capability for this agent + agent.SeedCapability = server.Capabilities.CreateCapability(scene.SeedCapabilityHandler, false, agentID); + // Assign a circuit code and insert the agent into the unassociatedAgents dictionary - agent.CircuitCode = server.UDP.CreateCircuit(agent); + agent.CircuitCode = scene.UDP.CreateCircuit(agent); agent.TickLastPacketReceived = Environment.TickCount; - agent.LastLoginTime = Utils.DateTimeToUnixTime(DateTime.Now); + agent.Info.LastLoginTime = Utils.DateTimeToUnixTime(DateTime.Now); // Get this machine's IP address IPHostEntry entry = Dns.GetHostEntry(System.Environment.MachineName); IPAddress simIP = entry.AddressList.Length > 0 ? entry.AddressList[entry.AddressList.Length - 1] : IPAddress.Loopback; - agent.CurrentRegionHandle = server.Scene.RegionHandle; - agent.HomeRegionHandle = server.Scene.RegionHandle; - response.AgentID = agent.ID; response.SecureSessionID = agent.SecureSessionID; response.SessionID = agent.SessionID; response.CircuitCode = agent.CircuitCode; - response.AgentAccess = agent.AccessLevel; + response.AgentAccess = agent.Info.AccessLevel; response.BuddyList = null; // FIXME: - response.FirstName = agent.FirstName; - response.HomeLookAt = agent.HomeLookAt; - response.HomePosition = agent.HomePosition; - response.HomeRegion = agent.HomeRegionHandle; - response.InventoryRoot = agent.InventoryRoot; + response.FirstName = agent.Info.FirstName; + response.HomeLookAt = agent.Info.HomeLookAt; + response.HomePosition = agent.Info.HomePosition; + response.HomeRegion = agent.Info.HomeRegionHandle; + response.InventoryRoot = agent.Info.InventoryRoot; response.InventorySkeleton = null; // FIXME: - response.LastName = agent.LastName; - response.LibraryOwner = agent.InventoryLibraryOwner; - response.LibraryRoot = agent.InventoryLibraryRoot; + response.LastName = agent.Info.LastName; + response.LibraryOwner = agent.Info.InventoryLibraryOwner; + response.LibraryRoot = agent.Info.InventoryLibraryRoot; response.LibrarySkeleton = null; // FIXME: response.LookAt = agent.CurrentLookAt; response.Message = "Welcome to Simian"; response.Reason = String.Empty; - response.RegionX = server.Scene.RegionX * 256; - response.RegionY = server.Scene.RegionY * 256; + response.RegionX = scene.RegionX * 256; + response.RegionY = scene.RegionY * 256; response.SecondsSinceEpoch = DateTime.Now; - response.SeedCapability = seedCap.ToString(); + response.SeedCapability = agent.SeedCapability.ToString(); response.SimIP = simIP; - response.SimPort = (ushort)server.UDPPort; + response.SimPort = (ushort)scene.IPAndPort.Port; response.StartLocation = "last"; // FIXME: response.Success = true; } diff --git a/Programs/Simian/Extensions/Messaging.cs b/Programs/Simian/Extensions/Messaging.cs deleted file mode 100644 index 999b65f5..00000000 --- a/Programs/Simian/Extensions/Messaging.cs +++ /dev/null @@ -1,72 +0,0 @@ -using System; -using System.Collections.Generic; -using ExtensionLoader; -using OpenMetaverse; -using OpenMetaverse.Packets; - -namespace Simian.Extensions -{ - public class Messaging : IExtension - { - Simian server; - - public Messaging() - { - } - - public void Start(Simian server) - { - this.server = server; - - server.UDP.RegisterPacketCallback(PacketType.ChatFromViewer, new PacketCallback(ChatFromViewerHandler)); - server.UDP.RegisterPacketCallback(PacketType.ImprovedInstantMessage, new PacketCallback(ImprovedInstantMessageHandler)); - } - - public void Stop() - { - } - - void ChatFromViewerHandler(Packet packet, Agent agent) - { - ChatFromViewerPacket viewerChat = (ChatFromViewerPacket)packet; - - server.Scene.ObjectChat(this, agent.ID, agent.ID, ChatAudibleLevel.Fully, (ChatType)viewerChat.ChatData.Type, - ChatSourceType.Agent, agent.FullName, agent.Avatar.GetSimulatorPosition(), viewerChat.ChatData.Channel, - Utils.BytesToString(viewerChat.ChatData.Message)); - } - - void ImprovedInstantMessageHandler(Packet packet, Agent agent) - { - ImprovedInstantMessagePacket im = (ImprovedInstantMessagePacket)packet; - InstantMessageDialog dialog = (InstantMessageDialog)im.MessageBlock.Dialog; - - if (dialog == InstantMessageDialog.MessageFromAgent) - { - // HACK: Only works for agents currently online - Agent recipient; - if (server.Scene.TryGetAgent(im.MessageBlock.ToAgentID, out recipient)) - { - // FIXME: Look into the fields we are setting to default values - ImprovedInstantMessagePacket sendIM = new ImprovedInstantMessagePacket(); - sendIM.MessageBlock.RegionID = server.Scene.RegionID; - sendIM.MessageBlock.ParentEstateID = 1; - sendIM.MessageBlock.FromGroup = false; - sendIM.MessageBlock.FromAgentName = Utils.StringToBytes(agent.FullName); - sendIM.MessageBlock.ToAgentID = im.MessageBlock.ToAgentID; - sendIM.MessageBlock.Dialog = im.MessageBlock.Dialog; - sendIM.MessageBlock.Offline = (byte)InstantMessageOnline.Online; - sendIM.MessageBlock.ID = agent.ID; - sendIM.MessageBlock.Message = im.MessageBlock.Message; - sendIM.MessageBlock.BinaryBucket = Utils.EmptyBytes; - sendIM.MessageBlock.Timestamp = Utils.DateTimeToUnixTime(DateTime.Now); - sendIM.MessageBlock.Position = agent.Avatar.GetSimulatorPosition(); - - sendIM.AgentData.AgentID = agent.ID; - - server.UDP.SendPacket(recipient.ID, sendIM, PacketCategory.Messaging); - } - } - } - - } -} diff --git a/Programs/Simian/Extensions/MessagingLocal.cs b/Programs/Simian/Extensions/MessagingLocal.cs index f90005c1..a87f606d 100644 --- a/Programs/Simian/Extensions/MessagingLocal.cs +++ b/Programs/Simian/Extensions/MessagingLocal.cs @@ -3,7 +3,7 @@ using System.Collections.Generic; using ExtensionLoader; using OpenMetaverse; -namespace Simian.Extensions +namespace Simian { // FIXME: Implement this class class MessagingLocal : IExtension, IMessagingProvider @@ -16,9 +16,10 @@ namespace Simian.Extensions { } - public void Start(Simian server) + public bool Start(Simian server) { this.server = server; + return true; } public void Stop() diff --git a/Programs/Simian/Extensions/PermissionsFreeForAll.cs b/Programs/Simian/Extensions/PermissionsFreeForAll.cs index 7bb26a35..691ae940 100644 --- a/Programs/Simian/Extensions/PermissionsFreeForAll.cs +++ b/Programs/Simian/Extensions/PermissionsFreeForAll.cs @@ -2,7 +2,7 @@ using ExtensionLoader; using OpenMetaverse; -namespace Simian.Extensions +namespace Simian { public class PermissionsFreeForAll : IExtension, IPermissionsProvider { @@ -12,9 +12,10 @@ namespace Simian.Extensions { } - public void Start(Simian server) + public bool Start(Simian server) { this.server = server; + return true; } public void Stop() diff --git a/Programs/Simian/Extensions/RenderingPluginMesher.cs b/Programs/Simian/Extensions/RenderingPluginMesher.cs index 0458d8a8..be64eb4a 100644 --- a/Programs/Simian/Extensions/RenderingPluginMesher.cs +++ b/Programs/Simian/Extensions/RenderingPluginMesher.cs @@ -4,7 +4,7 @@ using ExtensionLoader; using OpenMetaverse; using OpenMetaverse.Rendering; -namespace Simian.Extensions +namespace Simian { public class RenderingPluginMesher : IExtension, IMeshingProvider { @@ -15,7 +15,7 @@ namespace Simian.Extensions { } - public void Start(Simian server) + public bool Start(Simian server) { this.server = server; @@ -35,11 +35,12 @@ namespace Simian.Extensions else { Logger.Log("No suitable OpenMetaverse.Rendering plugins found", Helpers.LogLevel.Error); - return; + return false; } } Renderer = RenderingLoader.LoadRenderer(renderer); + return true; } public void Stop() diff --git a/Programs/Simian/Extensions/SceneManager.cs b/Programs/Simian/Extensions/SceneManager.cs index 95ef1f56..0f85ea1a 100644 --- a/Programs/Simian/Extensions/SceneManager.cs +++ b/Programs/Simian/Extensions/SceneManager.cs @@ -4,6 +4,7 @@ using System.Drawing; using System.Drawing.Imaging; using System.IO; using System.Net; +using System.Reflection; using System.Runtime.InteropServices; using System.Threading; using ExtensionLoader; @@ -14,7 +15,7 @@ using OpenMetaverse.Packets; using OpenMetaverse.StructuredData; using OpenMetaverse.Http; -namespace Simian.Extensions +namespace Simian { class EventQueueServerCap { @@ -28,20 +29,17 @@ namespace Simian.Extensions } } - public class SceneManager : IExtension, ISceneProvider + public class SceneManager : ISceneProvider { - Simian server; - // Contains all scene objects, including prims and avatars - DoubleDictionary sceneObjects = new DoubleDictionary(); - // A duplicate of the avatar information stored in sceneObjects, improves operations such as iterating over all agents - Dictionary sceneAgents = new Dictionary(); - // Event queues for each avatar in the scene - Dictionary eventQueues = new Dictionary(); - int currentLocalID = 1; - ulong regionHandle; - UUID regionID = UUID.Random(); - TerrainPatch[,] heightmap = new TerrainPatch[16, 16]; - Vector2[,] windSpeeds = new Vector2[16, 16]; + // Interfaces. Although no other classes will access these interfaces directly + // (getters are used instead), they must be marked public so ExtensionLoader + // can automatically assign them + public IAvatarProvider avatars; + public IParcelProvider parcels; + public IPhysicsProvider physics; + public IScriptEngine scriptEngine; + public ITaskInventoryProvider taskInventory; + public IUDPProvider udp; public event ObjectAddOrUpdateCallback OnObjectAddOrUpdate; public event ObjectRemoveCallback OnObjectRemove; @@ -61,12 +59,39 @@ namespace Simian.Extensions public event TerrainUpdateCallback OnTerrainUpdate; public event WindUpdateCallback OnWindUpdate; - public uint RegionX { get { return 7777; } } - public uint RegionY { get { return 7777; } } + public Simian Server { get { return server; } } + public IAvatarProvider Avatars { get { return avatars; } } + public IParcelProvider Parcels { get { return parcels; } } + public IPhysicsProvider Physics { get { return physics; } } + public IScriptEngine ScriptEngine { get { return scriptEngine; } } + public ITaskInventoryProvider TaskInventory { get { return taskInventory; } } + public IUDPProvider UDP { get { return udp; } } + + public uint RegionX + { + get { return regionX; } + set + { + regionX = value; + regionHandle = Utils.UIntsToLong(regionX * 256, regionY * 256); + } + } + public uint RegionY + { + get { return regionY; } + set + { + regionY = value; + regionHandle = Utils.UIntsToLong(regionX * 256, regionY * 256); + } + } public ulong RegionHandle { get { return regionHandle; } } public UUID RegionID { get { return regionID; } } - public string RegionName { get { return "Simian"; } } + public string RegionName { get { return regionName; } set { regionName = value; } } public RegionFlags RegionFlags { get { return RegionFlags.None; } } + public IPEndPoint IPAndPort { get { return endpoint; } set { endpoint = value; } } + public Vector3 DefaultPosition { get { return defaultPosition; } } + public Vector3 DefaultLookAt { get { return defaultLookAt; } } public float WaterHeight { get { return 20f; } } @@ -75,21 +100,91 @@ namespace Simian.Extensions public uint TerrainPatchCountWidth { get { return 16; } } public uint TerrainPatchCountHeight { get { return 16; } } + Simian server; + // Contains all scene objects, including prims and avatars + DoubleDictionary sceneObjects = new DoubleDictionary(); + // A duplicate of the avatar information stored in sceneObjects, improves operations such as iterating over all agents + Dictionary sceneAgents = new Dictionary(); + // Event queues for each avatar in the scene + Dictionary eventQueues = new Dictionary(); + int currentLocalID = 1; + ulong regionHandle; + UUID regionID = UUID.Random(); + TerrainPatch[,] heightmap = new TerrainPatch[16, 16]; + Vector2[,] windSpeeds = new Vector2[16, 16]; + ExtensionLoader extensions = new ExtensionLoader(); + IPEndPoint endpoint; + uint regionX; + uint regionY; + string regionName; + Vector3 defaultPosition = new Vector3(128f, 128f, 30f); + Vector3 defaultLookAt = Vector3.UnitX; + public SceneManager() { - regionHandle = Utils.UIntsToLong(RegionX * 256, RegionY * 256); } - public void Start(Simian server) + public bool Start(Simian server, string name, IPEndPoint endpoint, uint regionX, uint regionY, + string defaultTerrainFile, int staticObjects, int physicalObjects) { this.server = server; + this.regionName = name; + this.endpoint = endpoint; - server.UDP.RegisterPacketCallback(PacketType.CompleteAgentMovement, new PacketCallback(CompleteAgentMovementHandler)); - LoadTerrain(Simian.DATA_DIR + "heightmap.tga"); + // Set the properties because this will automatically update the regionHandle + RegionX = regionX; + RegionY = regionY; + + #region ISceneProvider Extension Loading + + try + { + // Create a list of references for .cs extensions that are compiled at runtime + List references = new List(); + references.Add("OpenMetaverseTypes.dll"); + references.Add("OpenMetaverse.dll"); + references.Add("Simian.exe"); + + // Load extensions from the current executing assembly, Simian.*.dll assemblies on disk, and + // Simian.*.cs source files on disk. + extensions.LoadAllExtensions(Assembly.GetExecutingAssembly(), + AppDomain.CurrentDomain.BaseDirectory, server.ExtensionList, references, + "Simian.*.dll", "Simian.*.cs"); + + // Automatically assign extensions that implement interfaces to the list of interface + // variables in "assignables" + extensions.AssignExtensions(this, extensions.GetInterfaces(this)); + + // Start all of the extensions + foreach (IExtension extension in extensions.Extensions) + { + Logger.Log("Starting Scene extension " + extension.GetType().Name, Helpers.LogLevel.Info); + extension.Start(this); + } + } + catch (ExtensionException ex) + { + Logger.Log("SceneManager extension loading failed, shutting down: " + ex.Message, Helpers.LogLevel.Error); + Stop(); + return false; + } + + #endregion ISceneProvider Extension Loading + + udp.RegisterPacketCallback(PacketType.CompleteAgentMovement, new PacketCallback(CompleteAgentMovementHandler)); + + if (!String.IsNullOrEmpty(defaultTerrainFile)) + LoadTerrain(Simian.DATA_DIR + defaultTerrainFile); + + return true; } public void Stop() { + Logger.Log("Stopping region " + regionName, Helpers.LogLevel.Info); + + // Remove all of the agents from the scene. This will shutdown UDP connections and event queues to + // each of the agents as well lock (sceneAgents) { List agents = new List(sceneAgents.Values); @@ -97,7 +192,14 @@ namespace Simian.Extensions ObjectRemove(this, agents[i].ID); } - Logger.DebugLog("SceneManager is stopped"); + // Stop ISceneProvider extensions + foreach (IExtension extension in extensions.Extensions) + { + Logger.Log("Stopping Scene extension " + extension.GetType().Name, Helpers.LogLevel.Info); + extension.Stop(); + } + + Logger.Log("Region " + regionName + " is stopped", Helpers.LogLevel.Info); } #region Object Interfaces @@ -136,7 +238,7 @@ namespace Simian.Extensions // Set the RegionHandle if no RegionHandle is set if (obj.Prim.RegionHandle == 0) - obj.Prim.RegionHandle = server.Scene.RegionHandle; + obj.Prim.RegionHandle = regionHandle; // Make sure this object has properties if (obj.Prim.Properties == null) @@ -236,7 +338,7 @@ namespace Simian.Extensions kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock(); kill.ObjectData[0].ID = obj.Prim.LocalID; - server.UDP.BroadcastPacket(kill, PacketCategory.State); + udp.BroadcastPacket(kill, PacketCategory.State); return true; } @@ -263,7 +365,7 @@ namespace Simian.Extensions kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock(); kill.ObjectData[0].ID = obj.Prim.LocalID; - server.UDP.BroadcastPacket(kill, PacketCategory.State); + udp.BroadcastPacket(kill, PacketCategory.State); return true; } @@ -332,7 +434,7 @@ namespace Simian.Extensions sendAnim.AnimationList[i].AnimSequenceID = animations[i].SequenceID; } - server.UDP.BroadcastPacket(sendAnim, PacketCategory.State); + udp.BroadcastPacket(sendAnim, PacketCategory.State); } public void ObjectChat(object sender, UUID ownerID, UUID sourceID, ChatAudibleLevel audible, ChatType type, ChatSourceType sourceType, @@ -356,7 +458,7 @@ namespace Simian.Extensions chat.ChatData.FromName = Utils.StringToBytes(fromName); chat.ChatData.Message = Utils.StringToBytes(message); - server.UDP.BroadcastPacket(chat, PacketCategory.Messaging); + udp.BroadcastPacket(chat, PacketCategory.Messaging); } } @@ -376,7 +478,7 @@ namespace Simian.Extensions obj.Prim = prim; // Inform clients - server.Scene.ObjectAddOrUpdate(this, obj, obj.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.FullUpdate); + ObjectAddOrUpdate(this, obj, obj.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.FullUpdate); } else { @@ -401,7 +503,7 @@ namespace Simian.Extensions obj.Prim = prim; // Inform clients - server.Scene.ObjectAddOrUpdate(this, obj, obj.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.FullUpdate); + ObjectAddOrUpdate(this, obj, obj.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.FullUpdate); } else { @@ -458,7 +560,7 @@ namespace Simian.Extensions } SoundTriggerPacket sound = new SoundTriggerPacket(); - sound.SoundData.Handle = server.Scene.RegionHandle; + sound.SoundData.Handle = regionHandle; sound.SoundData.ObjectID = objectID; sound.SoundData.ParentID = parentID; sound.SoundData.OwnerID = ownerID; @@ -466,7 +568,7 @@ namespace Simian.Extensions sound.SoundData.SoundID = soundID; sound.SoundData.Gain = gain; - server.UDP.BroadcastPacket(sound, PacketCategory.State); + udp.BroadcastPacket(sound, PacketCategory.State); } public void TriggerEffects(object sender, ViewerEffect[] effects) @@ -497,7 +599,7 @@ namespace Simian.Extensions effect.Effect[i] = block; } - server.UDP.BroadcastPacket(effect, PacketCategory.State); + udp.BroadcastPacket(effect, PacketCategory.State); } #endregion Object Interfaces @@ -506,6 +608,9 @@ namespace Simian.Extensions public bool AgentAdd(object sender, Agent agent, PrimFlags creatorFlags) { + // Sanity check, since this should have already been done + agent.Avatar.Prim.ID = agent.Info.ID; + // Check if the agent already exists in the scene lock (sceneAgents) { @@ -513,6 +618,9 @@ namespace Simian.Extensions sceneAgents.Remove(agent.ID); } + // Update the current region handle + agent.Avatar.Prim.RegionHandle = regionHandle; + // Avatars always have physics agent.Avatar.Prim.Flags |= PrimFlags.Physics; @@ -527,17 +635,17 @@ namespace Simian.Extensions // Set the avatar name NameValue[] name = new NameValue[2]; name[0] = new NameValue("FirstName", NameValue.ValueType.String, NameValue.ClassType.ReadWrite, - NameValue.SendtoType.SimViewer, agent.FirstName); + NameValue.SendtoType.SimViewer, agent.Info.FirstName); name[1] = new NameValue("LastName", NameValue.ValueType.String, NameValue.ClassType.ReadWrite, - NameValue.SendtoType.SimViewer, agent.LastName); + NameValue.SendtoType.SimViewer, agent.Info.LastName); agent.Avatar.Prim.NameValues = name; // Give testers a provisionary balance of 1000L - agent.Balance = 1000; + agent.Info.Balance = 1000; // Some default avatar prim properties agent.Avatar.Prim.Properties = new Primitive.ObjectProperties(); - agent.Avatar.Prim.Properties.CreationDate = Utils.UnixTimeToDateTime(agent.CreationTime); + agent.Avatar.Prim.Properties.CreationDate = Utils.UnixTimeToDateTime(agent.Info.CreationTime); agent.Avatar.Prim.Properties.Name = agent.FullName; agent.Avatar.Prim.Properties.ObjectID = agent.ID; @@ -570,14 +678,14 @@ namespace Simian.Extensions RemoveEventQueue(agent.ID); // Remove the UDP client - server.UDP.RemoveClient(agent); + udp.RemoveClient(agent); // Notify everyone in the scene that this agent has gone offline OfflineNotificationPacket offline = new OfflineNotificationPacket(); offline.AgentBlock = new OfflineNotificationPacket.AgentBlockBlock[1]; offline.AgentBlock[0] = new OfflineNotificationPacket.AgentBlockBlock(); offline.AgentBlock[0].AgentID = agent.ID; - server.UDP.BroadcastPacket(offline, PacketCategory.State); + udp.BroadcastPacket(offline, PacketCategory.State); } public void AgentAppearance(object sender, Agent agent, Primitive.TextureEntry textures, byte[] visualParams) @@ -591,14 +699,14 @@ namespace Simian.Extensions // TODO: Is this necessary here? //ObjectUpdatePacket update = SimulationObject.BuildFullUpdate(agent.Avatar, // regionHandle, agent.Flags); - //server.UDP.BroadcastPacket(update, PacketCategory.State); + //scene.UDP.BroadcastPacket(update, PacketCategory.State); // Update the avatar agent.Avatar.Prim.Textures = textures; if (visualParams != null && visualParams.Length > 1) - agent.VisualParams = visualParams; + agent.Info.VisualParams = visualParams; - if (agent.VisualParams != null) + if (agent.Info.VisualParams != null) { // Send the appearance packet to all other clients AvatarAppearancePacket appearance = BuildAppearancePacket(agent); @@ -606,7 +714,7 @@ namespace Simian.Extensions delegate(Agent recipient) { if (recipient != agent) - server.UDP.SendPacket(recipient.ID, appearance, PacketCategory.State); + udp.SendPacket(recipient.ID, appearance, PacketCategory.State); } ); } @@ -745,7 +853,7 @@ namespace Simian.Extensions heightmap[y, x].Height = copy; LayerDataPacket layer = TerrainCompressor.CreateLandPacket(heightmap[y, x].Height, (int)x, (int)y); - server.UDP.BroadcastPacket(layer, PacketCategory.Terrain); + udp.BroadcastPacket(layer, PacketCategory.Terrain); } public Vector2 GetWindSpeedAt(float fx, float fy) @@ -901,7 +1009,7 @@ namespace Simian.Extensions complete.Data.Timestamp = Utils.DateTimeToUnixTime(DateTime.Now); complete.SimData.ChannelVersion = Utils.StringToBytes("Simian"); - server.UDP.SendPacket(agent.ID, complete, PacketCategory.Transaction); + udp.SendPacket(agent.ID, complete, PacketCategory.Transaction); // Send updates and appearances for every avatar to this new avatar SynchronizeStateTo(agent); @@ -911,7 +1019,7 @@ namespace Simian.Extensions online.AgentBlock = new OnlineNotificationPacket.AgentBlockBlock[1]; online.AgentBlock[0] = new OnlineNotificationPacket.AgentBlockBlock(); online.AgentBlock[0].AgentID = agent.ID; - server.UDP.BroadcastPacket(online, PacketCategory.State); + udp.BroadcastPacket(online, PacketCategory.State); } #endregion Callback Handlers @@ -920,18 +1028,18 @@ namespace Simian.Extensions void SynchronizeStateTo(Agent agent) { // Send the parcel overlay - server.Parcels.SendParcelOverlay(agent); + parcels.SendParcelOverlay(agent); // Send object updates for objects and avatars sceneObjects.ForEach(delegate(SimulationObject obj) { ObjectUpdatePacket update = new ObjectUpdatePacket(); update.RegionData.RegionHandle = regionHandle; - update.RegionData.TimeDilation = (ushort)(server.Physics.TimeDilation * (float)UInt16.MaxValue); + update.RegionData.TimeDilation = (ushort)(physics.TimeDilation * (float)UInt16.MaxValue); update.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; update.ObjectData[0] = SimulationObject.BuildUpdateBlock(obj.Prim, obj.Prim.Flags, obj.CRC); - server.UDP.SendPacket(agent.ID, update, PacketCategory.State); + udp.SendPacket(agent.ID, update, PacketCategory.State); }); // Send appearances for all avatars @@ -942,7 +1050,7 @@ namespace Simian.Extensions { // Send appearances for this avatar AvatarAppearancePacket appearance = BuildAppearancePacket(otherAgent); - server.UDP.SendPacket(agent.ID, appearance, PacketCategory.State); + udp.SendPacket(agent.ID, appearance, PacketCategory.State); } } ); @@ -1026,7 +1134,7 @@ namespace Simian.Extensions for (int x = 0; x < 16; x++) { LayerDataPacket layer = TerrainCompressor.CreateLandPacket(heightmap[y, x].Height, x, y); - server.UDP.SendPacket(agent.ID, layer, PacketCategory.Terrain); + udp.SendPacket(agent.ID, layer, PacketCategory.Terrain); } } } @@ -1044,12 +1152,12 @@ namespace Simian.Extensions // Send an update out to the creator ObjectUpdatePacket updateToOwner = new ObjectUpdatePacket(); updateToOwner.RegionData.RegionHandle = regionHandle; - updateToOwner.RegionData.TimeDilation = (ushort)(server.Physics.TimeDilation * (float)UInt16.MaxValue); + updateToOwner.RegionData.TimeDilation = (ushort)(physics.TimeDilation * (float)UInt16.MaxValue); updateToOwner.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; updateToOwner.ObjectData[0] = SimulationObject.BuildUpdateBlock(obj.Prim, obj.Prim.Flags | creatorFlags | PrimFlags.ObjectYouOwner, obj.CRC); - server.UDP.SendPacket(obj.Prim.OwnerID, updateToOwner, PacketCategory.State); + udp.SendPacket(obj.Prim.OwnerID, updateToOwner, PacketCategory.State); } // Send an update out to everyone else @@ -1060,11 +1168,11 @@ namespace Simian.Extensions updateToOthers.ObjectData[0] = SimulationObject.BuildUpdateBlock(obj.Prim, obj.Prim.Flags, obj.CRC); - server.Scene.ForEachAgent( + ForEachAgent( delegate(Agent recipient) { if (recipient.ID != obj.Prim.OwnerID) - server.UDP.SendPacket(recipient.ID, updateToOthers, PacketCategory.State); + udp.SendPacket(recipient.ID, updateToOthers, PacketCategory.State); } ); @@ -1307,13 +1415,13 @@ namespace Simian.Extensions // Send an update out to the creator ObjectUpdateCompressedPacket updateToOwner = new ObjectUpdateCompressedPacket(); updateToOwner.RegionData.RegionHandle = regionHandle; - updateToOwner.RegionData.TimeDilation = (ushort)(server.Physics.TimeDilation * (float)UInt16.MaxValue); + updateToOwner.RegionData.TimeDilation = (ushort)(physics.TimeDilation * (float)UInt16.MaxValue); updateToOwner.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[1]; updateToOwner.ObjectData[0] = new ObjectUpdateCompressedPacket.ObjectDataBlock(); updateToOwner.ObjectData[0].UpdateFlags = (uint)(obj.Prim.Flags | creatorFlags | PrimFlags.ObjectYouOwner); updateToOwner.ObjectData[0].Data = data; - server.UDP.SendPacket(obj.Prim.OwnerID, updateToOwner, PacketCategory.State); + udp.SendPacket(obj.Prim.OwnerID, updateToOwner, PacketCategory.State); } // Send an update out to everyone else @@ -1325,11 +1433,11 @@ namespace Simian.Extensions updateToOthers.ObjectData[0].UpdateFlags = (uint)obj.Prim.Flags; updateToOthers.ObjectData[0].Data = data; - server.Scene.ForEachAgent( + ForEachAgent( delegate(Agent recipient) { if (recipient.ID != obj.Prim.OwnerID) - server.UDP.SendPacket(recipient.ID, updateToOthers, PacketCategory.State); + udp.SendPacket(recipient.ID, updateToOthers, PacketCategory.State); } ); @@ -1385,7 +1493,7 @@ namespace Simian.Extensions ImprovedTerseObjectUpdatePacket update = new ImprovedTerseObjectUpdatePacket(); update.RegionData.RegionHandle = RegionHandle; - update.RegionData.TimeDilation = (ushort)(server.Physics.TimeDilation * (float)UInt16.MaxValue); + update.RegionData.TimeDilation = (ushort)(physics.TimeDilation * (float)UInt16.MaxValue); update.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; update.ObjectData[0] = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); update.ObjectData[0].Data = data; @@ -1407,7 +1515,7 @@ namespace Simian.Extensions update.ObjectData[0].TextureEntry = Utils.EmptyBytes; } - server.UDP.BroadcastPacket(update, PacketCategory.State); + udp.BroadcastPacket(update, PacketCategory.State); #endregion ImprovedTerseObjectUpdate } @@ -1420,16 +1528,17 @@ namespace Simian.Extensions appearance.Sender.ID = agent.ID; appearance.Sender.IsTrial = false; - appearance.VisualParam = new AvatarAppearancePacket.VisualParamBlock[agent.VisualParams.Length]; - for (int i = 0; i < agent.VisualParams.Length; i++) + int count = agent.Info.VisualParams != null ? agent.Info.VisualParams.Length : 0; + + appearance.VisualParam = new AvatarAppearancePacket.VisualParamBlock[count]; + for (int i = 0; i < count; i++) { appearance.VisualParam[i] = new AvatarAppearancePacket.VisualParamBlock(); - appearance.VisualParam[i].ParamValue = agent.VisualParams[i]; + appearance.VisualParam[i].ParamValue = agent.Info.VisualParams[i]; } - if (agent.VisualParams.Length != 218) - Logger.Log("Built an appearance packet with VisualParams.Length=" + agent.VisualParams.Length, - Helpers.LogLevel.Warning); + if (count != 218) + Logger.Log("Built an odd appearance packet with VisualParams.Length=" + count, Helpers.LogLevel.Warning); return appearance; } diff --git a/Programs/Simian/Extensions/XMLPersistence.cs b/Programs/Simian/Extensions/XMLPersistence.cs index 62fc5c1c..994149bb 100644 --- a/Programs/Simian/Extensions/XMLPersistence.cs +++ b/Programs/Simian/Extensions/XMLPersistence.cs @@ -6,7 +6,7 @@ using ExtensionLoader; using OpenMetaverse; using OpenMetaverse.StructuredData; -namespace Simian.Extensions +namespace Simian { public class XMLPersistence : IExtension, IPersistenceProvider { @@ -16,7 +16,7 @@ namespace Simian.Extensions { } - public void Start(Simian server) + public bool Start(Simian server) { this.server = server; @@ -30,12 +30,13 @@ namespace Simian.Extensions } catch (FileNotFoundException) { - return; + return true; } catch (Exception ex) { - Logger.Log("Failed to load saved data: " + ex.Message, Helpers.LogLevel.Error); - return; + Logger.Log("Failed to load saved data. You may have to move or delete simiandata.xml: " + + ex.Message, Helpers.LogLevel.Error); + return false; } if (osd is OSDMap) @@ -58,6 +59,8 @@ namespace Simian.Extensions } } } + + return true; } public void Stop() diff --git a/Programs/Simian/Interfaces/IAccountProvider.cs b/Programs/Simian/Interfaces/IAccountProvider.cs index fd5c8218..22612468 100644 --- a/Programs/Simian/Interfaces/IAccountProvider.cs +++ b/Programs/Simian/Interfaces/IAccountProvider.cs @@ -5,10 +5,10 @@ namespace Simian { public interface IAccountProvider { - void AddAccount(Agent agent); + void AddAccount(AgentInfo agent); bool RemoveAccount(UUID agentID); - Agent CreateInstance(UUID agentID); - bool TryGetAccount(UUID agentID, out Agent agent); - bool TryGetAccount(string fullName, out Agent agent); + AgentInfo CreateInstance(UUID agentID); + bool TryGetAccount(UUID agentID, out AgentInfo agent); + bool TryGetAccount(string fullName, out AgentInfo agent); } } diff --git a/Programs/Simian/Interfaces/IGridProvider.cs b/Programs/Simian/Interfaces/IGridProvider.cs new file mode 100644 index 00000000..6d5610f2 --- /dev/null +++ b/Programs/Simian/Interfaces/IGridProvider.cs @@ -0,0 +1,120 @@ +using System; +using System.Net; +using OpenMetaverse; +using OpenMetaverse.StructuredData; + +namespace Simian +{ + public class RegionInfo + { + public string Name; + public UUID ID; + public ulong Handle; + public bool Online; + public IPEndPoint IPAndPort; + public Uri HttpServer; + public UUID MapTextureID; + public Uri Owner; + + public uint X + { + get + { + uint x, y; + OpenMetaverse.Utils.LongToUInts(Handle, out x, out y); + return x; + } + + set + { + uint x, y; + OpenMetaverse.Utils.LongToUInts(Handle, out x, out y); + Handle = OpenMetaverse.Utils.UIntsToLong(value, y); + } + } + + public uint Y + { + get + { + uint x, y; + OpenMetaverse.Utils.LongToUInts(Handle, out x, out y); + return y; + } + + set + { + uint x, y; + OpenMetaverse.Utils.LongToUInts(Handle, out x, out y); + Handle = OpenMetaverse.Utils.UIntsToLong(x, value); + } + } + + public OSDMap SerializeToOSD() + { + OSDMap osdata = new OSDMap(); + + osdata["handle"] = OSD.FromULong(Handle); + osdata["id"] = OSD.FromUUID(ID); + osdata["map_texture_id"] = OSD.FromUUID(MapTextureID); + osdata["name"] = OSD.FromString(Name); + osdata["owner"] = OSD.FromUri(Owner); + osdata["ipaddr"] = OSD.FromString(IPAndPort.Address.ToString()); + osdata["port"] = OSD.FromInteger(IPAndPort.Port); + + return osdata; + } + + public void Deserialize(OSD osdata) + { + if (osdata.Type == OSDType.Map) + { + OSDMap map = (OSDMap)osdata; + + Handle = map["handle"].AsULong(); + ID = map["id"].AsUUID(); + MapTextureID = map["map_texture_id"].AsUUID(); + Name = map["name"].AsString(); + Owner = map["owner"].AsUri(); + + IPAddress address; + if (IPAddress.TryParse(map["ipaddr"].AsString(), out address)) + IPAndPort = new IPEndPoint(address, map["port"].AsInteger()); + } + } + } + + public delegate void NeighborSimNotice(RegionInfo neighbor, bool online); + + public interface IGridProvider + { + bool TryRegisterGridSpace(RegionInfo region, out UUID regionID); + /// + /// Attempts to register any available space closest to the given grid + /// coordinates + /// + /// Information about the region to be registered. + /// The X, Y, and Handle values may be modified if the exact grid + /// coordinate requested is not available + /// If true, the registered grid space must not + /// be adjacent to any other regions + /// The unique identifier of the registered + /// region upon success. This will also be assigned to region.ID + /// True if the registration was successful, otherwise false + bool TryRegisterAnyGridSpace(RegionInfo region, bool isolated, out UUID regionID); + bool UnregisterGridSpace(RegionInfo region); + + void RegionUpdate(RegionInfo region); + void RegionHeartbeat(RegionInfo region); + + bool TryGetRegion(UUID regionID, out RegionInfo region); + bool TryGetRegion(uint x, uint y, out RegionInfo region); + + /// + /// Gets the default scene running on this server + /// + /// A reference to the default scene on this server, or null + /// if there are no scenes + ISceneProvider GetDefaultLocalScene(); + } +} diff --git a/Programs/Simian/Interfaces/IInventoryProvider.cs b/Programs/Simian/Interfaces/IInventoryProvider.cs index 209965c0..388ee67c 100644 --- a/Programs/Simian/Interfaces/IInventoryProvider.cs +++ b/Programs/Simian/Interfaces/IInventoryProvider.cs @@ -1,17 +1,21 @@ using System; +using System.Collections.Generic; using OpenMetaverse; namespace Simian { public interface IInventoryProvider { - UUID CreateItem(UUID agentID, string name, string description, InventoryType invType, AssetType type, + InventoryItem CreateItem(UUID agentID, string name, string description, InventoryType invType, AssetType type, UUID assetID, UUID parentID, PermissionMask ownerMask, PermissionMask nextOwnerMask, UUID ownerID, - UUID creatorID, UUID transactionID, uint callbackID, bool sendPacket); - bool CreateFolder(UUID agentID, UUID folderID, string name, AssetType preferredType, UUID parentID, - UUID ownerID); + UUID creatorID, UUID transactionID, uint callbackID); + bool CreateFolder(UUID agentID, UUID folderID, string name, AssetType preferredType, UUID parentID, UUID ownerID); bool CreateRootFolder(UUID agentID, UUID folderID, string name, UUID ownerID); OpenMetaverse.InventoryFolder[] CreateInventorySkeleton(UUID agentID); + InventoryObject MoveInventory(UUID agentID, UUID objectID, UUID newFolderID, string newName, UUID transactionID, + uint callbackID); + void PurgeFolder(UUID agentID, UUID folderID); bool TryGetInventory(UUID agentID, UUID objectID, out InventoryObject obj); + bool InventoryExists(UUID agentID); } } diff --git a/Programs/Simian/Interfaces/ISceneProvider.cs b/Programs/Simian/Interfaces/ISceneProvider.cs index cb99e52b..533855bc 100644 --- a/Programs/Simian/Interfaces/ISceneProvider.cs +++ b/Programs/Simian/Interfaces/ISceneProvider.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Net; using HttpServer; using OpenMetaverse; using OpenMetaverse.StructuredData; @@ -123,12 +124,23 @@ namespace Simian event TerrainUpdateCallback OnTerrainUpdate; event WindUpdateCallback OnWindUpdate; - uint RegionX { get; } - uint RegionY { get; } + Simian Server { get; } + IAvatarProvider Avatars { get; } + IParcelProvider Parcels { get; } + IPhysicsProvider Physics { get; } + IScriptEngine ScriptEngine { get; } + ITaskInventoryProvider TaskInventory { get; } + IUDPProvider UDP { get; } + + uint RegionX { get; set; } + uint RegionY { get; set; } ulong RegionHandle { get; } UUID RegionID { get; } - string RegionName { get; } + string RegionName { get; set; } RegionFlags RegionFlags { get; } + Vector3 DefaultLookAt { get; } + Vector3 DefaultPosition { get; } + IPEndPoint IPAndPort { get; set; } float WaterHeight { get; } @@ -137,6 +149,9 @@ namespace Simian uint TerrainPatchCountWidth { get; } uint TerrainPatchCountHeight { get; } + bool Start(Simian server, string name, IPEndPoint endpoint, uint regionX, uint regionY, string defaultTerrainFile, int staticObjects, int physicalObjects); + void Stop(); + void ObjectAddOrUpdate(object sender, SimulationObject obj, UUID ownerID, int scriptStartParam, PrimFlags creatorFlags, UpdateFlags updateFlags); bool ObjectRemove(object sender, uint localID); bool ObjectRemove(object sender, UUID id); diff --git a/Programs/Simian/Interfaces/IScriptApi.cs b/Programs/Simian/Interfaces/IScriptApi.cs index 2b9c16d6..fb64eec5 100644 --- a/Programs/Simian/Interfaces/IScriptApi.cs +++ b/Programs/Simian/Interfaces/IScriptApi.cs @@ -33,7 +33,7 @@ namespace Simian public interface IScriptApi { - void Start(Simian server, SimulationObject hostObject, UUID scriptID, bool isGodMode, bool automaticLinkPermission); + void Start(ISceneProvider scene, SimulationObject hostObject, UUID scriptID, bool isGodMode, bool automaticLinkPermission); void Stop(); void state(string newState); diff --git a/Programs/Simian/Interfaces/IUDPProvider.cs b/Programs/Simian/Interfaces/IUDPProvider.cs index 100ce993..ce6d145d 100644 --- a/Programs/Simian/Interfaces/IUDPProvider.cs +++ b/Programs/Simian/Interfaces/IUDPProvider.cs @@ -33,7 +33,7 @@ namespace Simian /// Coupled with RegisterCallback(), this is triggered whenever a packet /// of a registered type is received /// - public delegate void PacketCallback(Packet packet, Agent agent); + public delegate void PacketCallback(Packet packet, /*ISceneProvider scene,*/ Agent agent); /// /// Triggered whenever a packet is going to be sent out to one or more /// clients diff --git a/Programs/Simian/SceneExtensions/AvatarManager.cs b/Programs/Simian/SceneExtensions/AvatarManager.cs new file mode 100644 index 00000000..9ce6d687 --- /dev/null +++ b/Programs/Simian/SceneExtensions/AvatarManager.cs @@ -0,0 +1,64 @@ +using System; +using System.Collections.Generic; +using System.Threading; +using ExtensionLoader; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenMetaverse.Packets; + +namespace Simian +{ + class AvatarManager : IExtension, IAvatarProvider + { + ISceneProvider scene; + int currentWearablesSerialNum = -1; + int currentAnimSequenceNum = 0; + + public AvatarManager() + { + } + + public bool Start(ISceneProvider scene) + { + this.scene = scene; + return true; + } + + public void Stop() + { + } + + public bool SetDefaultAnimation(Agent agent, UUID animID) + { + return agent.Animations.SetDefaultAnimation(animID, ref currentAnimSequenceNum); + } + + public bool AddAnimation(Agent agent, UUID animID) + { + return agent.Animations.Add(animID, ref currentAnimSequenceNum); + } + + public bool RemoveAnimation(Agent agent, UUID animID) + { + return agent.Animations.Remove(animID); + } + + public bool ClearAnimations(Agent agent) + { + agent.Animations.Clear(); + return true; + } + + public void SendAnimations(Agent agent) + { + scene.ObjectAnimate(this, agent.ID, agent.ID, agent.Animations.GetAnimations()); + } + + public void SendAlert(Agent agent, string message) + { + AlertMessagePacket alert = new AlertMessagePacket(); + alert.AlertData.Message = Utils.StringToBytes(message); + scene.UDP.SendPacket(agent.ID, alert, PacketCategory.Transaction); + } + } +} diff --git a/Programs/Simian/Extensions/ConnectionManagement.cs b/Programs/Simian/SceneExtensions/ConnectionManagement.cs similarity index 69% rename from Programs/Simian/Extensions/ConnectionManagement.cs rename to Programs/Simian/SceneExtensions/ConnectionManagement.cs index 81c817d4..5da484fc 100644 --- a/Programs/Simian/Extensions/ConnectionManagement.cs +++ b/Programs/Simian/SceneExtensions/ConnectionManagement.cs @@ -3,23 +3,24 @@ using ExtensionLoader; using OpenMetaverse; using OpenMetaverse.Packets; -namespace Simian.Extensions +namespace Simian { - public class ConnectionManagement : IExtension + public class ConnectionManagement : IExtension { - Simian server; + ISceneProvider scene; public ConnectionManagement() { } - public void Start(Simian server) + public bool Start(ISceneProvider scene) { - this.server = server; + this.scene = scene; - server.UDP.RegisterPacketCallback(PacketType.UseCircuitCode, UseCircuitCodeHandler); - server.UDP.RegisterPacketCallback(PacketType.StartPingCheck, StartPingCheckHandler); - server.UDP.RegisterPacketCallback(PacketType.LogoutRequest, LogoutRequestHandler); + scene.UDP.RegisterPacketCallback(PacketType.UseCircuitCode, UseCircuitCodeHandler); + scene.UDP.RegisterPacketCallback(PacketType.StartPingCheck, StartPingCheckHandler); + scene.UDP.RegisterPacketCallback(PacketType.LogoutRequest, LogoutRequestHandler); + return true; } public void Stop() @@ -32,11 +33,11 @@ namespace Simian.Extensions handshake.RegionInfo.BillableFactor = 0f; handshake.RegionInfo.CacheID = UUID.Random(); handshake.RegionInfo.IsEstateManager = false; - handshake.RegionInfo.RegionFlags = (uint)server.Scene.RegionFlags; + handshake.RegionInfo.RegionFlags = (uint)scene.RegionFlags; handshake.RegionInfo.SimOwner = UUID.Random(); handshake.RegionInfo.SimAccess = (byte)SimAccess.Min; - handshake.RegionInfo.SimName = Utils.StringToBytes(server.Scene.RegionName); - handshake.RegionInfo.WaterHeight = server.Scene.WaterHeight; + handshake.RegionInfo.SimName = Utils.StringToBytes(scene.RegionName); + handshake.RegionInfo.WaterHeight = scene.WaterHeight; handshake.RegionInfo.TerrainBase0 = UUID.Zero; handshake.RegionInfo.TerrainBase1 = UUID.Zero; handshake.RegionInfo.TerrainBase2 = UUID.Zero; @@ -53,9 +54,9 @@ namespace Simian.Extensions handshake.RegionInfo.TerrainStartHeight01 = 40f; handshake.RegionInfo.TerrainStartHeight10 = 0f; handshake.RegionInfo.TerrainStartHeight11 = 40f; - handshake.RegionInfo2.RegionID = server.Scene.RegionID; + handshake.RegionInfo2.RegionID = scene.RegionID; - server.UDP.SendPacket(agent.ID, handshake, PacketCategory.Transaction); + scene.UDP.SendPacket(agent.ID, handshake, PacketCategory.Transaction); } void StartPingCheckHandler(Packet packet, Agent agent) @@ -66,7 +67,7 @@ namespace Simian.Extensions complete.Header.Reliable = false; complete.PingID.PingID = start.PingID.PingID; - server.UDP.SendPacket(agent.ID, complete, PacketCategory.Overhead); + scene.UDP.SendPacket(agent.ID, complete, PacketCategory.Overhead); } void LogoutRequestHandler(Packet packet, Agent agent) @@ -78,9 +79,9 @@ namespace Simian.Extensions reply.InventoryData[0] = new LogoutReplyPacket.InventoryDataBlock(); reply.InventoryData[0].ItemID = UUID.Zero; - server.UDP.SendPacket(agent.ID, reply, PacketCategory.Transaction); + scene.UDP.SendPacket(agent.ID, reply, PacketCategory.Transaction); - server.Scene.ObjectRemove(this, agent.ID); + scene.ObjectRemove(this, agent.ID); } } } diff --git a/Programs/Simian/Extensions/ImageDelivery.cs b/Programs/Simian/SceneExtensions/ImageDelivery.cs similarity index 92% rename from Programs/Simian/Extensions/ImageDelivery.cs rename to Programs/Simian/SceneExtensions/ImageDelivery.cs index fce886cc..27d35a66 100644 --- a/Programs/Simian/Extensions/ImageDelivery.cs +++ b/Programs/Simian/SceneExtensions/ImageDelivery.cs @@ -5,7 +5,7 @@ using ExtensionLoader; using OpenMetaverse; using OpenMetaverse.Packets; -namespace Simian.Extensions +namespace Simian { public class ImageDownload { @@ -102,20 +102,21 @@ namespace Simian.Extensions } } - public class ImageDelivery : IExtension + public class ImageDelivery : IExtension { - Simian server; + ISceneProvider scene; Dictionary CurrentDownloads = new Dictionary(); public ImageDelivery() { } - public void Start(Simian server) + public bool Start(ISceneProvider scene) { - this.server = server; + this.scene = scene; - server.UDP.RegisterPacketCallback(PacketType.RequestImage, RequestImageHandler); + scene.UDP.RegisterPacketCallback(PacketType.RequestImage, RequestImageHandler); + return true; } public void Stop() @@ -170,7 +171,7 @@ namespace Simian.Extensions // New download, check if we have this image Asset asset; - if (server.Assets.TryGetAsset(block.Image, out asset) && asset is AssetTexture) + if (scene.Server.Assets.TryGetAsset(block.Image, out asset) && asset is AssetTexture) { SendTexture(agent, (AssetTexture)asset, block.DiscardLevel, (int)block.Packet, block.DownloadPriority); } @@ -180,7 +181,7 @@ namespace Simian.Extensions ImageNotInDatabasePacket notfound = new ImageNotInDatabasePacket(); notfound.ImageID.ID = block.Image; - server.UDP.SendPacket(agent.ID, notfound, PacketCategory.Texture); + scene.UDP.SendPacket(agent.ID, notfound, PacketCategory.Texture); } } } @@ -217,7 +218,7 @@ namespace Simian.Extensions Helpers.LogLevel.Error); } - server.UDP.SendPacket(agent.ID, data, PacketCategory.Texture); + scene.UDP.SendPacket(agent.ID, data, PacketCategory.Texture); // Check if ImagePacket packets need to be sent to complete this transfer if (download.CurrentPacket <= download.StopPacket) @@ -258,7 +259,7 @@ namespace Simian.Extensions imagePacketSize), Helpers.LogLevel.Error); } - server.UDP.SendPacket(agent.ID, transfer, PacketCategory.Texture); + scene.UDP.SendPacket(agent.ID, transfer, PacketCategory.Texture); ++download.CurrentPacket; } diff --git a/Programs/Simian/Extensions/AvatarManager.cs b/Programs/Simian/SceneExtensions/LLAgents.cs similarity index 70% rename from Programs/Simian/Extensions/AvatarManager.cs rename to Programs/Simian/SceneExtensions/LLAgents.cs index 92ae4d87..6508657c 100644 --- a/Programs/Simian/Extensions/AvatarManager.cs +++ b/Programs/Simian/SceneExtensions/LLAgents.cs @@ -1,91 +1,53 @@ -using System; +using System; using System.Collections.Generic; using System.Threading; using ExtensionLoader; using OpenMetaverse; -using OpenMetaverse.StructuredData; using OpenMetaverse.Packets; -namespace Simian.Extensions +namespace Simian { - class AvatarManager : IExtension, IAvatarProvider + public class LLAgents : IExtension { - Simian server; + ISceneProvider scene; int currentWearablesSerialNum = -1; int currentAnimSequenceNum = 0; - Timer CoarseLocationTimer; + Timer coarseLocationTimer; - public AvatarManager() + public LLAgents() { } - public void Start(Simian server) + public bool Start(ISceneProvider scene) { - this.server = server; + this.scene = scene; - server.UDP.RegisterPacketCallback(PacketType.AvatarPropertiesRequest, AvatarPropertiesRequestHandler); - server.UDP.RegisterPacketCallback(PacketType.AgentWearablesRequest, AgentWearablesRequestHandler); - server.UDP.RegisterPacketCallback(PacketType.AgentIsNowWearing, AgentIsNowWearingHandler); - server.UDP.RegisterPacketCallback(PacketType.AgentSetAppearance, AgentSetAppearanceHandler); - server.UDP.RegisterPacketCallback(PacketType.AgentCachedTexture, AgentCachedTextureHandler); - server.UDP.RegisterPacketCallback(PacketType.AgentHeightWidth, AgentHeightWidthHandler); - server.UDP.RegisterPacketCallback(PacketType.AgentAnimation, AgentAnimationHandler); - server.UDP.RegisterPacketCallback(PacketType.SoundTrigger, SoundTriggerHandler); - server.UDP.RegisterPacketCallback(PacketType.ViewerEffect, ViewerEffectHandler); - server.UDP.RegisterPacketCallback(PacketType.UUIDNameRequest, UUIDNameRequestHandler); + scene.UDP.RegisterPacketCallback(PacketType.AvatarPropertiesRequest, AvatarPropertiesRequestHandler); + scene.UDP.RegisterPacketCallback(PacketType.AgentWearablesRequest, AgentWearablesRequestHandler); + scene.UDP.RegisterPacketCallback(PacketType.AgentIsNowWearing, AgentIsNowWearingHandler); + scene.UDP.RegisterPacketCallback(PacketType.AgentSetAppearance, AgentSetAppearanceHandler); + scene.UDP.RegisterPacketCallback(PacketType.AgentCachedTexture, AgentCachedTextureHandler); + scene.UDP.RegisterPacketCallback(PacketType.AgentHeightWidth, AgentHeightWidthHandler); + scene.UDP.RegisterPacketCallback(PacketType.AgentAnimation, AgentAnimationHandler); + scene.UDP.RegisterPacketCallback(PacketType.SoundTrigger, SoundTriggerHandler); + scene.UDP.RegisterPacketCallback(PacketType.ViewerEffect, ViewerEffectHandler); + scene.UDP.RegisterPacketCallback(PacketType.UUIDNameRequest, UUIDNameRequestHandler); - if (CoarseLocationTimer != null) CoarseLocationTimer.Dispose(); - CoarseLocationTimer = new Timer(CoarseLocationTimer_Elapsed); - CoarseLocationTimer.Change(1000, 1000); + if (coarseLocationTimer != null) coarseLocationTimer.Dispose(); + coarseLocationTimer = new Timer(coarseLocationTimer_Elapsed); + coarseLocationTimer.Change(1000, 1000); + return true; } public void Stop() { - if (CoarseLocationTimer != null) + if (coarseLocationTimer != null) { - CoarseLocationTimer.Dispose(); - CoarseLocationTimer = null; + coarseLocationTimer.Dispose(); + coarseLocationTimer = null; } } - public bool SetDefaultAnimation(Agent agent, UUID animID) - { - return agent.Animations.SetDefaultAnimation(animID, ref currentAnimSequenceNum); - } - - public bool AddAnimation(Agent agent, UUID animID) - { - return agent.Animations.Add(animID, ref currentAnimSequenceNum); - } - - public bool RemoveAnimation(Agent agent, UUID animID) - { - return agent.Animations.Remove(animID); - } - - public bool ClearAnimations(Agent agent) - { - agent.Animations.Clear(); - return true; - } - - public void SendAnimations(Agent agent) - { - server.Scene.ObjectAnimate(this, agent.ID, agent.ID, agent.Animations.GetAnimations()); - } - - public void TriggerSound(Agent agent, UUID soundID, float gain) - { - server.Scene.TriggerSound(this, agent.ID, agent.ID, agent.ID, soundID, agent.Avatar.Prim.Position, gain); - } - - public void SendAlert(Agent agent, string message) - { - AlertMessagePacket alert = new AlertMessagePacket(); - alert.AlertData.Message = Utils.StringToBytes(message); - server.UDP.SendPacket(agent.ID, alert, PacketCategory.Transaction); - } - void AgentAnimationHandler(Packet packet, Agent agent) { AgentAnimationPacket animPacket = (AgentAnimationPacket)packet; @@ -108,7 +70,7 @@ namespace Simian.Extensions } if (changed) - SendAnimations(agent); + scene.Avatars.SendAnimations(agent); } void ViewerEffectHandler(Packet packet, Agent agent) @@ -124,7 +86,7 @@ namespace Simian.Extensions new Color4(block.Color, 0, true), block.Duration, block.TypeData); } - server.Scene.TriggerEffects(this, outgoingEffects); + scene.TriggerEffects(this, outgoingEffects); } void AvatarPropertiesRequestHandler(Packet packet, Agent agent) @@ -132,22 +94,22 @@ namespace Simian.Extensions AvatarPropertiesRequestPacket request = (AvatarPropertiesRequestPacket)packet; Agent foundAgent; - if (server.Scene.TryGetAgent(request.AgentData.AvatarID, out foundAgent)) + if (scene.TryGetAgent(request.AgentData.AvatarID, out foundAgent)) { AvatarPropertiesReplyPacket reply = new AvatarPropertiesReplyPacket(); reply.AgentData.AgentID = agent.ID; reply.AgentData.AvatarID = request.AgentData.AvatarID; - reply.PropertiesData.AboutText = Utils.StringToBytes(foundAgent.ProfileAboutText); - reply.PropertiesData.BornOn = Utils.StringToBytes(foundAgent.ProfileBornOn); + reply.PropertiesData.AboutText = Utils.StringToBytes(foundAgent.Info.ProfileAboutText); + reply.PropertiesData.BornOn = Utils.StringToBytes(foundAgent.Info.ProfileBornOn); reply.PropertiesData.CharterMember = new byte[1]; - reply.PropertiesData.FLAboutText = Utils.StringToBytes(foundAgent.ProfileFirstText); - reply.PropertiesData.Flags = (uint)foundAgent.ProfileFlags; - reply.PropertiesData.FLImageID = foundAgent.ProfileFirstImage; - reply.PropertiesData.ImageID = foundAgent.ProfileImage; - reply.PropertiesData.PartnerID = foundAgent.PartnerID; - reply.PropertiesData.ProfileURL = Utils.StringToBytes(foundAgent.ProfileURL); + reply.PropertiesData.FLAboutText = Utils.StringToBytes(foundAgent.Info.ProfileFirstText); + reply.PropertiesData.Flags = (uint)foundAgent.Info.ProfileFlags; + reply.PropertiesData.FLImageID = foundAgent.Info.ProfileFirstImage; + reply.PropertiesData.ImageID = foundAgent.Info.ProfileImage; + reply.PropertiesData.PartnerID = foundAgent.Info.PartnerID; + reply.PropertiesData.ProfileURL = Utils.StringToBytes(foundAgent.Info.ProfileURL); - server.UDP.SendPacket(agent.ID, reply, PacketCategory.Transaction); + scene.UDP.SendPacket(agent.ID, reply, PacketCategory.Transaction); } else { @@ -156,69 +118,6 @@ namespace Simian.Extensions } } - bool TryAddWearable(UUID agentID, Dictionary wearables, WearableType type, UUID itemID) - { - InventoryObject obj; - if (itemID != UUID.Zero && server.Inventory.TryGetInventory(agentID, itemID, out obj) && - obj is InventoryItem) - { - wearables.Add(type, (InventoryItem)obj); - return true; - } - else - { - return false; - } - } - - Dictionary GetCurrentWearables(Agent agent) - { - Dictionary wearables = new Dictionary(); - - TryAddWearable(agent.ID, wearables, WearableType.Shape, agent.ShapeItem); - TryAddWearable(agent.ID, wearables, WearableType.Skin, agent.SkinItem); - TryAddWearable(agent.ID, wearables, WearableType.Hair, agent.HairItem); - TryAddWearable(agent.ID, wearables, WearableType.Eyes, agent.EyesItem); - TryAddWearable(agent.ID, wearables, WearableType.Shirt, agent.ShirtItem); - TryAddWearable(agent.ID, wearables, WearableType.Pants, agent.PantsItem); - TryAddWearable(agent.ID, wearables, WearableType.Shoes, agent.ShoesItem); - TryAddWearable(agent.ID, wearables, WearableType.Socks, agent.SocksItem); - TryAddWearable(agent.ID, wearables, WearableType.Jacket, agent.JacketItem); - TryAddWearable(agent.ID, wearables, WearableType.Gloves, agent.GlovesItem); - TryAddWearable(agent.ID, wearables, WearableType.Undershirt, agent.UndershirtItem); - TryAddWearable(agent.ID, wearables, WearableType.Underpants, agent.UnderpantsItem); - TryAddWearable(agent.ID, wearables, WearableType.Skirt, agent.SkirtItem); - - return wearables; - } - - void SendWearables(Agent agent) - { - AgentWearablesUpdatePacket update = new AgentWearablesUpdatePacket(); - update.AgentData.AgentID = agent.ID; - - Dictionary wearables = GetCurrentWearables(agent); - update.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[wearables.Count]; - int i = 0; - - foreach (KeyValuePair kvp in wearables) - { - update.WearableData[i] = new AgentWearablesUpdatePacket.WearableDataBlock(); - update.WearableData[i].AssetID = kvp.Value.AssetID; - update.WearableData[i].ItemID = kvp.Value.ID; - update.WearableData[i].WearableType = (byte)kvp.Key; - ++i; - } - - // Technically this should be per-agent, but if the only requirement is that it - // increments this is easier - update.AgentData.SerialNum = (uint)Interlocked.Increment(ref currentWearablesSerialNum); - - Logger.DebugLog(String.Format("Sending info about {0} wearables", wearables.Count)); - - server.UDP.SendPacket(agent.ID, update, PacketCategory.Asset); - } - void AgentWearablesRequestHandler(Packet packet, Agent agent) { SendWearables(agent); @@ -237,43 +136,43 @@ namespace Simian.Extensions switch ((WearableType)wearing.WearableData[i].WearableType) { case WearableType.Shape: - agent.ShapeItem = itemID; + agent.Info.ShapeItem = itemID; break; case WearableType.Skin: - agent.SkinItem = itemID; + agent.Info.SkinItem = itemID; break; case WearableType.Hair: - agent.HairItem = itemID; + agent.Info.HairItem = itemID; break; case WearableType.Eyes: - agent.EyesItem = itemID; + agent.Info.EyesItem = itemID; break; case WearableType.Shirt: - agent.ShirtItem = itemID; + agent.Info.ShirtItem = itemID; break; case WearableType.Pants: - agent.PantsItem = itemID; + agent.Info.PantsItem = itemID; break; case WearableType.Shoes: - agent.ShoesItem = itemID; + agent.Info.ShoesItem = itemID; break; case WearableType.Socks: - agent.SocksItem = itemID; + agent.Info.SocksItem = itemID; break; case WearableType.Jacket: - agent.JacketItem = itemID; + agent.Info.JacketItem = itemID; break; case WearableType.Gloves: - agent.GlovesItem = itemID; + agent.Info.GlovesItem = itemID; break; case WearableType.Undershirt: - agent.UndershirtItem = itemID; + agent.Info.UndershirtItem = itemID; break; case WearableType.Underpants: - agent.UnderpantsItem = itemID; + agent.Info.UnderpantsItem = itemID; break; case WearableType.Skirt: - agent.SkirtItem = itemID; + agent.Info.SkirtItem = itemID; break; } @@ -308,7 +207,7 @@ namespace Simian.Extensions for (int i = 0; i < set.VisualParam.Length; i++) visualParams[i] = set.VisualParam[i].ParamValue; - server.Scene.AgentAppearance(this, agent, textureEntry, visualParams); + scene.AgentAppearance(this, agent, textureEntry, visualParams); } void AgentCachedTextureHandler(Packet packet, Agent agent) @@ -332,7 +231,7 @@ namespace Simian.Extensions response.Header.Zerocoded = true; - server.UDP.SendPacket(agent.ID, response, PacketCategory.Transaction); + scene.UDP.SendPacket(agent.ID, response, PacketCategory.Transaction); } void AgentHeightWidthHandler(Packet packet, Agent agent) @@ -365,10 +264,10 @@ namespace Simian.Extensions reply.UUIDNameBlock[i].ID = id; Agent foundAgent; - if (server.Scene.TryGetAgent(id, out foundAgent)) + if (scene.TryGetAgent(id, out foundAgent)) { - reply.UUIDNameBlock[i].FirstName = Utils.StringToBytes(foundAgent.FirstName); - reply.UUIDNameBlock[i].LastName = Utils.StringToBytes(foundAgent.LastName); + reply.UUIDNameBlock[i].FirstName = Utils.StringToBytes(foundAgent.Info.FirstName); + reply.UUIDNameBlock[i].LastName = Utils.StringToBytes(foundAgent.Info.LastName); } else { @@ -377,16 +276,84 @@ namespace Simian.Extensions } } - server.UDP.SendPacket(agent.ID, reply, PacketCategory.Transaction); + scene.UDP.SendPacket(agent.ID, reply, PacketCategory.Transaction); } - void CoarseLocationTimer_Elapsed(object sender) + void TriggerSound(Agent agent, UUID soundID, float gain) + { + scene.TriggerSound(this, agent.ID, agent.ID, agent.ID, soundID, agent.Avatar.Prim.Position, gain); + } + + void SendWearables(Agent agent) + { + AgentWearablesUpdatePacket update = new AgentWearablesUpdatePacket(); + update.AgentData.AgentID = agent.ID; + + Dictionary wearables = GetCurrentWearables(agent); + update.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[wearables.Count]; + int i = 0; + + foreach (KeyValuePair kvp in wearables) + { + update.WearableData[i] = new AgentWearablesUpdatePacket.WearableDataBlock(); + update.WearableData[i].AssetID = kvp.Value.AssetID; + update.WearableData[i].ItemID = kvp.Value.ID; + update.WearableData[i].WearableType = (byte)kvp.Key; + ++i; + } + + // Technically this should be per-agent, but if the only requirement is that it + // increments this is easier + update.AgentData.SerialNum = (uint)Interlocked.Increment(ref currentWearablesSerialNum); + + Logger.DebugLog(String.Format("Sending info about {0} wearables", wearables.Count)); + + scene.UDP.SendPacket(agent.ID, update, PacketCategory.Asset); + } + + Dictionary GetCurrentWearables(Agent agent) + { + Dictionary wearables = new Dictionary(); + + TryAddWearable(agent.ID, wearables, WearableType.Shape, agent.Info.ShapeItem); + TryAddWearable(agent.ID, wearables, WearableType.Skin, agent.Info.SkinItem); + TryAddWearable(agent.ID, wearables, WearableType.Hair, agent.Info.HairItem); + TryAddWearable(agent.ID, wearables, WearableType.Eyes, agent.Info.EyesItem); + TryAddWearable(agent.ID, wearables, WearableType.Shirt, agent.Info.ShirtItem); + TryAddWearable(agent.ID, wearables, WearableType.Pants, agent.Info.PantsItem); + TryAddWearable(agent.ID, wearables, WearableType.Shoes, agent.Info.ShoesItem); + TryAddWearable(agent.ID, wearables, WearableType.Socks, agent.Info.SocksItem); + TryAddWearable(agent.ID, wearables, WearableType.Jacket, agent.Info.JacketItem); + TryAddWearable(agent.ID, wearables, WearableType.Gloves, agent.Info.GlovesItem); + TryAddWearable(agent.ID, wearables, WearableType.Undershirt, agent.Info.UndershirtItem); + TryAddWearable(agent.ID, wearables, WearableType.Underpants, agent.Info.UnderpantsItem); + TryAddWearable(agent.ID, wearables, WearableType.Skirt, agent.Info.SkirtItem); + + return wearables; + } + + bool TryAddWearable(UUID agentID, Dictionary wearables, WearableType type, UUID itemID) + { + InventoryObject obj; + if (itemID != UUID.Zero && scene.Server.Inventory.TryGetInventory(agentID, itemID, out obj) && + obj is InventoryItem) + { + wearables.Add(type, (InventoryItem)obj); + return true; + } + else + { + return false; + } + } + + void coarseLocationTimer_Elapsed(object sender) { // Create lists containing all of the agent blocks List agentDatas = new List(); List agentLocations = new List(); - server.Scene.ForEachAgent( + scene.ForEachAgent( delegate(Agent agent) { CoarseLocationUpdatePacket.AgentDataBlock dataBlock = new CoarseLocationUpdatePacket.AgentDataBlock(); @@ -402,7 +369,7 @@ namespace Simian.Extensions ); // Send location updates out to each agent - server.Scene.ForEachAgent( + scene.ForEachAgent( delegate(Agent agent) { CoarseLocationUpdatePacket update = new CoarseLocationUpdatePacket(); @@ -431,7 +398,7 @@ namespace Simian.Extensions } } - server.UDP.SendPacket(agent.ID, update, PacketCategory.State); + scene.UDP.SendPacket(agent.ID, update, PacketCategory.State); } ); } diff --git a/Programs/Simian/SceneExtensions/LLInventory.cs b/Programs/Simian/SceneExtensions/LLInventory.cs new file mode 100644 index 00000000..2de1724b --- /dev/null +++ b/Programs/Simian/SceneExtensions/LLInventory.cs @@ -0,0 +1,683 @@ +using System; +using System.Collections.Generic; +using ExtensionLoader; +using OpenMetaverse; +using OpenMetaverse.Packets; + +namespace Simian +{ + public class LLInventory : IExtension + { + ISceneProvider scene; + + public LLInventory() + { + } + + public bool Start(ISceneProvider scene) + { + this.scene = scene; + + scene.UDP.RegisterPacketCallback(PacketType.CreateInventoryItem, CreateInventoryItemHandler); + scene.UDP.RegisterPacketCallback(PacketType.CreateInventoryFolder, CreateInventoryFolderHandler); + scene.UDP.RegisterPacketCallback(PacketType.UpdateInventoryItem, UpdateInventoryItemHandler); + scene.UDP.RegisterPacketCallback(PacketType.FetchInventoryDescendents, FetchInventoryDescendentsHandler); + scene.UDP.RegisterPacketCallback(PacketType.FetchInventory, FetchInventoryHandler); + scene.UDP.RegisterPacketCallback(PacketType.CopyInventoryItem, CopyInventoryItemHandler); + scene.UDP.RegisterPacketCallback(PacketType.MoveInventoryItem, MoveInventoryItemHandler); + scene.UDP.RegisterPacketCallback(PacketType.MoveInventoryFolder, MoveInventoryFolderHandler); + scene.UDP.RegisterPacketCallback(PacketType.PurgeInventoryDescendents, PurgeInventoryDescendentsHandler); + scene.UDP.RegisterPacketCallback(PacketType.DeRezObject, DeRezObjectHandler); + + return true; + } + + public void Stop() + { + } + + void CreateInventoryItemHandler(Packet packet, Agent agent) + { + CreateInventoryItemPacket create = (CreateInventoryItemPacket)packet; + UUID assetID; + if (create.InventoryBlock.TransactionID != UUID.Zero) + assetID = UUID.Combine(create.InventoryBlock.TransactionID, agent.SecureSessionID); + else + assetID = UUID.Random(); + + UUID parentID = (create.InventoryBlock.FolderID != UUID.Zero) ? create.InventoryBlock.FolderID : agent.Info.InventoryRoot; + AssetType assetType = (AssetType)create.InventoryBlock.Type; + + switch (assetType) + { + case AssetType.Gesture: + Logger.Log("Need to create a default gesture asset!", Helpers.LogLevel.Warning); + break; + } + + if (parentID == UUID.Zero) + parentID = agent.Info.InventoryRoot; + + // Create the inventory item + InventoryItem item = scene.Server.Inventory.CreateItem(agent.ID, Utils.BytesToString(create.InventoryBlock.Name), + "Created in Simian", (InventoryType)create.InventoryBlock.InvType, assetType, assetID, parentID, + PermissionMask.All, (PermissionMask)create.InventoryBlock.NextOwnerMask, agent.ID, + agent.ID, create.InventoryBlock.TransactionID, create.InventoryBlock.CallbackID); + + // Send a success response + SendItemCreatedPacket(agent, item, create.InventoryBlock.TransactionID, create.InventoryBlock.CallbackID); + } + + void CreateInventoryFolderHandler(Packet packet, Agent agent) + { + CreateInventoryFolderPacket create = (CreateInventoryFolderPacket)packet; + + UUID folderID = create.FolderData.FolderID; + if (folderID == UUID.Zero) + folderID = agent.Info.InventoryRoot; + + scene.Server.Inventory.CreateFolder(agent.ID, folderID, Utils.BytesToString(create.FolderData.Name), + (AssetType)create.FolderData.Type, create.FolderData.ParentID, agent.ID); + } + + void UpdateInventoryItemHandler(Packet packet, Agent agent) + { + UpdateInventoryItemPacket update = (UpdateInventoryItemPacket)packet; + + // No packet is sent back to the client, we just need to update the + // inventory item locally + for (int i = 0; i < update.InventoryData.Length; i++) + { + UpdateInventoryItemPacket.InventoryDataBlock block = update.InventoryData[i]; + + InventoryObject obj; + if (scene.Server.Inventory.TryGetInventory(agent.ID, block.ItemID, out obj) && obj is InventoryItem) + { + InventoryItem item = (InventoryItem)obj; + + //item.Permissions.BaseMask = (PermissionMask)block.BaseMask; + item.Permissions.BaseMask = PermissionMask.All; + //item.Permissions.EveryoneMask = (PermissionMask)block.EveryoneMask; + item.Permissions.EveryoneMask = PermissionMask.All; + //item.Permissions.GroupMask = (PermissionMask)block.GroupMask; + item.Permissions.GroupMask = PermissionMask.All; + //item.Permissions.NextOwnerMask = (PermissionMask)block.NextOwnerMask; + item.Permissions.NextOwnerMask = PermissionMask.All; + //item.Permissions.OwnerMask = (PermissionMask)block.OwnerMask; + item.Permissions.OwnerMask = PermissionMask.All; + + //block.CRC; + item.CreationDate = Utils.UnixTimeToDateTime(block.CreationDate); + item.CreatorID = block.CreatorID; + item.Name = Utils.BytesToString(block.Description); + item.Flags = block.Flags; + item.ParentID = block.FolderID; + item.GroupID = block.GroupID; + item.GroupOwned = block.GroupOwned; + item.InventoryType = (InventoryType)block.InvType; + item.Name = Utils.BytesToString(block.Name); + item.OwnerID = block.OwnerID; + item.SalePrice = block.SalePrice; + item.SaleType = (SaleType)block.SaleType; + item.AssetType = (AssetType)block.Type; + item.AssetID = UUID.Combine(block.TransactionID, agent.SecureSessionID); + + Logger.DebugLog(String.Format( + "UpdateInventoryItem: CallbackID: {0}, TransactionID: {1}", + block.CallbackID, block.TransactionID)); + } + else + { + Logger.Log("Received an UpdateInventoryItem packet for unknown inventory item " + + block.ItemID.ToString(), Helpers.LogLevel.Warning); + } + } + } + + void FetchInventoryDescendentsHandler(Packet packet, Agent agent) + { + // A very safe estimate of the fixed minimum packet size + const int PACKET_OVERHEAD = 96; + + FetchInventoryDescendentsPacket fetch = (FetchInventoryDescendentsPacket)packet; + bool sendFolders = fetch.InventoryData.FetchFolders; + bool sendItems = fetch.InventoryData.FetchItems; + // TODO: Obey SortOrder + //InventorySortOrder order = (InventorySortOrder)fetch.InventoryData.SortOrder; + + // TODO: Use OwnerID + // TODO: Do we need to obey InventorySortOrder? + InventoryObject invObject; + if (scene.Server.Inventory.TryGetInventory(agent.ID, fetch.InventoryData.FolderID, out invObject) && invObject is InventoryFolder) + { + InventoryFolder folder = (InventoryFolder)invObject; + + int descendCount; + int version; + + List items = new List(); + List folders = new List(); + InventoryDescendentsPacket.FolderDataBlock[] folderBlocks; + InventoryDescendentsPacket.ItemDataBlock[] itemBlocks; + + lock (folder.Children.Dictionary) + { + // These two are coupled to the actual items in the dictionary, + // so they are set inside the lock + descendCount = folder.Children.Count; + version = folder.Version; + + if (sendItems || sendFolders) + { + // Create a list of all of the folders and items under this folder + folder.Children.ForEach( + delegate(InventoryObject obj) + { + if (obj is InventoryItem) + items.Add((InventoryItem)obj); + else + folders.Add((InventoryFolder)obj); + } + ); + } + } + + if (sendFolders) + { + folderBlocks = new InventoryDescendentsPacket.FolderDataBlock[folders.Count]; + for (int i = 0; i < folders.Count; i++) + { + InventoryFolder currentFolder = folders[i]; + + folderBlocks[i] = new InventoryDescendentsPacket.FolderDataBlock(); + folderBlocks[i].FolderID = currentFolder.ID; + folderBlocks[i].Name = Utils.StringToBytes(currentFolder.Name); + folderBlocks[i].ParentID = currentFolder.ParentID; + folderBlocks[i].Type = (sbyte)currentFolder.PreferredType; + } + } + else + { + folderBlocks = new InventoryDescendentsPacket.FolderDataBlock[0]; + } + + if (sendItems) + { + itemBlocks = new InventoryDescendentsPacket.ItemDataBlock[items.Count]; + for (int i = 0; i < items.Count; i++) + { + InventoryItem currentItem = items[i]; + + itemBlocks[i] = new InventoryDescendentsPacket.ItemDataBlock(); + itemBlocks[i].AssetID = currentItem.AssetID; + itemBlocks[i].BaseMask = (uint)currentItem.Permissions.BaseMask; + itemBlocks[i].CRC = currentItem.CRC; + itemBlocks[i].CreationDate = (int)Utils.DateTimeToUnixTime(currentItem.CreationDate); + itemBlocks[i].CreatorID = currentItem.CreatorID; + itemBlocks[i].Description = Utils.StringToBytes(currentItem.Description); + itemBlocks[i].EveryoneMask = (uint)currentItem.Permissions.EveryoneMask; + itemBlocks[i].Flags = currentItem.Flags; + itemBlocks[i].FolderID = currentItem.ParentID; + itemBlocks[i].GroupID = currentItem.GroupID; + itemBlocks[i].GroupMask = (uint)currentItem.Permissions.GroupMask; + itemBlocks[i].GroupOwned = currentItem.GroupOwned; + itemBlocks[i].InvType = (sbyte)currentItem.InventoryType; + itemBlocks[i].ItemID = currentItem.ID; + itemBlocks[i].Name = Utils.StringToBytes(currentItem.Name); + itemBlocks[i].NextOwnerMask = (uint)currentItem.Permissions.NextOwnerMask; + itemBlocks[i].OwnerID = currentItem.OwnerID; + itemBlocks[i].OwnerMask = (uint)currentItem.Permissions.OwnerMask; + itemBlocks[i].SalePrice = currentItem.SalePrice; + itemBlocks[i].SaleType = (byte)currentItem.SaleType; + itemBlocks[i].Type = (sbyte)currentItem.AssetType; + } + } + else + { + itemBlocks = new InventoryDescendentsPacket.ItemDataBlock[0]; + } + + // FolderDataBlock and ItemDataBlock are both variable and possibly very large, + // so we handle the splitting separately. This could be replaced by some custom + // splitting + if (folderBlocks.Length > 0) + { + List splitPoints = Helpers.SplitBlocks(folderBlocks, PACKET_OVERHEAD); + Logger.DebugLog(String.Format("Sending {0} InventoryDescendents packets containing {1} folders", + splitPoints.Count, folderBlocks.Length)); + + for (int i = 0; i < splitPoints.Count; i++) + { + int count = (i != splitPoints.Count - 1) ? splitPoints[i + 1] - splitPoints[i] : + folderBlocks.Length - splitPoints[i]; + + InventoryDescendentsPacket descendents = new InventoryDescendentsPacket(); + descendents.AgentData.AgentID = agent.ID; + descendents.AgentData.FolderID = folder.ID; + descendents.AgentData.OwnerID = folder.OwnerID; + descendents.AgentData.Descendents = descendCount; + descendents.AgentData.Version = version; + descendents.FolderData = new InventoryDescendentsPacket.FolderDataBlock[count]; + descendents.ItemData = new InventoryDescendentsPacket.ItemDataBlock[0]; + + for (int j = 0; j < count; j++) + descendents.FolderData[j] = folderBlocks[splitPoints[i] + j]; + + scene.UDP.SendPacket(agent.ID, descendents, PacketCategory.Inventory); + } + } + else + { + Logger.DebugLog("Sending a single InventoryDescendents for folders"); + + InventoryDescendentsPacket descendents = new InventoryDescendentsPacket(); + descendents.AgentData.AgentID = agent.ID; + descendents.AgentData.FolderID = folder.ID; + descendents.AgentData.OwnerID = folder.OwnerID; + descendents.AgentData.Descendents = descendCount; + descendents.AgentData.Version = version; + descendents.FolderData = new InventoryDescendentsPacket.FolderDataBlock[0]; + descendents.ItemData = new InventoryDescendentsPacket.ItemDataBlock[0]; + + scene.UDP.SendPacket(agent.ID, descendents, PacketCategory.Inventory); + } + + if (itemBlocks.Length > 0) + { + List splitPoints = Helpers.SplitBlocks(itemBlocks, PACKET_OVERHEAD); + Logger.DebugLog(String.Format("Sending {0} InventoryDescendents packets containing {1} items", + splitPoints.Count, itemBlocks.Length)); + + for (int i = 0; i < splitPoints.Count; i++) + { + int count = (i != splitPoints.Count - 1) ? splitPoints[i + 1] - splitPoints[i] : + itemBlocks.Length - splitPoints[i]; + + InventoryDescendentsPacket descendents = new InventoryDescendentsPacket(); + descendents.AgentData.AgentID = agent.ID; + descendents.AgentData.FolderID = folder.ID; + descendents.AgentData.OwnerID = folder.OwnerID; + descendents.AgentData.Descendents = descendCount; + descendents.AgentData.Version = version; + descendents.FolderData = new InventoryDescendentsPacket.FolderDataBlock[0]; + descendents.ItemData = new InventoryDescendentsPacket.ItemDataBlock[count]; + + for (int j = 0; j < count; j++) + descendents.ItemData[j] = itemBlocks[splitPoints[i] + j]; + + scene.UDP.SendPacket(agent.ID, descendents, PacketCategory.Inventory); + } + } + } + else + { + Logger.Log("FetchInventoryDescendents called for an unknown folder " + fetch.InventoryData.FolderID, + Helpers.LogLevel.Warning); + } + } + + void FetchInventoryHandler(Packet packet, Agent agent) + { + // This is probably too large, but better to be on the safe side + const int PACKET_OVERHEAD = 32; + + FetchInventoryPacket fetch = (FetchInventoryPacket)packet; + + // Create all of the blocks first. These will be split up into different packets + FetchInventoryReplyPacket.InventoryDataBlock[] blocks = + new FetchInventoryReplyPacket.InventoryDataBlock[fetch.InventoryData.Length]; + + for (int i = 0; i < fetch.InventoryData.Length; i++) + { + UUID itemID = fetch.InventoryData[i].ItemID; + + blocks[i] = new FetchInventoryReplyPacket.InventoryDataBlock(); + blocks[i].ItemID = itemID; + + InventoryObject obj; + if (scene.Server.Inventory.TryGetInventory(agent.ID, itemID, out obj) && obj is InventoryItem) + { + InventoryItem item = (InventoryItem)obj; + + blocks[i].AssetID = item.AssetID; + blocks[i].BaseMask = (uint)item.Permissions.BaseMask; + blocks[i].CRC = item.CRC; + blocks[i].CreationDate = (int)Utils.DateTimeToUnixTime(item.CreationDate); + blocks[i].CreatorID = item.CreatorID; + blocks[i].Description = Utils.StringToBytes(item.Description); + blocks[i].EveryoneMask = (uint)item.Permissions.EveryoneMask; + blocks[i].Flags = item.Flags; + blocks[i].FolderID = item.ParentID; + blocks[i].GroupID = item.GroupID; + blocks[i].GroupMask = (uint)item.Permissions.GroupMask; + blocks[i].GroupOwned = item.GroupOwned; + blocks[i].InvType = (sbyte)item.InventoryType; + blocks[i].Name = Utils.StringToBytes(item.Name); + blocks[i].NextOwnerMask = (uint)item.Permissions.NextOwnerMask; + blocks[i].OwnerID = item.OwnerID; + blocks[i].OwnerMask = (uint)item.Permissions.OwnerMask; + blocks[i].SalePrice = item.SalePrice; + blocks[i].SaleType = (byte)item.SaleType; + blocks[i].Type = (sbyte)item.AssetType; + } + else + { + Logger.Log("FetchInventory called for an unknown item " + itemID.ToString(), + Helpers.LogLevel.Warning); + + blocks[i].Name = Utils.EmptyBytes; + blocks[i].Description = Utils.EmptyBytes; + } + } + + // Split the blocks up into multiple packets + List splitPoints = Helpers.SplitBlocks(blocks, PACKET_OVERHEAD); + for (int i = 0; i < splitPoints.Count; i++) + { + int count = (i != splitPoints.Count - 1) ? splitPoints[i + 1] - splitPoints[i] : + blocks.Length - splitPoints[i]; + + FetchInventoryReplyPacket reply = new FetchInventoryReplyPacket(); + reply.AgentData.AgentID = agent.ID; + reply.InventoryData = new FetchInventoryReplyPacket.InventoryDataBlock[count]; + + for (int j = 0; j < count; j++) + reply.InventoryData[j] = blocks[splitPoints[i] + j]; + + scene.UDP.SendPacket(agent.ID, reply, PacketCategory.Inventory); + } + } + + void CopyInventoryItemHandler(Packet packet, Agent agent) + { + CopyInventoryItemPacket copy = (CopyInventoryItemPacket)packet; + + for (int i = 0; i < copy.InventoryData.Length; i++) + { + CopyInventoryItemPacket.InventoryDataBlock block = copy.InventoryData[i]; + + // TODO: This allows someone to copy objects from another + // agent's inventory. Should we allow that, or do any + // permission checks? + + // Get the original object + InventoryObject obj; + if (scene.Server.Inventory.TryGetInventory(agent.ID, block.OldItemID, out obj) && obj is InventoryItem) + { + InventoryItem item = (InventoryItem)obj; + + // Get the new folder + InventoryObject folderObj; + if (scene.Server.Inventory.TryGetInventory(agent.ID, block.NewFolderID, out folderObj) && folderObj is InventoryFolder) + { + string newName = Utils.BytesToString(block.NewName); + if (String.IsNullOrEmpty(newName)) + newName = item.Name; + + // Create the copy + InventoryItem newItem = scene.Server.Inventory.CreateItem(agent.ID, newName, item.Description, item.InventoryType, + item.AssetType, item.AssetID, folderObj.ID, item.Permissions.OwnerMask, item.Permissions.NextOwnerMask, + agent.ID, item.CreatorID, UUID.Zero, block.CallbackID); + + SendItemCreatedPacket(agent, newItem, UUID.Zero, block.CallbackID); + } + else + { + Logger.Log("CopyInventoryItem called with an unknown target folder " + block.NewFolderID, + Helpers.LogLevel.Warning); + } + + } + else + { + Logger.Log("CopyInventoryItem called for an unknown item " + block.OldItemID, + Helpers.LogLevel.Warning); + } + } + } + + void MoveInventoryItemHandler(Packet packet, Agent agent) + { + MoveInventoryItemPacket move = (MoveInventoryItemPacket)packet; + // TODO: What is move.AgentData.Stamp for? + + List objs = new List(move.InventoryData.Length); + + for (int i = 0; i < move.InventoryData.Length; i++) + { + MoveInventoryItemPacket.InventoryDataBlock block = move.InventoryData[i]; + UUID newFolderID = block.FolderID; + if (newFolderID == UUID.Zero) + newFolderID = agent.Info.InventoryRoot; + InventoryObject obj = scene.Server.Inventory.MoveInventory(agent.ID, block.ItemID, newFolderID, + Utils.BytesToString(block.NewName), UUID.Zero, 0); + + if (obj != null) objs.Add(obj); + } + + SendBulkUpdate(agent, objs, UUID.Zero, 0); + } + + void MoveInventoryFolderHandler(Packet packet, Agent agent) + { + MoveInventoryFolderPacket move = (MoveInventoryFolderPacket)packet; + // TODO: What is move.AgentData.Stamp for? + + List objs = new List(move.InventoryData.Length); + + for (int i = 0; i < move.InventoryData.Length; i++) + { + MoveInventoryFolderPacket.InventoryDataBlock block = move.InventoryData[i]; + UUID newFolderID = block.ParentID; + if (newFolderID == UUID.Zero) + newFolderID = agent.Info.InventoryRoot; + InventoryObject obj = scene.Server.Inventory.MoveInventory(agent.ID, block.FolderID, newFolderID, + null, UUID.Zero, 0); + + if (obj != null) objs.Add(obj); + } + + SendBulkUpdate(agent, objs, UUID.Zero, 0); + } + + void PurgeInventoryDescendentsHandler(Packet packet, Agent agent) + { + PurgeInventoryDescendentsPacket purge = (PurgeInventoryDescendentsPacket)packet; + scene.Server.Inventory.PurgeFolder(agent.ID, purge.InventoryData.FolderID); + } + + void DeRezObjectHandler(Packet packet, Agent agent) + { + DeRezObjectPacket derez = (DeRezObjectPacket)packet; + DeRezDestination destination = (DeRezDestination)derez.AgentBlock.Destination; + + // TODO: Check permissions + for (int i = 0; i < derez.ObjectData.Length; i++) + { + uint localID = derez.ObjectData[i].ObjectLocalID; + + SimulationObject obj; + if (scene.TryGetObject(localID, out obj)) + { + switch (destination) + { + case DeRezDestination.AgentInventorySave: + Logger.Log("DeRezObject: Got an AgentInventorySave, DestID: " + + derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning); + break; + case DeRezDestination.AgentInventoryCopy: + Logger.Log("DeRezObject: Got an AgentInventorySave, DestID: " + + derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning); + break; + case DeRezDestination.TaskInventory: + Logger.Log("DeRezObject: Got a TaskInventory, DestID: " + + derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning); + break; + case DeRezDestination.Attachment: + Logger.Log("DeRezObject: Got an Attachment, DestID: " + + derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning); + break; + case DeRezDestination.AgentInventoryTake: + Logger.Log("DeRezObject: Got an AgentInventoryTake, DestID: " + + derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning); + break; + case DeRezDestination.ForceToGodInventory: + Logger.Log("DeRezObject: Got a ForceToGodInventory, DestID: " + + derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning); + break; + case DeRezDestination.TrashFolder: + InventoryObject invObj; + if (scene.Server.Inventory.TryGetInventory(agent.ID, derez.AgentBlock.DestinationID, out invObj) && + invObj is InventoryFolder) + { + // FIXME: Handle children + InventoryFolder trash = (InventoryFolder)invObj; + InventoryItem item = scene.Server.Inventory.CreateItem(agent.ID, obj.Prim.Properties.Name, + obj.Prim.Properties.Description, InventoryType.Object, AssetType.Object, obj.Prim.ID, + trash.ID, PermissionMask.All, PermissionMask.All, agent.ID, obj.Prim.Properties.CreatorID, + derez.AgentBlock.TransactionID, 0); + scene.ObjectRemove(this, obj.Prim.LocalID); + + SendItemCreatedPacket(agent, item, derez.AgentBlock.TransactionID, 0); + Logger.DebugLog(String.Format("Derezzed prim {0} to agent inventory trash", obj.Prim.LocalID)); + } + else + { + Logger.Log("DeRezObject: Got a TrashFolder with an invalid trash folder: " + + derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning); + } + break; + case DeRezDestination.AttachmentToInventory: + Logger.Log("DeRezObject: Got an AttachmentToInventory, DestID: " + + derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning); + break; + case DeRezDestination.AttachmentExists: + Logger.Log("DeRezObject: Got an AttachmentExists, DestID: " + + derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning); + break; + case DeRezDestination.ReturnToOwner: + Logger.Log("DeRezObject: Got a ReturnToOwner, DestID: " + + derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning); + break; + case DeRezDestination.ReturnToLastOwner: + Logger.Log("DeRezObject: Got a ReturnToLastOwner, DestID: " + + derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning); + break; + } + } + } + } + + void SendItemCreatedPacket(Agent agent, InventoryItem item, UUID transactionID, uint callbackID) + { + UpdateCreateInventoryItemPacket update = new UpdateCreateInventoryItemPacket(); + update.AgentData.AgentID = agent.ID; + update.AgentData.SimApproved = true; + if (transactionID != UUID.Zero) + update.AgentData.TransactionID = transactionID; + else + update.AgentData.TransactionID = UUID.Random(); + update.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1]; + update.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock(); + update.InventoryData[0].AssetID = item.AssetID; + update.InventoryData[0].BaseMask = (uint)item.Permissions.BaseMask; + update.InventoryData[0].CallbackID = callbackID; + update.InventoryData[0].CreationDate = (int)Utils.DateTimeToUnixTime(item.CreationDate); + update.InventoryData[0].CRC = item.CRC; + update.InventoryData[0].CreatorID = item.CreatorID; + update.InventoryData[0].Description = Utils.StringToBytes(item.Description); + update.InventoryData[0].EveryoneMask = (uint)item.Permissions.EveryoneMask; + update.InventoryData[0].Flags = item.Flags; + update.InventoryData[0].FolderID = item.ParentID; + update.InventoryData[0].GroupID = item.GroupID; + update.InventoryData[0].GroupMask = (uint)item.Permissions.GroupMask; + update.InventoryData[0].GroupOwned = item.GroupOwned; + update.InventoryData[0].InvType = (sbyte)item.InventoryType; + update.InventoryData[0].ItemID = item.ID; + update.InventoryData[0].Name = Utils.StringToBytes(item.Name); + update.InventoryData[0].NextOwnerMask = (uint)item.Permissions.NextOwnerMask; + update.InventoryData[0].OwnerID = item.OwnerID; + update.InventoryData[0].OwnerMask = (uint)item.Permissions.OwnerMask; + update.InventoryData[0].SalePrice = item.SalePrice; + update.InventoryData[0].SaleType = (byte)item.SaleType; + update.InventoryData[0].Type = (sbyte)item.AssetType; + + scene.UDP.SendPacket(agent.ID, update, PacketCategory.Inventory); + } + + void SendBulkUpdate(Agent agent, List objs, UUID transactionID, uint callbackID) + { + BulkUpdateInventoryPacket update = new BulkUpdateInventoryPacket(); + update.AgentData.AgentID = agent.ID; + update.AgentData.TransactionID = transactionID; + + // Count the number of folders and items + int items = 0; + int folders = 0; + for (int i = 0; i < objs.Count; i++) + { + if (objs[i] is InventoryItem) + ++items; + else + ++folders; + } + + update.FolderData = new BulkUpdateInventoryPacket.FolderDataBlock[folders]; + update.ItemData = new BulkUpdateInventoryPacket.ItemDataBlock[items]; + + items = 0; + folders = 0; + + for (int i = 0; i < objs.Count; i++) + { + InventoryObject obj = objs[i]; + + if (obj is InventoryItem) + { + InventoryItem item = (InventoryItem)obj; + + update.ItemData[items] = new BulkUpdateInventoryPacket.ItemDataBlock(); + update.ItemData[items].AssetID = item.AssetID; + update.ItemData[items].BaseMask = (uint)item.Permissions.BaseMask; + update.ItemData[items].CallbackID = callbackID; + update.ItemData[items].CRC = item.CRC; + update.ItemData[items].CreationDate = (int)Utils.DateTimeToUnixTime(item.CreationDate); + update.ItemData[items].CreatorID = item.CreatorID; + update.ItemData[items].Description = Utils.StringToBytes(item.Description); + update.ItemData[items].EveryoneMask = (uint)item.Permissions.EveryoneMask; + update.ItemData[items].Flags = item.Flags; + update.ItemData[items].FolderID = item.ParentID; + update.ItemData[items].GroupID = item.GroupID; + update.ItemData[items].GroupMask = (uint)item.Permissions.GroupMask; + update.ItemData[items].GroupOwned = item.GroupOwned; + update.ItemData[items].InvType = (sbyte)item.InventoryType; + update.ItemData[items].ItemID = item.ID; + update.ItemData[items].Name = Utils.StringToBytes(item.Name); + update.ItemData[items].NextOwnerMask = (uint)item.Permissions.NextOwnerMask; + update.ItemData[items].OwnerID = item.OwnerID; + update.ItemData[items].OwnerMask = (uint)item.Permissions.OwnerMask; + update.ItemData[items].SalePrice = item.SalePrice; + update.ItemData[items].SaleType = (byte)item.SaleType; + update.ItemData[items].Type = (sbyte)item.InventoryType; + + ++items; + } + else + { + InventoryFolder folder = (InventoryFolder)obj; + + update.FolderData[folders] = new BulkUpdateInventoryPacket.FolderDataBlock(); + update.FolderData[folders].FolderID = folder.ID; + update.FolderData[folders].Name = Utils.StringToBytes(folder.Name); + update.FolderData[folders].ParentID = folder.ParentID; + update.FolderData[folders].Type = (sbyte)folder.PreferredType; + + ++folders; + } + } + + Logger.DebugLog("Sending bulk update for " + items + " items and " + folders + " folders"); + scene.UDP.SendPacket(agent.ID, update, PacketCategory.Inventory); + } + } +} diff --git a/Programs/Simian/SceneExtensions/LLMap.cs b/Programs/Simian/SceneExtensions/LLMap.cs new file mode 100644 index 00000000..50fe44ac --- /dev/null +++ b/Programs/Simian/SceneExtensions/LLMap.cs @@ -0,0 +1,595 @@ +using System; +using System.IO; +using System.Net; +using System.Xml; +using ExtensionLoader; +using OpenMetaverse; +using OpenMetaverse.Packets; +using OpenMetaverse.StructuredData; + +namespace Simian +{ + class HyperGridLink + { + public string RegionName; + public ulong RegionHandle; + public UUID RegionID; + public UUID RegionImage; + public int UDPPort; + public int RemotingPort; + } + + public class LLMap : IExtension + { + ISceneProvider scene; + + public LLMap() + { + } + + public bool Start(ISceneProvider scene) + { + this.scene = scene; + + scene.UDP.RegisterPacketCallback(PacketType.MapLayerRequest, MapLayerRequestHandler); + scene.UDP.RegisterPacketCallback(PacketType.MapBlockRequest, MapBlockRequestHandler); + scene.UDP.RegisterPacketCallback(PacketType.TeleportRequest, TeleportRequestHandler); + scene.UDP.RegisterPacketCallback(PacketType.TeleportLocationRequest, TeleportLocationRequestHandler); + return true; + } + + public void Stop() + { + } + + void MapLayerRequestHandler(Packet packet, Agent agent) + { + MapLayerRequestPacket request = (MapLayerRequestPacket)packet; + GridLayerType type = (GridLayerType)request.AgentData.Flags; + + MapLayerReplyPacket reply = new MapLayerReplyPacket(); + reply.AgentData.AgentID = agent.ID; + reply.AgentData.Flags = (uint)type; + reply.LayerData = new MapLayerReplyPacket.LayerDataBlock[1]; + reply.LayerData[0] = new MapLayerReplyPacket.LayerDataBlock(); + reply.LayerData[0].Bottom = 0; + reply.LayerData[0].Left = 0; + reply.LayerData[0].Top = UInt16.MaxValue; + reply.LayerData[0].Right = UInt16.MaxValue; + reply.LayerData[0].ImageID = new UUID("89556747-24cb-43ed-920b-47caed15465f"); + + scene.UDP.SendPacket(agent.ID, reply, PacketCategory.Transaction); + } + + void MapBlockRequestHandler(Packet packet, Agent agent) + { + MapBlockRequestPacket request = (MapBlockRequestPacket)packet; + GridLayerType type = (GridLayerType)request.AgentData.Flags; + + MapBlockReplyPacket reply = new MapBlockReplyPacket(); + reply.AgentData.AgentID = agent.ID; + reply.AgentData.Flags = (uint)type; + + reply.Data = new MapBlockReplyPacket.DataBlock[2]; + + reply.Data[0] = new MapBlockReplyPacket.DataBlock(); + reply.Data[0].Access = (byte)SimAccess.Min; + reply.Data[0].Agents = (byte)scene.AgentCount(); + reply.Data[0].MapImageID = new UUID("89556747-24cb-43ed-920b-47caed15465f"); + reply.Data[0].Name = Utils.StringToBytes(scene.RegionName); + reply.Data[0].RegionFlags = (uint)scene.RegionFlags; + reply.Data[0].WaterHeight = (byte)scene.WaterHeight; + reply.Data[0].X = (ushort)scene.RegionX; + reply.Data[0].Y = (ushort)scene.RegionY; + + reply.Data[1] = new MapBlockReplyPacket.DataBlock(); + reply.Data[1].Access = (byte)SimAccess.Min; + reply.Data[1].Agents = 0; + reply.Data[1].MapImageID = new UUID("89556747-24cb-43ed-920b-47caed15465f"); + reply.Data[1].Name = Utils.StringToBytes("HyperGrid Portal to OSGrid"); + reply.Data[1].RegionFlags = (uint)scene.RegionFlags; + reply.Data[1].WaterHeight = (byte)scene.WaterHeight; + reply.Data[1].X = (ushort)(scene.RegionX + 1); + reply.Data[1].Y = (ushort)scene.RegionY; + + scene.UDP.SendPacket(agent.ID, reply, PacketCategory.Transaction); + } + + void TeleportRequestHandler(Packet packet, Agent agent) + { + TeleportRequestPacket request = (TeleportRequestPacket)packet; + + // TODO: Stand the avatar up first + + if (request.Info.RegionID == scene.RegionID) + { + // Local teleport + agent.Avatar.Prim.Position = request.Info.Position; + agent.CurrentLookAt = request.Info.LookAt; + + // TODO: Actually adjust the agent's LookAt + + TeleportLocalPacket reply = new TeleportLocalPacket(); + reply.Info.AgentID = agent.ID; + reply.Info.LocationID = 0; // Unused by the client + reply.Info.LookAt = agent.CurrentLookAt; + reply.Info.Position = agent.Avatar.Prim.Position; + // TODO: Need a "Flying" boolean for Agent + reply.Info.TeleportFlags = (uint)TeleportFlags.ViaRegionID; + + scene.UDP.SendPacket(agent.ID, reply, PacketCategory.Transaction); + } + else + { + TeleportFailedPacket reply = new TeleportFailedPacket(); + reply.Info.AgentID = agent.ID; + reply.Info.Reason = Utils.StringToBytes("Unknown region"); + + scene.UDP.SendPacket(agent.ID, reply, PacketCategory.Transaction); + } + } + + void TeleportLocationRequestHandler(Packet packet, Agent agent) + { + TeleportLocationRequestPacket request = (TeleportLocationRequestPacket)packet; + + // TODO: Stand the avatar up first + + if (request.Info.RegionHandle == scene.RegionHandle) + { + // Local teleport + agent.Avatar.Prim.Position = request.Info.Position; + agent.CurrentLookAt = request.Info.LookAt; + + TeleportLocalPacket reply = new TeleportLocalPacket(); + reply.Info.AgentID = agent.ID; + reply.Info.LocationID = 0; // Unused by the client + reply.Info.LookAt = agent.CurrentLookAt; + reply.Info.Position = agent.Avatar.Prim.Position; + // TODO: Need a "Flying" boolean for Agent + reply.Info.TeleportFlags = (uint)TeleportFlags.ViaLocation; + + scene.UDP.SendPacket(agent.ID, reply, PacketCategory.Transaction); + } + else if (request.Info.RegionHandle == Utils.UIntsToLong((scene.RegionX + 1) * 256, scene.RegionY * 256)) + { + // Special case: adjacent simulator is the HyperGrid portal + HyperGridTeleport(agent, new Uri("http://osl2.nac.uci.edu:9006/"), request.Info.Position); + } + else + { + TeleportFailedPacket reply = new TeleportFailedPacket(); + reply.Info.AgentID = agent.ID; + reply.Info.Reason = Utils.StringToBytes("Unknown region"); + + scene.UDP.SendPacket(agent.ID, reply, PacketCategory.Transaction); + } + } + + bool HyperGridTeleport(Agent agent, Uri destination, Vector3 destPos) + { + HyperGridLink link; + + TeleportProgress(agent, "Resolving destination IP address", TeleportFlags.ViaLocation); + + IPHostEntry entry = Dns.GetHostEntry(destination.DnsSafeHost); + if (entry.AddressList != null && entry.AddressList.Length >= 1) + { + TeleportProgress(agent, "Retrieving destination details", TeleportFlags.ViaLocation); + + if (LinkRegion(destination, out link)) + { + TeleportProgress(agent, "Creating foreign agent", TeleportFlags.ViaLocation); + + // This is a crufty part of the HyperGrid protocol. We need to generate a fragment of a UUID + // (missing the last four digits) and send that as the caps_path variable. Locally, we expand + // that out to http://foreignsim:httpport/CAPS/fragment0000/ and use it as the seed caps path + // that is sent to the client + UUID seedID = UUID.Random(); + string seedCapFragment = seedID.ToString().Substring(0, 32); + Uri seedCap = new Uri(destination, "/CAPS/" + seedCapFragment + "0000/"); + + if (ExpectHyperGridUser(agent, destination, destPos, link, seedCap)) + { + TeleportProgress(agent, "Establishing foreign agent presence", TeleportFlags.ViaLocation); + + if (CreateChildAgent(agent, destination, destPos, link, seedCapFragment)) + { + // Send the final teleport message to the client + if (scene.HasRunningEventQueue(agent)) + { + uint x, y; + Utils.LongToUInts(link.RegionHandle, out x, out y); + x /= 256; + y /= 256; + Logger.Log(String.Format("HyperGrid teleporting to {0} ({1}, {2}) @ {3}", + link.RegionName, x, y, destination), Helpers.LogLevel.Info); + + OSDMap info = new OSDMap(); + info.Add("AgentID", OSD.FromUUID(agent.ID)); + info.Add("LocationID", OSD.FromInteger(4)); // Unused by the client + info.Add("RegionHandle", OSD.FromULong(link.RegionHandle)); + info.Add("SeedCapability", OSD.FromUri(seedCap)); + info.Add("SimAccess", OSD.FromInteger((byte)SimAccess.Min)); + info.Add("SimIP", OSD.FromBinary(entry.AddressList[0].GetAddressBytes())); + info.Add("SimPort", OSD.FromInteger(link.UDPPort)); + info.Add("TeleportFlags", OSD.FromUInteger((uint)TeleportFlags.ViaLocation)); + + OSDArray infoArray = new OSDArray(1); + infoArray.Add(info); + + OSDMap teleport = new OSDMap(); + teleport.Add("Info", infoArray); + + scene.SendEvent(agent, "TeleportFinish", teleport); + } + else + { + Logger.Log("No running EventQueue for " + agent.FullName + ", sending TeleportFinish over UDP", + Helpers.LogLevel.Warning); + + TeleportFinishPacket teleport = new TeleportFinishPacket(); + teleport.Info.AgentID = agent.ID; + teleport.Info.LocationID = 0; // Unused by the client + teleport.Info.RegionHandle = link.RegionHandle; + teleport.Info.SeedCapability = Utils.StringToBytes(seedCap.ToString()); + teleport.Info.SimAccess = (byte)SimAccess.Min; + teleport.Info.SimIP = Utils.BytesToUInt(entry.AddressList[0].GetAddressBytes()); + teleport.Info.SimPort = (ushort)link.UDPPort; + teleport.Info.TeleportFlags = (uint)TeleportFlags.ViaLocation; + + scene.UDP.SendPacket(agent.ID, teleport, PacketCategory.Transaction); + } + + // Remove the agent from the local scene (will also tear down the UDP connection) + //scene.ObjectRemove(this, agent.ID); + + return true; + } + } + } + } + + return false; + } + + bool LinkRegion(Uri destination, out HyperGridLink link) + { + try + { + #region Build Request + + HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(destination); + request.Method = "POST"; + request.ContentType = "text/xml"; + + MemoryStream memoryStream = new MemoryStream(); + using (XmlWriter writer = XmlWriter.Create(memoryStream)) + { + writer.WriteStartElement("methodCall"); + { + writer.WriteElementString("methodName", "link_region"); + + writer.WriteStartElement("params"); + writer.WriteStartElement("param"); + writer.WriteStartElement("value"); + writer.WriteStartElement("struct"); + { + WriteStringMember(writer, "region_name", String.Empty); + } + writer.WriteEndElement(); + writer.WriteEndElement(); + writer.WriteEndElement(); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + + writer.Flush(); + } + + request.ContentLength = memoryStream.Length; + + using (Stream writeStream = request.GetRequestStream()) + { + writeStream.Write(memoryStream.GetBuffer(), 0, (int)memoryStream.Length); + } + + #endregion Build Request + + #region Parse Response + + HttpWebResponse response = (HttpWebResponse)request.GetResponse(); + + XmlReaderSettings settings = new XmlReaderSettings(); + settings.IgnoreComments = true; + settings.IgnoreWhitespace = true; + + using (XmlReader reader = XmlReader.Create(response.GetResponseStream(), settings)) + { + link = new HyperGridLink(); + + reader.ReadStartElement("methodResponse"); + { + reader.ReadStartElement("params"); + reader.ReadStartElement("param"); + reader.ReadStartElement("value"); + reader.ReadStartElement("struct"); + { + while (reader.Name == "member") + { + reader.ReadStartElement("member"); + { + string name = reader.ReadElementContentAsString("name", String.Empty); + + reader.ReadStartElement("value"); + { + switch (name) + { + case "region_name": + link.RegionName = reader.ReadElementContentAsString("string", String.Empty); + break; + case "handle": + string handle = reader.ReadElementContentAsString("string", String.Empty); + link.RegionHandle = UInt64.Parse(handle); + break; + case "uuid": + string uuid = reader.ReadElementContentAsString("string", String.Empty); + link.RegionID = UUID.Parse(uuid); + break; + case "internal_port": + link.UDPPort = reader.ReadElementContentAsInt("string", String.Empty); + break; + case "region_image": + string imageuuid = reader.ReadElementContentAsString("string", String.Empty); + link.RegionImage = UUID.Parse(imageuuid); + break; + case "remoting_port": + link.RemotingPort = reader.ReadElementContentAsInt("string", String.Empty); + break; + default: + Logger.Log("[HyperGrid] Unrecognized response XML chunk: " + reader.ReadInnerXml(), + Helpers.LogLevel.Warning); + break; + } + } + reader.ReadEndElement(); + } + reader.ReadEndElement(); + } + } + reader.ReadEndElement(); + reader.ReadEndElement(); + reader.ReadEndElement(); + reader.ReadEndElement(); + } + reader.ReadEndElement(); + + return true; + } + + #endregion Parse Response + } + catch (Exception ex) + { + Logger.Log(ex.Message, Helpers.LogLevel.Error, ex); + } + + link = null; + return false; + } + + bool ExpectHyperGridUser(Agent agent, Uri destination, Vector3 destPos, HyperGridLink link, Uri seedCap) + { + try + { + #region Build Request + + HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(destination); + request.Method = "POST"; + request.ContentType = "text/xml"; + + MemoryStream memoryStream = new MemoryStream(); + using (XmlWriter writer = XmlWriter.Create(memoryStream)) + { + writer.WriteStartElement("methodCall"); + { + writer.WriteElementString("methodName", "expect_hg_user"); + + writer.WriteStartElement("params"); + writer.WriteStartElement("param"); + writer.WriteStartElement("value"); + writer.WriteStartElement("struct"); + { + WriteStringMember(writer, "session_id", agent.SessionID.ToString()); + WriteStringMember(writer, "secure_session_id", agent.SecureSessionID.ToString()); + WriteStringMember(writer, "firstname", agent.Info.FirstName); + WriteStringMember(writer, "lastname", agent.Info.LastName); + WriteStringMember(writer, "agent_id", agent.ID.ToString()); + WriteStringMember(writer, "circuit_code", agent.CircuitCode.ToString()); + WriteStringMember(writer, "startpos_x", destPos.X.ToString(Utils.EnUsCulture)); + WriteStringMember(writer, "startpos_y", destPos.Y.ToString(Utils.EnUsCulture)); + WriteStringMember(writer, "startpos_z", destPos.Z.ToString(Utils.EnUsCulture)); + WriteStringMember(writer, "caps_path", seedCap.ToString()); + + WriteStringMember(writer, "region_uuid", link.RegionID.ToString()); + //WriteStringMember(writer, "userserver_id", ""); + //WriteStringMember(writer, "assetserver_id", ""); + //WriteStringMember(writer, "inventoryserver_id", ""); + WriteStringMember(writer, "root_folder_id", agent.Info.InventoryRoot.ToString()); + + string port = scene.Server.HttpUri.Port.ToString(); + + WriteStringMember(writer, "internal_port", port); + WriteStringMember(writer, "regionhandle", scene.RegionHandle.ToString()); + WriteStringMember(writer, "home_address", IPAddress.Loopback.ToString()); + WriteStringMember(writer, "home_port", port); + WriteStringMember(writer, "home_remoting", port); + } + writer.WriteEndElement(); + writer.WriteEndElement(); + writer.WriteEndElement(); + writer.WriteEndElement(); + } + writer.WriteEndElement(); + + writer.Flush(); + } + + request.ContentLength = memoryStream.Length; + + using (Stream writeStream = request.GetRequestStream()) + { + writeStream.Write(memoryStream.GetBuffer(), 0, (int)memoryStream.Length); + } + + #endregion Build Request + + #region Parse Response + + HttpWebResponse response = (HttpWebResponse)request.GetResponse(); + + XmlReaderSettings settings = new XmlReaderSettings(); + settings.IgnoreComments = true; + settings.IgnoreWhitespace = true; + + using (XmlReader reader = XmlReader.Create(response.GetResponseStream(), settings)) + { + bool success = false; + string reason = String.Empty; + + reader.ReadStartElement("methodResponse"); + { + reader.ReadStartElement("params"); + reader.ReadStartElement("param"); + reader.ReadStartElement("value"); + reader.ReadStartElement("struct"); + { + while (reader.Name == "member") + { + reader.ReadStartElement("member"); + { + string name = reader.ReadElementContentAsString("name", String.Empty); + + reader.ReadStartElement("value"); + { + switch (name) + { + case "success": + success = (reader.ReadElementContentAsString("string", String.Empty).ToUpper() == "TRUE"); + break; + case "reason": + reason = reader.ReadElementContentAsString("string", String.Empty); + break; + default: + Logger.Log("[HyperGrid] Unrecognized response XML chunk: " + reader.ReadInnerXml(), + Helpers.LogLevel.Warning); + break; + } + } + reader.ReadEndElement(); + } + reader.ReadEndElement(); + } + } + reader.ReadEndElement(); + reader.ReadEndElement(); + reader.ReadEndElement(); + reader.ReadEndElement(); + } + reader.ReadEndElement(); + + if (!success) + Logger.Log("[HyperGrid] Teleport failed, reason: " + reason, Helpers.LogLevel.Warning); + + return success; + } + + #endregion Parse Response + } + catch (Exception ex) + { + Logger.Log(ex.Message, Helpers.LogLevel.Error, ex); + } + + return false; + } + + bool CreateChildAgent(Agent agent, Uri destination, Vector3 destPos, HyperGridLink link, string seedCapFragment) + { + try + { + destination = new Uri(destination, "/agent/" + agent.ID.ToString() + "/"); + + OSDMap args = new OSDMap(); + args["agent_id"] = OSD.FromUUID(agent.ID); + args["base_folder"] = OSD.FromUUID(UUID.Zero); + args["caps_path"] = OSD.FromString(seedCapFragment); + args["children_seeds"] = OSD.FromBoolean(false); + args["child"] = OSD.FromBoolean(false); + args["circuit_code"] = OSD.FromString(agent.CircuitCode.ToString()); + args["first_name"] = OSD.FromString(agent.Info.FirstName); + args["last_name"] = OSD.FromString(agent.Info.LastName); + args["inventory_folder"] = OSD.FromUUID(agent.Info.InventoryRoot); + args["secure_session_id"] = OSD.FromUUID(agent.SecureSessionID); + args["session_id"] = OSD.FromUUID(agent.SessionID); + args["start_pos"] = OSD.FromString(destPos.ToString()); + args["destination_handle"] = OSD.FromString(link.RegionHandle.ToString()); + + LitJson.JsonData jsonData = OSDParser.SerializeJson(args); + byte[] data = System.Text.Encoding.UTF8.GetBytes(jsonData.ToJson()); + + HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(destination); + request.Method = "POST"; + request.ContentType = "application/json"; + request.ContentLength = data.Length; + + using (Stream requestStream = request.GetRequestStream()) + { + requestStream.Write(data, 0, data.Length); + requestStream.Flush(); + } + + HttpWebResponse response = (HttpWebResponse)request.GetResponse(); + + bool success = false; + using (StreamReader reader = new StreamReader(response.GetResponseStream())) + { + Boolean.TryParse(reader.ReadToEnd(), out success); + } + + return success; + } + catch (Exception ex) + { + Logger.Log(ex.Message, Helpers.LogLevel.Error, ex); + } + + return false; + } + + void TeleportProgress(Agent agent, string message, TeleportFlags flags) + { + TeleportProgressPacket progress = new TeleportProgressPacket(); + progress.AgentData.AgentID = agent.ID; + progress.Info.Message = Utils.StringToBytes(message); + progress.Info.TeleportFlags = (uint)flags; + + scene.UDP.SendPacket(agent.ID, progress, PacketCategory.Transaction); + } + + static void WriteStringMember(XmlWriter writer, string name, string value) + { + writer.WriteStartElement("member"); + { + writer.WriteElementString("name", name); + + writer.WriteStartElement("value"); + { + writer.WriteElementString("string", value); + } + writer.WriteEndElement(); + } + writer.WriteEndElement(); + } + } +} diff --git a/Programs/Simian/Extensions/FriendManager.cs b/Programs/Simian/SceneExtensions/LLMessaging.cs similarity index 51% rename from Programs/Simian/Extensions/FriendManager.cs rename to Programs/Simian/SceneExtensions/LLMessaging.cs index e23b6e8c..75f79813 100644 --- a/Programs/Simian/Extensions/FriendManager.cs +++ b/Programs/Simian/SceneExtensions/LLMessaging.cs @@ -4,40 +4,79 @@ using ExtensionLoader; using OpenMetaverse; using OpenMetaverse.Packets; -namespace Simian.Extensions +namespace Simian { - public class FriendManager : IExtension + public class LLMessaging : IExtension { - Simian server; + ISceneProvider scene; - public FriendManager() + public LLMessaging() { } - public void Start(Simian server) + public bool Start(ISceneProvider scene) { - this.server = server; + this.scene = scene; - server.UDP.RegisterPacketCallback(PacketType.ImprovedInstantMessage, new PacketCallback(ImprovedInstantMessageHandler)); + scene.UDP.RegisterPacketCallback(PacketType.ChatFromViewer, ChatFromViewerHandler); + scene.UDP.RegisterPacketCallback(PacketType.ImprovedInstantMessage, ImprovedInstantMessageHandler); + return true; } public void Stop() { } + void ChatFromViewerHandler(Packet packet, Agent agent) + { + ChatFromViewerPacket viewerChat = (ChatFromViewerPacket)packet; + + scene.ObjectChat(this, agent.ID, agent.ID, ChatAudibleLevel.Fully, (ChatType)viewerChat.ChatData.Type, + ChatSourceType.Agent, agent.FullName, agent.Avatar.GetSimulatorPosition(), viewerChat.ChatData.Channel, + Utils.BytesToString(viewerChat.ChatData.Message)); + } + void ImprovedInstantMessageHandler(Packet packet, Agent agent) { ImprovedInstantMessagePacket im = (ImprovedInstantMessagePacket)packet; InstantMessageDialog dialog = (InstantMessageDialog)im.MessageBlock.Dialog; - if (dialog == InstantMessageDialog.FriendshipOffered || dialog == InstantMessageDialog.FriendshipAccepted || dialog == InstantMessageDialog.FriendshipDeclined) + if (dialog == InstantMessageDialog.MessageFromAgent) { // HACK: Only works for agents currently online Agent recipient; - if (server.Scene.TryGetAgent(im.MessageBlock.ToAgentID, out recipient)) + if (scene.TryGetAgent(im.MessageBlock.ToAgentID, out recipient)) + { + // FIXME: Look into the fields we are setting to default values + ImprovedInstantMessagePacket sendIM = new ImprovedInstantMessagePacket(); + sendIM.MessageBlock.RegionID = scene.RegionID; + sendIM.MessageBlock.ParentEstateID = 1; + sendIM.MessageBlock.FromGroup = false; + sendIM.MessageBlock.FromAgentName = Utils.StringToBytes(agent.FullName); + sendIM.MessageBlock.ToAgentID = im.MessageBlock.ToAgentID; + sendIM.MessageBlock.Dialog = im.MessageBlock.Dialog; + sendIM.MessageBlock.Offline = (byte)InstantMessageOnline.Online; + sendIM.MessageBlock.ID = agent.ID; + sendIM.MessageBlock.Message = im.MessageBlock.Message; + sendIM.MessageBlock.BinaryBucket = Utils.EmptyBytes; + sendIM.MessageBlock.Timestamp = Utils.DateTimeToUnixTime(DateTime.Now); + sendIM.MessageBlock.Position = agent.Avatar.GetSimulatorPosition(); + + sendIM.AgentData.AgentID = agent.ID; + + scene.UDP.SendPacket(recipient.ID, sendIM, PacketCategory.Messaging); + } + } + else if (dialog == InstantMessageDialog.FriendshipOffered || + dialog == InstantMessageDialog.FriendshipAccepted || + dialog == InstantMessageDialog.FriendshipDeclined) + { + // HACK: Only works for agents currently online + Agent recipient; + if (scene.TryGetAgent(im.MessageBlock.ToAgentID, out recipient)) { ImprovedInstantMessagePacket sendIM = new ImprovedInstantMessagePacket(); - sendIM.MessageBlock.RegionID = server.Scene.RegionID; + sendIM.MessageBlock.RegionID = scene.RegionID; sendIM.MessageBlock.ParentEstateID = 1; sendIM.MessageBlock.FromGroup = false; sendIM.MessageBlock.FromAgentName = Utils.StringToBytes(agent.FullName); @@ -52,12 +91,12 @@ namespace Simian.Extensions sendIM.AgentData.AgentID = agent.ID; - server.UDP.SendPacket(recipient.ID, sendIM, PacketCategory.Transaction); + scene.UDP.SendPacket(recipient.ID, sendIM, PacketCategory.Transaction); if (dialog == InstantMessageDialog.FriendshipAccepted) { - bool receiverOnline = server.Scene.ContainsObject(agent.ID); - bool senderOnline = server.Scene.ContainsObject(recipient.ID); + bool receiverOnline = scene.ContainsObject(agent.ID); + bool senderOnline = scene.ContainsObject(recipient.ID); if (receiverOnline) { @@ -67,7 +106,7 @@ namespace Simian.Extensions notify.AgentBlock = new OnlineNotificationPacket.AgentBlockBlock[0]; notify.AgentBlock[0] = new OnlineNotificationPacket.AgentBlockBlock(); notify.AgentBlock[0].AgentID = agent.ID; - server.UDP.SendPacket(recipient.ID, notify, PacketCategory.State); + scene.UDP.SendPacket(recipient.ID, notify, PacketCategory.State); } else { @@ -75,7 +114,7 @@ namespace Simian.Extensions notify.AgentBlock = new OfflineNotificationPacket.AgentBlockBlock[0]; notify.AgentBlock[0] = new OfflineNotificationPacket.AgentBlockBlock(); notify.AgentBlock[0].AgentID = agent.ID; - server.UDP.SendPacket(recipient.ID, notify, PacketCategory.State); + scene.UDP.SendPacket(recipient.ID, notify, PacketCategory.State); } } @@ -87,7 +126,7 @@ namespace Simian.Extensions notify.AgentBlock = new OnlineNotificationPacket.AgentBlockBlock[0]; notify.AgentBlock[0] = new OnlineNotificationPacket.AgentBlockBlock(); notify.AgentBlock[0].AgentID = recipient.ID; - server.UDP.SendPacket(agent.ID, notify, PacketCategory.State); + scene.UDP.SendPacket(agent.ID, notify, PacketCategory.State); } else { @@ -95,7 +134,7 @@ namespace Simian.Extensions notify.AgentBlock = new OfflineNotificationPacket.AgentBlockBlock[0]; notify.AgentBlock[0] = new OfflineNotificationPacket.AgentBlockBlock(); notify.AgentBlock[0].AgentID = recipient.ID; - server.UDP.SendPacket(agent.ID, notify, PacketCategory.State); + scene.UDP.SendPacket(agent.ID, notify, PacketCategory.State); } } } diff --git a/Programs/Simian/Extensions/Money.cs b/Programs/Simian/SceneExtensions/LLMoney.cs similarity index 62% rename from Programs/Simian/Extensions/Money.cs rename to Programs/Simian/SceneExtensions/LLMoney.cs index 018fd7eb..fa57dd84 100644 --- a/Programs/Simian/Extensions/Money.cs +++ b/Programs/Simian/SceneExtensions/LLMoney.cs @@ -4,23 +4,23 @@ using ExtensionLoader; using OpenMetaverse; using OpenMetaverse.Packets; -namespace Simian.Extensions +namespace Simian { - class Money : IExtension + public class LLMoney : IExtension { - Simian server; + ISceneProvider scene; - public Money() + public LLMoney() { - } - public void Start(Simian server) + public bool Start(ISceneProvider scene) { - this.server = server; + this.scene = scene; - server.UDP.RegisterPacketCallback(PacketType.MoneyBalanceRequest, new PacketCallback(MoneyBalanceRequestHandler)); - server.UDP.RegisterPacketCallback(PacketType.MoneyTransferRequest, new PacketCallback(MoneyTransferRequestHandler)); + scene.UDP.RegisterPacketCallback(PacketType.MoneyBalanceRequest, MoneyBalanceRequestHandler); + scene.UDP.RegisterPacketCallback(PacketType.MoneyTransferRequest, MoneyTransferRequestHandler); + return true; } public void Stop() @@ -31,11 +31,11 @@ namespace Simian.Extensions { MoneyBalanceReplyPacket reply = new MoneyBalanceReplyPacket(); reply.MoneyData.AgentID = agent.ID; - reply.MoneyData.MoneyBalance = agent.Balance; + reply.MoneyData.MoneyBalance = agent.Info.Balance; reply.MoneyData.TransactionID = transactionID; reply.MoneyData.Description = Utils.StringToBytes(message); - server.UDP.SendPacket(agent.ID, reply, PacketCategory.Transaction); + scene.UDP.SendPacket(agent.ID, reply, PacketCategory.Transaction); } void MoneyBalanceRequestHandler(Packet packet, Agent agent) @@ -49,15 +49,15 @@ namespace Simian.Extensions { MoneyTransferRequestPacket request = (MoneyTransferRequestPacket)packet; - if (request.MoneyData.Amount < 0 || request.MoneyData.Amount > agent.Balance) + if (request.MoneyData.Amount < 0 || request.MoneyData.Amount > agent.Info.Balance) return; // HACK: Only works for sending money to someone who is online Agent recipient; - if (server.Scene.TryGetAgent(request.MoneyData.DestID, out recipient)) + if (scene.TryGetAgent(request.MoneyData.DestID, out recipient)) { - agent.Balance -= request.MoneyData.Amount; - recipient.Balance += request.MoneyData.Amount; + agent.Info.Balance -= request.MoneyData.Amount; + recipient.Info.Balance += request.MoneyData.Amount; SendBalance(agent, UUID.Zero, String.Format("You paid L${0} to {1}.", request.MoneyData.Amount, recipient.FullName)); SendBalance(agent, UUID.Zero, String.Format("{1} paid you L${0}.", request.MoneyData.Amount, agent.FullName)); diff --git a/Programs/Simian/Extensions/Movement.cs b/Programs/Simian/SceneExtensions/Movement.cs similarity index 82% rename from Programs/Simian/Extensions/Movement.cs rename to Programs/Simian/SceneExtensions/Movement.cs index e998a6f4..da62bbf8 100644 --- a/Programs/Simian/Extensions/Movement.cs +++ b/Programs/Simian/SceneExtensions/Movement.cs @@ -6,9 +6,9 @@ using OpenMetaverse; using OpenMetaverse.Packets; using OpenMetaverse.Rendering; -namespace Simian.Extensions +namespace Simian { - public class Movement : IExtension + public class Movement : IExtension { const int UPDATE_ITERATION = 100; //rate in milliseconds to send ObjectUpdate const bool ENVIRONMENT_SOUNDS = true; //collision sounds, splashing, etc @@ -29,7 +29,7 @@ namespace Simian.Extensions const float SQRT_TWO = 1.41421356f; - Simian server; + ISceneProvider scene; Timer updateTimer; long lastTick; @@ -43,20 +43,21 @@ namespace Simian.Extensions { } - public void Start(Simian server) + public bool Start(ISceneProvider scene) { - this.server = server; + this.scene = scene; - server.Scene.OnObjectAddOrUpdate += Scene_OnObjectAddOrUpdate; + scene.OnObjectAddOrUpdate += Scene_OnObjectAddOrUpdate; - server.UDP.RegisterPacketCallback(PacketType.AgentRequestSit, AgentRequestSitHandler); - server.UDP.RegisterPacketCallback(PacketType.AgentSit, AgentSitHandler); - server.UDP.RegisterPacketCallback(PacketType.AgentUpdate, AgentUpdateHandler); - server.UDP.RegisterPacketCallback(PacketType.SetAlwaysRun, SetAlwaysRunHandler); + scene.UDP.RegisterPacketCallback(PacketType.AgentRequestSit, AgentRequestSitHandler); + scene.UDP.RegisterPacketCallback(PacketType.AgentSit, AgentSitHandler); + scene.UDP.RegisterPacketCallback(PacketType.AgentUpdate, AgentUpdateHandler); + scene.UDP.RegisterPacketCallback(PacketType.SetAlwaysRun, SetAlwaysRunHandler); updateTimer = new Timer(new TimerCallback(UpdateTimer_Elapsed)); LastTick = Environment.TickCount; updateTimer.Change(UPDATE_ITERATION, UPDATE_ITERATION); + return true; } public void Stop() @@ -95,7 +96,7 @@ namespace Simian.Extensions float seconds = (float)((tick - LastTick) / 1000f); LastTick = tick; - server.Scene.ForEachAgent( + scene.ForEachAgent( delegate(Agent agent) { if ((agent.Avatar.Prim.Flags & PrimFlags.Physics) == 0) @@ -139,10 +140,10 @@ namespace Simian.Extensions speed /= SQRT_TWO; Vector3 agentPosition = agent.Avatar.GetSimulatorPosition(); - float oldFloor = server.Scene.GetTerrainHeightAt(agentPosition.X, agentPosition.Y); + float oldFloor = scene.GetTerrainHeightAt(agentPosition.X, agentPosition.Y); agentPosition += (move * speed); - float newFloor = server.Scene.GetTerrainHeightAt(agentPosition.X, agentPosition.Y); + float newFloor = scene.GetTerrainHeightAt(agentPosition.X, agentPosition.Y); if (!flying && newFloor != oldFloor) speed /= (1 + (SQRT_TWO * Math.Abs(newFloor - oldFloor))); @@ -169,12 +170,12 @@ namespace Simian.Extensions rayStart.Z - 0.01f ); - server.Scene.ForEachObject(delegate(SimulationObject obj) + scene.ForEachObject(delegate(SimulationObject obj) { //HACK: check nearby objects (what did you expect, octree?) if (Vector3.Distance(rayStart, obj.Prim.Position) <= 15f) { - Vector3 collision = server.Physics.ObjectCollisionTest(rayStart, rayEnd, obj); + Vector3 collision = scene.Physics.ObjectCollisionTest(rayStart, rayEnd, obj); if (collision != rayEnd) //we collided! { @@ -189,7 +190,7 @@ namespace Simian.Extensions // Z acceleration resulting from gravity float gravity = 0f; - float waterChestHeight = server.Scene.WaterHeight - (agent.Avatar.Prim.Scale.Z * .33f); + float waterChestHeight = scene.WaterHeight - (agent.Avatar.Prim.Scale.Z * .33f); if (flying) { @@ -206,22 +207,22 @@ namespace Simian.Extensions if (move.X != 0 || move.Y != 0) { //flying horizontally - if (server.Avatars.SetDefaultAnimation(agent, Animations.FLY)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.FLY)) animsChanged = true; } else if (move.Z > 0) { //flying straight up - if (server.Avatars.SetDefaultAnimation(agent, Animations.HOVER_UP)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.HOVER_UP)) animsChanged = true; } else if (move.Z < 0) { //flying straight down - if (server.Avatars.SetDefaultAnimation(agent, Animations.HOVER_DOWN)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.HOVER_DOWN)) animsChanged = true; } else { //hovering in the air - if (server.Avatars.SetDefaultAnimation(agent, Animations.HOVER)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.HOVER)) animsChanged = true; } } @@ -229,7 +230,7 @@ namespace Simian.Extensions else if (agent.Avatar.Prim.Position.Z > lowerLimit + FALL_FORGIVENESS || agent.Avatar.Prim.Position.Z <= waterChestHeight) { //falling, floating, or landing from a jump - if (agent.Avatar.Prim.Position.Z > server.Scene.WaterHeight) + if (agent.Avatar.Prim.Position.Z > scene.WaterHeight) { //above water //override controls while drifting @@ -253,7 +254,7 @@ namespace Simian.Extensions { //falling if (fallElapsed > FALL_DELAY) { //falling long enough to trigger the animation - if (server.Avatars.SetDefaultAnimation(agent, Animations.FALLDOWN)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.FALLDOWN)) animsChanged = true; } } @@ -269,17 +270,17 @@ namespace Simian.Extensions if (move.Z > 0) { - if (server.Avatars.SetDefaultAnimation(agent, Animations.HOVER_UP)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.HOVER_UP)) animsChanged = true; } else if (move.X != 0 || move.Y != 0) { - if (server.Avatars.SetDefaultAnimation(agent, Animations.FLYSLOW)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.FLYSLOW)) animsChanged = true; } else { - if (server.Avatars.SetDefaultAnimation(agent, Animations.HOVER)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.HOVER)) animsChanged = true; } } @@ -290,7 +291,7 @@ namespace Simian.Extensions agent.Avatar.Prim.Velocity *= 0.5f * seconds; agent.Avatar.Prim.Velocity.Z += 0.75f * seconds; - if (server.Avatars.SetDefaultAnimation(agent, Animations.FALLDOWN)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.FALLDOWN)) animsChanged = true; } } @@ -310,7 +311,7 @@ namespace Simian.Extensions if (!jumping) { //begin prejump move.Z = 0; //override Z control - if (server.Avatars.SetDefaultAnimation(agent, Animations.PRE_JUMP)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.PRE_JUMP)) animsChanged = true; agent.TickJump = Environment.TickCount; @@ -325,7 +326,7 @@ namespace Simian.Extensions return; } - if (server.Avatars.SetDefaultAnimation(agent, Animations.JUMP)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.JUMP)) animsChanged = true; agent.Avatar.Prim.Velocity.X += agent.Avatar.Prim.Acceleration.X * JUMP_IMPULSE_HORIZONTAL; @@ -347,17 +348,17 @@ namespace Simian.Extensions if (move.Z < 0) { //crouchwalking - if (server.Avatars.SetDefaultAnimation(agent, Animations.CROUCHWALK)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.CROUCHWALK)) animsChanged = true; } else if (agent.Running) { //running - if (server.Avatars.SetDefaultAnimation(agent, Animations.RUN)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.RUN)) animsChanged = true; } else { //walking - if (server.Avatars.SetDefaultAnimation(agent, Animations.WALK)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.WALK)) animsChanged = true; } } @@ -365,12 +366,12 @@ namespace Simian.Extensions { //walking if (move.Z < 0) { //crouching - if (server.Avatars.SetDefaultAnimation(agent, Animations.CROUCH)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.CROUCH)) animsChanged = true; } else { //standing - if (server.Avatars.SetDefaultAnimation(agent, Animations.STAND)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.STAND)) animsChanged = true; } } @@ -378,7 +379,7 @@ namespace Simian.Extensions } if (animsChanged) - server.Avatars.SendAnimations(agent); + scene.Avatars.SendAnimations(agent); float maxVel = AVATAR_TERMINAL_VELOCITY * seconds; @@ -417,7 +418,7 @@ namespace Simian.Extensions AgentRequestSitPacket request = (AgentRequestSitPacket)packet; SimulationObject obj; - if (server.Scene.TryGetObject(request.TargetObject.TargetID, out obj)) + if (scene.TryGetObject(request.TargetObject.TargetID, out obj)) { agent.RequestedSitTarget = request.TargetObject.TargetID; agent.RequestedSitOffset = request.TargetObject.Offset; @@ -431,7 +432,7 @@ namespace Simian.Extensions response.SitTransform.SitPosition = request.TargetObject.Offset; response.SitTransform.SitRotation = obj.SitRotation; - server.UDP.SendPacket(agent.ID, response, PacketCategory.State); + scene.UDP.SendPacket(agent.ID, response, PacketCategory.State); } else { @@ -447,7 +448,7 @@ namespace Simian.Extensions { SimulationObject obj; SimulationObject avObj; - if (server.Scene.TryGetObject(agent.RequestedSitTarget, out obj) && server.Scene.TryGetObject(agent.ID, out avObj)) + if (scene.TryGetObject(agent.RequestedSitTarget, out obj) && scene.TryGetObject(agent.ID, out avObj)) { agent.Avatar.Prim.Flags &= ~PrimFlags.Physics; agent.Avatar.Prim.ParentID = obj.Prim.LocalID; @@ -456,10 +457,10 @@ namespace Simian.Extensions obj.Prim.Scale.Z * 0.5f, agent.Avatar.Prim.Scale.Z * 0.33f); - server.Scene.ObjectAddOrUpdate(this, avObj, avObj.Prim.OwnerID, 0, PrimFlags.None, + scene.ObjectAddOrUpdate(this, avObj, avObj.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.PrimFlags | UpdateFlags.ParentID | UpdateFlags.Position); - server.Avatars.SetDefaultAnimation(agent, Animations.SIT); - server.Avatars.SendAnimations(agent); + scene.Avatars.SetDefaultAnimation(agent, Animations.SIT); + scene.Avatars.SendAnimations(agent); } else { @@ -476,7 +477,7 @@ namespace Simian.Extensions AgentUpdatePacket update = (AgentUpdatePacket)packet; SimulationObject obj; - if (server.Scene.TryGetObject(agent.ID, out obj)) + if (scene.TryGetObject(agent.ID, out obj)) { if (agent.Avatar.Prim.ParentID == 0) agent.Avatar.Prim.Rotation = update.AgentData.BodyRotation; @@ -487,7 +488,7 @@ namespace Simian.Extensions // Check for standing up SimulationObject parent; - if (server.Scene.TryGetObject(agent.Avatar.Prim.ParentID, out parent) && + if (scene.TryGetObject(agent.Avatar.Prim.ParentID, out parent) && agent.Avatar.Prim.ParentID > 0 && (agent.ControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) == AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) { @@ -497,13 +498,13 @@ namespace Simian.Extensions agent.Avatar.Prim.ParentID = 0; - server.Avatars.SetDefaultAnimation(agent, Animations.STAND); - server.Avatars.SendAnimations(agent); + scene.Avatars.SetDefaultAnimation(agent, Animations.STAND); + scene.Avatars.SendAnimations(agent); agent.Avatar.Prim.Flags |= PrimFlags.Physics; } - server.Scene.ObjectAddOrUpdate(this, obj, obj.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Position | UpdateFlags.Rotation); + scene.ObjectAddOrUpdate(this, obj, obj.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Position | UpdateFlags.Rotation); } } diff --git a/Programs/Simian/Extensions/ObjectManager.cs b/Programs/Simian/SceneExtensions/ObjectManager.cs similarity index 70% rename from Programs/Simian/Extensions/ObjectManager.cs rename to Programs/Simian/SceneExtensions/ObjectManager.cs index 98380594..c14918b4 100644 --- a/Programs/Simian/Extensions/ObjectManager.cs +++ b/Programs/Simian/SceneExtensions/ObjectManager.cs @@ -6,36 +6,36 @@ using OpenMetaverse; using OpenMetaverse.Rendering; using OpenMetaverse.Packets; -namespace Simian.Extensions +namespace Simian { - public class ObjectManager : IExtension + public class ObjectManager : IExtension { - Simian server; + ISceneProvider scene; public ObjectManager() { } - public void Start(Simian server) + public bool Start(ISceneProvider scene) { - this.server = server; + this.scene = scene; - server.UDP.RegisterPacketCallback(PacketType.ObjectAdd, new PacketCallback(ObjectAddHandler)); - server.UDP.RegisterPacketCallback(PacketType.ObjectAttach, new PacketCallback(ObjectAttachHandler)); - server.UDP.RegisterPacketCallback(PacketType.ObjectDuplicate, new PacketCallback(ObjectDuplicateHandler)); - server.UDP.RegisterPacketCallback(PacketType.ObjectSelect, new PacketCallback(ObjectSelectHandler)); - server.UDP.RegisterPacketCallback(PacketType.ObjectDeselect, new PacketCallback(ObjectDeselectHandler)); - server.UDP.RegisterPacketCallback(PacketType.ObjectLink, new PacketCallback(ObjectLinkHandler)); - server.UDP.RegisterPacketCallback(PacketType.ObjectDelink, new PacketCallback(ObjectDelinkHandler)); - server.UDP.RegisterPacketCallback(PacketType.ObjectShape, new PacketCallback(ObjectShapeHandler)); - server.UDP.RegisterPacketCallback(PacketType.ObjectFlagUpdate, new PacketCallback(ObjectFlagUpdateHandler)); - server.UDP.RegisterPacketCallback(PacketType.ObjectExtraParams, new PacketCallback(ObjectExtraParamsHandler)); - server.UDP.RegisterPacketCallback(PacketType.ObjectImage, new PacketCallback(ObjectImageHandler)); - server.UDP.RegisterPacketCallback(PacketType.Undo, new PacketCallback(UndoHandler)); - server.UDP.RegisterPacketCallback(PacketType.Redo, new PacketCallback(RedoHandler)); - server.UDP.RegisterPacketCallback(PacketType.DeRezObject, new PacketCallback(DeRezObjectHandler)); - server.UDP.RegisterPacketCallback(PacketType.MultipleObjectUpdate, new PacketCallback(MultipleObjectUpdateHandler)); - server.UDP.RegisterPacketCallback(PacketType.RequestObjectPropertiesFamily, new PacketCallback(RequestObjectPropertiesFamilyHandler)); + scene.UDP.RegisterPacketCallback(PacketType.ObjectAdd, ObjectAddHandler); + scene.UDP.RegisterPacketCallback(PacketType.ObjectAttach, ObjectAttachHandler); + scene.UDP.RegisterPacketCallback(PacketType.ObjectDuplicate, ObjectDuplicateHandler); + scene.UDP.RegisterPacketCallback(PacketType.ObjectSelect, ObjectSelectHandler); + scene.UDP.RegisterPacketCallback(PacketType.ObjectDeselect, ObjectDeselectHandler); + scene.UDP.RegisterPacketCallback(PacketType.ObjectLink, ObjectLinkHandler); + scene.UDP.RegisterPacketCallback(PacketType.ObjectDelink, ObjectDelinkHandler); + scene.UDP.RegisterPacketCallback(PacketType.ObjectShape, ObjectShapeHandler); + scene.UDP.RegisterPacketCallback(PacketType.ObjectFlagUpdate, ObjectFlagUpdateHandler); + scene.UDP.RegisterPacketCallback(PacketType.ObjectExtraParams, ObjectExtraParamsHandler); + scene.UDP.RegisterPacketCallback(PacketType.ObjectImage, ObjectImageHandler); + scene.UDP.RegisterPacketCallback(PacketType.Undo, UndoHandler); + scene.UDP.RegisterPacketCallback(PacketType.Redo, RedoHandler); + scene.UDP.RegisterPacketCallback(PacketType.MultipleObjectUpdate, MultipleObjectUpdateHandler); + scene.UDP.RegisterPacketCallback(PacketType.RequestObjectPropertiesFamily, RequestObjectPropertiesFamilyHandler); + return true; } public void Stop() @@ -65,10 +65,10 @@ namespace Simian.Extensions if (add.ObjectData.RayTargetID != UUID.Zero) { SimulationObject obj; - if (server.Scene.TryGetObject(add.ObjectData.RayTargetID, out obj)) + if (scene.TryGetObject(add.ObjectData.RayTargetID, out obj)) { // Test for a collision with the specified object - position = server.Physics.ObjectCollisionTest(add.ObjectData.RayStart, add.ObjectData.RayEnd, obj); + position = scene.Physics.ObjectCollisionTest(add.ObjectData.RayStart, add.ObjectData.RayEnd, obj); } } @@ -154,17 +154,17 @@ namespace Simian.Extensions prim.Properties.Name = "New Object"; prim.Properties.ObjectID = prim.ID; prim.Properties.OwnerID = prim.OwnerID; - prim.Properties.Permissions = server.Permissions.GetDefaultPermissions(); + prim.Properties.Permissions = scene.Server.Permissions.GetDefaultPermissions(); prim.Properties.SalePrice = 10; - prim.RegionHandle = server.Scene.RegionHandle; + prim.RegionHandle = scene.RegionHandle; prim.Rotation = add.ObjectData.Rotation; prim.Scale = scale; prim.TextColor = Color4.Black; // Add this prim to the object database - SimulationObject simObj = new SimulationObject(prim, server); - server.Scene.ObjectAddOrUpdate(this, simObj, agent.ID, 0, flags, UpdateFlags.FullUpdate); + SimulationObject simObj = new SimulationObject(prim, scene); + scene.ObjectAddOrUpdate(this, simObj, agent.ID, 0, flags, UpdateFlags.FullUpdate); } void ObjectAttachHandler(Packet packet, Agent agent) @@ -174,7 +174,7 @@ namespace Simian.Extensions for (int i = 0; i < attach.ObjectData.Length; i++) { SimulationObject obj; - if (server.Scene.TryGetObject(attach.ObjectData[i].ObjectLocalID, out obj)) + if (scene.TryGetObject(attach.ObjectData[i].ObjectLocalID, out obj)) { obj.BeforeAttachmentRotation = attach.ObjectData[i].Rotation; @@ -186,7 +186,7 @@ namespace Simian.Extensions obj.Prim.PrimData.AttachmentPoint = (point == AttachmentPoint.Default ? obj.LastAttachmentPoint : point); // Send an update out to everyone - server.Scene.ObjectAddOrUpdate(this, obj, agent.ID, 0, obj.Prim.Flags, + scene.ObjectAddOrUpdate(this, obj, agent.ID, 0, obj.Prim.Flags, UpdateFlags.ParentID | UpdateFlags.Position | UpdateFlags.Rotation | UpdateFlags.AttachmentPoint); } } @@ -204,7 +204,7 @@ namespace Simian.Extensions uint dupeID = duplicate.ObjectData[i].ObjectLocalID; SimulationObject obj; - if (server.Scene.TryGetObject(dupeID, out obj)) + if (scene.TryGetObject(dupeID, out obj)) { SimulationObject newObj = new SimulationObject(obj); newObj.Prim.Position += offset; @@ -212,7 +212,7 @@ namespace Simian.Extensions newObj.Prim.LocalID = 0; newObj.Prim.Properties.CreationDate = DateTime.Now; - server.Scene.ObjectAddOrUpdate(this, newObj, agent.ID, 0, flags, UpdateFlags.FullUpdate); + scene.ObjectAddOrUpdate(this, newObj, agent.ID, 0, flags, UpdateFlags.FullUpdate); } else { @@ -223,7 +223,7 @@ namespace Simian.Extensions kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1]; kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock(); kill.ObjectData[0].ID = dupeID; - server.UDP.SendPacket(agent.ID, kill, PacketCategory.State); + scene.UDP.SendPacket(agent.ID, kill, PacketCategory.State); } } } @@ -239,7 +239,7 @@ namespace Simian.Extensions properties.ObjectData[0] = new ObjectPropertiesPacket.ObjectDataBlock(); SimulationObject obj; - if (server.Scene.TryGetObject(select.ObjectData[i].ObjectLocalID, out obj)) + if (scene.TryGetObject(select.ObjectData[i].ObjectLocalID, out obj)) { //Logger.DebugLog("Selecting object " + obj.Prim.LocalID); @@ -263,7 +263,7 @@ namespace Simian.Extensions properties.ObjectData[0].TextureID = Utils.EmptyBytes; // FIXME: What is this? properties.ObjectData[0].TouchName = Utils.StringToBytes(obj.Prim.Properties.TouchName); - server.UDP.SendPacket(agent.ID, properties, PacketCategory.Transaction); + scene.UDP.SendPacket(agent.ID, properties, PacketCategory.Transaction); } else { @@ -280,7 +280,7 @@ namespace Simian.Extensions kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1]; kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock(); kill.ObjectData[0].ID = select.ObjectData[i].ObjectLocalID; - server.UDP.SendPacket(agent.ID, kill, PacketCategory.State); + scene.UDP.SendPacket(agent.ID, kill, PacketCategory.State); } } @@ -295,7 +295,7 @@ namespace Simian.Extensions uint localID = deselect.ObjectData[i].ObjectLocalID; SimulationObject obj; - if (server.Scene.TryGetObject(localID, out obj)) + if (scene.TryGetObject(localID, out obj)) { //Logger.DebugLog("Deselecting object " + obj.Prim.LocalID); } @@ -311,7 +311,7 @@ namespace Simian.Extensions for (int i = 0; i < link.ObjectData.Length; i++) { SimulationObject obj; - if (!server.Scene.TryGetObject(link.ObjectData[i].ObjectLocalID, out obj)) + if (!scene.TryGetObject(link.ObjectData[i].ObjectLocalID, out obj)) { //TODO: Send an error message return; @@ -335,7 +335,7 @@ namespace Simian.Extensions { // Previously linked children SimulationObject parent; - if (server.Scene.TryGetObject(linkSet[i].Prim.ParentID, out parent)) + if (scene.TryGetObject(linkSet[i].Prim.ParentID, out parent)) { // Re-add old root orientation linkSet[i].Prim.Position = parent.Prim.Position + Vector3.Transform(linkSet[i].Prim.Position, @@ -360,7 +360,7 @@ namespace Simian.Extensions linkSet[i].Prim.ParentID = 0; } - server.Scene.ObjectAddOrUpdate(this, linkSet[i], agent.ID, 0, linkSet[i].Prim.Flags, + scene.ObjectAddOrUpdate(this, linkSet[i], agent.ID, 0, linkSet[i].Prim.Flags, UpdateFlags.Position | UpdateFlags.Rotation | UpdateFlags.ParentID); } } @@ -373,7 +373,7 @@ namespace Simian.Extensions for (int i = 0; i < delink.ObjectData.Length; i++) { SimulationObject obj; - if (!server.Scene.TryGetObject(delink.ObjectData[i].ObjectLocalID, out obj)) + if (!scene.TryGetObject(delink.ObjectData[i].ObjectLocalID, out obj)) { //TODO: Send an error message return; @@ -402,7 +402,7 @@ namespace Simian.Extensions linkSet[i].Prim.Rotation *= linkSet[0].Prim.Rotation; } - server.Scene.ObjectAddOrUpdate(this, linkSet[i], agent.ID, 0, linkSet[i].Prim.Flags, + scene.ObjectAddOrUpdate(this, linkSet[i], agent.ID, 0, linkSet[i].Prim.Flags, UpdateFlags.Position | UpdateFlags.Rotation | UpdateFlags.ParentID); } } @@ -416,7 +416,7 @@ namespace Simian.Extensions ObjectShapePacket.ObjectDataBlock block = shape.ObjectData[i]; SimulationObject obj; - if (server.Scene.TryGetObject(block.ObjectLocalID, out obj)) + if (scene.TryGetObject(block.ObjectLocalID, out obj)) { Primitive.ConstructionData data = obj.Prim.PrimData; @@ -440,7 +440,7 @@ namespace Simian.Extensions data.ProfileHollow = Primitive.UnpackProfileHollow(block.ProfileHollow); obj.Prim.PrimData = data; - server.Scene.ObjectAddOrUpdate(this, obj, obj.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.PrimData); + scene.ObjectAddOrUpdate(this, obj, obj.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.PrimData); } else { @@ -455,7 +455,7 @@ namespace Simian.Extensions ObjectFlagUpdatePacket update = (ObjectFlagUpdatePacket)packet; SimulationObject obj; - if (server.Scene.TryGetObject(update.AgentData.ObjectLocalID, out obj)) + if (scene.TryGetObject(update.AgentData.ObjectLocalID, out obj)) { PrimFlags flags = obj.Prim.Flags; @@ -480,7 +480,7 @@ namespace Simian.Extensions flags &= ~PrimFlags.Physics; obj.Prim.Flags = flags; - server.Scene.ObjectAddOrUpdate(this, obj, obj.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.PrimFlags); + scene.ObjectAddOrUpdate(this, obj, obj.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.PrimFlags); } else { @@ -498,7 +498,7 @@ namespace Simian.Extensions ObjectExtraParamsPacket.ObjectDataBlock block = extra.ObjectData[i]; SimulationObject obj; - if (server.Scene.TryGetObject(block.ObjectLocalID, out obj)) + if (scene.TryGetObject(block.ObjectLocalID, out obj)) { ExtraParamType type = (ExtraParamType)block.ParamType; @@ -533,7 +533,7 @@ namespace Simian.Extensions } } - server.Scene.ObjectAddOrUpdate(this, obj, obj.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.ExtraData); + scene.ObjectAddOrUpdate(this, obj, obj.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.ExtraData); } } } @@ -545,11 +545,11 @@ namespace Simian.Extensions for (int i = 0; i < image.ObjectData.Length; i++) { SimulationObject obj; - if (server.Scene.TryGetObject(image.ObjectData[i].ObjectLocalID, out obj)) + if (scene.TryGetObject(image.ObjectData[i].ObjectLocalID, out obj)) { obj.Prim.MediaURL = Utils.BytesToString(image.ObjectData[i].MediaURL); obj.Prim.Textures = new Primitive.TextureEntry(image.ObjectData[i].TextureEntry, 0, image.ObjectData[i].TextureEntry.Length); - server.Scene.ObjectAddOrUpdate(this, obj, obj.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.MediaURL | UpdateFlags.Textures); + scene.ObjectAddOrUpdate(this, obj, obj.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.MediaURL | UpdateFlags.Textures); } } } @@ -561,8 +561,8 @@ namespace Simian.Extensions for (int i = 0; i < undo.ObjectData.Length; i++) { SimulationObject obj; - if (server.Scene.TryGetObject(undo.ObjectData[i].ObjectID, out obj)) - server.Scene.ObjectUndo(this, obj); + if (scene.TryGetObject(undo.ObjectData[i].ObjectID, out obj)) + scene.ObjectUndo(this, obj); } } @@ -573,88 +573,8 @@ namespace Simian.Extensions for (int i = 0; i < redo.ObjectData.Length; i++) { SimulationObject obj; - if (server.Scene.TryGetObject(redo.ObjectData[i].ObjectID, out obj)) - server.Scene.ObjectRedo(this, obj); - } - } - - void DeRezObjectHandler(Packet packet, Agent agent) - { - DeRezObjectPacket derez = (DeRezObjectPacket)packet; - DeRezDestination destination = (DeRezDestination)derez.AgentBlock.Destination; - - // TODO: Check permissions - for (int i = 0; i < derez.ObjectData.Length; i++) - { - uint localID = derez.ObjectData[i].ObjectLocalID; - - SimulationObject obj; - if (server.Scene.TryGetObject(localID, out obj)) - { - switch (destination) - { - case DeRezDestination.AgentInventorySave: - Logger.Log("DeRezObject: Got an AgentInventorySave, DestID: " + - derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning); - break; - case DeRezDestination.AgentInventoryCopy: - Logger.Log("DeRezObject: Got an AgentInventorySave, DestID: " + - derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning); - break; - case DeRezDestination.TaskInventory: - Logger.Log("DeRezObject: Got a TaskInventory, DestID: " + - derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning); - break; - case DeRezDestination.Attachment: - Logger.Log("DeRezObject: Got an Attachment, DestID: " + - derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning); - break; - case DeRezDestination.AgentInventoryTake: - Logger.Log("DeRezObject: Got an AgentInventoryTake, DestID: " + - derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning); - break; - case DeRezDestination.ForceToGodInventory: - Logger.Log("DeRezObject: Got a ForceToGodInventory, DestID: " + - derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning); - break; - case DeRezDestination.TrashFolder: - InventoryObject invObj; - if (server.Inventory.TryGetInventory(agent.ID, derez.AgentBlock.DestinationID, out invObj) && - invObj is InventoryFolder) - { - // FIXME: Handle children - InventoryFolder trash = (InventoryFolder)invObj; - server.Inventory.CreateItem(agent.ID, obj.Prim.Properties.Name, obj.Prim.Properties.Description, InventoryType.Object, - AssetType.Object, obj.Prim.ID, trash.ID, PermissionMask.All, PermissionMask.All, agent.ID, - obj.Prim.Properties.CreatorID, derez.AgentBlock.TransactionID, 0, true); - server.Scene.ObjectRemove(this, obj.Prim.LocalID); - - Logger.DebugLog(String.Format("Derezzed prim {0} to agent inventory trash", obj.Prim.LocalID)); - } - else - { - Logger.Log("DeRezObject: Got a TrashFolder with an invalid trash folder: " + - derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning); - } - break; - case DeRezDestination.AttachmentToInventory: - Logger.Log("DeRezObject: Got an AttachmentToInventory, DestID: " + - derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning); - break; - case DeRezDestination.AttachmentExists: - Logger.Log("DeRezObject: Got an AttachmentExists, DestID: " + - derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning); - break; - case DeRezDestination.ReturnToOwner: - Logger.Log("DeRezObject: Got a ReturnToOwner, DestID: " + - derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning); - break; - case DeRezDestination.ReturnToLastOwner: - Logger.Log("DeRezObject: Got a ReturnToLastOwner, DestID: " + - derez.AgentBlock.DestinationID.ToString(), Helpers.LogLevel.Warning); - break; - } - } + if (scene.TryGetObject(redo.ObjectData[i].ObjectID, out obj)) + scene.ObjectRedo(this, obj); } } @@ -668,7 +588,7 @@ namespace Simian.Extensions MultipleObjectUpdatePacket.ObjectDataBlock block = update.ObjectData[i]; SimulationObject obj; - if (server.Scene.TryGetObject(block.ObjectLocalID, out obj)) + if (scene.TryGetObject(block.ObjectLocalID, out obj)) { UpdateType type = (UpdateType)block.Type; //bool linked = ((type & UpdateType.Linked) != 0); @@ -706,7 +626,7 @@ namespace Simian.Extensions obj.Prim.Rotation = rotation; if (scaled) obj.Prim.Scale = scale; - server.Scene.ObjectAddOrUpdate(this, obj, agent.ID, 0, PrimFlags.None, updateFlags); + scene.ObjectAddOrUpdate(this, obj, agent.ID, 0, PrimFlags.None, updateFlags); } else { @@ -715,7 +635,7 @@ namespace Simian.Extensions kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1]; kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock(); kill.ObjectData[0].ID = block.ObjectLocalID; - server.UDP.SendPacket(agent.ID, kill, PacketCategory.State); + scene.UDP.SendPacket(agent.ID, kill, PacketCategory.State); } } } @@ -726,7 +646,7 @@ namespace Simian.Extensions ReportType type = (ReportType)request.ObjectData.RequestFlags; SimulationObject obj; - if (server.Scene.TryGetObject(request.ObjectData.ObjectID, out obj)) + if (scene.TryGetObject(request.ObjectData.ObjectID, out obj)) { ObjectPropertiesFamilyPacket props = new ObjectPropertiesFamilyPacket(); props.ObjectData.BaseMask = (uint)obj.Prim.Properties.Permissions.BaseMask; @@ -746,7 +666,7 @@ namespace Simian.Extensions props.ObjectData.SalePrice = obj.Prim.Properties.SalePrice; props.ObjectData.SaleType = (byte)obj.Prim.Properties.SaleType; - server.UDP.SendPacket(agent.ID, props, PacketCategory.Transaction); + scene.UDP.SendPacket(agent.ID, props, PacketCategory.Transaction); } else { diff --git a/Programs/Simian/Extensions/ParcelManager.cs b/Programs/Simian/SceneExtensions/ParcelManager.cs similarity index 93% rename from Programs/Simian/Extensions/ParcelManager.cs rename to Programs/Simian/SceneExtensions/ParcelManager.cs index e719fe04..043915f4 100644 --- a/Programs/Simian/Extensions/ParcelManager.cs +++ b/Programs/Simian/SceneExtensions/ParcelManager.cs @@ -4,11 +4,11 @@ using ExtensionLoader; using OpenMetaverse; using OpenMetaverse.Packets; -namespace Simian.Extensions +namespace Simian { - public class ParcelManager : IExtension, IParcelProvider + public class ParcelManager : IExtension, IParcelProvider { - Simian server; + ISceneProvider scene; Dictionary parcels = new Dictionary(); /// X,Y ordered 2D array of the parcelIDs for each sq. meter of a simulator int[] parcelOverlay = new int[64 * 64]; @@ -17,9 +17,9 @@ namespace Simian.Extensions { } - public void Start(Simian server) + public bool Start(ISceneProvider scene) { - this.server = server; + this.scene = scene; lock (parcels) parcels.Clear(); @@ -48,8 +48,9 @@ namespace Simian.Extensions // Add the default parcel to the list parcels[parcel.LocalID] = parcel; - server.UDP.RegisterPacketCallback(PacketType.ParcelPropertiesRequest, ParcelPropertiesRequestHandler); - server.UDP.RegisterPacketCallback(PacketType.ParcelPropertiesUpdate, ParcelPropertiesUpdateHandler); + scene.UDP.RegisterPacketCallback(PacketType.ParcelPropertiesRequest, ParcelPropertiesRequestHandler); + scene.UDP.RegisterPacketCallback(PacketType.ParcelPropertiesUpdate, ParcelPropertiesUpdateHandler); + return true; } public void Stop() @@ -108,7 +109,7 @@ namespace Simian.Extensions ParcelOverlayPacket overlay = new ParcelOverlayPacket(); overlay.ParcelData.SequenceID = sequenceID; overlay.ParcelData.Data = byteArray; - server.UDP.SendPacket(agent.ID, overlay, PacketCategory.State); + scene.UDP.SendPacket(agent.ID, overlay, PacketCategory.State); byteArrayCount = 0; ++sequenceID; @@ -217,7 +218,7 @@ namespace Simian.Extensions // HACK: Make everyone think they are the owner of this parcel properties.ParcelData.OwnerID = agent.ID; - server.UDP.SendPacket(agent.ID, properties, PacketCategory.Transaction); + scene.UDP.SendPacket(agent.ID, properties, PacketCategory.Transaction); } else { diff --git a/Programs/Simian/Extensions/Periscope.cs b/Programs/Simian/SceneExtensions/Periscope.cs similarity index 77% rename from Programs/Simian/Extensions/Periscope.cs rename to Programs/Simian/SceneExtensions/Periscope.cs index 0a72ea24..6487b701 100644 --- a/Programs/Simian/Extensions/Periscope.cs +++ b/Programs/Simian/SceneExtensions/Periscope.cs @@ -6,30 +6,31 @@ using ExtensionLoader; using OpenMetaverse; using OpenMetaverse.Packets; -namespace Simian.Extensions +namespace Simian { - public class Periscope : IExtension + public class Periscope : IExtension { // Change this to login to a different grid const string PERISCOPE_LOGIN_URI = Settings.AGNI_LOGIN_SERVER; public Agent MasterAgent = null; - Simian server; + ISceneProvider scene; GridClient client; PeriscopeImageDelivery imageDelivery; PeriscopeMovement movement; PeriscopeTransferManager transferManager; bool ignoreObjectKill = false; object loginLock = new object(); + string lastPasswordHash = String.Empty; public Periscope() { } - public void Start(Simian server) + public bool Start(ISceneProvider scene) { - this.server = server; + this.scene = scene; client = new GridClient(); Settings.LOG_LEVEL = Helpers.LogLevel.Info; @@ -49,17 +50,18 @@ namespace Simian.Extensions client.Network.RegisterCallback(PacketType.AvatarAnimation, AvatarAnimationHandler); client.Network.RegisterCallback(PacketType.RegionHandshake, RegionHandshakeHandler); - server.UDP.RegisterPacketCallback(PacketType.AgentUpdate, AgentUpdateHandler); - server.UDP.RegisterPacketCallback(PacketType.ChatFromViewer, ChatFromViewerHandler); - server.UDP.RegisterPacketCallback(PacketType.ObjectGrab, ObjectGrabHandler); - server.UDP.RegisterPacketCallback(PacketType.ObjectGrabUpdate, ObjectGrabUpdateHandler); - server.UDP.RegisterPacketCallback(PacketType.ObjectDeGrab, ObjectDeGrabHandler); - server.UDP.RegisterPacketCallback(PacketType.ViewerEffect, ViewerEffectHandler); - server.UDP.RegisterPacketCallback(PacketType.AgentAnimation, AgentAnimationHandler); + scene.UDP.RegisterPacketCallback(PacketType.AgentUpdate, AgentUpdateHandler); + scene.UDP.RegisterPacketCallback(PacketType.ChatFromViewer, ChatFromViewerHandler); + scene.UDP.RegisterPacketCallback(PacketType.ObjectGrab, ObjectGrabHandler); + scene.UDP.RegisterPacketCallback(PacketType.ObjectGrabUpdate, ObjectGrabUpdateHandler); + scene.UDP.RegisterPacketCallback(PacketType.ObjectDeGrab, ObjectDeGrabHandler); + scene.UDP.RegisterPacketCallback(PacketType.ViewerEffect, ViewerEffectHandler); + scene.UDP.RegisterPacketCallback(PacketType.AgentAnimation, AgentAnimationHandler); - imageDelivery = new PeriscopeImageDelivery(server, client); - movement = new PeriscopeMovement(server, this); - transferManager = new PeriscopeTransferManager(server, client); + imageDelivery = new PeriscopeImageDelivery(scene, client); + movement = new PeriscopeMovement(scene, this); + transferManager = new PeriscopeTransferManager(scene, client); + return true; } public void Stop() @@ -74,32 +76,26 @@ namespace Simian.Extensions void Objects_OnNewPrim(Simulator simulator, Primitive prim, ulong regionHandle, ushort timeDilation) { - SimulationObject simObj = new SimulationObject(prim, server); + SimulationObject simObj = new SimulationObject(prim, scene); if (MasterAgent != null) simObj.Prim.OwnerID = MasterAgent.ID; - server.Scene.ObjectAddOrUpdate(this, simObj, MasterAgent.ID, 0, PrimFlags.None, UpdateFlags.FullUpdate); + scene.ObjectAddOrUpdate(this, simObj, MasterAgent.ID, 0, PrimFlags.None, UpdateFlags.FullUpdate); } void Objects_OnNewAttachment(Simulator simulator, Primitive prim, ulong regionHandle, ushort timeDilation) { - SimulationObject simObj = new SimulationObject(prim, server); - server.Scene.ObjectAddOrUpdate(this, simObj, MasterAgent.ID, 0, PrimFlags.None, UpdateFlags.FullUpdate); + SimulationObject simObj = new SimulationObject(prim, scene); + scene.ObjectAddOrUpdate(this, simObj, MasterAgent.ID, 0, PrimFlags.None, UpdateFlags.FullUpdate); } void Objects_OnNewAvatar(Simulator simulator, Avatar avatar, ulong regionHandle, ushort timeDilation) { - ulong localRegionHandle = Utils.UIntsToLong(256 * server.Scene.RegionX, 256 * server.Scene.RegionY); - // Add the avatar to both the agents list and the scene objects - SimulationObject obj = new SimulationObject(avatar, server); - Agent agent = new Agent(obj); - agent.Avatar.Prim.ID = avatar.ID; - agent.CurrentRegionHandle = localRegionHandle; - agent.FirstName = avatar.FirstName; - agent.LastName = avatar.LastName; + SimulationObject obj = new SimulationObject(avatar, scene); + Agent agent = new Agent(obj, AgentInfoFromAvatar(avatar)); - server.Scene.AgentAdd(this, agent, avatar.Flags); - server.Scene.ObjectAddOrUpdate(this, obj, obj.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.FullUpdate); + scene.AgentAdd(this, agent, avatar.Flags); + scene.ObjectAddOrUpdate(this, obj, obj.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.FullUpdate); } void Objects_OnObjectUpdated(Simulator simulator, ObjectUpdate update, ulong regionHandle, ushort timeDilation) @@ -111,7 +107,7 @@ namespace Simian.Extensions if (update.Avatar) flags |= UpdateFlags.CollisionPlane; if (update.Textures != null) flags |= UpdateFlags.Textures; - if (server.Scene.TryGetObject(update.LocalID, out obj)) + if (scene.TryGetObject(update.LocalID, out obj)) { obj.Prim.Acceleration = update.Acceleration; obj.Prim.AngularVelocity = update.AngularVelocity; @@ -121,7 +117,7 @@ namespace Simian.Extensions if (update.Avatar) obj.Prim.CollisionPlane = update.CollisionPlane; if (update.Textures != null) obj.Prim.Textures = update.Textures; - server.Scene.ObjectAddOrUpdate(this, obj, obj.Prim.OwnerID, 0, PrimFlags.None, flags); + scene.ObjectAddOrUpdate(this, obj, obj.Prim.OwnerID, 0, PrimFlags.None, flags); } if (update.LocalID == client.Self.LocalID) @@ -134,14 +130,14 @@ namespace Simian.Extensions if (update.Avatar) MasterAgent.Avatar.Prim.CollisionPlane = update.CollisionPlane; if (update.Textures != null) MasterAgent.Avatar.Prim.Textures = update.Textures; - server.Scene.ObjectAddOrUpdate(this, MasterAgent.Avatar, MasterAgent.ID, 0, PrimFlags.None, flags); + scene.ObjectAddOrUpdate(this, MasterAgent.Avatar, MasterAgent.ID, 0, PrimFlags.None, flags); } } void Objects_OnObjectKilled(Simulator simulator, uint objectID) { if (!ignoreObjectKill) - server.Scene.ObjectRemove(this, objectID); + scene.ObjectRemove(this, objectID); } void Avatars_OnAvatarAppearance(UUID avatarID, bool isTrial, Primitive.TextureEntryFace defaultTexture, @@ -152,16 +148,16 @@ namespace Simian.Extensions byte[] vp = (visualParams != null && visualParams.Count > 1 ? visualParams.ToArray() : null); Agent agent; - if (server.Scene.TryGetAgent(avatarID, out agent)) + if (scene.TryGetAgent(avatarID, out agent)) { - Logger.Log("[Periscope] Updating foreign avatar appearance for " + agent.FirstName + " " + agent.LastName, Helpers.LogLevel.Info); - server.Scene.AgentAppearance(this, agent, te, vp); + Logger.Log("[Periscope] Updating foreign avatar appearance for " + agent.FullName, Helpers.LogLevel.Info); + scene.AgentAppearance(this, agent, te, vp); } if (avatarID == client.Self.AgentID) { Logger.Log("[Periscope] Updating foreign avatar appearance for the MasterAgent", Helpers.LogLevel.Info); - server.Scene.AgentAppearance(this, MasterAgent, te, vp); + scene.AgentAppearance(this, MasterAgent, te, vp); } } @@ -176,26 +172,26 @@ namespace Simian.Extensions } } - server.Scene.SetTerrainPatch(this, (uint)x, (uint)y, patchData); + scene.SetTerrainPatch(this, (uint)x, (uint)y, patchData); } void Self_OnChat(string message, ChatAudibleLevel audible, ChatType type, ChatSourceType sourceType, string fromName, UUID id, UUID ownerid, Vector3 position) { - server.Scene.ObjectChat(this, ownerid, id, audible, type, sourceType, fromName, position, 0, message); + scene.ObjectChat(this, ownerid, id, audible, type, sourceType, fromName, position, 0, message); } void Self_OnTeleport(string message, TeleportStatus status, TeleportFlags flags) { if (status == TeleportStatus.Finished) { - ulong localRegionHandle = server.Scene.RegionHandle; + ulong localRegionHandle = scene.RegionHandle; - server.Scene.RemoveAllAgents( + scene.RemoveAllAgents( delegate(Agent agent) { return agent.Avatar.Prim.RegionHandle != client.Network.CurrentSim.Handle && agent.Avatar.Prim.RegionHandle != localRegionHandle; }); - server.Scene.RemoveAllObjects( + scene.RemoveAllObjects( delegate(SimulationObject obj) { return obj.Prim.RegionHandle != client.Network.CurrentSim.Handle && obj.Prim.RegionHandle != localRegionHandle; }); } @@ -212,7 +208,7 @@ namespace Simian.Extensions AvatarAnimationPacket animations = (AvatarAnimationPacket)packet; Agent agent; - if (server.Scene.TryGetAgent(animations.Sender.ID, out agent)) + if (scene.TryGetAgent(animations.Sender.ID, out agent)) { agent.Animations.Clear(); @@ -222,7 +218,7 @@ namespace Simian.Extensions agent.Animations.Add(block.AnimID, block.AnimSequenceID); } - server.Avatars.SendAnimations(agent); + scene.Avatars.SendAnimations(agent); } if (animations.Sender.ID == client.Self.AgentID) @@ -235,7 +231,7 @@ namespace Simian.Extensions MasterAgent.Animations.Add(block.AnimID, block.AnimSequenceID); } - server.Avatars.SendAnimations(MasterAgent); + scene.Avatars.SendAnimations(MasterAgent); } } @@ -245,12 +241,12 @@ namespace Simian.Extensions handshake.RegionInfo.SimOwner = (MasterAgent != null ? MasterAgent.ID : UUID.Zero); handshake.RegionInfo.RegionFlags &= ~(uint)RegionFlags.NoFly; - handshake.RegionInfo2.RegionID = server.Scene.RegionID; + handshake.RegionInfo2.RegionID = scene.RegionID; // TODO: Need more methods to manipulate the scene so we can apply these properties. // Right now this only gets sent out to people who are logged in when the master avatar // is already logged in - server.UDP.BroadcastPacket(handshake, PacketCategory.Transaction); + scene.UDP.BroadcastPacket(handshake, PacketCategory.Transaction); } #region Simian client packet handlers @@ -277,18 +273,18 @@ namespace Simian.Extensions Single.TryParse(messageParts[3], out y) && Single.TryParse(messageParts[4], out z)) { - server.Avatars.SendAlert(agent, String.Format("Attempting teleport to {0} <{1}, {2}, {3}>", + scene.Avatars.SendAlert(agent, String.Format("Attempting teleport to {0} <{1}, {2}, {3}>", messageParts[1], messageParts[2], messageParts[3], messageParts[4])); client.Self.Teleport(messageParts[1], new Vector3(x, y, z)); } else { - server.Avatars.SendAlert(agent, "Usage: /teleport \"sim name\" x y z"); + scene.Avatars.SendAlert(agent, "Usage: /teleport \"sim name\" x y z"); } return; } case "/stats": - server.Avatars.SendAlert(agent, String.Format("Downloading textures: {0}, Queued textures: {1}", + scene.Avatars.SendAlert(agent, String.Format("Downloading textures: {0}, Queued textures: {1}", imageDelivery.Pipeline.CurrentCount, imageDelivery.Pipeline.QueuedCount)); return; case "/objectkill": @@ -297,12 +293,12 @@ namespace Simian.Extensions if (messageParts[1] == "off" || messageParts[1] == "0") { ignoreObjectKill = true; - server.Avatars.SendAlert(agent, "Ignoring upstream ObjectKill packets"); + scene.Avatars.SendAlert(agent, "Ignoring upstream ObjectKill packets"); } else { ignoreObjectKill = false; - server.Avatars.SendAlert(agent, "Enabling upstream ObjectKill packets"); + scene.Avatars.SendAlert(agent, "Enabling upstream ObjectKill packets"); } } return; @@ -316,8 +312,8 @@ namespace Simian.Extensions Thread saveThread = new Thread(new ThreadStart( delegate() { - Logger.Log(String.Format("Preparing to serialize {0} objects", server.Scene.ObjectCount()), Helpers.LogLevel.Info); - OarFile.SavePrims(server, directoryname + "/objects", directoryname + "/assets", Simian.ASSET_CACHE_DIR); + Logger.Log(String.Format("Preparing to serialize {0} objects", scene.ObjectCount()), Helpers.LogLevel.Info); + OarFile.SavePrims(scene, directoryname + "/objects", directoryname + "/assets", Simian.ASSET_CACHE_DIR); try { Directory.Delete(directoryname + "/terrains", true); } catch (Exception) { } @@ -332,7 +328,7 @@ namespace Simian.Extensions { for (int x = 0; x < 256; x++) { - float t = server.Scene.GetTerrainHeightAt(x, y); + float t = scene.GetTerrainHeightAt(x, y); stream.Write(BitConverter.GetBytes(t), 0, 4); } } @@ -351,11 +347,11 @@ namespace Simian.Extensions catch (Exception ex) { Logger.Log("Failed to delete temporary directory " + directoryname + ": " + ex.Message, Helpers.LogLevel.Error); } - server.Avatars.SendAlert(agent, "Finished OAR export to " + filename); + scene.Avatars.SendAlert(agent, "Finished OAR export to " + filename); })); saveThread.Start(); - server.Avatars.SendAlert(agent, "Starting OAR export to " + filename); + scene.Avatars.SendAlert(agent, "Starting OAR export to " + filename); } return; } @@ -379,21 +375,21 @@ namespace Simian.Extensions curAgent.Avatar.Textures.FaceTextures[(int)AppearanceManager.TextureIndex.UpperShirt] = null; curAgent.Avatar.Textures.FaceTextures[(int)AppearanceManager.TextureIndex.UpperUndershirt] = null; - server.Scene.AvatarAppearance(this, curAgent, curAgent.Avatar.Textures, curAgent.VisualParams); + scene.AvatarAppearance(this, curAgent, curAgent.Avatar.Textures, curAgent.VisualParams); ++count; } } - server.Avatars.SendAlert(agent, String.Format("Modified appearances for {0} avatar(s)", count));*/ + scene.Avatars.SendAlert(agent, String.Format("Modified appearances for {0} avatar(s)", count));*/ return; } } string finalMessage; - if (agent.FirstName == client.Self.FirstName && agent.LastName == client.Self.LastName) + if (agent.Info.FirstName == client.Self.FirstName && agent.Info.LastName == client.Self.LastName) finalMessage = message; else - finalMessage = String.Format("<{0} {1}> {2}", agent.FirstName, agent.LastName, message); + finalMessage = String.Format("<{0} {1}> {2}", agent.Info.FirstName, agent.Info.LastName, message); client.Self.Chat(finalMessage, chat.ChatData.Channel, (ChatType)chat.ChatData.Type); } @@ -402,20 +398,23 @@ namespace Simian.Extensions { AgentUpdatePacket update = (AgentUpdatePacket)packet; - if (MasterAgent == null || (!client.Network.Connected && client.Network.LoginStatusCode == LoginStatus.Failed)) + if (MasterAgent == null || + (!client.Network.Connected && client.Network.LoginStatusCode == LoginStatus.Failed && agent.Info.PasswordHash != lastPasswordHash)) { MasterAgent = null; + // To keep from repeatedly trying to login with a bad password + lastPasswordHash = agent.Info.PasswordHash; lock (loginLock) { // Double-checked locking to avoid hitting the loginLock each time - if (MasterAgent == null && server.Scene.TryGetAgent(update.AgentData.AgentID, out MasterAgent)) + if (MasterAgent == null && scene.TryGetAgent(update.AgentData.AgentID, out MasterAgent)) { Logger.Log(String.Format("[Periscope] {0} {1} is the controlling agent", - MasterAgent.FirstName, MasterAgent.LastName), Helpers.LogLevel.Info); + MasterAgent.Info.FirstName, MasterAgent.Info.LastName), Helpers.LogLevel.Info); - LoginParams login = client.Network.DefaultLoginParams(agent.FirstName, agent.LastName, agent.PasswordHash, - "Simian Periscope", "1.0.0"); + LoginParams login = client.Network.DefaultLoginParams(agent.Info.FirstName, agent.Info.LastName, + agent.Info.PasswordHash, "Simian Periscope", "1.0.0"); login.URI = PERISCOPE_LOGIN_URI; login.Start = "last"; client.Network.Login(login); @@ -509,6 +508,23 @@ namespace Simian.Extensions #endregion Simian client packet handlers + AgentInfo AgentInfoFromAvatar(Avatar avatar) + { + // Some parts of the code use the FirstName/LastName, and other extensions + // might try to access this data. Fill in enough to keep things sane + AgentInfo info = new AgentInfo(); + info.AccessLevel = String.Empty; + info.Balance = 0; + info.CreationTime = Utils.DateTimeToUnixTime(Utils.Epoch); + info.FirstName = avatar.FirstName; + info.Height = 1.9f; + info.ID = avatar.ID; + info.LastLoginTime = Utils.DateTimeToUnixTime(DateTime.Now); + info.LastName = avatar.LastName; + + return info; + } + static void EraseTexture(Avatar avatar, AppearanceManager.TextureIndex texture) { Primitive.TextureEntryFace face = avatar.Textures.FaceTextures[(int)texture]; diff --git a/Programs/Simian/Extensions/PeriscopeImageDelivery.cs b/Programs/Simian/SceneExtensions/PeriscopeImageDelivery.cs similarity index 90% rename from Programs/Simian/Extensions/PeriscopeImageDelivery.cs rename to Programs/Simian/SceneExtensions/PeriscopeImageDelivery.cs index 9a5c36ea..f08786d0 100644 --- a/Programs/Simian/Extensions/PeriscopeImageDelivery.cs +++ b/Programs/Simian/SceneExtensions/PeriscopeImageDelivery.cs @@ -5,25 +5,25 @@ using ExtensionLoader; using OpenMetaverse; using OpenMetaverse.Packets; -namespace Simian.Extensions +namespace Simian { public class PeriscopeImageDelivery { public TexturePipeline Pipeline; - Simian server; + ISceneProvider scene; GridClient client; Dictionary currentDownloads = new Dictionary(); - public PeriscopeImageDelivery(Simian server, GridClient client) + public PeriscopeImageDelivery(ISceneProvider scene, GridClient client) { - this.server = server; + this.scene = scene; this.client = client; Pipeline = new TexturePipeline(client, 12); Pipeline.OnDownloadFinished += new TexturePipeline.DownloadFinishedCallback(pipeline_OnDownloadFinished); - server.UDP.RegisterPacketCallback(PacketType.RequestImage, RequestImageHandler); + scene.UDP.RegisterPacketCallback(PacketType.RequestImage, RequestImageHandler); } public void Stop() @@ -64,7 +64,7 @@ namespace Simian.Extensions // New download, check if we have this image Asset asset; - if (server.Assets.TryGetAsset(block.Image, out asset) && asset is AssetTexture) + if (scene.Server.Assets.TryGetAsset(block.Image, out asset) && asset is AssetTexture) { SendTexture(agent, (AssetTexture)asset, block.DiscardLevel, (int)block.Packet, block.DownloadPriority); } @@ -98,7 +98,7 @@ namespace Simian.Extensions Pipeline.RemoveFromPipeline(id); // Store this texture in the local asset store for later - server.Assets.StoreAsset(texture); + scene.Server.Assets.StoreAsset(texture); SendTexture(download.Agent, download.Texture, download.DiscardLevel, download.CurrentPacket, download.Priority); } @@ -108,7 +108,7 @@ namespace Simian.Extensions ImageNotInDatabasePacket notfound = new ImageNotInDatabasePacket(); notfound.ImageID.ID = id; - server.UDP.SendPacket(download.Agent.ID, notfound, PacketCategory.Texture); + scene.UDP.SendPacket(download.Agent.ID, notfound, PacketCategory.Texture); } } else @@ -147,7 +147,7 @@ namespace Simian.Extensions Helpers.LogLevel.Error); } - server.UDP.SendPacket(agent.ID, data, PacketCategory.Texture); + scene.UDP.SendPacket(agent.ID, data, PacketCategory.Texture); // Check if ImagePacket packets need to be sent to complete this transfer if (download.CurrentPacket <= download.StopPacket) @@ -188,7 +188,7 @@ namespace Simian.Extensions imagePacketSize), Helpers.LogLevel.Error); } - server.UDP.SendPacket(agent.ID, transfer, PacketCategory.Texture); + scene.UDP.SendPacket(agent.ID, transfer, PacketCategory.Texture); ++download.CurrentPacket; } diff --git a/Programs/Simian/Extensions/PeriscopeMovement.cs b/Programs/Simian/SceneExtensions/PeriscopeMovement.cs similarity index 85% rename from Programs/Simian/Extensions/PeriscopeMovement.cs rename to Programs/Simian/SceneExtensions/PeriscopeMovement.cs index 6a3253b4..ed2a4fa6 100644 --- a/Programs/Simian/Extensions/PeriscopeMovement.cs +++ b/Programs/Simian/SceneExtensions/PeriscopeMovement.cs @@ -5,7 +5,7 @@ using ExtensionLoader; using OpenMetaverse; using OpenMetaverse.Packets; -namespace Simian.Extensions +namespace Simian { public class PeriscopeMovement { @@ -27,7 +27,7 @@ namespace Simian.Extensions const float SQRT_TWO = 1.41421356f; - Simian server; + ISceneProvider scene; Periscope periscope; Timer updateTimer; long lastTick; @@ -38,13 +38,13 @@ namespace Simian.Extensions set { Interlocked.Exchange(ref lastTick, value); } } - public PeriscopeMovement(Simian server, Periscope periscope) + public PeriscopeMovement(ISceneProvider scene, Periscope periscope) { - this.server = server; + this.scene = scene; this.periscope = periscope; - server.UDP.RegisterPacketCallback(PacketType.AgentUpdate, AgentUpdateHandler); - server.UDP.RegisterPacketCallback(PacketType.SetAlwaysRun, SetAlwaysRunHandler); + scene.UDP.RegisterPacketCallback(PacketType.AgentUpdate, AgentUpdateHandler); + scene.UDP.RegisterPacketCallback(PacketType.SetAlwaysRun, SetAlwaysRunHandler); updateTimer = new Timer(new TimerCallback(UpdateTimer_Elapsed)); LastTick = Environment.TickCount; @@ -66,7 +66,7 @@ namespace Simian.Extensions float seconds = (float)((tick - LastTick) / 1000f); LastTick = tick; - server.Scene.ForEachAgent( + scene.ForEachAgent( delegate(Agent agent) { // Don't handle movement for the master agent or foreign agents @@ -110,10 +110,10 @@ namespace Simian.Extensions speed /= SQRT_TWO; Vector3 agentPosition = agent.Avatar.GetSimulatorPosition(); - float oldFloor = server.Scene.GetTerrainHeightAt(agentPosition.X, agentPosition.Y); + float oldFloor = scene.GetTerrainHeightAt(agentPosition.X, agentPosition.Y); agentPosition += (move * speed); - float newFloor = server.Scene.GetTerrainHeightAt(agentPosition.X, agentPosition.Y); + float newFloor = scene.GetTerrainHeightAt(agentPosition.X, agentPosition.Y); if (!flying && newFloor != oldFloor) speed /= (1 + (SQRT_TWO * Math.Abs(newFloor - oldFloor))); @@ -125,7 +125,7 @@ namespace Simian.Extensions // Z acceleration resulting from gravity float gravity = 0f; - float waterChestHeight = server.Scene.WaterHeight - (agent.Avatar.Prim.Scale.Z * .33f); + float waterChestHeight = scene.WaterHeight - (agent.Avatar.Prim.Scale.Z * .33f); if (flying) { @@ -142,29 +142,29 @@ namespace Simian.Extensions if (move.X != 0 || move.Y != 0) { //flying horizontally - if (server.Avatars.SetDefaultAnimation(agent, Animations.FLY)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.FLY)) animsChanged = true; } else if (move.Z > 0) { //flying straight up - if (server.Avatars.SetDefaultAnimation(agent, Animations.HOVER_UP)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.HOVER_UP)) animsChanged = true; } else if (move.Z < 0) { //flying straight down - if (server.Avatars.SetDefaultAnimation(agent, Animations.HOVER_DOWN)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.HOVER_DOWN)) animsChanged = true; } else { //hovering in the air - if (server.Avatars.SetDefaultAnimation(agent, Animations.HOVER)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.HOVER)) animsChanged = true; } } else if (agent.Avatar.Prim.Position.Z > lowerLimit + FALL_FORGIVENESS || agent.Avatar.Prim.Position.Z <= waterChestHeight) { //falling, floating, or landing from a jump - if (agent.Avatar.Prim.Position.Z > server.Scene.WaterHeight) + if (agent.Avatar.Prim.Position.Z > scene.WaterHeight) { //above water move = Vector3.Zero; //override controls while drifting @@ -184,7 +184,7 @@ namespace Simian.Extensions { //falling if (fallElapsed > FALL_DELAY) { //falling long enough to trigger the animation - if (server.Avatars.SetDefaultAnimation(agent, Animations.FALLDOWN)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.FALLDOWN)) animsChanged = true; } } @@ -207,7 +207,7 @@ namespace Simian.Extensions if (!jumping) { //begin prejump move.Z = 0; //override Z control - if (server.Avatars.SetDefaultAnimation(agent, Animations.PRE_JUMP)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.PRE_JUMP)) animsChanged = true; agent.TickJump = Environment.TickCount; @@ -222,7 +222,7 @@ namespace Simian.Extensions return; } - if (server.Avatars.SetDefaultAnimation(agent, Animations.JUMP)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.JUMP)) animsChanged = true; agent.Avatar.Prim.Velocity.X += agent.Avatar.Prim.Acceleration.X * JUMP_IMPULSE_HORIZONTAL; @@ -246,17 +246,17 @@ namespace Simian.Extensions if (move.Z < 0) { //crouchwalking - if (server.Avatars.SetDefaultAnimation(agent, Animations.CROUCHWALK)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.CROUCHWALK)) animsChanged = true; } else if (agent.Running) { //running - if (server.Avatars.SetDefaultAnimation(agent, Animations.RUN)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.RUN)) animsChanged = true; } else { //walking - if (server.Avatars.SetDefaultAnimation(agent, Animations.WALK)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.WALK)) animsChanged = true; } } @@ -264,12 +264,12 @@ namespace Simian.Extensions { //walking if (move.Z < 0) { //crouching - if (server.Avatars.SetDefaultAnimation(agent, Animations.CROUCH)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.CROUCH)) animsChanged = true; } else { //standing - if (server.Avatars.SetDefaultAnimation(agent, Animations.STAND)) + if (scene.Avatars.SetDefaultAnimation(agent, Animations.STAND)) animsChanged = true; } } @@ -277,7 +277,7 @@ namespace Simian.Extensions } if (animsChanged) - server.Avatars.SendAnimations(agent); + scene.Avatars.SendAnimations(agent); float maxVel = AVATAR_TERMINAL_VELOCITY * seconds; @@ -329,10 +329,10 @@ namespace Simian.Extensions } SimulationObject obj; - if (server.Scene.TryGetObject(update.AgentData.AgentID, out obj)) + if (scene.TryGetObject(update.AgentData.AgentID, out obj)) { obj.Prim.Rotation = update.AgentData.BodyRotation; - server.Scene.ObjectAddOrUpdate(this, obj, obj.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Rotation); + scene.ObjectAddOrUpdate(this, obj, obj.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Rotation); } } diff --git a/Programs/Simian/Extensions/PeriscopeTransferManager.cs b/Programs/Simian/SceneExtensions/PeriscopeTransferManager.cs similarity index 89% rename from Programs/Simian/Extensions/PeriscopeTransferManager.cs rename to Programs/Simian/SceneExtensions/PeriscopeTransferManager.cs index f78a44f0..65bf5ef1 100644 --- a/Programs/Simian/Extensions/PeriscopeTransferManager.cs +++ b/Programs/Simian/SceneExtensions/PeriscopeTransferManager.cs @@ -6,29 +6,29 @@ using OpenMetaverse; using OpenMetaverse.Imaging; using OpenMetaverse.Packets; -namespace Simian.Extensions +namespace Simian { public class PeriscopeTransferManager { public const string UPLOAD_DIR = "uploadedAssets"; - Simian server; + ISceneProvider scene; GridClient client; Dictionary CurrentUploads = new Dictionary(); /// A map from TransactionIDs to AvatarIDs Dictionary> currentDownloads = new Dictionary>(); - public PeriscopeTransferManager(Simian server, GridClient client) + public PeriscopeTransferManager(ISceneProvider scene, GridClient client) { - this.server = server; + this.scene = scene; this.client = client; client.Assets.OnAssetReceived += new OpenMetaverse.AssetManager.AssetReceivedCallback(Assets_OnAssetReceived); - server.UDP.RegisterPacketCallback(PacketType.AssetUploadRequest, new PacketCallback(AssetUploadRequestHandler)); - server.UDP.RegisterPacketCallback(PacketType.SendXferPacket, new PacketCallback(SendXferPacketHandler)); - server.UDP.RegisterPacketCallback(PacketType.AbortXfer, new PacketCallback(AbortXferHandler)); - server.UDP.RegisterPacketCallback(PacketType.TransferRequest, new PacketCallback(TransferRequestHandler)); + scene.UDP.RegisterPacketCallback(PacketType.AssetUploadRequest, new PacketCallback(AssetUploadRequestHandler)); + scene.UDP.RegisterPacketCallback(PacketType.SendXferPacket, new PacketCallback(SendXferPacketHandler)); + scene.UDP.RegisterPacketCallback(PacketType.AbortXfer, new PacketCallback(AbortXferHandler)); + scene.UDP.RegisterPacketCallback(PacketType.TransferRequest, new PacketCallback(TransferRequestHandler)); } public void Stop() @@ -58,14 +58,14 @@ namespace Simian.Extensions asset.Temporary = (request.AssetBlock.Tempfile | request.AssetBlock.StoreLocal); // Store the asset - server.Assets.StoreAsset(asset); + scene.Server.Assets.StoreAsset(asset); // Send a success response AssetUploadCompletePacket complete = new AssetUploadCompletePacket(); complete.AssetBlock.Success = true; complete.AssetBlock.Type = request.AssetBlock.Type; complete.AssetBlock.UUID = assetID; - server.UDP.SendPacket(agent.ID, complete, PacketCategory.Inventory); + scene.UDP.SendPacket(agent.ID, complete, PacketCategory.Inventory); } else { @@ -94,7 +94,7 @@ namespace Simian.Extensions lock (CurrentUploads) CurrentUploads[xfer.XferID.ID] = asset; - server.UDP.SendPacket(agent.ID, xfer, PacketCategory.Inventory); + scene.UDP.SendPacket(agent.ID, xfer, PacketCategory.Inventory); } } @@ -123,7 +123,7 @@ namespace Simian.Extensions ConfirmXferPacketPacket confirm = new ConfirmXferPacketPacket(); confirm.XferID.ID = xfer.XferID.ID; confirm.XferID.Packet = xfer.XferID.Packet; - server.UDP.SendPacket(agent.ID, confirm, PacketCategory.Asset); + scene.UDP.SendPacket(agent.ID, confirm, PacketCategory.Asset); } else { @@ -134,7 +134,7 @@ namespace Simian.Extensions ConfirmXferPacketPacket confirm = new ConfirmXferPacketPacket(); confirm.XferID.ID = xfer.XferID.ID; confirm.XferID.Packet = xfer.XferID.Packet; - server.UDP.SendPacket(agent.ID, confirm, PacketCategory.Asset); + scene.UDP.SendPacket(agent.ID, confirm, PacketCategory.Asset); if ((xfer.XferID.Packet & (uint)0x80000000) != 0) { @@ -144,13 +144,13 @@ namespace Simian.Extensions lock (CurrentUploads) CurrentUploads.Remove(xfer.XferID.ID); - server.Assets.StoreAsset(asset); + scene.Server.Assets.StoreAsset(asset); AssetUploadCompletePacket complete = new AssetUploadCompletePacket(); complete.AssetBlock.Success = true; complete.AssetBlock.Type = (sbyte)asset.AssetType; complete.AssetBlock.UUID = asset.AssetID; - server.UDP.SendPacket(agent.ID, complete, PacketCategory.Asset); + scene.UDP.SendPacket(agent.ID, complete, PacketCategory.Asset); } } } @@ -202,7 +202,7 @@ namespace Simian.Extensions // Check if we have this asset Asset asset; - if (server.Assets.TryGetAsset(assetID, out asset)) + if (scene.Server.Assets.TryGetAsset(assetID, out asset)) { if (asset.AssetType == type) { @@ -286,7 +286,7 @@ namespace Simian.Extensions response.TransferInfo.Status = (int)StatusCode.OK; response.TransferInfo.TargetType = (int)TargetType.Unknown; // Doesn't seem to be used by the client - server.UDP.SendPacket(agent.ID, response, PacketCategory.Asset); + scene.UDP.SendPacket(agent.ID, response, PacketCategory.Asset); // Transfer system does not wait for ACKs, just sends all of the // packets for this transfer out @@ -310,7 +310,7 @@ namespace Simian.Extensions else transfer.TransferData.Status = (int)StatusCode.OK; - server.UDP.SendPacket(agent.ID, transfer, PacketCategory.Asset); + scene.UDP.SendPacket(agent.ID, transfer, PacketCategory.Asset); } } @@ -324,11 +324,11 @@ namespace Simian.Extensions { currentDownloads.Remove(transfer.ID); - if (server.Scene.TryGetAgent(kvp.Key, out agent)) + if (scene.TryGetAgent(kvp.Key, out agent)) { if (transfer.Success) { - server.Assets.StoreAsset(asset); + scene.Server.Assets.StoreAsset(asset); TransferToClient(asset, agent, kvp.Value); } else @@ -349,7 +349,7 @@ namespace Simian.Extensions response.TransferInfo.Status = (int)StatusCode.UnknownSource; response.TransferInfo.TargetType = (int)TargetType.Unknown; - server.UDP.SendPacket(agent.ID, response, PacketCategory.Asset); + scene.UDP.SendPacket(agent.ID, response, PacketCategory.Asset); } } else diff --git a/Programs/Simian/Extensions/PhysicsSimple.cs b/Programs/Simian/SceneExtensions/PhysicsSimple.cs similarity index 96% rename from Programs/Simian/Extensions/PhysicsSimple.cs rename to Programs/Simian/SceneExtensions/PhysicsSimple.cs index f0485f44..61103181 100644 --- a/Programs/Simian/Extensions/PhysicsSimple.cs +++ b/Programs/Simian/SceneExtensions/PhysicsSimple.cs @@ -3,11 +3,11 @@ using ExtensionLoader; using OpenMetaverse; using OpenMetaverse.Rendering; -namespace Simian.Extensions +namespace Simian { - public class PhysicsSimple : IExtension, IPhysicsProvider + public class PhysicsSimple : IExtension, IPhysicsProvider { - Simian server; + ISceneProvider scene; public float TimeDilation { @@ -18,9 +18,10 @@ namespace Simian.Extensions { } - public void Start(Simian server) + public bool Start(ISceneProvider scene) { - this.server = server; + this.scene = scene; + return true; } public void Stop() @@ -67,7 +68,7 @@ namespace Simian.Extensions public bool TryGetObjectMass(UUID objectID, out float mass) { SimulationObject obj; - if (server.Scene.TryGetObject(objectID, out obj)) + if (scene.TryGetObject(objectID, out obj)) { mass = CalculateMass(obj.Prim); return true; diff --git a/Programs/Simian/Extensions/ScriptApi.cs b/Programs/Simian/SceneExtensions/ScriptApi.cs similarity index 92% rename from Programs/Simian/Extensions/ScriptApi.cs rename to Programs/Simian/SceneExtensions/ScriptApi.cs index b6441e7c..61ec817d 100644 --- a/Programs/Simian/Extensions/ScriptApi.cs +++ b/Programs/Simian/SceneExtensions/ScriptApi.cs @@ -38,7 +38,7 @@ using LSL_Rotation = Simian.ScriptTypes.LSL_Rotation; using LSL_String = Simian.ScriptTypes.LSL_String; using LSL_Vector = Simian.ScriptTypes.LSL_Vector; -namespace Simian.Extensions +namespace Simian { /// /// Contains all LSL ll-functions. This class will be in Default AppDomain. @@ -163,7 +163,7 @@ namespace Simian.Extensions #endregion Base64 Data - Simian server; + ISceneProvider scene; SimulationObject hostObject; UUID scriptID; bool isGodMode; @@ -174,9 +174,9 @@ namespace Simian.Extensions { } - public void Start(Simian server, SimulationObject hostObject, UUID scriptID, bool isGodMode, bool automaticLinkPermission) + public void Start(ISceneProvider scene, SimulationObject hostObject, UUID scriptID, bool isGodMode, bool automaticLinkPermission) { - this.server = server; + this.scene = scene; this.hostObject = hostObject; this.scriptID = scriptID; this.isGodMode = isGodMode; @@ -220,13 +220,13 @@ namespace Simian.Extensions public void state(string newState) { - server.ScriptEngine.TriggerState(scriptID, newState); + scene.ScriptEngine.TriggerState(scriptID, newState); } public void llResetScript() { hostObject.AddScriptLPS(1); - server.ScriptEngine.ApiResetScript(scriptID); + scene.ScriptEngine.ApiResetScript(scriptID); } public void llResetOtherScript(string name) @@ -235,7 +235,7 @@ namespace Simian.Extensions hostObject.AddScriptLPS(1); if ((otherScriptID = ScriptByName(name)) != UUID.Zero) - server.ScriptEngine.ResetScript(otherScriptID); + scene.ScriptEngine.ResetScript(otherScriptID); else ShoutError("llResetOtherScript: script " + name + " not found"); } @@ -247,7 +247,7 @@ namespace Simian.Extensions if ((otherScriptID = ScriptByName(name)) != UUID.Zero) { - return server.ScriptEngine.GetScriptState(otherScriptID) ? 1 : 0; + return scene.ScriptEngine.GetScriptState(otherScriptID) ? 1 : 0; } ShoutError("llGetScriptState: script " + name + " not found"); @@ -264,7 +264,7 @@ namespace Simian.Extensions if ((otherScriptID = ScriptByName(name)) != UUID.Zero) { - server.ScriptEngine.SetScriptState(otherScriptID, run == 0 ? false : true); + scene.ScriptEngine.SetScriptState(otherScriptID, run == 0 ? false : true); } else { @@ -619,7 +619,7 @@ namespace Simian.Extensions if (text.Length > 1023) text = text.Substring(0, 1023); - server.Scene.ObjectChat(this, hostObject.Prim.Properties.OwnerID, hostObject.Prim.ID, ChatAudibleLevel.Fully, ChatType.Whisper, + scene.ObjectChat(this, hostObject.Prim.Properties.OwnerID, hostObject.Prim.ID, ChatAudibleLevel.Fully, ChatType.Whisper, ChatSourceType.Object, hostObject.Prim.Properties.Name, hostObject.GetSimulatorPosition(), channelID, text); } @@ -630,7 +630,7 @@ namespace Simian.Extensions if (text.Length > 1023) text = text.Substring(0, 1023); - server.Scene.ObjectChat(this, hostObject.Prim.Properties.OwnerID, hostObject.Prim.ID, ChatAudibleLevel.Fully, ChatType.Normal, + scene.ObjectChat(this, hostObject.Prim.Properties.OwnerID, hostObject.Prim.ID, ChatAudibleLevel.Fully, ChatType.Normal, ChatSourceType.Object, hostObject.Prim.Properties.Name, hostObject.GetSimulatorPosition(), channelID, text); } @@ -641,7 +641,7 @@ namespace Simian.Extensions if (text.Length > 1023) text = text.Substring(0, 1023); - server.Scene.ObjectChat(this, hostObject.Prim.Properties.OwnerID, hostObject.Prim.ID, ChatAudibleLevel.Fully, ChatType.Shout, + scene.ObjectChat(this, hostObject.Prim.Properties.OwnerID, hostObject.Prim.ID, ChatAudibleLevel.Fully, ChatType.Shout, ChatSourceType.Object, hostObject.Prim.Properties.Name, hostObject.GetSimulatorPosition(), channelID, text); } @@ -658,7 +658,7 @@ namespace Simian.Extensions if (text.Length > 1023) text = text.Substring(0, 1023); - server.Scene.ObjectChat(this, hostObject.Prim.Properties.OwnerID, hostObject.Prim.ID, ChatAudibleLevel.Fully, ChatType.RegionSay, + scene.ObjectChat(this, hostObject.Prim.Properties.OwnerID, hostObject.Prim.ID, ChatAudibleLevel.Fully, ChatType.RegionSay, ChatSourceType.Object, hostObject.Prim.Properties.Name, hostObject.GetSimulatorPosition(), channelID, text); } @@ -669,19 +669,19 @@ namespace Simian.Extensions UUID keyID; UUID.TryParse(ID, out keyID); - return server.ScriptEngine.AddListener(scriptID, hostObject.Prim.ID, channelID, name, keyID, msg); + return scene.ScriptEngine.AddListener(scriptID, hostObject.Prim.ID, channelID, name, keyID, msg); } public void llListenControl(int number, int active) { hostObject.AddScriptLPS(1); - server.ScriptEngine.SetListenerState(scriptID, number, active == 0 ? false : true); + scene.ScriptEngine.SetListenerState(scriptID, number, active == 0 ? false : true); } public void llListenRemove(int number) { hostObject.AddScriptLPS(1); - server.ScriptEngine.RemoveListener(scriptID, number); + scene.ScriptEngine.RemoveListener(scriptID, number); } public void llSensor(string name, string id, int type, double range, double arc) @@ -691,7 +691,7 @@ namespace Simian.Extensions UUID keyID = UUID.Zero; UUID.TryParse(id, out keyID); - server.ScriptEngine.SensorOnce(scriptID, hostObject.Prim.ID, name, keyID, type, range, arc); + scene.ScriptEngine.SensorOnce(scriptID, hostObject.Prim.ID, name, keyID, type, range, arc); } public void llSensorRepeat(string name, string id, int type, double range, double arc, double rate) @@ -701,19 +701,19 @@ namespace Simian.Extensions UUID keyID = UUID.Zero; UUID.TryParse(id, out keyID); - server.ScriptEngine.SensorRepeat(scriptID, hostObject.Prim.ID, name, keyID, type, range, arc, rate); + scene.ScriptEngine.SensorRepeat(scriptID, hostObject.Prim.ID, name, keyID, type, range, arc, rate); } public void llSensorRemove() { hostObject.AddScriptLPS(1); - server.ScriptEngine.SensorRemove(scriptID); + scene.ScriptEngine.SensorRemove(scriptID); } public LSL_String llDetectedName(int number) { hostObject.AddScriptLPS(1); - DetectParams detectedParams = server.ScriptEngine.GetDetectParams(scriptID, number); + DetectParams detectedParams = scene.ScriptEngine.GetDetectParams(scriptID, number); if (detectedParams == null) return LSL_String.Empty; @@ -723,7 +723,7 @@ namespace Simian.Extensions public LSL_Key llDetectedKey(int number) { hostObject.AddScriptLPS(1); - DetectParams detectedParams = server.ScriptEngine.GetDetectParams(scriptID, number); + DetectParams detectedParams = scene.ScriptEngine.GetDetectParams(scriptID, number); if (detectedParams == null) return LSL_Key.Zero; @@ -733,7 +733,7 @@ namespace Simian.Extensions public LSL_Key llDetectedOwner(int number) { hostObject.AddScriptLPS(1); - DetectParams detectedParams = server.ScriptEngine.GetDetectParams(scriptID, number); + DetectParams detectedParams = scene.ScriptEngine.GetDetectParams(scriptID, number); if (detectedParams == null) return LSL_Key.Zero; @@ -743,7 +743,7 @@ namespace Simian.Extensions public LSL_Integer llDetectedType(int number) { hostObject.AddScriptLPS(1); - DetectParams detectedParams = server.ScriptEngine.GetDetectParams(scriptID, number); + DetectParams detectedParams = scene.ScriptEngine.GetDetectParams(scriptID, number); if (detectedParams == null) return LSL_Integer.Zero; @@ -753,7 +753,7 @@ namespace Simian.Extensions public LSL_Vector llDetectedPos(int number) { hostObject.AddScriptLPS(1); - DetectParams detectedParams = server.ScriptEngine.GetDetectParams(scriptID, number); + DetectParams detectedParams = scene.ScriptEngine.GetDetectParams(scriptID, number); if (detectedParams == null) return LSL_Vector.Zero; @@ -763,7 +763,7 @@ namespace Simian.Extensions public LSL_Vector llDetectedVel(int number) { hostObject.AddScriptLPS(1); - DetectParams detectedParams = server.ScriptEngine.GetDetectParams(scriptID, number); + DetectParams detectedParams = scene.ScriptEngine.GetDetectParams(scriptID, number); if (detectedParams == null) return LSL_Vector.Zero; @@ -773,7 +773,7 @@ namespace Simian.Extensions public LSL_Vector llDetectedGrab(int number) { hostObject.AddScriptLPS(1); - DetectParams detectedParams = server.ScriptEngine.GetDetectParams(scriptID, number); + DetectParams detectedParams = scene.ScriptEngine.GetDetectParams(scriptID, number); if (detectedParams == null) return LSL_Vector.Zero; @@ -783,7 +783,7 @@ namespace Simian.Extensions public LSL_Rotation llDetectedRot(int number) { hostObject.AddScriptLPS(1); - DetectParams detectedParams = server.ScriptEngine.GetDetectParams(scriptID, number); + DetectParams detectedParams = scene.ScriptEngine.GetDetectParams(scriptID, number); if (detectedParams == null) return LSL_Rotation.Identity; @@ -793,7 +793,7 @@ namespace Simian.Extensions public LSL_Integer llDetectedGroup(int number) { hostObject.AddScriptLPS(1); - DetectParams detectedParams = server.ScriptEngine.GetDetectParams(scriptID, number); + DetectParams detectedParams = scene.ScriptEngine.GetDetectParams(scriptID, number); if (detectedParams == null) return ScriptTypes.FALSE; @@ -805,7 +805,7 @@ namespace Simian.Extensions public LSL_Integer llDetectedLinkNumber(int number) { hostObject.AddScriptLPS(1); - DetectParams parms = server.ScriptEngine.GetDetectParams(scriptID, number); + DetectParams parms = scene.ScriptEngine.GetDetectParams(scriptID, number); if (parms == null) return LSL_Integer.Zero; @@ -818,7 +818,7 @@ namespace Simian.Extensions public LSL_Vector llDetectedTouchBinormal(int number) { hostObject.AddScriptLPS(1); - DetectParams detectedParams = server.ScriptEngine.GetDetectParams(scriptID, number); + DetectParams detectedParams = scene.ScriptEngine.GetDetectParams(scriptID, number); if (detectedParams == null) return LSL_Vector.Zero; @@ -831,7 +831,7 @@ namespace Simian.Extensions public LSL_Integer llDetectedTouchFace(int number) { hostObject.AddScriptLPS(1); - DetectParams detectedParams = server.ScriptEngine.GetDetectParams(scriptID, number); + DetectParams detectedParams = scene.ScriptEngine.GetDetectParams(scriptID, number); if (detectedParams == null) return ScriptTypes.TOUCH_INVALID_FACE; @@ -844,7 +844,7 @@ namespace Simian.Extensions public LSL_Vector llDetectedTouchNormal(int number) { hostObject.AddScriptLPS(1); - DetectParams detectedParams = server.ScriptEngine.GetDetectParams(scriptID, number); + DetectParams detectedParams = scene.ScriptEngine.GetDetectParams(scriptID, number); if (detectedParams == null) return LSL_Vector.Zero; @@ -857,7 +857,7 @@ namespace Simian.Extensions public LSL_Vector llDetectedTouchPos(int number) { hostObject.AddScriptLPS(1); - DetectParams detectedParams = server.ScriptEngine.GetDetectParams(scriptID, number); + DetectParams detectedParams = scene.ScriptEngine.GetDetectParams(scriptID, number); if (detectedParams == null) return LSL_Vector.Zero; @@ -870,7 +870,7 @@ namespace Simian.Extensions public LSL_Vector llDetectedTouchST(int number) { hostObject.AddScriptLPS(1); - DetectParams detectedParams = server.ScriptEngine.GetDetectParams(scriptID, number); + DetectParams detectedParams = scene.ScriptEngine.GetDetectParams(scriptID, number); if (detectedParams == null) return ScriptTypes.TOUCH_INVALID_TEXCOORD; return detectedParams.TouchST; @@ -882,7 +882,7 @@ namespace Simian.Extensions public LSL_Vector llDetectedTouchUV(int number) { hostObject.AddScriptLPS(1); - DetectParams detectedParams = server.ScriptEngine.GetDetectParams(scriptID, number); + DetectParams detectedParams = scene.ScriptEngine.GetDetectParams(scriptID, number); if (detectedParams == null) return ScriptTypes.TOUCH_INVALID_TEXCOORD; @@ -904,8 +904,8 @@ namespace Simian.Extensions float y = pos.Y + (float)offset.y; // Clamp to valid position - float simWidth = (float)(server.Scene.TerrainPatchCountWidth * server.Scene.TerrainPatchWidth); - float simHeight = (float)(server.Scene.TerrainPatchCountHeight * server.Scene.TerrainPatchHeight); + float simWidth = (float)(scene.TerrainPatchCountWidth * scene.TerrainPatchWidth); + float simHeight = (float)(scene.TerrainPatchCountHeight * scene.TerrainPatchHeight); if (x < 0.0f) x = 0.0f; @@ -916,7 +916,7 @@ namespace Simian.Extensions else if (y >= simHeight) y = simHeight - 1.0f; - return server.Scene.GetTerrainHeightAt(x, y); + return scene.GetTerrainHeightAt(x, y); } public LSL_Float llCloud(LSL_Vector offset) @@ -929,7 +929,7 @@ namespace Simian.Extensions public LSL_Vector llWind(LSL_Vector offset) { hostObject.AddScriptLPS(1); - Vector2 windSpeed = server.Scene.GetWindSpeedAt((float)offset.x, (float)offset.y); + Vector2 windSpeed = scene.GetWindSpeedAt((float)offset.x, (float)offset.y); return new LSL_Vector(windSpeed.X, windSpeed.Y, 0.0); } @@ -1019,10 +1019,10 @@ namespace Simian.Extensions if ((statusrotationaxis & Y_AXIS) != 0) rotationAxis.Y = setValue; if ((statusrotationaxis & Z_AXIS) != 0) rotationAxis.Z = setValue; - server.Scene.ObjectSetRotationAxis(this, parent, rotationAxis); + scene.ObjectSetRotationAxis(this, parent, rotationAxis); } - server.Scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.PrimFlags); + scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.PrimFlags); } public LSL_Integer llGetStatus(int status) @@ -1078,7 +1078,7 @@ namespace Simian.Extensions // TODO: Apply constraints hostObject.Prim.Scale = new Vector3((float)scale.x, (float)scale.y, (float)scale.z); - server.Scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.Scale); + scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.Scale); } public LSL_Vector llGetScale() @@ -1092,7 +1092,7 @@ namespace Simian.Extensions hostObject.AddScriptLPS(1); hostObject.Prim.ClickAction = (ClickAction)action; - server.Scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.ClickAction); + scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.ClickAction); } public void llSetColor(LSL_Vector color, int face) @@ -1258,7 +1258,7 @@ namespace Simian.Extensions // Child prims do not have velocity, only parents SimulationObject parent = hostObject.GetLinksetParent(); parent.Prim.Velocity = velocity; - server.Scene.ObjectAddOrUpdate(this, parent, parent.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Velocity); + scene.ObjectAddOrUpdate(this, parent, parent.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Velocity); } public LSL_Vector llGetForce() @@ -1323,7 +1323,7 @@ namespace Simian.Extensions // Child prims do not move, only parents SimulationObject parent = hostObject.GetLinksetParent(); - server.Scene.ObjectApplyImpulse(this, parent, new Vector3((float)force.x, (float)force.y, (float)force.z)); + scene.ObjectApplyImpulse(this, parent, new Vector3((float)force.x, (float)force.y, (float)force.z)); } public void llApplyRotationalImpulse(LSL_Vector force, int local) @@ -1339,7 +1339,7 @@ namespace Simian.Extensions // Can't apply rotational impulse to avatars if (!(parent.Prim is Avatar)) - server.Scene.ObjectApplyRotationalImpulse(this, parent, new Vector3((float)force.x, (float)force.y, (float)force.z)); + scene.ObjectApplyRotationalImpulse(this, parent, new Vector3((float)force.x, (float)force.y, (float)force.z)); } public void llSetTorque(LSL_Vector torque, int local) @@ -1354,7 +1354,7 @@ namespace Simian.Extensions // Can't set torque on avatars if (!(parent.Prim is Avatar)) - server.Scene.ObjectSetTorque(this, parent, new Vector3((float)torque.x, (float)torque.y, (float)torque.z)); + scene.ObjectSetTorque(this, parent, new Vector3((float)torque.x, (float)torque.y, (float)torque.z)); } public LSL_Vector llGetTorque() @@ -1464,7 +1464,7 @@ namespace Simian.Extensions hostObject.Prim.SoundFlags = SoundFlags.Loop; hostObject.Prim.SoundRadius = 20f; // TODO: Randomly selected - server.Scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.Sound); + scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.Sound); } public void llLoopSoundMaster(string sound, double volume) @@ -1479,7 +1479,7 @@ namespace Simian.Extensions hostObject.Prim.SoundFlags = SoundFlags.Loop | SoundFlags.SyncMaster; hostObject.Prim.SoundRadius = 20f; // TODO: Randomly selected - server.Scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.Sound); + scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.Sound); } public void llLoopSoundSlave(string sound, double volume) @@ -1494,7 +1494,7 @@ namespace Simian.Extensions hostObject.Prim.SoundFlags = SoundFlags.Loop | SoundFlags.SyncSlave; hostObject.Prim.SoundRadius = 20f; // TODO: Randomly selected - server.Scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.Sound); + scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.Sound); } public void llPlaySoundSlave(string sound, double volume) @@ -1509,14 +1509,14 @@ namespace Simian.Extensions hostObject.Prim.SoundFlags = SoundFlags.SyncSlave; hostObject.Prim.SoundRadius = 20f; // TODO: Randomly selected - server.Scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.Sound); + scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.Sound); } public void llTriggerSound(string sound, double volume) { hostObject.AddScriptLPS(1); - server.Scene.TriggerSound(this, hostObject.Prim.ID, hostObject.GetLinksetParent().Prim.ID, + scene.TriggerSound(this, hostObject.Prim.ID, hostObject.GetLinksetParent().Prim.ID, hostObject.Prim.Properties.OwnerID, KeyOrName(sound), hostObject.GetSimulatorPosition(), (float)volume); } @@ -1531,7 +1531,7 @@ namespace Simian.Extensions hostObject.Prim.SoundFlags = SoundFlags.None; hostObject.Prim.SoundRadius = 0f; - server.Scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.Sound); + scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.Sound); } public void llPreloadSound(string sound) @@ -1546,7 +1546,7 @@ namespace Simian.Extensions hostObject.Prim.SoundFlags = SoundFlags.Queue; // TODO: Is this correct? hostObject.Prim.SoundRadius = 20f; // TODO: Randomly selected - server.Scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.Sound); + scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.Sound); // ScriptSleep(1000); } @@ -1851,15 +1851,15 @@ namespace Simian.Extensions // Special handler to allow llRez*() functions to work from the scripting console Primitive cube = new Primitive(); cube.PrimData = OpenMetaverse.ObjectManager.BuildBasicShape(PrimType.Box); - SimulationObject obj = new SimulationObject(cube, server); + SimulationObject obj = new SimulationObject(cube, scene); newLinkset = new List(1); newLinkset.Add(obj); } if ((item != null && - server.TaskInventory.TryGetAsset(hostObject.Prim.ID, item.AssetID, out asset) && + scene.TaskInventory.TryGetAsset(hostObject.Prim.ID, item.AssetID, out asset) && asset is AssetPrim && - server.Assets.TryDecodePrimAsset(((AssetPrim)asset).AssetData, out newLinkset)) || + scene.Server.Assets.TryDecodePrimAsset(((AssetPrim)asset).AssetData, out newLinkset)) || newLinkset != null) { for (int i = 0; i < newLinkset.Count; i++) @@ -1876,7 +1876,7 @@ namespace Simian.Extensions newObj.Prim.Rotation = llrot; } - server.Scene.ObjectAddOrUpdate(this, newObj, hostObject.Prim.Properties.OwnerID, param, PrimFlags.None, UpdateFlags.FullUpdate); + scene.ObjectAddOrUpdate(this, newObj, hostObject.Prim.Properties.OwnerID, param, PrimFlags.None, UpdateFlags.FullUpdate); if (newObj.Prim.ParentID == 0) newParent = newObj; @@ -1884,7 +1884,7 @@ namespace Simian.Extensions if (newParent != null) { - server.ScriptEngine.PostObjectEvent(hostObject.Prim.ID, new EventParams("object_rez", + scene.ScriptEngine.PostObjectEvent(hostObject.Prim.ID, new EventParams("object_rez", new Object[] { new LSL_String(newParent.ToString()) }, new DetectParams[0]) ); @@ -1953,7 +1953,7 @@ namespace Simian.Extensions sec = MIN_TIMER_INTERVAL; // Setting timer repeat - server.ScriptEngine.SetTimerEvent(scriptID, sec); + scene.ScriptEngine.SetTimerEvent(scriptID, sec); } public void llSleep(double sec) @@ -2029,7 +2029,7 @@ namespace Simian.Extensions UUID toID; UUID.TryParse(user, out toID); - server.Messages.SendInstantMessage(this, hostObject.Prim.ID, hostObject.Prim.Properties.Name, toID, + scene.Server.Messages.SendInstantMessage(this, hostObject.Prim.ID, hostObject.Prim.Properties.Name, toID, InstantMessageDialog.MessageFromObject, false, hostObject.Prim.ID, false, hostObject.GetSimulatorPosition(), 0, UUID.Zero, DateTime.Now, message, Utils.EmptyBytes); ScriptSleep(2000); @@ -2039,7 +2039,7 @@ namespace Simian.Extensions { hostObject.AddScriptLPS(1); - server.Messages.SendEmail(this, hostObject.Prim.ID, address, subject, message); + scene.Server.Messages.SendEmail(this, hostObject.Prim.ID, address, subject, message); ScriptSleep(20000); } @@ -2048,9 +2048,9 @@ namespace Simian.Extensions hostObject.AddScriptLPS(1); Email email; - if (server.Messages.GetNextEmail(hostObject.Prim.ID, address, subject, out email)) + if (scene.Server.Messages.GetNextEmail(hostObject.Prim.ID, address, subject, out email)) { - server.ScriptEngine.PostObjectEvent(hostObject.Prim.ID, new EventParams("email", new Object[] { + scene.ScriptEngine.PostObjectEvent(hostObject.Prim.ID, new EventParams("email", new Object[] { new LSL_String(email.Time.ToString()), new LSL_String(email.Sender), new LSL_String(email.Subject), @@ -2072,7 +2072,7 @@ namespace Simian.Extensions hostObject.AddScriptLPS(1); //SimulationObject parent = hostObject.GetLinksetParent(); NotImplemented("llSetBuoyancy"); - //server.Scene.ObjectSetBuoyancy(this, parent, (float)buoyancy); + //scene.ObjectSetBuoyancy(this, parent, (float)buoyancy); } public void llSetHoverHeight(double height, int water, double tau) @@ -2084,13 +2084,13 @@ namespace Simian.Extensions if (water == 1) { - float waterHeight = server.Scene.WaterHeight; + float waterHeight = scene.WaterHeight; if (waterHeight > targetHeight) targetHeight = waterHeight + (float)height; } else { - float landHeight = server.Scene.GetTerrainHeightAt(pos.X, pos.Y); + float landHeight = scene.GetTerrainHeightAt(pos.X, pos.Y); targetHeight = landHeight + (float)height; } @@ -2103,7 +2103,7 @@ namespace Simian.Extensions parent.Prim.Position = newPosition; // Don't set UpdateFlags.PrimFlags since Flying is a server-side only flag - server.Scene.ObjectAddOrUpdate(this, parent, parent.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Position); + scene.ObjectAddOrUpdate(this, parent, parent.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Position); } public void llStopHover() @@ -2115,13 +2115,13 @@ namespace Simian.Extensions // Trigger an object transformation even though we don't directly manipulate any parameters that are sent // to the client. This will make sure the physics engine realizes the flying flag has been turned off - server.Scene.ObjectAddOrUpdate(this, parent, parent.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Position); + scene.ObjectAddOrUpdate(this, parent, parent.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Position); } public void llMinEventDelay(double delay) { hostObject.AddScriptLPS(1); - server.ScriptEngine.SetScriptMinEventDelay(hostObject.Prim.ID, delay); + scene.ScriptEngine.SetScriptMinEventDelay(hostObject.Prim.ID, delay); } /// @@ -2161,14 +2161,14 @@ namespace Simian.Extensions { if ((item.GrantedPermissions & ScriptTypes.PERMISSION_TRIGGER_ANIMATION) != 0) { - if (server.Scene.TryGetAgent(item.PermissionGranter, out agent)) + if (scene.TryGetAgent(item.PermissionGranter, out agent)) { UUID animID = InventoryKey(anim, AssetType.Animation).AssetID; if (animID != UUID.Zero) { - server.Avatars.AddAnimation(agent, animID); - server.Avatars.SendAnimations(agent); + scene.Avatars.AddAnimation(agent, animID); + scene.Avatars.SendAnimations(agent); } } } @@ -2189,14 +2189,14 @@ namespace Simian.Extensions { if ((item.GrantedPermissions & ScriptTypes.PERMISSION_TRIGGER_ANIMATION) != 0) { - if (server.Scene.TryGetAgent(item.PermissionGranter, out agent)) + if (scene.TryGetAgent(item.PermissionGranter, out agent)) { UUID animID = InventoryKey(anim, AssetType.Animation).AssetID; if (animID != UUID.Zero) { - server.Avatars.RemoveAnimation(agent, animID); - server.Avatars.SendAnimations(agent); + scene.Avatars.RemoveAnimation(agent, animID); + scene.Avatars.SendAnimations(agent); } } } @@ -2224,13 +2224,13 @@ namespace Simian.Extensions angVel *= (float)spinrate; hostObject.Prim.AngularVelocity = angVel; - server.Scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.AngularVelocity); + scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.AngularVelocity); } public LSL_Integer llGetStartParameter() { hostObject.AddScriptLPS(1); - return server.ScriptEngine.GetStartParameter(scriptID); + return scene.ScriptEngine.GetStartParameter(scriptID); } public void llGodLikeRezObject(string inventory, LSL_Vector pos) @@ -2257,7 +2257,7 @@ namespace Simian.Extensions scriptItem.PermissionGranter = UUID.Zero; scriptItem.GrantedPermissions = 0; - server.ScriptEngine.PostScriptEvent(scriptID, new EventParams( + scene.ScriptEngine.PostScriptEvent(scriptID, new EventParams( "run_time_permissions", new Object[] { LSL_Integer.Zero }, new DetectParams[0])); @@ -2362,7 +2362,7 @@ namespace Simian.Extensions { hostObject.AddScriptLPS(1); - InventoryTaskItem scriptItem = server.TaskInventory.FindItem(hostObject.Prim.ID, + InventoryTaskItem scriptItem = scene.TaskInventory.FindItem(hostObject.Prim.ID, delegate(InventoryTaskItem item) { return item.ID == scriptID; }); if (scriptItem != null) @@ -2375,7 +2375,7 @@ namespace Simian.Extensions { hostObject.AddScriptLPS(1); - InventoryTaskItem scriptItem = server.TaskInventory.FindItem(hostObject.Prim.ID, + InventoryTaskItem scriptItem = scene.TaskInventory.FindItem(hostObject.Prim.ID, delegate(InventoryTaskItem item) { return item.ID == scriptID; }); uint perms = 0; @@ -2499,7 +2499,7 @@ namespace Simian.Extensions hostObject.AddScriptLPS(1); int count = 0; - server.TaskInventory.ForEachItem(hostObject.Prim.ID, + scene.TaskInventory.ForEachItem(hostObject.Prim.ID, delegate(InventoryTaskItem item) { if (type == -1 || (int)item.AssetType == type) @@ -2549,13 +2549,13 @@ namespace Simian.Extensions (float)Utils.Clamp(alpha, 0f, 1f)); hostObject.Prim.Text = text; - server.Scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.Text); + scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.Text); } public LSL_Float llWater(LSL_Vector offset) { hostObject.AddScriptLPS(1); - return server.Scene.WaterHeight; + return scene.WaterHeight; } public void llPassTouches(int pass) @@ -3418,9 +3418,9 @@ namespace Simian.Extensions Agent agent; SimulationObject obj; - if (server.Scene.TryGetAgent(key, out agent)) + if (scene.TryGetAgent(key, out agent)) return agent.FullName; - else if (server.Scene.TryGetObject(key, out obj)) + else if (scene.TryGetObject(key, out obj)) return obj.Prim.Properties.Name; } @@ -3445,7 +3445,7 @@ namespace Simian.Extensions pTexAnim.Start = (float)start; hostObject.Prim.TextureAnim = pTexAnim; - server.Scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.TextureAnim); + scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.TextureAnim); } public void llTriggerSoundLimited(string sound, double volume, LSL_Vector top_north_east, LSL_Vector bottom_south_west) @@ -3558,8 +3558,8 @@ namespace Simian.Extensions UUID key; Agent agent; - if (UUID.TryParse(id, out key) && server.Scene.TryGetAgent(key, out agent)) - return new LSL_Vector(0.45, 0.6, agent.Height); + if (UUID.TryParse(id, out key) && scene.TryGetAgent(key, out agent)) + return new LSL_Vector(0.45, 0.6, agent.Info.Height); else return LSL_Vector.Zero; } @@ -3631,7 +3631,7 @@ namespace Simian.Extensions public LSL_String llGetRegionName() { hostObject.AddScriptLPS(1); - return server.Scene.RegionName; + return scene.RegionName; } public LSL_Float llGetRegionTimeDilation() @@ -3793,7 +3793,7 @@ namespace Simian.Extensions hostObject.Prim.ParticleSys = prules; } - server.Scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.Particles); + scene.ObjectAddOrUpdate(this, hostObject, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.Particles); } public void llGroundRepel(double height, int water, double tau) @@ -4520,7 +4520,7 @@ namespace Simian.Extensions { hostObject.AddScriptLPS(1); - InventoryTaskItem findItem = server.TaskInventory.FindItem(hostObject.Prim.ID, + InventoryTaskItem findItem = scene.TaskInventory.FindItem(hostObject.Prim.ID, delegate(InventoryTaskItem item) { return item.Name == itemName; }); if (findItem != null) @@ -4558,7 +4558,7 @@ namespace Simian.Extensions if (msg.Length > 1023) msg = msg.Substring(0, 1023); - server.Scene.ObjectChat(this, hostObject.Prim.Properties.OwnerID, hostObject.Prim.ID, ChatAudibleLevel.Fully, ChatType.OwnerSay, + scene.ObjectChat(this, hostObject.Prim.Properties.OwnerID, hostObject.Prim.ID, ChatAudibleLevel.Fully, ChatType.OwnerSay, ChatSourceType.Object, hostObject.Prim.Properties.Name, hostObject.GetSimulatorPosition(), 0, msg); } @@ -4997,12 +4997,12 @@ namespace Simian.Extensions { // try agents Agent agent; - if (server.Scene.TryGetAgent(objectID, out agent)) + if (scene.TryGetAgent(objectID, out agent)) return agent.FullName; // try scene objects SimulationObject obj; - if (server.Scene.TryGetObject(objectID, out obj)) + if (scene.TryGetObject(objectID, out obj)) return obj.Prim.Properties.Name; return String.Empty; @@ -5014,7 +5014,7 @@ namespace Simian.Extensions List parts; if (hostObject.Prim.ParentID != 0) - server.Scene.TryGetObject(hostObject.Prim.ParentID, out parent); + scene.TryGetObject(hostObject.Prim.ParentID, out parent); switch (linkType) { @@ -5103,7 +5103,7 @@ namespace Simian.Extensions private InventoryTaskItem InventorySelf() { hostObject.AddScriptLPS(1); - return server.TaskInventory.FindItem(hostObject.Prim.ID, + return scene.TaskInventory.FindItem(hostObject.Prim.ID, delegate(InventoryTaskItem item) { return item.AssetID == scriptID; }); } @@ -5111,7 +5111,7 @@ namespace Simian.Extensions { hostObject.AddScriptLPS(1); - return server.TaskInventory.FindItem(hostObject.Prim.ID, + return scene.TaskInventory.FindItem(hostObject.Prim.ID, delegate(InventoryTaskItem item) { return item.AssetType == type && item.Name == name; }); } @@ -5119,7 +5119,7 @@ namespace Simian.Extensions { hostObject.AddScriptLPS(1); - return server.TaskInventory.FindItem(hostObject.Prim.ID, + return scene.TaskInventory.FindItem(hostObject.Prim.ID, delegate(InventoryTaskItem item) { return item.Name == name; }); } @@ -5151,7 +5151,7 @@ namespace Simian.Extensions UUID ScriptByName(string name) { - InventoryTaskItem scriptItem = server.TaskInventory.FindItem(hostObject.Prim.ID, + InventoryTaskItem scriptItem = scene.TaskInventory.FindItem(hostObject.Prim.ID, delegate(InventoryTaskItem item) { return item.AssetType == AssetType.LSLText && item.Name == name; }); return (scriptItem != null) ? scriptItem.ID : UUID.Zero; @@ -5197,7 +5197,7 @@ namespace Simian.Extensions texcolor.A = Utils.Clamp((float)alpha, 0.0f, 1.0f); tex.FaceTextures[face].RGBA = texcolor; - server.Scene.ObjectAddOrUpdate(this, part, part.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Textures); + scene.ObjectAddOrUpdate(this, part, part.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Textures); } else if (face == ScriptTypes.ALL_SIDES) { @@ -5215,7 +5215,7 @@ namespace Simian.Extensions texcolor.A = Utils.Clamp((float)alpha, 0.0f, 1.0f); tex.DefaultTexture.RGBA = texcolor; - server.Scene.ObjectAddOrUpdate(this, part, part.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Textures); + scene.ObjectAddOrUpdate(this, part, part.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Textures); } } @@ -5241,7 +5241,7 @@ namespace Simian.Extensions part.Prim.PrimData.PathCurve = PathCurve.Line; } - server.Scene.ObjectAddOrUpdate(this, part, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.ExtraData | UpdateFlags.PrimData); + scene.ObjectAddOrUpdate(this, part, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.ExtraData | UpdateFlags.PrimData); } private void SetPointLight(SimulationObject part, bool light, LSL_Vector color, float intensity, float radius, float falloff) @@ -5264,7 +5264,7 @@ namespace Simian.Extensions part.Prim.Light = null; } - server.Scene.ObjectAddOrUpdate(this, part, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.ExtraData); + scene.ObjectAddOrUpdate(this, part, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.ExtraData); } private LSL_Vector GetColor(SimulationObject part, int face) @@ -5567,7 +5567,7 @@ namespace Simian.Extensions prim.Prim.PrimData.ProfileBegin = Primitive.UnpackBeginCut((ushort)(50000.0 * dimple.x)); prim.Prim.PrimData.ProfileEnd = Primitive.UnpackBeginCut((ushort)(50000.0 * (1.0 - dimple.y))); - server.Scene.ObjectAddOrUpdate(this, prim, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.PrimData); + scene.ObjectAddOrUpdate(this, prim, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.PrimData); } private void SetPrimitiveShapeParams(SimulationObject prim, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, @@ -5962,7 +5962,7 @@ namespace Simian.Extensions else parent.Prim.Flags &= ~PrimFlags.Phantom; - server.Scene.ObjectAddOrUpdate(this, parent, parent.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.PrimFlags); + scene.ObjectAddOrUpdate(this, parent, parent.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.PrimFlags); break; case ScriptTypes.PRIM_PHYSICS: if (remain < 1) return; @@ -5974,7 +5974,7 @@ namespace Simian.Extensions else parent.Prim.Flags &= ~PrimFlags.Physics; - server.Scene.ObjectAddOrUpdate(this, parent, parent.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.PrimFlags); + scene.ObjectAddOrUpdate(this, parent, parent.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.PrimFlags); break; case ScriptTypes.PRIM_TEMP_ON_REZ: if (remain < 1) return; @@ -5986,7 +5986,7 @@ namespace Simian.Extensions else parent.Prim.Flags &= ~PrimFlags.TemporaryOnRez; - server.Scene.ObjectAddOrUpdate(this, parent, parent.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.PrimFlags); + scene.ObjectAddOrUpdate(this, parent, parent.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.PrimFlags); break; } } @@ -6001,7 +6001,7 @@ namespace Simian.Extensions return; part.Prim.Scale = new Vector3((float)scale.x, (float)scale.y, (float)scale.z); - server.Scene.ObjectAddOrUpdate(this, part, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.Scale); + scene.ObjectAddOrUpdate(this, part, hostObject.Prim.Properties.OwnerID, 0, PrimFlags.None, UpdateFlags.Scale); } private void SetColor(SimulationObject part, LSL_Vector color, int face) @@ -6039,7 +6039,7 @@ namespace Simian.Extensions } part.Prim.Textures = tex; - server.Scene.ObjectAddOrUpdate(this, part, part.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Textures); + scene.ObjectAddOrUpdate(this, part, part.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Textures); } public void SetGlow(SimulationObject part, int face, float glow) @@ -6063,7 +6063,7 @@ namespace Simian.Extensions } part.Prim.Textures = tex; - server.Scene.ObjectAddOrUpdate(this, part, part.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Textures); + scene.ObjectAddOrUpdate(this, part, part.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Textures); } public void SetShiny(SimulationObject part, int face, int shiny, Bumpiness bump) @@ -6113,7 +6113,7 @@ namespace Simian.Extensions } part.Prim.Textures = tex; - server.Scene.ObjectAddOrUpdate(this, part, part.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Textures); + scene.ObjectAddOrUpdate(this, part, part.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Textures); } public void SetFullBright(SimulationObject part, int face, bool bright) @@ -6139,7 +6139,7 @@ namespace Simian.Extensions } part.Prim.Textures = tex; - server.Scene.ObjectAddOrUpdate(this, part, part.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Textures); + scene.ObjectAddOrUpdate(this, part, part.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Textures); } private void SetTexture(SimulationObject part, string texture, int face) @@ -6174,7 +6174,7 @@ namespace Simian.Extensions } part.Prim.Textures = tex; - server.Scene.ObjectAddOrUpdate(this, part, part.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Textures); + scene.ObjectAddOrUpdate(this, part, part.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Textures); } private void ScaleTexture(SimulationObject part, double u, double v, int face) @@ -6204,7 +6204,7 @@ namespace Simian.Extensions } part.Prim.Textures = tex; - server.Scene.ObjectAddOrUpdate(this, part, part.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Textures); + scene.ObjectAddOrUpdate(this, part, part.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Textures); } private void OffsetTexture(SimulationObject part, double u, double v, int face) @@ -6234,7 +6234,7 @@ namespace Simian.Extensions } part.Prim.Textures = tex; - server.Scene.ObjectAddOrUpdate(this, part, part.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Textures); + scene.ObjectAddOrUpdate(this, part, part.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Textures); } private void RotateTexture(SimulationObject part, double rotation, int face) @@ -6261,7 +6261,7 @@ namespace Simian.Extensions } part.Prim.Textures = tex; - server.Scene.ObjectAddOrUpdate(this, part, part.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Textures); + scene.ObjectAddOrUpdate(this, part, part.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Textures); } private void SetPos(SimulationObject part, LSL_Vector targetPos) @@ -6272,13 +6272,13 @@ namespace Simian.Extensions targetPos = currentPos + SCRIPT_DISTANCE_FACTOR * 10.0f * llVecNorm(targetPos - currentPos); part.Prim.Position = new Vector3((float)targetPos.x, (float)targetPos.y, (float)targetPos.z); - server.Scene.ObjectAddOrUpdate(this, part, part.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Position); + scene.ObjectAddOrUpdate(this, part, part.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Position); } private void SetRot(SimulationObject part, Quaternion rot) { part.Prim.Rotation = rot; - server.Scene.ObjectAddOrUpdate(this, part, part.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Rotation); + scene.ObjectAddOrUpdate(this, part, part.Prim.OwnerID, 0, PrimFlags.None, UpdateFlags.Rotation); } private LSL_Vector GetTextureOffset(SimulationObject part, int face) diff --git a/Programs/Simian/Extensions/ScriptConsole.cs b/Programs/Simian/SceneExtensions/ScriptConsole.cs similarity index 88% rename from Programs/Simian/Extensions/ScriptConsole.cs rename to Programs/Simian/SceneExtensions/ScriptConsole.cs index 88e7c749..2892c8fc 100644 --- a/Programs/Simian/Extensions/ScriptConsole.cs +++ b/Programs/Simian/SceneExtensions/ScriptConsole.cs @@ -4,7 +4,7 @@ using System.Reflection; using ExtensionLoader; using OpenMetaverse; -namespace Simian.Extensions +namespace Simian { public class ScriptFunction { @@ -14,9 +14,9 @@ namespace Simian.Extensions public Type Return; } - public class ScriptConsole : IExtension + public class ScriptConsole : IExtension { - Simian server; + ISceneProvider scene; IScriptApi api; Dictionary functions; @@ -24,13 +24,13 @@ namespace Simian.Extensions { } - public void Start(Simian server) + public bool Start(ISceneProvider scene) { - this.server = server; + this.scene = scene; // Create a single local scripting API instance that we will manage api = new ScriptApi(); - api.Start(server, null, UUID.Zero, false, false); + api.Start(scene, null, UUID.Zero, false, false); // Create a dictionary of all of the scripting functions functions = new Dictionary(); @@ -56,7 +56,8 @@ namespace Simian.Extensions } } - server.Scene.OnObjectChat += new ObjectChatCallback(Scene_OnObjectChat); + scene.OnObjectChat += Scene_OnObjectChat; + return true; } public void Stop() @@ -76,7 +77,7 @@ namespace Simian.Extensions } message += ")"; - server.Scene.ObjectChat(this, UUID.Zero, UUID.Zero, ChatAudibleLevel.Fully, ChatType.OwnerSay, ChatSourceType.Object, + scene.ObjectChat(this, UUID.Zero, UUID.Zero, ChatAudibleLevel.Fully, ChatType.OwnerSay, ChatSourceType.Object, "Script Console", Vector3.Zero, 0, message); } @@ -197,18 +198,18 @@ namespace Simian.Extensions { // Find the avatar that sent this chat SimulationObject avatar; - if (server.Scene.TryGetObject(ownerID, out avatar)) + if (scene.TryGetObject(ownerID, out avatar)) { // Lock the API, setup the member values, and invoke the function lock (api) { - api.Start(server, avatar, UUID.Random(), false, false); + api.Start(scene, avatar, UUID.Random(), false, false); object ret = function.Method.Invoke(api, objParameters); if (ret != null) { - server.Scene.ObjectChat(this, UUID.Zero, UUID.Zero, ChatAudibleLevel.Fully, ChatType.OwnerSay, + scene.ObjectChat(this, UUID.Zero, UUID.Zero, ChatAudibleLevel.Fully, ChatType.OwnerSay, ChatSourceType.Object, "Script Console", Vector3.Zero, 0, ret.ToString()); } diff --git a/Programs/Simian/Extensions/TaskInventoryManager.cs b/Programs/Simian/SceneExtensions/TaskInventoryManager.cs similarity index 82% rename from Programs/Simian/Extensions/TaskInventoryManager.cs rename to Programs/Simian/SceneExtensions/TaskInventoryManager.cs index a3118f22..c34cf818 100644 --- a/Programs/Simian/Extensions/TaskInventoryManager.cs +++ b/Programs/Simian/SceneExtensions/TaskInventoryManager.cs @@ -4,20 +4,21 @@ using ExtensionLoader; using OpenMetaverse; using OpenMetaverse.Packets; -namespace Simian.Extensions +namespace Simian { // FIXME: Implement this class - class TaskInventoryManager : IExtension, ITaskInventoryProvider + class TaskInventoryManager : IExtension, ITaskInventoryProvider { - Simian server; + ISceneProvider scene; public TaskInventoryManager() { } - public void Start(Simian server) + public bool Start(ISceneProvider scene) { - this.server = server; + this.scene = scene; + return true; } public void Stop() diff --git a/Programs/Simian/Extensions/TransferManager.cs b/Programs/Simian/SceneExtensions/TransferManager.cs similarity index 88% rename from Programs/Simian/Extensions/TransferManager.cs rename to Programs/Simian/SceneExtensions/TransferManager.cs index 35b5a112..42541bbf 100644 --- a/Programs/Simian/Extensions/TransferManager.cs +++ b/Programs/Simian/SceneExtensions/TransferManager.cs @@ -4,25 +4,26 @@ using ExtensionLoader; using OpenMetaverse; using OpenMetaverse.Packets; -namespace Simian.Extensions +namespace Simian { - public class TransferManager : IExtension + public class TransferManager : IExtension { - Simian server; + ISceneProvider scene; Dictionary CurrentUploads = new Dictionary(); public TransferManager() { } - public void Start(Simian server) + public bool Start(ISceneProvider scene) { - this.server = server; + this.scene = scene; - server.UDP.RegisterPacketCallback(PacketType.AssetUploadRequest, new PacketCallback(AssetUploadRequestHandler)); - server.UDP.RegisterPacketCallback(PacketType.SendXferPacket, new PacketCallback(SendXferPacketHandler)); - server.UDP.RegisterPacketCallback(PacketType.AbortXfer, new PacketCallback(AbortXferHandler)); - server.UDP.RegisterPacketCallback(PacketType.TransferRequest, new PacketCallback(TransferRequestHandler)); + scene.UDP.RegisterPacketCallback(PacketType.AssetUploadRequest, new PacketCallback(AssetUploadRequestHandler)); + scene.UDP.RegisterPacketCallback(PacketType.SendXferPacket, new PacketCallback(SendXferPacketHandler)); + scene.UDP.RegisterPacketCallback(PacketType.AbortXfer, new PacketCallback(AbortXferHandler)); + scene.UDP.RegisterPacketCallback(PacketType.TransferRequest, new PacketCallback(TransferRequestHandler)); + return true; } public void Stop() @@ -53,14 +54,14 @@ namespace Simian.Extensions asset.Temporary = (request.AssetBlock.Tempfile | request.AssetBlock.StoreLocal); // Store the asset - server.Assets.StoreAsset(asset); + scene.Server.Assets.StoreAsset(asset); // Send a success response AssetUploadCompletePacket complete = new AssetUploadCompletePacket(); complete.AssetBlock.Success = true; complete.AssetBlock.Type = request.AssetBlock.Type; complete.AssetBlock.UUID = assetID; - server.UDP.SendPacket(agent.ID, complete, PacketCategory.Inventory); + scene.UDP.SendPacket(agent.ID, complete, PacketCategory.Inventory); } else { @@ -89,7 +90,7 @@ namespace Simian.Extensions lock (CurrentUploads) CurrentUploads[xfer.XferID.ID] = asset; - server.UDP.SendPacket(agent.ID, xfer, PacketCategory.Inventory); + scene.UDP.SendPacket(agent.ID, xfer, PacketCategory.Inventory); } } @@ -118,7 +119,7 @@ namespace Simian.Extensions ConfirmXferPacketPacket confirm = new ConfirmXferPacketPacket(); confirm.XferID.ID = xfer.XferID.ID; confirm.XferID.Packet = xfer.XferID.Packet; - server.UDP.SendPacket(agent.ID, confirm, PacketCategory.Asset); + scene.UDP.SendPacket(agent.ID, confirm, PacketCategory.Asset); } else { @@ -129,7 +130,7 @@ namespace Simian.Extensions ConfirmXferPacketPacket confirm = new ConfirmXferPacketPacket(); confirm.XferID.ID = xfer.XferID.ID; confirm.XferID.Packet = xfer.XferID.Packet; - server.UDP.SendPacket(agent.ID, confirm, PacketCategory.Asset); + scene.UDP.SendPacket(agent.ID, confirm, PacketCategory.Asset); if ((xfer.XferID.Packet & (uint)0x80000000) != 0) { @@ -139,13 +140,13 @@ namespace Simian.Extensions lock (CurrentUploads) CurrentUploads.Remove(xfer.XferID.ID); - server.Assets.StoreAsset(asset); + scene.Server.Assets.StoreAsset(asset); AssetUploadCompletePacket complete = new AssetUploadCompletePacket(); complete.AssetBlock.Success = true; complete.AssetBlock.Type = (sbyte)asset.AssetType; complete.AssetBlock.UUID = asset.AssetID; - server.UDP.SendPacket(agent.ID, complete, PacketCategory.Asset); + scene.UDP.SendPacket(agent.ID, complete, PacketCategory.Asset); } } } @@ -210,7 +211,7 @@ namespace Simian.Extensions // Check if we have this asset Asset asset; - if (server.Assets.TryGetAsset(assetID, out asset)) + if (scene.Server.Assets.TryGetAsset(assetID, out asset)) { if (asset.AssetType == type) { @@ -221,7 +222,7 @@ namespace Simian.Extensions response.TransferInfo.Status = (int)StatusCode.OK; response.TransferInfo.TargetType = (int)TargetType.Unknown; // Doesn't seem to be used by the client - server.UDP.SendPacket(agent.ID, response, PacketCategory.Asset); + scene.UDP.SendPacket(agent.ID, response, PacketCategory.Asset); // Transfer system does not wait for ACKs, just sends all of the // packets for this transfer out @@ -245,7 +246,7 @@ namespace Simian.Extensions else transfer.TransferData.Status = (int)StatusCode.OK; - server.UDP.SendPacket(agent.ID, transfer, PacketCategory.Asset); + scene.UDP.SendPacket(agent.ID, transfer, PacketCategory.Asset); } } else @@ -265,7 +266,7 @@ namespace Simian.Extensions response.TransferInfo.Status = (int)StatusCode.UnknownSource; response.TransferInfo.TargetType = (int)TargetType.Unknown; - server.UDP.SendPacket(agent.ID, response, PacketCategory.Asset); + scene.UDP.SendPacket(agent.ID, response, PacketCategory.Asset); } } else if (source == SourceType.SimEstate) diff --git a/Programs/Simian/Extensions/UDPManager.cs b/Programs/Simian/SceneExtensions/UDPManager.cs similarity index 94% rename from Programs/Simian/Extensions/UDPManager.cs rename to Programs/Simian/SceneExtensions/UDPManager.cs index 91d6e44f..fb21a8fb 100644 --- a/Programs/Simian/Extensions/UDPManager.cs +++ b/Programs/Simian/SceneExtensions/UDPManager.cs @@ -71,9 +71,9 @@ namespace Simian } } - public class UDPManager : IExtension, IUDPProvider + public class UDPManager : IExtension, IUDPProvider { - Simian server; + ISceneProvider scene; UDPServer udpServer; public event OutgoingPacketCallback OnOutgoingPacket; @@ -82,10 +82,11 @@ namespace Simian { } - public void Start(Simian server) + public bool Start(ISceneProvider scene) { - this.server = server; - udpServer = new UDPServer(server.UDPPort, server); + this.scene = scene; + udpServer = new UDPServer(scene.IPAndPort, scene); + return true; } public void Stop() @@ -131,7 +132,7 @@ namespace Simian { /// This is only used to fetch unassociated agents, which will /// be exposed through a login interface at some point - Simian server; + ISceneProvider scene; /// Handlers for incoming packets PacketEventDictionary packetEvents = new PacketEventDictionary(); /// Incoming packets that are awaiting handling @@ -143,10 +144,11 @@ namespace Simian /// int currentCircuitCode = 0; - public UDPServer(int port, Simian server) - : base(port) + // FIXME: Upgrade UDPBase to be able to listen on different endpoints + public UDPServer(IPEndPoint endpoint, ISceneProvider scene) + : base(endpoint.Port) { - this.server = server; + this.scene = scene; Start(); @@ -186,7 +188,7 @@ namespace Simian lock (unassociatedAgents) unassociatedAgents[circuitCode] = agent; - Logger.Log("Created circuit " + circuitCode + " for " + agent.FirstName, Helpers.LogLevel.Info); + Logger.Log("Created circuit " + circuitCode + " for " + agent.FullName, Helpers.LogLevel.Info); return circuitCode; } @@ -424,7 +426,7 @@ namespace Simian Logger.Log(String.Format("Ack timeout for {0}, disconnecting", client.Agent.FullName), Helpers.LogLevel.Warning); - server.Scene.ObjectRemove(this, client.Agent.ID); + scene.ObjectRemove(this, client.Agent.ID); return; } } @@ -473,7 +475,7 @@ namespace Simian { Logger.Log("Client UDP reference already exists for " + agent.ID.ToString() + ", removing", Helpers.LogLevel.Warning); - server.Scene.ObjectRemove(this, agent.ID); + scene.ObjectRemove(this, agent.ID); clients.Remove(agent.ID); } @@ -622,7 +624,7 @@ namespace Simian if (unassociatedAgents.TryGetValue(circuitCode, out agent)) { unassociatedAgents.Remove(circuitCode); - server.Scene.AgentAdd(this, agent, PrimFlags.None); + scene.AgentAdd(this, agent, PrimFlags.None); return true; } else diff --git a/Programs/Simian/Extensions/XScriptEngine.cs b/Programs/Simian/SceneExtensions/XScriptEngine.cs similarity index 87% rename from Programs/Simian/Extensions/XScriptEngine.cs rename to Programs/Simian/SceneExtensions/XScriptEngine.cs index 596e0cc3..65e39aa8 100644 --- a/Programs/Simian/Extensions/XScriptEngine.cs +++ b/Programs/Simian/SceneExtensions/XScriptEngine.cs @@ -3,20 +3,21 @@ using System.Collections.Generic; using ExtensionLoader; using OpenMetaverse; -namespace Simian.Extensions +namespace Simian { // FIXME: Implement this class - class XScriptEngine : IExtension, IScriptEngine + class XScriptEngine : IExtension, IScriptEngine { - Simian server; + ISceneProvider scene; public XScriptEngine() { } - public void Start(Simian server) + public bool Start(ISceneProvider scene) { - this.server = server; + this.scene = scene; + return true; } public void Stop() diff --git a/Programs/Simian/Simian.cs b/Programs/Simian/Simian.cs index 8f1460d8..b666f38b 100644 --- a/Programs/Simian/Simian.cs +++ b/Programs/Simian/Simian.cs @@ -18,52 +18,50 @@ namespace Simian { public partial class Simian { - public const string CONFIG_FILE = "Simian.ini"; public const string DATA_DIR = "SimianData/"; - public const string ASSET_CACHE_DIR = "SimianData/AssetCache/"; - - public int UDPPort { get { return 9000; } } - public int HttpPort { get { return 8002; } } - public bool SSL { get { return false; } } - public string HostName { get { return Dns.GetHostName(); } } + public const string CONFIG_FILE = DATA_DIR + "Simian.ini"; + public const string REGION_CONFIG_DIR = DATA_DIR + "RegionConfig/"; + public const string ASSET_CACHE_DIR = DATA_DIR + "AssetCache/"; + public const string DEFAULT_ASSET_DIR = DATA_DIR + "DefaultAssets/"; + public Uri HttpUri; public HttpListener HttpServer; public IniConfigSource ConfigFile; + public List ExtensionList; - // Interfaces - public IAuthenticationProvider Authentication; + // Server Interfaces public IAccountProvider Accounts; - public IUDPProvider UDP; - public ISceneProvider Scene; public IAssetProvider Assets; - public IPermissionsProvider Permissions; - public IAvatarProvider Avatars; - public IInventoryProvider Inventory; - public ITaskInventoryProvider TaskInventory; - public IParcelProvider Parcels; - public IMeshingProvider Mesher; + public IAuthenticationProvider Authentication; public ICapabilitiesProvider Capabilities; - public IScriptEngine ScriptEngine; + public IGridProvider Grid; + public IInventoryProvider Inventory; + public IMeshingProvider Mesher; public IMessagingProvider Messages; - public IPhysicsProvider Physics; + public IPermissionsProvider Permissions; + // Regions/Scenes + public List Scenes = new List(); // Persistent extensions public List PersistentExtensions = new List(); + ExtensionLoader extensions = new ExtensionLoader(); + public Simian() { } public bool Start() { - List extensionList = null; + IConfig httpConfig; try { // Load the extension list (and ordering) from our config file ConfigFile = new IniConfigSource(CONFIG_FILE); + httpConfig = ConfigFile.Configs["Http"]; IConfig extensionConfig = ConfigFile.Configs["Extensions"]; - extensionList = new List(extensionConfig.GetKeys()); + ExtensionList = new List(extensionConfig.GetKeys()); } catch (Exception) { @@ -71,9 +69,51 @@ namespace Simian return false; } - // TODO: SSL support - HttpServer = HttpListener.Create(log4netLogWriter.Instance, IPAddress.Any, HttpPort); + #region HTTP Server + + int port = httpConfig.GetInt("ListenPort"); + string hostname = httpConfig.GetString("Hostname", null); + string sslCertFile = httpConfig.GetString("SSLCertFile", null); + IPAddress address = IPAddress.Any; + + if (String.IsNullOrEmpty(hostname)) + { + hostname = Dns.GetHostName(); + } + else + { + IPHostEntry entry = Dns.GetHostEntry(hostname); + if (entry != null && entry.AddressList.Length > 0) + address = entry.AddressList[0]; + } + + if (!String.IsNullOrEmpty(sslCertFile)) + { + // HTTPS mode + X509Certificate serverCert; + try { serverCert = X509Certificate.CreateFromCertFile(sslCertFile); } + catch (Exception ex) + { + Logger.Log("Failed to load SSL certificate file \"" + sslCertFile + "\": " + ex.Message, + Helpers.LogLevel.Error); + return false; + } + HttpServer = HttpListener.Create(log4netLogWriter.Instance, address, port, serverCert); + HttpUri = new Uri("https://" + hostname + (port != 80 ? (":" + port) : String.Empty)); + } + else + { + // HTTP mode + HttpServer = HttpListener.Create(log4netLogWriter.Instance, address, port); + HttpUri = new Uri("http://" + hostname + (port != 80 ? (":" + port) : String.Empty)); + } + HttpServer.Start(10); + Logger.Log("Simian is listening at " + HttpUri.ToString(), Helpers.LogLevel.Info); + + #endregion HTTP Server + + #region Server Extensions try { @@ -83,15 +123,15 @@ namespace Simian references.Add("OpenMetaverse.dll"); references.Add("Simian.exe"); - // Search the Simian class for member variables that are interfaces - List assignables = ExtensionLoader.GetInterfaces(this); - // Load extensions from the current executing assembly, Simian.*.dll assemblies on disk, and - // Simian.*.cs source files on disk. Automatically assign extensions that implement interfaces - // to the list of interface variables in "assignables" - ExtensionLoader.LoadAllExtensions(Assembly.GetExecutingAssembly(), - AppDomain.CurrentDomain.BaseDirectory, extensionList, references, - "Simian.*.dll", "Simian.*.cs", this, assignables); + // Simian.*.cs source files on disk. + extensions.LoadAllExtensions(Assembly.GetExecutingAssembly(), + AppDomain.CurrentDomain.BaseDirectory, ExtensionList, references, + "Simian.*.dll", "Simian.*.cs"); + + // Automatically assign extensions that implement interfaces to the list of interface + // variables in "assignables" + extensions.AssignExtensions(this, extensions.GetInterfaces(this)); } catch (ExtensionException ex) { @@ -100,7 +140,7 @@ namespace Simian return false; } - foreach (IExtension extension in ExtensionLoader.Extensions) + foreach (IExtension extension in extensions.Extensions) { // Track all of the extensions with persistence if (extension is IPersistable) @@ -108,29 +148,89 @@ namespace Simian } // Start all of the extensions - foreach (IExtension extension in ExtensionLoader.Extensions) + foreach (IExtension extension in extensions.Extensions) { - Logger.Log("Starting extension " + extension.GetType().Name, Helpers.LogLevel.Info); + Logger.Log("Starting Simian extension " + extension.GetType().Name, Helpers.LogLevel.Info); extension.Start(this); } + #endregion Server Extensions + + #region Region Loading + + try + { + string[] configFiles = Directory.GetFiles(REGION_CONFIG_DIR, "*.ini", SearchOption.AllDirectories); + + for (int i = 0; i < configFiles.Length; i++) + { + IniConfigSource source = new IniConfigSource(configFiles[i]); + IConfig regionConfig = source.Configs["Region"]; + + string name = regionConfig.GetString("Name", null); + string defaultTerrain = regionConfig.GetString("DefaultTerrain", null); + int udpPort = regionConfig.GetInt("UDPPort", 0); + uint regionX, regionY; + UInt32.TryParse(regionConfig.GetString("RegionX", "0"), out regionX); + UInt32.TryParse(regionConfig.GetString("RegionY", "0"), out regionY); + int staticObjectLimit = regionConfig.GetInt("StaticObjectLimit", 0); + int physicalObjectLimit = regionConfig.GetInt("PhysicalObjectLimit", 0); + + if (String.IsNullOrEmpty(name) || regionX == 0 || regionY == 0) + { + Logger.Log("Incomplete information in " + configFiles[i] + ", skipping", Helpers.LogLevel.Warning); + continue; + } + + // Get the IPEndPoint for this region + IPEndPoint endpoint = new IPEndPoint(IPAddress.Any, 9000); + + // TODO: Support non-SceneManager scenes? + ISceneProvider scene = new SceneManager(); + scene.Start(this, name, endpoint, regionX, regionY, defaultTerrain, staticObjectLimit, physicalObjectLimit); + Scenes.Add(scene); + + // FIXME: Use IGridProvider to actually register the scenes into spaces + break; + } + } + catch (Exception ex) + { + Logger.Log("Failed to load region config files: " + ex.Message, Helpers.LogLevel.Error); + return false; + } + + #endregion Region Loading + return true; } public void Stop() { - foreach (IExtension extension in ExtensionLoader.Extensions) + // FIXME: Scenes shouldn't be publically exposed. This will end in tears + for (int i = 0; i < Scenes.Count; i++) + { + Scenes[i].Stop(); + } + + foreach (IExtension extension in extensions.Extensions) { // Stop persistence providers first if (extension is IPersistenceProvider) + { + Logger.Log("Stopping Simian extension " + extension.GetType().Name, Helpers.LogLevel.Info); extension.Stop(); + } } - foreach (IExtension extension in ExtensionLoader.Extensions) + foreach (IExtension extension in extensions.Extensions) { // Stop all other extensions if (!(extension is IPersistenceProvider)) + { + Logger.Log("Stopping Simian extension " + extension.GetType().Name, Helpers.LogLevel.Info); extension.Stop(); + } } HttpServer.Stop(); diff --git a/Programs/Simian/SimulationObject.cs b/Programs/Simian/SimulationObject.cs index 1155557c..8a02272d 100644 --- a/Programs/Simian/SimulationObject.cs +++ b/Programs/Simian/SimulationObject.cs @@ -42,7 +42,7 @@ namespace Simian /// rotation, since it is only applicable to parent objects public Quaternion BeforeAttachmentRotation = Quaternion.Identity; - protected Simian Server; + protected ISceneProvider Scene; protected SimpleMesh[] Meshes; protected SimpleMesh[] WorldTransformedMeshes; @@ -79,16 +79,16 @@ namespace Simian public SimulationObject(SimulationObject obj) { Prim = new Primitive(obj.Prim); - Server = obj.Server; + Scene = obj.Scene; LinkNumber = obj.LinkNumber; Frozen = obj.Frozen; // Skip everything else because it can be lazily reconstructed } - public SimulationObject(Primitive prim, Simian server) + public SimulationObject(Primitive prim, ISceneProvider scene) { Prim = prim; - Server = server; + Scene = scene; } public SimulationObject GetLinksetParent() @@ -98,7 +98,7 @@ namespace Simian return this; SimulationObject parent; - if (Server.Scene.TryGetObject(Prim.ParentID, out parent)) + if (Scene.TryGetObject(Prim.ParentID, out parent)) { // Check if this is the root object, but is attached to an avatar if (parent.Prim is Avatar) @@ -118,7 +118,7 @@ namespace Simian { Logger.DebugLog("Running expensive SimulationObject.GetLinksetPrim() function"); - return Server.Scene.FindObject(delegate(SimulationObject obj) + return Scene.FindObject(delegate(SimulationObject obj) { return obj.Prim.ParentID == this.Prim.ParentID && obj.LinkNumber == linkNum; }); } @@ -127,7 +127,7 @@ namespace Simian Logger.DebugLog("Running expensive SimulationObject.GetChildren() function"); List children = new List(); - Server.Scene.ForEachObject(delegate(SimulationObject obj) + Scene.ForEachObject(delegate(SimulationObject obj) { if (obj.Prim.ParentID == this.Prim.LocalID) children.Add(obj); }); return children; } @@ -151,7 +151,7 @@ namespace Simian SimulationObject parent; Vector3 position = Prim.Position; - if (Prim.ParentID != 0 && Server.Scene.TryGetObject(Prim.ParentID, out parent)) + if (Prim.ParentID != 0 && Scene.TryGetObject(Prim.ParentID, out parent)) position += Vector3.Transform(parent.Prim.Position, Matrix4.CreateFromQuaternion(parent.Prim.Rotation)); return position; @@ -162,7 +162,7 @@ namespace Simian SimulationObject parent; Quaternion rotation = Prim.Rotation; - if (Prim.ParentID != 0 && Server.Scene.TryGetObject(Prim.ParentID, out parent)) + if (Prim.ParentID != 0 && Scene.TryGetObject(Prim.ParentID, out parent)) rotation *= parent.Prim.Rotation; return rotation; @@ -193,7 +193,7 @@ namespace Simian } else { - SimpleMesh mesh = Server.Mesher.GenerateSimpleMesh(Prim, lod); + SimpleMesh mesh = Scene.Server.Mesher.GenerateSimpleMesh(Prim, lod); Meshes[i] = mesh; return mesh; } diff --git a/bin/SimianData/cloud-fc4b9f0b-d008-45c6-96a4-01dd947ac621.jp2 b/bin/SimianData/DefaultAssets/cloud-fc4b9f0b-d008-45c6-96a4-01dd947ac621.jp2 similarity index 100% rename from bin/SimianData/cloud-fc4b9f0b-d008-45c6-96a4-01dd947ac621.jp2 rename to bin/SimianData/DefaultAssets/cloud-fc4b9f0b-d008-45c6-96a4-01dd947ac621.jp2 diff --git a/bin/SimianData/default_avatar-c228d1cf-4b5d-4ba8-84f4-899a0796aa97.jp2 b/bin/SimianData/DefaultAssets/default_avatar-c228d1cf-4b5d-4ba8-84f4-899a0796aa97.jp2 similarity index 100% rename from bin/SimianData/default_avatar-c228d1cf-4b5d-4ba8-84f4-899a0796aa97.jp2 rename to bin/SimianData/DefaultAssets/default_avatar-c228d1cf-4b5d-4ba8-84f4-899a0796aa97.jp2 diff --git a/bin/SimianData/default_body-e1a21d3f-7db4-4802-978f-4ace1bad8e7e.jp2 b/bin/SimianData/DefaultAssets/default_body-e1a21d3f-7db4-4802-978f-4ace1bad8e7e.jp2 similarity index 100% rename from bin/SimianData/default_body-e1a21d3f-7db4-4802-978f-4ace1bad8e7e.jp2 rename to bin/SimianData/DefaultAssets/default_body-e1a21d3f-7db4-4802-978f-4ace1bad8e7e.jp2 diff --git a/bin/SimianData/default_bottom-9bebfaae-6de4-41c7-af5b-f6a3bd052ed3.jp2 b/bin/SimianData/DefaultAssets/default_bottom-9bebfaae-6de4-41c7-af5b-f6a3bd052ed3.jp2 similarity index 100% rename from bin/SimianData/default_bottom-9bebfaae-6de4-41c7-af5b-f6a3bd052ed3.jp2 rename to bin/SimianData/DefaultAssets/default_bottom-9bebfaae-6de4-41c7-af5b-f6a3bd052ed3.jp2 diff --git a/bin/SimianData/default_eyes-6522e74d-1660-4e7f-b601-6f48c1659a78.jp2 b/bin/SimianData/DefaultAssets/default_eyes-6522e74d-1660-4e7f-b601-6f48c1659a78.jp2 similarity index 100% rename from bin/SimianData/default_eyes-6522e74d-1660-4e7f-b601-6f48c1659a78.jp2 rename to bin/SimianData/DefaultAssets/default_eyes-6522e74d-1660-4e7f-b601-6f48c1659a78.jp2 diff --git a/bin/SimianData/default_eyes-78d20332-9b07-44a2-bf74-3b368605f4b5.bodypart b/bin/SimianData/DefaultAssets/default_eyes-78d20332-9b07-44a2-bf74-3b368605f4b5.bodypart similarity index 100% rename from bin/SimianData/default_eyes-78d20332-9b07-44a2-bf74-3b368605f4b5.bodypart rename to bin/SimianData/DefaultAssets/default_eyes-78d20332-9b07-44a2-bf74-3b368605f4b5.bodypart diff --git a/bin/SimianData/default_face-c4e3fbf4-55ef-4a06-8497-48d4dc993cbb.jp2 b/bin/SimianData/DefaultAssets/default_face-c4e3fbf4-55ef-4a06-8497-48d4dc993cbb.jp2 similarity index 100% rename from bin/SimianData/default_face-c4e3fbf4-55ef-4a06-8497-48d4dc993cbb.jp2 rename to bin/SimianData/DefaultAssets/default_face-c4e3fbf4-55ef-4a06-8497-48d4dc993cbb.jp2 diff --git a/bin/SimianData/default_hair-dc675529-7ba5-4976-b91d-dcb9e5e36188.bodypart b/bin/SimianData/DefaultAssets/default_hair-dc675529-7ba5-4976-b91d-dcb9e5e36188.bodypart similarity index 100% rename from bin/SimianData/default_hair-dc675529-7ba5-4976-b91d-dcb9e5e36188.bodypart rename to bin/SimianData/DefaultAssets/default_hair-dc675529-7ba5-4976-b91d-dcb9e5e36188.bodypart diff --git a/bin/SimianData/default_pants-3e8ee2d6-4f21-4a55-832d-77daa505edff.clothing b/bin/SimianData/DefaultAssets/default_pants-3e8ee2d6-4f21-4a55-832d-77daa505edff.clothing similarity index 100% rename from bin/SimianData/default_pants-3e8ee2d6-4f21-4a55-832d-77daa505edff.clothing rename to bin/SimianData/DefaultAssets/default_pants-3e8ee2d6-4f21-4a55-832d-77daa505edff.clothing diff --git a/bin/SimianData/default_pants-54a55781-afa8-a64d-cc69-6d63e6da76fb.jp2 b/bin/SimianData/DefaultAssets/default_pants-54a55781-afa8-a64d-cc69-6d63e6da76fb.jp2 similarity index 100% rename from bin/SimianData/default_pants-54a55781-afa8-a64d-cc69-6d63e6da76fb.jp2 rename to bin/SimianData/DefaultAssets/default_pants-54a55781-afa8-a64d-cc69-6d63e6da76fb.jp2 diff --git a/bin/SimianData/default_shape-530a2614-052e-49a2-af0e-534bb3c05af0.bodypart b/bin/SimianData/DefaultAssets/default_shape-530a2614-052e-49a2-af0e-534bb3c05af0.bodypart similarity index 100% rename from bin/SimianData/default_shape-530a2614-052e-49a2-af0e-534bb3c05af0.bodypart rename to bin/SimianData/DefaultAssets/default_shape-530a2614-052e-49a2-af0e-534bb3c05af0.bodypart diff --git a/bin/SimianData/default_shirt-6a714f37-fe53-4230-b46f-8db384465981.clothing b/bin/SimianData/DefaultAssets/default_shirt-6a714f37-fe53-4230-b46f-8db384465981.clothing similarity index 100% rename from bin/SimianData/default_shirt-6a714f37-fe53-4230-b46f-8db384465981.clothing rename to bin/SimianData/DefaultAssets/default_shirt-6a714f37-fe53-4230-b46f-8db384465981.clothing diff --git a/bin/SimianData/default_shirt-ec108661-ac4b-6006-f23f-220ba96c15a8.jp2 b/bin/SimianData/DefaultAssets/default_shirt-ec108661-ac4b-6006-f23f-220ba96c15a8.jp2 similarity index 100% rename from bin/SimianData/default_shirt-ec108661-ac4b-6006-f23f-220ba96c15a8.jp2 rename to bin/SimianData/DefaultAssets/default_shirt-ec108661-ac4b-6006-f23f-220ba96c15a8.jp2 diff --git a/bin/SimianData/default_skin-5f787f25-f761-4a35-9764-6418ee4774c4.bodypart b/bin/SimianData/DefaultAssets/default_skin-5f787f25-f761-4a35-9764-6418ee4774c4.bodypart similarity index 100% rename from bin/SimianData/default_skin-5f787f25-f761-4a35-9764-6418ee4774c4.bodypart rename to bin/SimianData/DefaultAssets/default_skin-5f787f25-f761-4a35-9764-6418ee4774c4.bodypart diff --git a/bin/SimianData/moon-d07f6eed-b96a-47cd-b51d-400ad4a1c428.jp2 b/bin/SimianData/DefaultAssets/moon-d07f6eed-b96a-47cd-b51d-400ad4a1c428.jp2 similarity index 100% rename from bin/SimianData/moon-d07f6eed-b96a-47cd-b51d-400ad4a1c428.jp2 rename to bin/SimianData/DefaultAssets/moon-d07f6eed-b96a-47cd-b51d-400ad4a1c428.jp2 diff --git a/bin/SimianData/plywood-89556747-24cb-43ed-920b-47caed15465f.jp2 b/bin/SimianData/DefaultAssets/plywood-89556747-24cb-43ed-920b-47caed15465f.jp2 similarity index 100% rename from bin/SimianData/plywood-89556747-24cb-43ed-920b-47caed15465f.jp2 rename to bin/SimianData/DefaultAssets/plywood-89556747-24cb-43ed-920b-47caed15465f.jp2 diff --git a/bin/SimianData/uialert-ed124764-705d-d497-167a-182cd9fa2e6c.ogg b/bin/SimianData/DefaultAssets/uialert-ed124764-705d-d497-167a-182cd9fa2e6c.ogg similarity index 100% rename from bin/SimianData/uialert-ed124764-705d-d497-167a-182cd9fa2e6c.ogg rename to bin/SimianData/DefaultAssets/uialert-ed124764-705d-d497-167a-182cd9fa2e6c.ogg diff --git a/bin/SimianData/uibadkeystroke-2ca849ba-2885-4bc3-90ef-d4987a5b983a.ogg b/bin/SimianData/DefaultAssets/uibadkeystroke-2ca849ba-2885-4bc3-90ef-d4987a5b983a.ogg similarity index 100% rename from bin/SimianData/uibadkeystroke-2ca849ba-2885-4bc3-90ef-d4987a5b983a.ogg rename to bin/SimianData/DefaultAssets/uibadkeystroke-2ca849ba-2885-4bc3-90ef-d4987a5b983a.ogg diff --git a/bin/SimianData/uiclick-4c8c3c77-de8d-bde2-b9b8-32635e0fd4a6.ogg b/bin/SimianData/DefaultAssets/uiclick-4c8c3c77-de8d-bde2-b9b8-32635e0fd4a6.ogg similarity index 100% rename from bin/SimianData/uiclick-4c8c3c77-de8d-bde2-b9b8-32635e0fd4a6.ogg rename to bin/SimianData/DefaultAssets/uiclick-4c8c3c77-de8d-bde2-b9b8-32635e0fd4a6.ogg diff --git a/bin/SimianData/uihealthreduction-219c5d93-6c09-31c5-fb3f-c5fe7495c115.ogg b/bin/SimianData/DefaultAssets/uihealthreduction-219c5d93-6c09-31c5-fb3f-c5fe7495c115.ogg similarity index 100% rename from bin/SimianData/uihealthreduction-219c5d93-6c09-31c5-fb3f-c5fe7495c115.ogg rename to bin/SimianData/DefaultAssets/uihealthreduction-219c5d93-6c09-31c5-fb3f-c5fe7495c115.ogg diff --git a/bin/SimianData/uihealthreduction_male-e057c244-5768-1056-c37e-1537454eeb62.ogg b/bin/SimianData/DefaultAssets/uihealthreduction_male-e057c244-5768-1056-c37e-1537454eeb62.ogg similarity index 100% rename from bin/SimianData/uihealthreduction_male-e057c244-5768-1056-c37e-1537454eeb62.ogg rename to bin/SimianData/DefaultAssets/uihealthreduction_male-e057c244-5768-1056-c37e-1537454eeb62.ogg diff --git a/bin/SimianData/uiinvalidop-4174f859-0d3d-c517-c424-72923dc21f65.ogg b/bin/SimianData/DefaultAssets/uiinvalidop-4174f859-0d3d-c517-c424-72923dc21f65.ogg similarity index 100% rename from bin/SimianData/uiinvalidop-4174f859-0d3d-c517-c424-72923dc21f65.ogg rename to bin/SimianData/DefaultAssets/uiinvalidop-4174f859-0d3d-c517-c424-72923dc21f65.ogg diff --git a/bin/SimianData/uimoneychange_down-104974e3-dfda-428b-99ee-b0d4e748d3a3.ogg b/bin/SimianData/DefaultAssets/uimoneychange_down-104974e3-dfda-428b-99ee-b0d4e748d3a3.ogg similarity index 100% rename from bin/SimianData/uimoneychange_down-104974e3-dfda-428b-99ee-b0d4e748d3a3.ogg rename to bin/SimianData/DefaultAssets/uimoneychange_down-104974e3-dfda-428b-99ee-b0d4e748d3a3.ogg diff --git a/bin/SimianData/uimoneychange_up-77a018af-098e-c037-51a6-178f05877c6f.ogg b/bin/SimianData/DefaultAssets/uimoneychange_up-77a018af-098e-c037-51a6-178f05877c6f.ogg similarity index 100% rename from bin/SimianData/uimoneychange_up-77a018af-098e-c037-51a6-178f05877c6f.ogg rename to bin/SimianData/DefaultAssets/uimoneychange_up-77a018af-098e-c037-51a6-178f05877c6f.ogg diff --git a/bin/SimianData/uinewim-67cc2844-00f3-2b3c-b991-6418d01e1bb7.ogg b/bin/SimianData/DefaultAssets/uinewim-67cc2844-00f3-2b3c-b991-6418d01e1bb7.ogg similarity index 100% rename from bin/SimianData/uinewim-67cc2844-00f3-2b3c-b991-6418d01e1bb7.ogg rename to bin/SimianData/DefaultAssets/uinewim-67cc2844-00f3-2b3c-b991-6418d01e1bb7.ogg diff --git a/bin/SimianData/uiobjectcreate-f4a0660f-5446-dea2-80b7-6482a082803c.ogg b/bin/SimianData/DefaultAssets/uiobjectcreate-f4a0660f-5446-dea2-80b7-6482a082803c.ogg similarity index 100% rename from bin/SimianData/uiobjectcreate-f4a0660f-5446-dea2-80b7-6482a082803c.ogg rename to bin/SimianData/DefaultAssets/uiobjectcreate-f4a0660f-5446-dea2-80b7-6482a082803c.ogg diff --git a/bin/SimianData/uiobjectdelete-0cb7b00a-4c10-6948-84de-a93c09af2ba9.ogg b/bin/SimianData/DefaultAssets/uiobjectdelete-0cb7b00a-4c10-6948-84de-a93c09af2ba9.ogg similarity index 100% rename from bin/SimianData/uiobjectdelete-0cb7b00a-4c10-6948-84de-a93c09af2ba9.ogg rename to bin/SimianData/DefaultAssets/uiobjectdelete-0cb7b00a-4c10-6948-84de-a93c09af2ba9.ogg diff --git a/bin/SimianData/uiobjectrezin-3c8fc726-1fd6-862d-fa01-16c5b2568db6.ogg b/bin/SimianData/DefaultAssets/uiobjectrezin-3c8fc726-1fd6-862d-fa01-16c5b2568db6.ogg similarity index 100% rename from bin/SimianData/uiobjectrezin-3c8fc726-1fd6-862d-fa01-16c5b2568db6.ogg rename to bin/SimianData/DefaultAssets/uiobjectrezin-3c8fc726-1fd6-862d-fa01-16c5b2568db6.ogg diff --git a/bin/SimianData/uipiemenu0-d9f73cf8-17b4-6f7a-1565-7951226c305d.ogg b/bin/SimianData/DefaultAssets/uipiemenu0-d9f73cf8-17b4-6f7a-1565-7951226c305d.ogg similarity index 100% rename from bin/SimianData/uipiemenu0-d9f73cf8-17b4-6f7a-1565-7951226c305d.ogg rename to bin/SimianData/DefaultAssets/uipiemenu0-d9f73cf8-17b4-6f7a-1565-7951226c305d.ogg diff --git a/bin/SimianData/uipiemenu1-f6ba9816-dcaf-f755-7b67-51b31b6233e5.ogg b/bin/SimianData/DefaultAssets/uipiemenu1-f6ba9816-dcaf-f755-7b67-51b31b6233e5.ogg similarity index 100% rename from bin/SimianData/uipiemenu1-f6ba9816-dcaf-f755-7b67-51b31b6233e5.ogg rename to bin/SimianData/DefaultAssets/uipiemenu1-f6ba9816-dcaf-f755-7b67-51b31b6233e5.ogg diff --git a/bin/SimianData/uipiemenu2-7aff2265-d05b-8b72-63c7-dbf96dc2f21f.ogg b/bin/SimianData/DefaultAssets/uipiemenu2-7aff2265-d05b-8b72-63c7-dbf96dc2f21f.ogg similarity index 100% rename from bin/SimianData/uipiemenu2-7aff2265-d05b-8b72-63c7-dbf96dc2f21f.ogg rename to bin/SimianData/DefaultAssets/uipiemenu2-7aff2265-d05b-8b72-63c7-dbf96dc2f21f.ogg diff --git a/bin/SimianData/uipiemenu3-09b2184e-8601-44e2-afbb-ce37434b8ba1.ogg b/bin/SimianData/DefaultAssets/uipiemenu3-09b2184e-8601-44e2-afbb-ce37434b8ba1.ogg similarity index 100% rename from bin/SimianData/uipiemenu3-09b2184e-8601-44e2-afbb-ce37434b8ba1.ogg rename to bin/SimianData/DefaultAssets/uipiemenu3-09b2184e-8601-44e2-afbb-ce37434b8ba1.ogg diff --git a/bin/SimianData/uipiemenu4-bbe4c7fc-7044-b05e-7b89-36924a67593c.ogg b/bin/SimianData/DefaultAssets/uipiemenu4-bbe4c7fc-7044-b05e-7b89-36924a67593c.ogg similarity index 100% rename from bin/SimianData/uipiemenu4-bbe4c7fc-7044-b05e-7b89-36924a67593c.ogg rename to bin/SimianData/DefaultAssets/uipiemenu4-bbe4c7fc-7044-b05e-7b89-36924a67593c.ogg diff --git a/bin/SimianData/uipiemenu5-d166039b-b4f5-c2ec-4911-c85c727b016c.ogg b/bin/SimianData/DefaultAssets/uipiemenu5-d166039b-b4f5-c2ec-4911-c85c727b016c.ogg similarity index 100% rename from bin/SimianData/uipiemenu5-d166039b-b4f5-c2ec-4911-c85c727b016c.ogg rename to bin/SimianData/DefaultAssets/uipiemenu5-d166039b-b4f5-c2ec-4911-c85c727b016c.ogg diff --git a/bin/SimianData/uipiemenu6-242af82b-43c2-9a3b-e108-3b0c7e384981.ogg b/bin/SimianData/DefaultAssets/uipiemenu6-242af82b-43c2-9a3b-e108-3b0c7e384981.ogg similarity index 100% rename from bin/SimianData/uipiemenu6-242af82b-43c2-9a3b-e108-3b0c7e384981.ogg rename to bin/SimianData/DefaultAssets/uipiemenu6-242af82b-43c2-9a3b-e108-3b0c7e384981.ogg diff --git a/bin/SimianData/uipiemenu7-c1f334fb-a5be-8fe7-22b3-29631c21cf0b.ogg b/bin/SimianData/DefaultAssets/uipiemenu7-c1f334fb-a5be-8fe7-22b3-29631c21cf0b.ogg similarity index 100% rename from bin/SimianData/uipiemenu7-c1f334fb-a5be-8fe7-22b3-29631c21cf0b.ogg rename to bin/SimianData/DefaultAssets/uipiemenu7-c1f334fb-a5be-8fe7-22b3-29631c21cf0b.ogg diff --git a/bin/SimianData/uipiemenuappear-8eaed61f-92ff-6485-de83-4dcc938a478e.ogg b/bin/SimianData/DefaultAssets/uipiemenuappear-8eaed61f-92ff-6485-de83-4dcc938a478e.ogg similarity index 100% rename from bin/SimianData/uipiemenuappear-8eaed61f-92ff-6485-de83-4dcc938a478e.ogg rename to bin/SimianData/DefaultAssets/uipiemenuappear-8eaed61f-92ff-6485-de83-4dcc938a478e.ogg diff --git a/bin/SimianData/uisnapshot-3d09f582-3851-c0e0-f5ba-277ac5c73fb4.ogg b/bin/SimianData/DefaultAssets/uisnapshot-3d09f582-3851-c0e0-f5ba-277ac5c73fb4.ogg similarity index 100% rename from bin/SimianData/uisnapshot-3d09f582-3851-c0e0-f5ba-277ac5c73fb4.ogg rename to bin/SimianData/DefaultAssets/uisnapshot-3d09f582-3851-c0e0-f5ba-277ac5c73fb4.ogg diff --git a/bin/SimianData/uistartim-c825dfbc-9827-7e02-6507-3713d18916c1.ogg b/bin/SimianData/DefaultAssets/uistartim-c825dfbc-9827-7e02-6507-3713d18916c1.ogg similarity index 100% rename from bin/SimianData/uistartim-c825dfbc-9827-7e02-6507-3713d18916c1.ogg rename to bin/SimianData/DefaultAssets/uistartim-c825dfbc-9827-7e02-6507-3713d18916c1.ogg diff --git a/bin/SimianData/uiteleportout-d7a9a565-a013-2a69-797d-5332baa1a947.ogg b/bin/SimianData/DefaultAssets/uiteleportout-d7a9a565-a013-2a69-797d-5332baa1a947.ogg similarity index 100% rename from bin/SimianData/uiteleportout-d7a9a565-a013-2a69-797d-5332baa1a947.ogg rename to bin/SimianData/DefaultAssets/uiteleportout-d7a9a565-a013-2a69-797d-5332baa1a947.ogg diff --git a/bin/SimianData/uityping-5e191c7b-8996-9ced-a177-b2ac32bfea06.ogg b/bin/SimianData/DefaultAssets/uityping-5e191c7b-8996-9ced-a177-b2ac32bfea06.ogg similarity index 100% rename from bin/SimianData/uityping-5e191c7b-8996-9ced-a177-b2ac32bfea06.ogg rename to bin/SimianData/DefaultAssets/uityping-5e191c7b-8996-9ced-a177-b2ac32bfea06.ogg diff --git a/bin/SimianData/uiwindowclose-2c346eda-b60c-ab33-1119-b8941916a499.ogg b/bin/SimianData/DefaultAssets/uiwindowclose-2c346eda-b60c-ab33-1119-b8941916a499.ogg similarity index 100% rename from bin/SimianData/uiwindowclose-2c346eda-b60c-ab33-1119-b8941916a499.ogg rename to bin/SimianData/DefaultAssets/uiwindowclose-2c346eda-b60c-ab33-1119-b8941916a499.ogg diff --git a/bin/SimianData/uiwindowopen-c80260ba-41fd-8a46-768a-6bf236360e3a.ogg b/bin/SimianData/DefaultAssets/uiwindowopen-c80260ba-41fd-8a46-768a-6bf236360e3a.ogg similarity index 100% rename from bin/SimianData/uiwindowopen-c80260ba-41fd-8a46-768a-6bf236360e3a.ogg rename to bin/SimianData/DefaultAssets/uiwindowopen-c80260ba-41fd-8a46-768a-6bf236360e3a.ogg diff --git a/bin/SimianData/RegionConfig/Baboon.ini b/bin/SimianData/RegionConfig/Baboon.ini new file mode 100644 index 00000000..05b6b973 --- /dev/null +++ b/bin/SimianData/RegionConfig/Baboon.ini @@ -0,0 +1,23 @@ +[Region] + +; Region name +Name = Baboon + +; UDP Port for this region to listen on. If this value is not present, the next +; available port (starting from 9000) will be assigned +;UDPPort = 9000 + +; Coordinates of this simulator on the grid. If these values are not present, +; the server will automatically assign grid coordinates +RegionX = 1000 +RegionY = 1000 + +; The default terrain file to use if no terrain data has been stored for this +; region yet. This path is relative to the SimianData directory +DefaultTerrain = flat30m.tga + +; Maximum number of static (non-physical) objects allowed in the scene +StaticObjectLimit = 16000 + +; Maximum number of physical objects allowed in the scene. This includes avatars +PhysicalObjectLimit = 1000 diff --git a/bin/SimianData/RegionConfig/Capuchin.ini b/bin/SimianData/RegionConfig/Capuchin.ini new file mode 100644 index 00000000..ce5dd03f --- /dev/null +++ b/bin/SimianData/RegionConfig/Capuchin.ini @@ -0,0 +1,23 @@ +[Region] + +; Region name +Name = Capuchin + +; UDP Port for this region to listen on. If this value is not present, the next +; available port (starting from 9000) will be assigned +;UDPPort = 9000 + +; Coordinates of this simulator on the grid. If these values are not present, +; the server will automatically assign grid coordinates +RegionX = 1000 +RegionY = 1000 + +; The default terrain file to use if no terrain data has been stored for this +; region yet. This path is relative to the SimianData directory +DefaultTerrain = flat30m.tga + +; Maximum number of static (non-physical) objects allowed in the scene +StaticObjectLimit = 16000 + +; Maximum number of physical objects allowed in the scene. This includes avatars +PhysicalObjectLimit = 1000 diff --git a/bin/SimianData/RegionConfig/Chimpanzee.ini b/bin/SimianData/RegionConfig/Chimpanzee.ini new file mode 100644 index 00000000..31c83c40 --- /dev/null +++ b/bin/SimianData/RegionConfig/Chimpanzee.ini @@ -0,0 +1,23 @@ +[Region] + +; Region name +Name = Chimpanzee + +; UDP Port for this region to listen on. If this value is not present, the next +; available port (starting from 9000) will be assigned +;UDPPort = 9000 + +; Coordinates of this simulator on the grid. If these values are not present, +; the server will automatically assign grid coordinates +RegionX = 1000 +RegionY = 1000 + +; The default terrain file to use if no terrain data has been stored for this +; region yet. This path is relative to the SimianData directory +DefaultTerrain = flat30m.tga + +; Maximum number of static (non-physical) objects allowed in the scene +StaticObjectLimit = 16000 + +; Maximum number of physical objects allowed in the scene. This includes avatars +PhysicalObjectLimit = 1000 diff --git a/bin/SimianData/RegionConfig/Macaque.ini b/bin/SimianData/RegionConfig/Macaque.ini new file mode 100644 index 00000000..f51ea252 --- /dev/null +++ b/bin/SimianData/RegionConfig/Macaque.ini @@ -0,0 +1,23 @@ +[Region] + +; Region name +Name = Macaque + +; UDP Port for this region to listen on. If this value is not present, the next +; available port (starting from 9000) will be assigned +;UDPPort = 9000 + +; Coordinates of this simulator on the grid. If these values are not present, +; the server will automatically assign grid coordinates +RegionX = 1000 +RegionY = 1000 + +; The default terrain file to use if no terrain data has been stored for this +; region yet. This path is relative to the SimianData directory +DefaultTerrain = flat30m.tga + +; Maximum number of static (non-physical) objects allowed in the scene +StaticObjectLimit = 16000 + +; Maximum number of physical objects allowed in the scene. This includes avatars +PhysicalObjectLimit = 1000 diff --git a/bin/SimianData/RegionConfig/Mandrill.ini b/bin/SimianData/RegionConfig/Mandrill.ini new file mode 100644 index 00000000..e7fa09bd --- /dev/null +++ b/bin/SimianData/RegionConfig/Mandrill.ini @@ -0,0 +1,23 @@ +[Region] + +; Region name +Name = Mandrill + +; UDP Port for this region to listen on. If this value is not present, the next +; available port (starting from 9000) will be assigned +;UDPPort = 9000 + +; Coordinates of this simulator on the grid. If these values are not present, +; the server will automatically assign grid coordinates +RegionX = 1000 +RegionY = 1000 + +; The default terrain file to use if no terrain data has been stored for this +; region yet. This path is relative to the SimianData directory +DefaultTerrain = flat30m.tga + +; Maximum number of static (non-physical) objects allowed in the scene +StaticObjectLimit = 16000 + +; Maximum number of physical objects allowed in the scene. This includes avatars +PhysicalObjectLimit = 1000 diff --git a/bin/SimianData/RegionConfig/Marmoset.ini b/bin/SimianData/RegionConfig/Marmoset.ini new file mode 100644 index 00000000..20bc92b2 --- /dev/null +++ b/bin/SimianData/RegionConfig/Marmoset.ini @@ -0,0 +1,23 @@ +[Region] + +; Region name +Name = Marmoset + +; UDP Port for this region to listen on. If this value is not present, the next +; available port (starting from 9000) will be assigned +;UDPPort = 9000 + +; Coordinates of this simulator on the grid. If these values are not present, +; the server will automatically assign grid coordinates +RegionX = 1000 +RegionY = 1000 + +; The default terrain file to use if no terrain data has been stored for this +; region yet. This path is relative to the SimianData directory +DefaultTerrain = flat30m.tga + +; Maximum number of static (non-physical) objects allowed in the scene +StaticObjectLimit = 16000 + +; Maximum number of physical objects allowed in the scene. This includes avatars +PhysicalObjectLimit = 1000 diff --git a/bin/SimianData/RegionConfig/Orangutan.ini b/bin/SimianData/RegionConfig/Orangutan.ini new file mode 100644 index 00000000..80885957 --- /dev/null +++ b/bin/SimianData/RegionConfig/Orangutan.ini @@ -0,0 +1,23 @@ +[Region] + +; Region name +Name = Orangutan + +; UDP Port for this region to listen on. If this value is not present, the next +; available port (starting from 9000) will be assigned +;UDPPort = 9000 + +; Coordinates of this simulator on the grid. If these values are not present, +; the server will automatically assign grid coordinates +RegionX = 1000 +RegionY = 1000 + +; The default terrain file to use if no terrain data has been stored for this +; region yet. This path is relative to the SimianData directory +DefaultTerrain = flat30m.tga + +; Maximum number of static (non-physical) objects allowed in the scene +StaticObjectLimit = 16000 + +; Maximum number of physical objects allowed in the scene. This includes avatars +PhysicalObjectLimit = 1000 diff --git a/bin/SimianData/RegionConfig/Spider Monkey.ini b/bin/SimianData/RegionConfig/Spider Monkey.ini new file mode 100644 index 00000000..814211fa --- /dev/null +++ b/bin/SimianData/RegionConfig/Spider Monkey.ini @@ -0,0 +1,23 @@ +[Region] + +; Region name +Name = Spider Monkey + +; UDP Port for this region to listen on. If this value is not present, the next +; available port (starting from 9000) will be assigned +;UDPPort = 9000 + +; Coordinates of this simulator on the grid. If these values are not present, +; the server will automatically assign grid coordinates +RegionX = 1000 +RegionY = 1000 + +; The default terrain file to use if no terrain data has been stored for this +; region yet. This path is relative to the SimianData directory +DefaultTerrain = flat30m.tga + +; Maximum number of static (non-physical) objects allowed in the scene +StaticObjectLimit = 16000 + +; Maximum number of physical objects allowed in the scene. This includes avatars +PhysicalObjectLimit = 1000 diff --git a/bin/SimianData/RegionConfig/Tamarin.ini b/bin/SimianData/RegionConfig/Tamarin.ini new file mode 100644 index 00000000..d48da687 --- /dev/null +++ b/bin/SimianData/RegionConfig/Tamarin.ini @@ -0,0 +1,23 @@ +[Region] + +; Region name +Name = Tamarin + +; UDP Port for this region to listen on. If this value is not present, the next +; available port (starting from 9000) will be assigned +;UDPPort = 9000 + +; Coordinates of this simulator on the grid. If these values are not present, +; the server will automatically assign grid coordinates +RegionX = 1000 +RegionY = 1000 + +; The default terrain file to use if no terrain data has been stored for this +; region yet. This path is relative to the SimianData directory +DefaultTerrain = flat30m.tga + +; Maximum number of static (non-physical) objects allowed in the scene +StaticObjectLimit = 16000 + +; Maximum number of physical objects allowed in the scene. This includes avatars +PhysicalObjectLimit = 1000 diff --git a/bin/Simian.ini b/bin/SimianData/Simian.ini similarity index 73% rename from bin/Simian.ini rename to bin/SimianData/Simian.ini index 1efb4c59..bb618082 100644 --- a/bin/Simian.ini +++ b/bin/SimianData/Simian.ini @@ -1,3 +1,18 @@ +[Http] + +; The port number for the asset server to listen on. If a valid SSL certificate +; file is given for SSLCertFile, the HTTPS protocol will be used. Otherwise, the +; HTTP protocol is used. +ListenPort = 8002 + +; The hostname used to construct the HTTP URL for this server. If no hostname is +; specified, the default system hostname will be used. +;Hostname = my.hostname.com + +; An SSL certificate file for the server. If a valid raw certificate or PKCS#12 +; file is given the server will run in HTTPS mode. +;SSLCertFile = server.p12 + [Extensions] ; Handles sending and receiving packets in the LLUDP format @@ -30,28 +45,28 @@ LindenLogin ; single simulator running in standalone mode, and will have unexpected results ; if the simulator is part of a larger grid. -; A simulator-local account store +; A local account store AccountManager -; A simulator-local asset store using the filesystem to store assets +; A local asset store using the filesystem to store assets AssetManager -; A simulator-local inventory store +; A local inventory store InventoryManager -; A simulator-local task inventory store -TaskInventoryManager +; A local grid service provider +GridLocal ; A simulator-local messaging layer for instant messages and script e-mails MessagingLocal -; A world map that shows the local region and a single HyperGrid link -MapLocal - ; ; ---End Local Simulator Extensions--- ; +; A task inventory store. Handles inventory for objects in a simulator +TaskInventoryManager + ; Manages creation and deletion of capabilities (see ; http://wiki.secondlife.com/wiki/Capabilities for more information). CapsManager @@ -59,15 +74,6 @@ CapsManager ; Various avatar-related functions including appearance, animations and sounds AvatarManager -; Friendship management and alerts -FriendManager - -; Chat and instant messaging -Messaging - -; Money management and accounting functions -Money - ; Texture downloads ImageDelivery @@ -113,6 +119,29 @@ ScriptConsole ; extensions ;Periscope +; +; ---Linden Client Extensions--- +; + +; Packet handling for miscellaneous agent and avatar functions +LLAgents + +; Packet handling for inventory +LLInventory + +; Packet handling for money packets +LLMoney + +; Packet handling for chat and instant messaging +LLMessaging + +; Packet handling for world map display +LLMap + +; +; ---End Linden Client Extensions--- +; + ; ; ---Persistence Providers--- ; diff --git a/bin/SimianData/flat30m.tga b/bin/SimianData/flat30m.tga new file mode 100644 index 00000000..7534a0c1 Binary files /dev/null and b/bin/SimianData/flat30m.tga differ diff --git a/prebuild.xml b/prebuild.xml index 930c2634..e241c779 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -807,6 +807,7 @@ +