From 09dd4bd6834861791008e66652826a66724efa0e Mon Sep 17 00:00:00 2001 From: gareth Date: Tue, 27 Feb 2007 23:00:49 +0000 Subject: Brought in code from branches/gareth --- src/Agent_Manager.cs | 879 +++++++++++++++++++++++++++++++++++++++++ src/AssetManagement.cs | 455 +++++++++++++++++++++ src/Asset_manager.cs | 231 +++++++++++ src/Config.cs | 140 +++++++ src/GridManager.cs | 372 +++++++++++++++++ src/InventoryManager.cs | 242 ++++++++++++ src/Login_manager.cs | 228 +++++++++++ src/Main.cs | 138 +++++++ src/OpenSimClient.cs | 339 ++++++++++++++++ src/Physics_manager.cs | 41 ++ src/Prim_manager.cs | 382 ++++++++++++++++++ src/SceneGraphManager.cs | 40 ++ src/Script_manager.cs | 103 +++++ src/Second-server.csproj | 60 +++ src/Second-server.sln | 34 ++ src/Second-server.suo | Bin 0 -> 27648 bytes src/Server.cs | 707 +++++++++++++++++++++++++++++++++ src/StorageManager.cs | 53 +++ src/Texture_manager.cs | 238 +++++++++++ src/Util.cs | 75 ++++ src/VersionInfo.cs.template | 37 ++ src/types/BitPack.cs | 138 +++++++ src/types/Mesh.cs | 28 ++ src/types/Triangle.cs | 28 ++ src/world/Avatar.cs | 70 ++++ src/world/Entity.cs | 53 +++ src/world/Primitive.cs | 33 ++ src/world/ScriptEngine.cs | 18 + src/world/SurfacePatch.cs | 22 ++ src/world/World.cs | 57 +++ src/world/scripting/IScript.cs | 16 + 31 files changed, 5257 insertions(+) create mode 100644 src/Agent_Manager.cs create mode 100644 src/AssetManagement.cs create mode 100644 src/Asset_manager.cs create mode 100644 src/Config.cs create mode 100644 src/GridManager.cs create mode 100644 src/InventoryManager.cs create mode 100644 src/Login_manager.cs create mode 100644 src/Main.cs create mode 100644 src/OpenSimClient.cs create mode 100644 src/Physics_manager.cs create mode 100644 src/Prim_manager.cs create mode 100644 src/SceneGraphManager.cs create mode 100644 src/Script_manager.cs create mode 100644 src/Second-server.csproj create mode 100644 src/Second-server.sln create mode 100644 src/Second-server.suo create mode 100644 src/Server.cs create mode 100644 src/StorageManager.cs create mode 100644 src/Texture_manager.cs create mode 100644 src/Util.cs create mode 100644 src/VersionInfo.cs.template create mode 100644 src/types/BitPack.cs create mode 100644 src/types/Mesh.cs create mode 100644 src/types/Triangle.cs create mode 100644 src/world/Avatar.cs create mode 100644 src/world/Entity.cs create mode 100644 src/world/Primitive.cs create mode 100644 src/world/ScriptEngine.cs create mode 100644 src/world/SurfacePatch.cs create mode 100644 src/world/World.cs create mode 100644 src/world/scripting/IScript.cs (limited to 'src') diff --git a/src/Agent_Manager.cs b/src/Agent_Manager.cs new file mode 100644 index 0000000..195065e --- /dev/null +++ b/src/Agent_Manager.cs @@ -0,0 +1,879 @@ +/* +Copyright (c) OpenSim project, http://osgrid.org/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +using System; +using System.Collections.Generic; +using libsecondlife; +using libsecondlife.Packets; +using libsecondlife.AssetSystem; +using System.IO; +using Axiom.MathLib; + +namespace OpenSim +{ + /// + /// Description of Agent_Manager. + /// + public class AgentManager + { + public Dictionary AgentList; + public static Dictionary AnimsLLUUID = new Dictionary(); + public static Dictionary AnimsNames = new Dictionary(); + + private uint _localNumber=0; + private Server _server; + public PrimManager Prim_Manager; + public AssetManagement assetManager; + + private libsecondlife.Packets.RegionHandshakePacket RegionPacket; + private System.Text.Encoding _enc = System.Text.Encoding.ASCII; + private libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock AvatarTemplate; + + /// + /// + /// + /// + public AgentManager(Server server) + { + AgentList = new Dictionary(); + _server = server; + this.initialise(); + } + + /// + /// + /// + /// + /// + public AvatarData GetAgent(LLUUID id) + { + if(!this.AgentList.ContainsKey(id)) + { + return null; + } + else + { + AvatarData avatar = this.AgentList[id]; + return avatar; + } + } + /// + /// + /// + /// + public void AddAgent(AvatarData agent) + { + this.AgentList.Add(agent.FullID, agent); + } + /// + /// + /// + /// + /// + /// + /// + /// + + /// + /// + /// + /// + /// + /// + /// + public bool NewAgent(UserAgentInfo userInfo, string first, string last, LLUUID baseFolder, LLUUID inventoryFolder) + { + AvatarData agent = new AvatarData(); + agent.FullID = userInfo.AgentID; + agent.NetInfo = userInfo; + agent.NetInfo.first_name =first; + agent.NetInfo.last_name = last; + agent.Position = new LLVector3(100, 100, 22); + agent.BaseFolder = baseFolder; + agent.InventoryFolder = inventoryFolder; + agent.AnimID = AnimsLLUUID["ANIM_AGENT_STAND"]; + agent.AnimSequenceID = 1; + + this.AgentList.Add(agent.FullID, agent); + + //Create new Wearable Assets and place in Inventory + this.assetManager.CreateNewInventorySet(ref agent, userInfo); + + return(true); + } + + /// + /// + /// + /// + public void RemoveAgent(UserAgentInfo userInfo) + { + this.AgentList.Remove(userInfo.AgentID); + + //tell other clients to delete this avatar + } + + /// + /// + /// + /// + public void AgentJoin(UserAgentInfo userInfo) + { + //send region data + _server.SendPacket(RegionPacket,true, userInfo); + + //inform client of join comlete + libsecondlife.Packets.AgentMovementCompletePacket mov = new AgentMovementCompletePacket(); + mov.AgentData.SessionID = userInfo.SessionID; + mov.AgentData.AgentID = userInfo.AgentID; + mov.Data.RegionHandle = Globals.Instance.RegionHandle; + mov.Data.Timestamp = 1169838966; + mov.Data.Position = new LLVector3(100f, 100f, 22f); + mov.Data.LookAt = new LLVector3(0.99f, 0.042f, 0); + _server.SendPacket(mov, true, userInfo); + + } + + /// + /// + /// + public void UpdatePositions() + { + //update positions + foreach (KeyValuePair kp in this.AgentList) + { + + kp.Value.Position.X += (kp.Value.Velocity.X * 0.2f); + kp.Value.Position.Y += (kp.Value.Velocity.Y * 0.2f); + kp.Value.Position.Z += (kp.Value.Velocity.Z * 0.2f); + } + + } + + public void UpdateAnim(UserAgentInfo userInfo, LLUUID AnimID, int AnimSeq) + { + AgentList[userInfo.AgentID].AnimID = AnimID; + AgentList[userInfo.AgentID].AnimSequenceID = AnimSeq; + UpdateAnim(userInfo); + } + + public void UpdateAnim(UserAgentInfo userInfo) + { + Console.WriteLine("Agent_Manager.cs: UpdateAnim(UserAgentInfo userInfo): called for Agent " + userInfo.AgentID.ToString()); + AvatarAnimationPacket ani = new AvatarAnimationPacket(); + ani.AnimationSourceList = new AvatarAnimationPacket.AnimationSourceListBlock[1]; + ani.AnimationSourceList[0] = new AvatarAnimationPacket.AnimationSourceListBlock(); + ani.AnimationSourceList[0].ObjectID = new LLUUID("00000000000000000000000000000000"); + ani.Sender = new AvatarAnimationPacket.SenderBlock(); + ani.Sender.ID = userInfo.AgentID; + ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[1]; + ani.AnimationList[0] = new AvatarAnimationPacket.AnimationListBlock(); + ani.AnimationList[0].AnimID = AgentList[userInfo.AgentID].AnimID; + ani.AnimationList[0].AnimSequenceID = AgentList[userInfo.AgentID].AnimSequenceID; + Console.WriteLine("Agenct_Manager.cs: UpdateAnim(UserAgentInfo userInfo): Sent Animation to client - " + AgentManager.AnimsNames[ani.AnimationList[0].AnimID]); + _server.SendPacket(ani, true, userInfo); + + // update other agents as appropiate + Axiom.MathLib.Sphere BoundingSphere; + foreach (KeyValuePair kp in this.AgentList) + { + if(kp.Key!=userInfo.AgentID) { + // Make a bounding sphere for the other avatar + BoundingSphere = new Sphere(new Vector3(kp.Value.Position.X,kp.Value.Position.Y,kp.Value.Position.Z), kp.Value.far); + + // If it intersects with our position, send an update packet + if(BoundingSphere.Intersects(new Vector3(this.AgentList[userInfo.AgentID].Position.X,this.AgentList[userInfo.AgentID].Position.Y,this.AgentList[userInfo.AgentID].Position.Z))) { + ani.AnimationSourceList[0].ObjectID = userInfo.AgentID; + ani.Sender = new AvatarAnimationPacket.SenderBlock(); + ani.Sender.ID = userInfo.AgentID; + ani.AnimationList = new AvatarAnimationPacket.AnimationListBlock[1]; + ani.AnimationList[0] = new AvatarAnimationPacket.AnimationListBlock(); + ani.AnimationList[0].AnimID = AgentList[userInfo.AgentID].AnimID; + ani.AnimationList[0].AnimSequenceID = AgentList[userInfo.AgentID].AnimSequenceID; + _server.SendPacket(ani, true, kp.Value.NetInfo); + } + } + } + } + /// + /// + /// + private void initialise() + { + //Region data + RegionPacket = new RegionHandshakePacket(); + RegionPacket.RegionInfo.BillableFactor = 0; + RegionPacket.RegionInfo.IsEstateManager = false; + RegionPacket.RegionInfo.TerrainHeightRange00 = 60; + RegionPacket.RegionInfo.TerrainHeightRange01 = 60; + RegionPacket.RegionInfo.TerrainHeightRange10 = 60; + RegionPacket.RegionInfo.TerrainHeightRange11 = 60; + RegionPacket.RegionInfo.TerrainStartHeight00 = 20; + RegionPacket.RegionInfo.TerrainStartHeight01 = 20; + RegionPacket.RegionInfo.TerrainStartHeight10 = 20; + RegionPacket.RegionInfo.TerrainStartHeight11 = 20; + RegionPacket.RegionInfo.SimAccess = 13; + RegionPacket.RegionInfo.WaterHeight = 5; + RegionPacket.RegionInfo.RegionFlags = 72458694; + RegionPacket.RegionInfo.SimName = _enc.GetBytes( Globals.Instance.RegionName); + RegionPacket.RegionInfo.SimOwner = new LLUUID("00000000-0000-0000-0000-000000000000"); + RegionPacket.RegionInfo.TerrainBase0 = new LLUUID("b8d3965a-ad78-bf43-699b-bff8eca6c975"); + RegionPacket.RegionInfo.TerrainBase1 = new LLUUID("abb783e6-3e93-26c0-248a-247666855da3"); + RegionPacket.RegionInfo.TerrainBase2 = new LLUUID("179cdabd-398a-9b6b-1391-4dc333ba321f"); + RegionPacket.RegionInfo.TerrainBase3 = new LLUUID("beb169c7-11ea-fff2-efe5-0f24dc881df2"); + RegionPacket.RegionInfo.TerrainDetail0 = new LLUUID("00000000-0000-0000-0000-000000000000"); + RegionPacket.RegionInfo.TerrainDetail1 = new LLUUID("00000000-0000-0000-0000-000000000000"); + RegionPacket.RegionInfo.TerrainDetail2 = new LLUUID("00000000-0000-0000-0000-000000000000"); + RegionPacket.RegionInfo.TerrainDetail3 = new LLUUID("00000000-0000-0000-0000-000000000000"); + RegionPacket.RegionInfo.CacheID = new LLUUID("545ec0a5-5751-1026-8a0b-216e38a7ab37"); + + //this.SetupTemplate("objectupate168.dat"); + this.LoadAnims(); + } + + /// + /// + /// + /// + private void SetupTemplate(string name) + { + + int i = 0; + FileInfo fInfo = new FileInfo(name); + long numBytes = fInfo.Length; + FileStream fStream = new FileStream(name, FileMode.Open, FileAccess.Read); + BinaryReader br = new BinaryReader(fStream); + byte [] data1 = br.ReadBytes((int)numBytes); + br.Close(); + fStream.Close(); + + libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock objdata = new libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock(data1, ref i); + + System.Text.Encoding enc = System.Text.Encoding.ASCII; + libsecondlife.LLVector3 pos = new LLVector3(objdata.ObjectData, 16); + pos.X = 100f; + objdata.ID = 8880000; + objdata.NameValue = enc.GetBytes("FirstName STRING RW SV Test \nLastName STRING RW SV User \0"); + libsecondlife.LLVector3 pos2 = new LLVector3(13.981f,100.0f,20.0f); + //objdata.FullID=user.AgentID; + byte[] pb = pos.GetBytes(); + Array.Copy(pb, 0, objdata.ObjectData, 16, pb.Length); + + AvatarTemplate = objdata; + + } + + private void LoadAnims() + { + AnimsLLUUID.Add("ANIM_AGENT_AFRAID", new LLUUID("6b61c8e8-4747-0d75-12d7-e49ff207a4ca")); + AnimsLLUUID.Add("ANIM_AGENT_AIM_BAZOOKA_R", new LLUUID("b5b4a67d-0aee-30d2-72cd-77b333e932ef")); + AnimsLLUUID.Add("ANIM_AGENT_AIM_BOW_L", new LLUUID("46bb4359-de38-4ed8-6a22-f1f52fe8f506")); + AnimsLLUUID.Add("ANIM_AGENT_AIM_HANDGUN_R", new LLUUID("3147d815-6338-b932-f011-16b56d9ac18b")); + AnimsLLUUID.Add("ANIM_AGENT_AIM_RIFLE_R", new LLUUID("ea633413-8006-180a-c3ba-96dd1d756720")); + AnimsLLUUID.Add("ANIM_AGENT_ANGRY", new LLUUID("5747a48e-073e-c331-f6f3-7c2149613d3e")); + AnimsLLUUID.Add("ANIM_AGENT_AWAY", new LLUUID("fd037134-85d4-f241-72c6-4f42164fedee")); + AnimsLLUUID.Add("ANIM_AGENT_BACKFLIP", new LLUUID("c4ca6188-9127-4f31-0158-23c4e2f93304")); + AnimsLLUUID.Add("ANIM_AGENT_BELLY_LAUGH", new LLUUID("18b3a4b5-b463-bd48-e4b6-71eaac76c515")); + AnimsLLUUID.Add("ANIM_AGENT_BLOW_KISS", new LLUUID("db84829b-462c-ee83-1e27-9bbee66bd624")); + AnimsLLUUID.Add("ANIM_AGENT_BORED", new LLUUID("b906c4ba-703b-1940-32a3-0c7f7d791510")); + AnimsLLUUID.Add("ANIM_AGENT_BOW", new LLUUID("82e99230-c906-1403-4d9c-3889dd98daba")); + AnimsLLUUID.Add("ANIM_AGENT_BRUSH", new LLUUID("349a3801-54f9-bf2c-3bd0-1ac89772af01")); + AnimsLLUUID.Add("ANIM_AGENT_BUSY", new LLUUID("efcf670c-2d18-8128-973a-034ebc806b67")); + AnimsLLUUID.Add("ANIM_AGENT_CLAP", new LLUUID("9b0c1c4e-8ac7-7969-1494-28c874c4f668")); + AnimsLLUUID.Add("ANIM_AGENT_COURTBOW", new LLUUID("9ba1c942-08be-e43a-fb29-16ad440efc50")); + AnimsLLUUID.Add("ANIM_AGENT_CROUCH", new LLUUID("201f3fdf-cb1f-dbec-201f-7333e328ae7c")); + AnimsLLUUID.Add("ANIM_AGENT_CROUCHWALK", new LLUUID("47f5f6fb-22e5-ae44-f871-73aaaf4a6022")); + AnimsLLUUID.Add("ANIM_AGENT_CRY", new LLUUID("92624d3e-1068-f1aa-a5ec-8244585193ed")); + AnimsLLUUID.Add("ANIM_AGENT_CUSTOMIZE", new LLUUID("038fcec9-5ebd-8a8e-0e2e-6e71a0a1ac53")); + AnimsLLUUID.Add("ANIM_AGENT_CUSTOMIZE_DONE", new LLUUID("6883a61a-b27b-5914-a61e-dda118a9ee2c")); + AnimsLLUUID.Add("ANIM_AGENT_DANCE1", new LLUUID("b68a3d7c-de9e-fc87-eec8-543d787e5b0d")); + AnimsLLUUID.Add("ANIM_AGENT_DANCE2", new LLUUID("928cae18-e31d-76fd-9cc9-2f55160ff818")); + AnimsLLUUID.Add("ANIM_AGENT_DANCE3", new LLUUID("30047778-10ea-1af7-6881-4db7a3a5a114")); + AnimsLLUUID.Add("ANIM_AGENT_DANCE4", new LLUUID("951469f4-c7b2-c818-9dee-ad7eea8c30b7")); + AnimsLLUUID.Add("ANIM_AGENT_DANCE5", new LLUUID("4bd69a1d-1114-a0b4-625f-84e0a5237155")); + AnimsLLUUID.Add("ANIM_AGENT_DANCE6", new LLUUID("cd28b69b-9c95-bb78-3f94-8d605ff1bb12")); + AnimsLLUUID.Add("ANIM_AGENT_DANCE7", new LLUUID("a54d8ee2-28bb-80a9-7f0c-7afbbe24a5d6")); + AnimsLLUUID.Add("ANIM_AGENT_DANCE8", new LLUUID("b0dc417c-1f11-af36-2e80-7e7489fa7cdc")); + AnimsLLUUID.Add("ANIM_AGENT_DEAD", new LLUUID("57abaae6-1d17-7b1b-5f98-6d11a6411276")); + AnimsLLUUID.Add("ANIM_AGENT_DRINK", new LLUUID("0f86e355-dd31-a61c-fdb0-3a96b9aad05f")); + AnimsLLUUID.Add("ANIM_AGENT_EMBARRASSED", new LLUUID("514af488-9051-044a-b3fc-d4dbf76377c6")); + AnimsLLUUID.Add("ANIM_AGENT_EXPRESS_AFRAID", new LLUUID("aa2df84d-cf8f-7218-527b-424a52de766e")); + AnimsLLUUID.Add("ANIM_AGENT_EXPRESS_ANGER", new LLUUID("1a03b575-9634-b62a-5767-3a679e81f4de")); + AnimsLLUUID.Add("ANIM_AGENT_EXPRESS_BORED", new LLUUID("214aa6c1-ba6a-4578-f27c-ce7688f61d0d")); + AnimsLLUUID.Add("ANIM_AGENT_EXPRESS_CRY", new LLUUID("d535471b-85bf-3b4d-a542-93bea4f59d33")); + AnimsLLUUID.Add("ANIM_AGENT_EXPRESS_DISDAIN", new LLUUID("d4416ff1-09d3-300f-4183-1b68a19b9fc1")); + AnimsLLUUID.Add("ANIM_AGENT_EXPRESS_EMBARRASSED", new LLUUID("0b8c8211-d78c-33e8-fa28-c51a9594e424")); + AnimsLLUUID.Add("ANIM_AGENT_EXPRESS_FROWN", new LLUUID("fee3df48-fa3d-1015-1e26-a205810e3001")); + AnimsLLUUID.Add("ANIM_AGENT_EXPRESS_KISS", new LLUUID("1e8d90cc-a84e-e135-884c-7c82c8b03a14")); + AnimsLLUUID.Add("ANIM_AGENT_EXPRESS_LAUGH", new LLUUID("62570842-0950-96f8-341c-809e65110823")); + AnimsLLUUID.Add("ANIM_AGENT_EXPRESS_OPEN_MOUTH", new LLUUID("d63bc1f9-fc81-9625-a0c6-007176d82eb7")); + AnimsLLUUID.Add("ANIM_AGENT_EXPRESS_REPULSED", new LLUUID("f76cda94-41d4-a229-2872-e0296e58afe1")); + AnimsLLUUID.Add("ANIM_AGENT_EXPRESS_SAD", new LLUUID("eb6ebfb2-a4b3-a19c-d388-4dd5c03823f7")); + AnimsLLUUID.Add("ANIM_AGENT_EXPRESS_SHRUG", new LLUUID("a351b1bc-cc94-aac2-7bea-a7e6ebad15ef")); + AnimsLLUUID.Add("ANIM_AGENT_EXPRESS_SMILE", new LLUUID("b7c7c833-e3d3-c4e3-9fc0-131237446312")); + AnimsLLUUID.Add("ANIM_AGENT_EXPRESS_SURPRISE", new LLUUID("728646d9-cc79-08b2-32d6-937f0a835c24")); + AnimsLLUUID.Add("ANIM_AGENT_EXPRESS_TONGUE_OUT", new LLUUID("835965c6-7f2f-bda2-5deb-2478737f91bf")); + AnimsLLUUID.Add("ANIM_AGENT_EXPRESS_TOOTHSMILE", new LLUUID("b92ec1a5-e7ce-a76b-2b05-bcdb9311417e")); + AnimsLLUUID.Add("ANIM_AGENT_EXPRESS_WINK", new LLUUID("da020525-4d94-59d6-23d7-81fdebf33148")); + AnimsLLUUID.Add("ANIM_AGENT_EXPRESS_WORRY", new LLUUID("9c05e5c7-6f07-6ca4-ed5a-b230390c3950")); + AnimsLLUUID.Add("ANIM_AGENT_FALLDOWN", new LLUUID("666307d9-a860-572d-6fd4-c3ab8865c094")); + AnimsLLUUID.Add("ANIM_AGENT_FEMALE_WALK", new LLUUID("f5fc7433-043d-e819-8298-f519a119b688")); + AnimsLLUUID.Add("ANIM_AGENT_FINGER_WAG", new LLUUID("c1bc7f36-3ba0-d844-f93c-93be945d644f")); + AnimsLLUUID.Add("ANIM_AGENT_FIST_PUMP", new LLUUID("7db00ccd-f380-f3ee-439d-61968ec69c8a")); + AnimsLLUUID.Add("ANIM_AGENT_FLY", new LLUUID("aec4610c-757f-bc4e-c092-c6e9caf18daf")); + AnimsLLUUID.Add("ANIM_AGENT_FLYSLOW", new LLUUID("2b5a38b2-5e00-3a97-a495-4c826bc443e6")); + AnimsLLUUID.Add("ANIM_AGENT_HELLO", new LLUUID("9b29cd61-c45b-5689-ded2-91756b8d76a9")); + AnimsLLUUID.Add("ANIM_AGENT_HOLD_BAZOOKA_R", new LLUUID("ef62d355-c815-4816-2474-b1acc21094a6")); + AnimsLLUUID.Add("ANIM_AGENT_HOLD_BOW_L", new LLUUID("8b102617-bcba-037b-86c1-b76219f90c88")); + AnimsLLUUID.Add("ANIM_AGENT_HOLD_HANDGUN_R", new LLUUID("efdc1727-8b8a-c800-4077-975fc27ee2f2")); + AnimsLLUUID.Add("ANIM_AGENT_HOLD_RIFLE_R", new LLUUID("3d94bad0-c55b-7dcc-8763-033c59405d33")); + AnimsLLUUID.Add("ANIM_AGENT_HOLD_THROW_R", new LLUUID("7570c7b5-1f22-56dd-56ef-a9168241bbb6")); + AnimsLLUUID.Add("ANIM_AGENT_HOVER", new LLUUID("4ae8016b-31b9-03bb-c401-b1ea941db41d")); + AnimsLLUUID.Add("ANIM_AGENT_HOVER_DOWN", new LLUUID("20f063ea-8306-2562-0b07-5c853b37b31e")); + AnimsLLUUID.Add("ANIM_AGENT_HOVER_UP", new LLUUID("62c5de58-cb33-5743-3d07-9e4cd4352864")); + AnimsLLUUID.Add("ANIM_AGENT_IMPATIENT", new LLUUID("5ea3991f-c293-392e-6860-91dfa01278a3")); + AnimsLLUUID.Add("ANIM_AGENT_JUMP", new LLUUID("2305bd75-1ca9-b03b-1faa-b176b8a8c49e")); + AnimsLLUUID.Add("ANIM_AGENT_JUMP_FOR_JOY", new LLUUID("709ea28e-1573-c023-8bf8-520c8bc637fa")); + AnimsLLUUID.Add("ANIM_AGENT_KISS_MY_BUTT", new LLUUID("19999406-3a3a-d58c-a2ac-d72e555dcf51")); + AnimsLLUUID.Add("ANIM_AGENT_LAND", new LLUUID("7a17b059-12b2-41b1-570a-186368b6aa6f")); + AnimsLLUUID.Add("ANIM_AGENT_LAUGH_SHORT", new LLUUID("ca5b3f14-3194-7a2b-c894-aa699b718d1f")); + AnimsLLUUID.Add("ANIM_AGENT_MEDIUM_LAND", new LLUUID("f4f00d6e-b9fe-9292-f4cb-0ae06ea58d57")); + AnimsLLUUID.Add("ANIM_AGENT_MOTORCYCLE_SIT", new LLUUID("08464f78-3a8e-2944-cba5-0c94aff3af29")); + AnimsLLUUID.Add("ANIM_AGENT_MUSCLE_BEACH", new LLUUID("315c3a41-a5f3-0ba4-27da-f893f769e69b")); + AnimsLLUUID.Add("ANIM_AGENT_NO", new LLUUID("5a977ed9-7f72-44e9-4c4c-6e913df8ae74")); + AnimsLLUUID.Add("ANIM_AGENT_NO_UNHAPPY", new LLUUID("d83fa0e5-97ed-7eb2-e798-7bd006215cb4")); + AnimsLLUUID.Add("ANIM_AGENT_NYAH_NYAH", new LLUUID("f061723d-0a18-754f-66ee-29a44795a32f")); + AnimsLLUUID.Add("ANIM_AGENT_ONETWO_PUNCH", new LLUUID("eefc79be-daae-a239-8c04-890f5d23654a")); + AnimsLLUUID.Add("ANIM_AGENT_PEACE", new LLUUID("b312b10e-65ab-a0a4-8b3c-1326ea8e3ed9")); + AnimsLLUUID.Add("ANIM_AGENT_POINT_ME", new LLUUID("17c024cc-eef2-f6a0-3527-9869876d7752")); + AnimsLLUUID.Add("ANIM_AGENT_POINT_YOU", new LLUUID("ec952cca-61ef-aa3b-2789-4d1344f016de")); + AnimsLLUUID.Add("ANIM_AGENT_PRE_JUMP", new LLUUID("7a4e87fe-de39-6fcb-6223-024b00893244")); + AnimsLLUUID.Add("ANIM_AGENT_PUNCH_LEFT", new LLUUID("f3300ad9-3462-1d07-2044-0fef80062da0")); + AnimsLLUUID.Add("ANIM_AGENT_PUNCH_RIGHT", new LLUUID("c8e42d32-7310-6906-c903-cab5d4a34656")); + AnimsLLUUID.Add("ANIM_AGENT_REPULSED", new LLUUID("36f81a92-f076-5893-dc4b-7c3795e487cf")); + AnimsLLUUID.Add("ANIM_AGENT_ROUNDHOUSE_KICK", new LLUUID("49aea43b-5ac3-8a44-b595-96100af0beda")); + AnimsLLUUID.Add("ANIM_AGENT_RPS_COUNTDOWN", new LLUUID("35db4f7e-28c2-6679-cea9-3ee108f7fc7f")); + AnimsLLUUID.Add("ANIM_AGENT_RPS_PAPER", new LLUUID("0836b67f-7f7b-f37b-c00a-460dc1521f5a")); + AnimsLLUUID.Add("ANIM_AGENT_RPS_ROCK", new LLUUID("42dd95d5-0bc6-6392-f650-777304946c0f")); + AnimsLLUUID.Add("ANIM_AGENT_RPS_SCISSORS", new LLUUID("16803a9f-5140-e042-4d7b-d28ba247c325")); + AnimsLLUUID.Add("ANIM_AGENT_RUN", new LLUUID("05ddbff8-aaa9-92a1-2b74-8fe77a29b445")); + AnimsLLUUID.Add("ANIM_AGENT_SAD", new LLUUID("0eb702e2-cc5a-9a88-56a5-661a55c0676a")); + AnimsLLUUID.Add("ANIM_AGENT_SALUTE", new LLUUID("cd7668a6-7011-d7e2-ead8-fc69eff1a104")); + AnimsLLUUID.Add("ANIM_AGENT_SHOOT_BOW_L", new LLUUID("e04d450d-fdb5-0432-fd68-818aaf5935f8")); + AnimsLLUUID.Add("ANIM_AGENT_SHOUT", new LLUUID("6bd01860-4ebd-127a-bb3d-d1427e8e0c42")); + AnimsLLUUID.Add("ANIM_AGENT_SHRUG", new LLUUID("70ea714f-3a97-d742-1b01-590a8fcd1db5")); + AnimsLLUUID.Add("ANIM_AGENT_SIT", new LLUUID("1a5fe8ac-a804-8a5d-7cbd-56bd83184568")); + AnimsLLUUID.Add("ANIM_AGENT_SIT_FEMALE", new LLUUID("b1709c8d-ecd3-54a1-4f28-d55ac0840782")); + AnimsLLUUID.Add("ANIM_AGENT_SIT_GENERIC", new LLUUID("245f3c54-f1c0-bf2e-811f-46d8eeb386e7")); + AnimsLLUUID.Add("ANIM_AGENT_SIT_GROUND", new LLUUID("1c7600d6-661f-b87b-efe2-d7421eb93c86")); + AnimsLLUUID.Add("ANIM_AGENT_SIT_GROUND_CONSTRAINED", new LLUUID("1a2bd58e-87ff-0df8-0b4c-53e047b0bb6e")); + AnimsLLUUID.Add("ANIM_AGENT_SIT_TO_STAND", new LLUUID("a8dee56f-2eae-9e7a-05a2-6fb92b97e21e")); + AnimsLLUUID.Add("ANIM_AGENT_SLEEP", new LLUUID("f2bed5f9-9d44-39af-b0cd-257b2a17fe40")); + AnimsLLUUID.Add("ANIM_AGENT_SMOKE_IDLE", new LLUUID("d2f2ee58-8ad1-06c9-d8d3-3827ba31567a")); + AnimsLLUUID.Add("ANIM_AGENT_SMOKE_INHALE", new LLUUID("6802d553-49da-0778-9f85-1599a2266526")); + AnimsLLUUID.Add("ANIM_AGENT_SMOKE_THROW_DOWN", new LLUUID("0a9fb970-8b44-9114-d3a9-bf69cfe804d6")); + AnimsLLUUID.Add("ANIM_AGENT_SNAPSHOT", new LLUUID("eae8905b-271a-99e2-4c0e-31106afd100c")); + AnimsLLUUID.Add("ANIM_AGENT_STAND", new LLUUID("2408fe9e-df1d-1d7d-f4ff-1384fa7b350f")); + AnimsLLUUID.Add("ANIM_AGENT_STANDUP", new LLUUID("3da1d753-028a-5446-24f3-9c9b856d9422")); + AnimsLLUUID.Add("ANIM_AGENT_STAND_1", new LLUUID("15468e00-3400-bb66-cecc-646d7c14458e")); + AnimsLLUUID.Add("ANIM_AGENT_STAND_2", new LLUUID("370f3a20-6ca6-9971-848c-9a01bc42ae3c")); + AnimsLLUUID.Add("ANIM_AGENT_STAND_3", new LLUUID("42b46214-4b44-79ae-deb8-0df61424ff4b")); + AnimsLLUUID.Add("ANIM_AGENT_STAND_4", new LLUUID("f22fed8b-a5ed-2c93-64d5-bdd8b93c889f")); + AnimsLLUUID.Add("ANIM_AGENT_STRETCH", new LLUUID("80700431-74ec-a008-14f8-77575e73693f")); + AnimsLLUUID.Add("ANIM_AGENT_STRIDE", new LLUUID("1cb562b0-ba21-2202-efb3-30f82cdf9595")); + AnimsLLUUID.Add("ANIM_AGENT_SURF", new LLUUID("41426836-7437-7e89-025d-0aa4d10f1d69")); + AnimsLLUUID.Add("ANIM_AGENT_SURPRISE", new LLUUID("313b9881-4302-73c0-c7d0-0e7a36b6c224")); + AnimsLLUUID.Add("ANIM_AGENT_SWORD_STRIKE", new LLUUID("85428680-6bf9-3e64-b489-6f81087c24bd")); + AnimsLLUUID.Add("ANIM_AGENT_TALK", new LLUUID("5c682a95-6da4-a463-0bf6-0f5b7be129d1")); + AnimsLLUUID.Add("ANIM_AGENT_TANTRUM", new LLUUID("11000694-3f41-adc2-606b-eee1d66f3724")); + AnimsLLUUID.Add("ANIM_AGENT_THROW_R", new LLUUID("aa134404-7dac-7aca-2cba-435f9db875ca")); + AnimsLLUUID.Add("ANIM_AGENT_TRYON_SHIRT", new LLUUID("83ff59fe-2346-f236-9009-4e3608af64c1")); + AnimsLLUUID.Add("ANIM_AGENT_TURNLEFT", new LLUUID("56e0ba0d-4a9f-7f27-6117-32f2ebbf6135")); + AnimsLLUUID.Add("ANIM_AGENT_TURNRIGHT", new LLUUID("2d6daa51-3192-6794-8e2e-a15f8338ec30")); + AnimsLLUUID.Add("ANIM_AGENT_TYPE", new LLUUID("c541c47f-e0c0-058b-ad1a-d6ae3a4584d9")); + AnimsLLUUID.Add("ANIM_AGENT_WALK", new LLUUID("6ed24bd8-91aa-4b12-ccc7-c97c857ab4e0")); + AnimsLLUUID.Add("ANIM_AGENT_WHISPER", new LLUUID("7693f268-06c7-ea71-fa21-2b30d6533f8f")); + AnimsLLUUID.Add("ANIM_AGENT_WHISTLE", new LLUUID("b1ed7982-c68e-a982-7561-52a88a5298c0")); + AnimsLLUUID.Add("ANIM_AGENT_WINK", new LLUUID("869ecdad-a44b-671e-3266-56aef2e3ac2e")); + AnimsLLUUID.Add("ANIM_AGENT_WINK_HOLLYWOOD", new LLUUID("c0c4030f-c02b-49de-24ba-2331f43fe41c")); + AnimsLLUUID.Add("ANIM_AGENT_WORRY", new LLUUID("9f496bd2-589a-709f-16cc-69bf7df1d36c")); + AnimsLLUUID.Add("ANIM_AGENT_YES", new LLUUID("15dd911d-be82-2856-26db-27659b142875")); + AnimsLLUUID.Add("ANIM_AGENT_YES_HAPPY", new LLUUID("b8c8b2a3-9008-1771-3bfc-90924955ab2d")); + AnimsLLUUID.Add("ANIM_AGENT_YOGA_FLOAT", new LLUUID("42ecd00b-9947-a97c-400a-bbc9174c7aeb")); + + + foreach (KeyValuePair kp in AgentManager.AnimsLLUUID) + { + AnimsNames.Add(kp.Value, kp.Key); + } + } + + /// + /// + /// + /// + public void SendInitialData(UserAgentInfo userInfo) + { + + //shouldn't have to read all this in from disk for every new client + string data_path = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, @"layer_data"); + + //send layerdata + LayerDataPacket layerpack = new LayerDataPacket(); + layerpack.LayerID.Type = 76; + this.SendLayerData(userInfo,ref layerpack, System.IO.Path.Combine(data_path, @"layerdata0.dat")); + + LayerDataPacket layerpack1 = new LayerDataPacket(); + layerpack1.LayerID.Type = 76; + this.SendLayerData(userInfo, ref layerpack, System.IO.Path.Combine(data_path, @"layerdata1.dat")); + + LayerDataPacket layerpack2 = new LayerDataPacket(); + layerpack2.LayerID.Type = 56; + this.SendLayerData(userInfo, ref layerpack, System.IO.Path.Combine(data_path, @"layerdata2.dat")); + + LayerDataPacket layerpack3 = new LayerDataPacket(); + layerpack3.LayerID.Type = 55; + this.SendLayerData(userInfo, ref layerpack, System.IO.Path.Combine(data_path, @"layerdata3.dat")); + + LayerDataPacket layerpack4 = new LayerDataPacket(); + layerpack4.LayerID.Type = 56; + this.SendLayerData(userInfo, ref layerpack, System.IO.Path.Combine(data_path, @"layerdata4.dat")); + + LayerDataPacket layerpack5 = new LayerDataPacket(); + layerpack5.LayerID.Type = 55; + this.SendLayerData(userInfo, ref layerpack, System.IO.Path.Combine(data_path, @"layerdata5.dat")); + + //send intial set of captured prims data? + this.Prim_Manager.ReadPrimDatabase( "objectdatabase.ini", userInfo); + + //send prims that have been created by users + //prim_man.send_existing_prims(User_info); + + //send update about clients avatar + this.SendInitialAvatarPosition(userInfo); + + //send updates about all other users + foreach (KeyValuePair kp in this.AgentList) + { + if(kp.Value.NetInfo.AgentID != userInfo.AgentID) + { + this.SendOtherAvatarPosition(userInfo, kp.Value); + } + } + } + + /// + /// + /// + /// + public void SendInitialAvatarPosition(UserAgentInfo userInfo) + { + //send a objectupdate packet with information about the clients avatar + ObjectUpdatePacket objupdate = new ObjectUpdatePacket(); + objupdate.RegionData.RegionHandle = Globals.Instance.RegionHandle; + objupdate.RegionData.TimeDilation = 64096; + objupdate.ObjectData = new libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock[1]; + + objupdate.ObjectData[0] = AvatarTemplate; + //give this avatar object a local id and assign the user a name + objupdate.ObjectData[0].ID = 8880000 + this._localNumber; + userInfo.localID = objupdate.ObjectData[0].ID; + //User_info.name="Test"+this.local_numer+" User"; + this.GetAgent(userInfo.AgentID).Started = true; + objupdate.ObjectData[0].FullID = userInfo.AgentID; + objupdate.ObjectData[0].NameValue = _enc.GetBytes("FirstName STRING RW SV " + userInfo.first_name + "\nLastName STRING RW SV " + userInfo.last_name + " \0"); + userInfo.name = "FirstName STRING RW SV " + userInfo.first_name + "\nLastName STRING RW SV " + userInfo.last_name + " \0"; + + libsecondlife.LLVector3 pos2 = new LLVector3(100f, 100.0f, 22.0f); + + byte[] pb = pos2.GetBytes(); + + Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length); + this._localNumber++; + + _server.SendPacket(objupdate, true, userInfo); + + //send this info to other existing clients + foreach (KeyValuePair kp in this.AgentList) + { + if(kp.Value.NetInfo.AgentID != userInfo.AgentID) + { + _server.SendPacket(objupdate, true, kp.Value.NetInfo); + this.SendOtherAppearance(kp.Value.NetInfo, objupdate.ObjectData[0].FullID); + } + } + + } + + /// + /// + /// + /// + public void SendIntialAvatarAppearance(UserAgentInfo userInfo) + { + AvatarData Agent = this.AgentList[userInfo.AgentID]; + AgentWearablesUpdatePacket aw = new AgentWearablesUpdatePacket(); + aw.AgentData.AgentID = userInfo.AgentID; + aw.AgentData.SerialNum = 0; + aw.AgentData.SessionID = userInfo.SessionID; + + aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[13]; + AgentWearablesUpdatePacket.WearableDataBlock awb = null; + awb = new AgentWearablesUpdatePacket.WearableDataBlock(); + awb.WearableType = (byte)0; + awb.AssetID = Agent.Wearables[0].AssetID; + awb.ItemID = Agent.Wearables[0].ItemID; + aw.WearableData[0] = awb; + + awb = new AgentWearablesUpdatePacket.WearableDataBlock(); + awb.WearableType =(byte)1; + awb.AssetID = Agent.Wearables[1].AssetID; + awb.ItemID = Agent.Wearables[1].ItemID; + aw.WearableData[1] = awb; + + for(int i=2; i<13; i++) + { + awb = new AgentWearablesUpdatePacket.WearableDataBlock(); + awb.WearableType = (byte)i; + awb.AssetID = new LLUUID("00000000-0000-0000-0000-000000000000"); + awb.ItemID = new LLUUID("00000000-0000-0000-0000-000000000000"); + aw.WearableData[i] = awb; + } + + _server.SendPacket(aw, true, userInfo); + } + + /// + /// + /// + /// + /// + public void SendOtherAppearance(UserAgentInfo userInfo, LLUUID id) + { + AvatarAppearancePacket avp = new AvatarAppearancePacket(); + + + avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[218]; + //avp.ObjectData.TextureEntry=this.avatar_template.TextureEntry;// br.ReadBytes((int)numBytes); + + FileInfo fInfo = new FileInfo("Avatar_texture3.dat"); + long numBytes = fInfo.Length; + FileStream fStream = new FileStream("Avatar_texture3.dat", FileMode.Open, FileAccess.Read); + BinaryReader br = new BinaryReader(fStream); + avp.ObjectData.TextureEntry = br.ReadBytes((int)numBytes); + br.Close(); + fStream.Close(); + + AvatarAppearancePacket.VisualParamBlock avblock = null; + for(int i = 0; i < 218; i++) + { + avblock = new AvatarAppearancePacket.VisualParamBlock(); + avblock.ParamValue = (byte)100; + avp.VisualParam[i] = avblock; + } + + avp.Sender.IsTrial = false; + avp.Sender.ID = id; + _server.SendPacket(avp, true, userInfo); + + } + + /// + /// + /// + /// + /// + public void SendOtherAvatarPosition(UserAgentInfo userInfo, AvatarData avatar) + { + //send a objectupdate packet with information about the clients avatar + ObjectUpdatePacket objupdate = new ObjectUpdatePacket(); + objupdate.RegionData.RegionHandle = Globals.Instance.RegionHandle; + objupdate.RegionData.TimeDilation = 64500; + objupdate.ObjectData = new libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock[1]; + + objupdate.ObjectData[0] = AvatarTemplate; + //give this avatar object a local id and assign the user a name + objupdate.ObjectData[0].ID = avatar.NetInfo.localID; + objupdate.ObjectData[0].FullID = avatar.NetInfo.AgentID; + objupdate.ObjectData[0].NameValue = _enc.GetBytes(avatar.NetInfo.name); + libsecondlife.LLVector3 pos2 = new LLVector3(avatar.Position.X, avatar.Position.Y, avatar.Position.Z); + + byte[] pb = pos2.GetBytes(); + Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length); + this._localNumber++; + + _server.SendPacket(objupdate, true, userInfo); + this.SendOtherAppearance(userInfo, avatar.NetInfo.AgentID); + + } + + /// + /// + /// + /// + /// + public void SendChatMessage(UserAgentInfo userInfo, string line) + { + libsecondlife.Packets.ChatFromSimulatorPacket reply = new ChatFromSimulatorPacket(); + reply.ChatData.Audible = 1; + reply.ChatData.Message = _enc.GetBytes(line); + reply.ChatData.ChatType = 1; + reply.ChatData.SourceType = 1; + reply.ChatData.Position = new LLVector3(120, 100, 21); //should set to actual position + reply.ChatData.FromName = _enc.GetBytes(userInfo.first_name + " " + userInfo.last_name + "\0"); + reply.ChatData.OwnerID = userInfo.AgentID; + reply.ChatData.SourceID = userInfo.AgentID; + //echo to sender + _server.SendPacket(reply, true, userInfo); + + //send to all users + foreach (KeyValuePair kp in this.AgentList) + { + if(kp.Value.NetInfo.AgentID!=userInfo.AgentID) + { + _server.SendPacket(reply, true, kp.Value.NetInfo); + } + } + } + + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + public void SendMoveCommand(UserAgentInfo userInfo, bool stop, float x, float y, float z, uint avatarID, libsecondlife.LLQuaternion body) + { + Console.WriteLine("sending move"); + uint ID = userInfo.localID; + byte[] bytes = new byte[60]; + int i=0; + + ImprovedTerseObjectUpdatePacket im = new ImprovedTerseObjectUpdatePacket(); + im.RegionData.RegionHandle = Globals.Instance.RegionHandle;; + im.RegionData.TimeDilation = 64096; + + im.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; + ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); + + im.ObjectData[0] = dat; + + dat.TextureEntry = AvatarTemplate.TextureEntry; + libsecondlife.LLVector3 pos2 = new LLVector3(x, y, z); + + bytes[i++] = (byte)(ID % 256); + bytes[i++] = (byte)((ID >> 8) % 256); + bytes[i++] = (byte)((ID >> 16) % 256); + bytes[i++] = (byte)((ID >> 24) % 256); + + bytes[i++] = 0; + bytes[i++] = 1; + + i += 14; + bytes[i++] = 128; + bytes[i++] = 63; + byte[] pb = pos2.GetBytes(); + + Array.Copy(pb, 0, bytes, i, pb.Length); + i += 12; + ushort ac = 32767; + Axiom.MathLib.Vector3 v3 = new Axiom.MathLib.Vector3(1, 0, 0); + Axiom.MathLib.Quaternion q = new Axiom.MathLib.Quaternion(body.W, body.X, body.Y, body.Z); + Axiom.MathLib.Vector3 direc = q * v3; + direc.Normalize(); + + direc = direc * (0.03f); + direc.x += 1; + direc.y += 1; + direc.z += 1; + ushort dx, dy, dz; + dx = (ushort)(32768 * direc.x); + dy = (ushort)(32768 * direc.y); + dz = (ushort)(32768 * direc.z); + + //vel + if(!stop) + { + bytes[i++] = (byte)(dx % 256); + bytes[i++] = (byte)((dx >> 8) % 256); + + bytes[i++] = (byte)(dy % 256); + bytes[i++] = (byte)((dy >> 8) % 256); + + bytes[i++] = (byte)(dz % 256); + bytes[i++] = (byte)((dz >> 8) % 256); + } + else + { + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + } + //accel + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + + //rot + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + + //rotation vel + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + + dat.Data=bytes; + + _server.SendPacket(im, true, userInfo); + + //should send to all users. + foreach (KeyValuePair kp in this.AgentList) + { + if(kp.Value.NetInfo.AgentID != userInfo.AgentID) + { + _server.SendPacket(im, true, kp.Value.NetInfo); + } + } + + //check if we should be standing or walking + if (this.AgentList[userInfo.AgentID].Walk) + { + this.AgentList[userInfo.AgentID].AnimID = AgentManager.AnimsLLUUID["ANIM_AGENT_WALK"]; + this.AgentList[userInfo.AgentID].AnimSequenceID = 1; + this.UpdateAnim(userInfo); + } + else + { + this.AgentList[userInfo.AgentID].AnimID = AgentManager.AnimsLLUUID["ANIM_AGENT_STAND"]; + this.AgentList[userInfo.AgentID].AnimSequenceID = 1; + this.UpdateAnim(userInfo); + } + } + + /// + /// + /// + /// + /// + /// + public void SendLayerData(UserAgentInfo userInfo, ref LayerDataPacket layer, string name) + { + FileInfo fInfo = new FileInfo(name); + long numBytes = fInfo.Length; + FileStream fStream = new FileStream(name, FileMode.Open, FileAccess.Read); + BinaryReader br = new BinaryReader(fStream); + byte [] data1 = br.ReadBytes((int)numBytes); + br.Close(); + fStream.Close(); + layer.LayerData.Data = data1; + _server.SendPacket(layer, true, userInfo); + + } + } + + public class AvatarData + { + public UserAgentInfo NetInfo; + public LLUUID FullID; + public LLVector3 Position; + public LLVector3 Velocity = new LLVector3(0,0,0); + //public LLQuaternion Rotation; + public bool Walk = false; + public bool Started = false; + //public TextureEntry TextureEntry; + public AvatarWearable[] Wearables; + public LLUUID InventoryFolder; + public LLUUID BaseFolder; + public LLUUID AnimID; + public int AnimSequenceID; + public float far; + public libsecondlife.LLVector3 CameraAtAxis; + public libsecondlife.LLVector3 CameraCenter; + public libsecondlife.LLVector3 CameraLeftAxis; + public libsecondlife.LLVector3 CameraUpAxis; + + public AvatarData() + { + Wearables=new AvatarWearable[2]; //should be 13 + for(int i = 0; i < 2; i++) + { + Wearables[i] = new AvatarWearable(); + } + } + } + + public class AvatarWearable + { + public LLUUID AssetID; + public LLUUID ItemID; + + public AvatarWearable() + { + + } + } + /* + public class AvatarParams + { + public byte[] Params; + + public AvatarParams() + { + + } + + } + */ +} diff --git a/src/AssetManagement.cs b/src/AssetManagement.cs new file mode 100644 index 0000000..f919476 --- /dev/null +++ b/src/AssetManagement.cs @@ -0,0 +1,455 @@ +/* + * +Copyright (c) OpenSim project, http://osgrid.org/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +* + */ + +using System; +using System.Net; +using System.Collections.Generic; +using libsecondlife; +using System.Collections; +using libsecondlife.Packets; +using libsecondlife.AssetSystem; +using System.IO; + +namespace OpenSim +{ + /// + /// Asset and Image management + /// + public class AssetManagement + { + public Dictionary Assets; + public Dictionary Textures; + + public ArrayList AssetRequests = new ArrayList(); //should change to a generic + public ArrayList TextureRequests = new ArrayList(); + //public ArrayList uploads=new ArrayList(); + private Server _server; + private InventoryManager _inventoryManager; + private System.Text.Encoding _enc = System.Text.Encoding.ASCII; + + /// + /// + /// + /// + public AssetManagement(Server server, InventoryManager inventoryManager) + { + this._server = server; + this._inventoryManager = inventoryManager; + Textures = new Dictionary (); + Assets = new Dictionary (); + this.initialise(); + } + + /// + /// + /// + private void initialise() + { + //Shape and skin base assets + AssetInfo Asset = new AssetInfo(); + Asset.filename = "base_shape.dat"; + Asset.FullID = new LLUUID("66c41e39-38f9-f75a-024e-585989bfab73"); + this.LoadAsset(Asset, false); + this.Assets.Add(Asset.FullID, Asset); + + Asset = new AssetInfo(); + Asset.filename = "base_skin.dat"; + Asset.FullID = new LLUUID("e0ee49b5a4184df8d3c9a65361fe7f49"); + this.LoadAsset(Asset, false); + this.Assets.Add(Asset.FullID, Asset); + + //our test images + //Change these filenames to images you want to use. + TextureImage Image = new TextureImage(); + Image.filename = "testpic2.jp2"; + Image.FullID = new LLUUID("00000000-0000-0000-5005-000000000005"); + Image.Name = "test Texture"; + this.LoadAsset(Image, true); + this.Textures.Add(Image.FullID, Image); + + Image = new TextureImage(); + Image.filename = "map_base.jp2"; + Image.FullID = new LLUUID("00000000-0000-0000-7007-000000000006"); + this.LoadAsset(Image, true); + this.Textures.Add(Image.FullID, Image); + + Image = new TextureImage(); + Image.filename = "map1.jp2"; + Image.FullID = new LLUUID("00000000-0000-0000-7009-000000000008"); + this.LoadAsset(Image, true); + this.Textures.Add(Image.FullID, Image); + } + + /// + /// + /// + /// + /// + /// + #region AssetRegion + + public void AddAssetRequest(UserAgentInfo userInfo, LLUUID assetID, TransferRequestPacket transferRequest) + { + + if(!this.Assets.ContainsKey(assetID)) + { + //not found asset + return; + } + AssetInfo info = this.Assets[assetID]; + //for now as it will be only skin or shape request just send back the asset + TransferInfoPacket Transfer = new TransferInfoPacket(); + Transfer.TransferInfo.ChannelType = 2; + Transfer.TransferInfo.Status = 0; + Transfer.TransferInfo.TargetType = 0; + Transfer.TransferInfo.Params = transferRequest.TransferInfo.Params; + Transfer.TransferInfo.Size = info.data.Length; + Transfer.TransferInfo.TransferID = transferRequest.TransferInfo.TransferID; + + _server.SendPacket(Transfer, true, userInfo); + + TransferPacketPacket TransferPacket = new TransferPacketPacket(); + TransferPacket.TransferData.Packet = 0; + TransferPacket.TransferData.ChannelType = 2; + TransferPacket.TransferData.TransferID=transferRequest.TransferInfo.TransferID; + if(info.data.Length>1000) //but needs to be less than 2000 at the moment + { + byte[] chunk = new byte[1000]; + Array.Copy(info.data,chunk,1000); + TransferPacket.TransferData.Data = chunk; + TransferPacket.TransferData.Status = 0; + _server.SendPacket(TransferPacket,true,userInfo); + + TransferPacket = new TransferPacketPacket(); + TransferPacket.TransferData.Packet = 1; + TransferPacket.TransferData.ChannelType = 2; + TransferPacket.TransferData.TransferID = transferRequest.TransferInfo.TransferID; + byte[] chunk1 = new byte[(info.data.Length-1000)]; + Array.Copy(info.data, 1000, chunk1, 0, chunk1.Length); + TransferPacket.TransferData.Data = chunk1; + TransferPacket.TransferData.Status = 1; + _server.SendPacket(TransferPacket, true, userInfo); + } + else + { + TransferPacket.TransferData.Status = 1; //last packet? so set to 1 + TransferPacket.TransferData.Data = info.data; + _server.SendPacket(TransferPacket, true, userInfo); + } + + } + + public void CreateNewInventorySet(ref AvatarData Avata,UserAgentInfo UserInfo) + { + //Create Folders + LLUUID BaseFolder = Avata.BaseFolder; + _inventoryManager.CreateNewFolder(UserInfo, Avata.InventoryFolder); + _inventoryManager.CreateNewFolder(UserInfo, BaseFolder); + + //Give a copy of default shape + AssetInfo Base = this.Assets[new LLUUID("66c41e39-38f9-f75a-024e-585989bfab73")]; + AssetInfo Shape = this.CloneAsset(UserInfo.AgentID, Base); + + Shape.filename = ""; + Shape.Name = "Default Shape"; + Shape.Description = "Default Shape"; + Shape.InvType = 18; + Shape.Type=13; + //Shape.Type = libsecondlife.AssetSystem.Asset.ASSET_TYPE_WEARABLE_BODY; + + byte[] Agentid = _enc.GetBytes(UserInfo.AgentID.ToStringHyphenated()); + Array.Copy(Agentid, 0, Shape.data, 294, Agentid.Length); + this.Assets.Add(Shape.FullID, Shape); + + Avata.Wearables[0].ItemID = _inventoryManager.AddToInventory(UserInfo, BaseFolder, Shape); + Avata.Wearables[0].AssetID = Shape.FullID; + + //Give copy of default skin + Base = this.Assets[new LLUUID("e0ee49b5a4184df8d3c9a65361fe7f49")]; + AssetInfo Skin=this.CloneAsset(UserInfo.AgentID, Base); + + Skin.filename = ""; + Skin.Name = "Default Skin"; + Skin.Description = "Default Skin"; + Skin.InvType = 18; + Skin.Type=13; + //Skin.Type = libsecondlife.AssetSystem.Asset.ASSET_TYPE_WEARABLE_BODY; + + Array.Copy(Agentid,0,Skin.data,238,Agentid.Length); + this.Assets.Add(Skin.FullID, Skin); + + Avata.Wearables[1].ItemID = _inventoryManager.AddToInventory(UserInfo, BaseFolder, Skin); + Avata.Wearables[1].AssetID = Skin.FullID; + + //give a copy of test texture + TextureImage Texture = this.CloneImage(UserInfo.AgentID, Textures[new LLUUID("00000000-0000-0000-5005-000000000005")]); + this.Textures.Add(Texture.FullID, Texture); + _inventoryManager.AddToInventory(UserInfo, BaseFolder, Texture); + + } + + + private void LoadAsset(AssetBase info, bool Image) + { + WebRequest AssetLoad = WebRequest.Create(Globals.Instance.AssetURL + "getasset/" + Globals.Instance.AssetSendKey + "/" + info.FullID + "/data"); + WebResponse AssetResponse = AssetLoad.GetResponse(); + byte[] idata = new byte[(int)AssetResponse.ContentLength]; + BinaryReader br = new BinaryReader(AssetResponse.GetResponseStream()); + idata = br.ReadBytes((int)AssetResponse.ContentLength); + br.Close(); + AssetResponse.Close(); + info.data = idata; + } + + public AssetInfo CloneAsset(LLUUID NewOwner, AssetInfo SourceAsset) + { + AssetInfo NewAsset = new AssetInfo(); + NewAsset.data = new byte[SourceAsset.data.Length]; + Array.Copy(SourceAsset.data, NewAsset.data, SourceAsset.data.Length); + NewAsset.FullID = LLUUID.Random(); + NewAsset.Type = SourceAsset.Type; + NewAsset.InvType = SourceAsset.InvType; + return(NewAsset); + } + #endregion + + #region TextureRegion + public void AddTextureRequest(UserAgentInfo userInfo, LLUUID imageID) + { + + if(!this.Textures.ContainsKey(imageID)) + { + //not found image so send back image not in data base message + ImageNotInDatabasePacket im_not = new ImageNotInDatabasePacket(); + im_not.ImageID.ID=imageID; + _server.SendPacket(im_not, true, userInfo); + return; + } + TextureImage imag = this.Textures[imageID]; + TextureRequest req = new TextureRequest(); + req.RequestUser = userInfo; + req.RequestImage = imageID; + req.ImageInfo = imag; + + if(imag.data.LongLength>600) //should be bigger or smaller? + { + //over 600 bytes so split up file + req.NumPackets = 1 + (int)(imag.data.Length-600+999)/1000; + } + else + { + req.NumPackets = 1; + } + + this.TextureRequests.Add(req); + + } + + public void AddTexture(LLUUID imageID, string name, byte[] data) + { + + } + public void DoWork(ulong time) + { + if(this.TextureRequests.Count == 0) + { + //no requests waiting + return; + } + int num; + //should be running in its own thread but for now is called by timer + if(this.TextureRequests.Count < 5) + { + //lower than 5 so do all of them + num = this.TextureRequests.Count; + } + else + { + num=5; + } + TextureRequest req; + for(int i = 0; i < num; i++) + { + req=(TextureRequest)this.TextureRequests[i]; + + if(req.PacketCounter == 0) + { + //first time for this request so send imagedata packet + if(req.NumPackets == 1) + { + //only one packet so send whole file + ImageDataPacket im = new ImageDataPacket(); + im.ImageID.Packets = 1; + im.ImageID.ID = req.ImageInfo.FullID; + im.ImageID.Size = (uint)req.ImageInfo.data.Length; + im.ImageData.Data = req.ImageInfo.data; + im.ImageID.Codec = 2; + _server.SendPacket(im, true, req.RequestUser); + req.PacketCounter++; + req.ImageInfo.last_used = time; + //System.Console.WriteLine("sent texture: "+req.image_info.FullID); + } + else + { + //more than one packet so split file up + ImageDataPacket im = new ImageDataPacket(); + im.ImageID.Packets = (ushort)req.NumPackets; + im.ImageID.ID = req.ImageInfo.FullID; + im.ImageID.Size = (uint)req.ImageInfo.data.Length; + im.ImageData.Data = new byte[600]; + Array.Copy(req.ImageInfo.data, 0, im.ImageData.Data, 0, 600); + im.ImageID.Codec = 2; + _server.SendPacket(im, true, req.RequestUser); + req.PacketCounter++; + req.ImageInfo.last_used = time; + //System.Console.WriteLine("sent first packet of texture: + } + } + else + { + //send imagepacket + //more than one packet so split file up + ImagePacketPacket im = new ImagePacketPacket(); + im.ImageID.Packet = (ushort)req.PacketCounter; + im.ImageID.ID = req.ImageInfo.FullID; + int size = req.ImageInfo.data.Length - 600 - 1000*(req.PacketCounter - 1); + if(size > 1000) size = 1000; + im.ImageData.Data = new byte[size]; + Array.Copy(req.ImageInfo.data, 600 + 1000*(req.PacketCounter - 1), im.ImageData.Data, 0, size); + _server.SendPacket(im, true, req.RequestUser); + req.PacketCounter++; + req.ImageInfo.last_used = time; + //System.Console.WriteLine("sent a packet of texture: "+req.image_info.FullID); + } + } + + //remove requests that have been completed + for(int i = 0; i < num; i++) + { + req=(TextureRequest)this.TextureRequests[i]; + if(req.PacketCounter == req.NumPackets) + { + this.TextureRequests.Remove(req); + } + } + } + + public void RecieveTexture(Packet pack) + { + + } + + public TextureImage CloneImage(LLUUID newOwner, TextureImage source) + { + TextureImage newImage = new TextureImage(); + newImage.data = new byte[source.data.Length]; + Array.Copy(source.data,newImage.data,source.data.Length); + newImage.filename = source.filename; + newImage.FullID = LLUUID.Random(); + newImage.Name = source.Name; + return(newImage); + } + + #endregion + } + + public class AssetRequest + { + public UserAgentInfo RequestUser; + public LLUUID RequestImage; + public AssetInfo asset_inf; + public long data_pointer = 0; + public int num_packets = 0; + public int packet_counter = 0; + + public AssetRequest() + { + + } + } + public class AssetInfo:AssetBase + { + //public byte[] data; + //public LLUUID Full_ID; + public bool loaded; + public ulong last_used; //need to add a tick/time counter and keep record + // of how often images are requested to unload unused ones. + + public AssetInfo() + { + + } + } + + public class AssetBase + { + public byte[] data; + public LLUUID FullID; + public sbyte Type; + public sbyte InvType; + public string Name; + public string Description; + public string filename; + + public AssetBase() + { + + } + } + public class TextureRequest + { + public UserAgentInfo RequestUser; + public LLUUID RequestImage; + public TextureImage ImageInfo; + public long DataPointer = 0; + public int NumPackets = 0; + public int PacketCounter = 0; + + public TextureRequest() + { + + } + } + public class TextureImage: AssetBase + { + //any need for this class now most has been moved into AssetBase? + //public byte[] data; + //public LLUUID Full_ID; + //public string name; + public bool loaded; + public ulong last_used; //need to add a tick/time counter and keep record + // of how often images are requested to unload unused ones. + + public TextureImage() + { + + } + } + + +} diff --git a/src/Asset_manager.cs b/src/Asset_manager.cs new file mode 100644 index 0000000..60f8945 --- /dev/null +++ b/src/Asset_manager.cs @@ -0,0 +1,231 @@ +/* +Copyright (c) OpenSim project, http://osgrid.org/ + +* Copyright (c) , +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +using System; +using System.Collections.Generic; +using libsecondlife; +using System.Collections; +using libsecondlife.Packets; +using libsecondlife.AssetSystem; +using System.IO; + +namespace OpenSim +{ + /// + /// Description of Asset_manager. + /// + public class AssetManager + { + public Dictionary Assets; + public ArrayList requests=new ArrayList(); //should change to a generic + // public ArrayList uploads=new ArrayList(); + private Server server; + public TextureManager TextureMan; + public InventoryManager InventoryManager; + private System.Text.Encoding enc = System.Text.Encoding.ASCII; + + public AssetManager(Server serve) + { + server=serve; + Assets=new Dictionary (); + this.initialise(); + } + + public void AddRequest(User_Agent_info user, LLUUID asset_id, TransferRequestPacket tran_req) + { + Console.WriteLine("Asset Request "+ asset_id); + if(!this.Assets.ContainsKey(asset_id)) + { + //not found asset + return; + } + AssetInfo info=this.Assets[asset_id]; + System.Console.WriteLine("send asset : "+asset_id); + //for now as it will be only skin or shape request just send back the asset + TransferInfoPacket Transfer=new TransferInfoPacket(); + Transfer.TransferInfo.ChannelType=2; + Transfer.TransferInfo.Status=0; + Transfer.TransferInfo.TargetType=0; + Transfer.TransferInfo.Params=tran_req.TransferInfo.Params; + Transfer.TransferInfo.Size=info.data.Length; + Transfer.TransferInfo.TransferID=tran_req.TransferInfo.TransferID; + + server.SendPacket(Transfer,true,user); + + TransferPacketPacket tran_p=new TransferPacketPacket(); + tran_p.TransferData.Packet=0; + tran_p.TransferData.ChannelType=2; + tran_p.TransferData.TransferID=tran_req.TransferInfo.TransferID; + if(info.data.Length>1000) //but needs to be less than 2000 at the moment + { + byte[] chunk=new byte[1000]; + Array.Copy(info.data,chunk,1000); + tran_p.TransferData.Data=chunk; + tran_p.TransferData.Status=0; + server.SendPacket(tran_p,true,user); + + tran_p=new TransferPacketPacket(); + tran_p.TransferData.Packet=1; + tran_p.TransferData.ChannelType=2; + tran_p.TransferData.TransferID=tran_req.TransferInfo.TransferID; + byte[] chunk1=new byte[(info.data.Length-1000)]; + Array.Copy(info.data,1000,chunk1,0,chunk1.Length); + tran_p.TransferData.Data=chunk1; + tran_p.TransferData.Status=1; + server.SendPacket(tran_p,true,user); + } + else + { + tran_p.TransferData.Status=1; //last packet? so set to 1 + tran_p.TransferData.Data=info.data; + server.SendPacket(tran_p,true,user); + } + + } + public void CreateNewBaseSet(ref AvatarData Avata,User_Agent_info UserInfo) + { + //LLUUID BaseFolder=new LLUUID("4f5f559e-77a0-a4b9-84f9-8c74c07f7cfc");//*/"4fb2dab6-a987-da66-05ee-96ca82bccbf1"); + //LLUUID BaseFolder=new LLUUID("480e2d92-61f6-9f16-f4f5-0f77cfa4f8f9"); + LLUUID BaseFolder=Avata.BaseFolder; + InventoryManager.CreateNewFolder(UserInfo,Avata.InventoryFolder); + InventoryManager.CreateNewFolder(UserInfo, BaseFolder); + + AssetInfo Base=this.Assets[new LLUUID("66c41e39-38f9-f75a-024e-585989bfab73")]; + AssetInfo Shape=new AssetInfo(); + + Shape.filename=""; + Shape.data=new byte[Base.data.Length]; + Array.Copy(Base.data,Shape.data,Base.data.Length); + Shape.Full_ID=LLUUID.Random(); + Shape.Name="Default Skin"; + Shape.Description="Default"; + Shape.InvType=18; + + Shape.Type=libsecondlife.AssetSystem.ASSET_TYPE_WEARABLE_BODY; + byte[] Agentid=enc.GetBytes(UserInfo.AgentID.ToStringHyphenated()); + Array.Copy(Agentid,0,Shape.data,294,Agentid.Length); + this.Assets.Add(Shape.Full_ID,Shape); + /*FileStream fStream = new FileStream("Assetshape.dat", FileMode.CreateNew); + BinaryWriter bw = new BinaryWriter(fStream); + bw.Write(Shape.data); + bw.Close(); + fStream.Close();*/ + + Avata.Wearables[0].ItemID=InventoryManager.AddToInventory(UserInfo,BaseFolder,Shape); + Avata.Wearables[0].AssetID=Shape.Full_ID; + //Avata.RootFolder=BaseFolder; + + //give test texture + + TextureImage Texture=TextureMan.textures[new LLUUID("00000000-0000-0000-5005-000000000005")]; + InventoryManager.AddToInventory(UserInfo,BaseFolder,Texture); + + } + + private void initialise() + { + //for now read in our test image + AssetInfo im=new AssetInfo(); + im.filename="base_shape.dat"; + im.Full_ID=new LLUUID("66c41e39-38f9-f75a-024e-585989bfab73"); + this.loadAsset(im); + this.Assets.Add(im.Full_ID,im); + + + im=new AssetInfo(); + im.filename="base_skin.dat"; + im.Full_ID=new LLUUID("e0ee49b5a4184df8d3c9a65361fe7f49"); + this.loadAsset(im); + this.Assets.Add(im.Full_ID,im); + } + private void loadAsset(AssetInfo info) + { + //should request Asset from storage manager + //but for now read from file + + string data_path = System.AppDomain.CurrentDomain.BaseDirectory + @"\assets\"; + string filename=data_path+@info.filename; + FileInfo fInfo = new FileInfo(filename); + + long numBytes = fInfo.Length; + + FileStream fStream = new FileStream(filename, FileMode.Open, FileAccess.Read); + byte[] idata=new byte[numBytes]; + BinaryReader br = new BinaryReader(fStream); + idata= br.ReadBytes((int)numBytes); + br.Close(); + fStream.Close(); + info.data=idata; + info.loaded=true; + } + } + + public class AssetRequest + { + public User_Agent_info RequestUser; + public LLUUID RequestImage; + public AssetInfo asset_inf; + public long data_pointer=0; + public int num_packets=0; + public int packet_counter=0; + + public AssetRequest() + { + + } + } + public class AssetInfo:AssetBase + { + //public byte[] data; + //public LLUUID Full_ID; + public string filename; + public bool loaded; + public ulong last_used; //need to add a tick/time counter and keep record + // of how often images are requested to unload unused ones. + + public AssetInfo() + { + + } + } + + public class AssetBase + { + public byte[] data; + public LLUUID Full_ID; + public sbyte Type; + public sbyte InvType; + public string Name; + public string Description; + + public AssetBase() + { + + } + } +} diff --git a/src/Config.cs b/src/Config.cs new file mode 100644 index 0000000..44e0689 --- /dev/null +++ b/src/Config.cs @@ -0,0 +1,140 @@ +/* +Copyright (c) OpenSim project, http://osgrid.org/ + +* Copyright (c) , +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +using System; +using System.Collections.Generic; +using System.IO; +using Db4objects.Db4o; +using libsecondlife; +using OpenSim.world; + +namespace OpenSim +{ + /// + /// This class handles connection to the underlying database used for configuration of the region. + /// Region content is also stored by this class. The main entry point is InitConfig() which attempts to locate + /// opensim.yap in the current working directory. If opensim.yap can not be found, default settings are loaded from + /// what is hardcoded here and then saved into opensim.yap for future startups. + /// + public class SimConfig + { + public string RegionName; + + public uint RegionLocX; + public uint RegionLocY; + public ulong RegionHandle; + + public int IPListenPort; + public string IPListenAddr; + + public string AssetURL; + public string AssetSendKey; + + public string GridURL; + public string GridSendKey; + + private IObjectContainer db; + + public void LoadDefaults() { + this.RegionName = "OpenSim test\0"; + this.RegionLocX = 997; + this.RegionLocY = 996; + this.RegionHandle = Helpers.UIntsToLong((RegionLocX*256), (RegionLocY*256)); + this.IPListenPort = 9000; + this.IPListenAddr = "4.78.190.75"; + this.AssetURL = "http://osgrid.org/ogs/assetserver/"; + this.AssetSendKey = "1234"; + this.GridURL = "http://osgrid.org/ogs/gridserver/"; + this.GridSendKey = "1234"; + } + + public void InitConfig() { + try { + db = Db4oFactory.OpenFile("opensim.yap"); + IObjectSet result = db.Get(typeof(SimConfig)); + if(result.Count==1) { + Console.WriteLine("Config.cs:InitConfig() - Found a SimConfig object in the local database, loading"); + foreach (SimConfig cfg in result) { + this.RegionName = cfg.RegionName; + this.RegionLocX = cfg.RegionLocX; + this.RegionLocY = cfg.RegionLocY; + this.RegionHandle = Helpers.UIntsToLong((RegionLocX*256), (RegionLocY*256)); + this.IPListenPort = cfg.IPListenPort; + this.IPListenAddr = cfg.IPListenAddr; + this.AssetURL = cfg.AssetURL; + this.AssetSendKey = cfg.AssetSendKey; + this.GridURL = cfg.GridURL; + this.GridSendKey = cfg.GridSendKey; + } + } else { + Console.WriteLine("Config.cs:InitConfig() - Could not find object in database, loading precompiled defaults"); + LoadDefaults(); + Console.WriteLine("Writing out default settings to local database"); + db.Set(this); + } + } catch(Exception e) { + db.Close(); + Console.WriteLine("Config.cs:InitConfig() - Exception occured"); + Console.WriteLine(e.ToString()); + } + } + + public World LoadWorld() { + IObjectSet world_result = db.Get(typeof(OpenSim.world.World)); + if(world_result.Count==1) { + Console.WriteLine("Config.cs:LoadWorld() - Found an OpenSim.world.World object in local database, loading"); + return (World)world_result.Next(); + } else { + Console.WriteLine("Config.cs:LoadWorld() - Could not find the world or too many worlds! Constructing blank one"); + World blank = new World(); + Console.WriteLine("Config.cs:LoadWorld() - Saving initial world state to disk"); + db.Set(blank); + db.Commit(); + return blank; + } + } + + public void LoadFromGrid() { + Console.WriteLine("Config.cs:LoadFromGrid() - dummy function, DOING ABSOLUTELY NOTHING AT ALL!!!"); + // TODO: Make this crap work + /* WebRequest GridLogin = WebRequest.Create(this.GridURL + "regions/" + this.RegionHandle.ToString() + "/login"); + WebResponse GridResponse = GridLogin.GetResponse(); + byte[] idata = new byte[(int)GridResponse.ContentLength]; + BinaryReader br = new BinaryReader(GridResponse.GetResponseStream()); + + br.Close(); + GridResponse.Close(); + */ + } + + public void Shutdown() { + db.Close(); + } + } +} diff --git a/src/GridManager.cs b/src/GridManager.cs new file mode 100644 index 0000000..3d3b35d --- /dev/null +++ b/src/GridManager.cs @@ -0,0 +1,372 @@ +/* +Copyright (c) OpenSim project, http://osgrid.org/ + +* Copyright (c) , +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +using System; +using System.Collections.Generic; +using libsecondlife; +using System.Collections; +using libsecondlife.Packets; +using libsecondlife.AssetSystem; +using System.IO; +using System.Xml; + + +namespace OpenSim +{ + /// + /// Description of GridManager. + /// + public class GridManager + { + private Server _server; + private System.Text.Encoding _enc = System.Text.Encoding.ASCII; + private AgentManager _agentManager; + public Dictionary Grid; + + /// + /// + /// + /// + /// + public GridManager(Server server, AgentManager agentManager) + { + Grid = new Dictionary(); + _server = server; + _agentManager = agentManager; + LoadGrid(); + } + + /// + /// + /// + /// + public void RequestMapLayer(UserAgentInfo userInfo) + { + //send a layer covering the 800,800 - 1200,1200 area + MapLayerReplyPacket MapReply = new MapLayerReplyPacket(); + MapReply.AgentData.AgentID = userInfo.AgentID; + MapReply.AgentData.Flags = 0; + MapReply.LayerData = new MapLayerReplyPacket.LayerDataBlock[1]; + MapReply.LayerData[0] = new MapLayerReplyPacket.LayerDataBlock(); + MapReply.LayerData[0].Bottom = 800; + MapReply.LayerData[0].Left = 800; + MapReply.LayerData[0].Top = 1200; + MapReply.LayerData[0].Right = 1200; + MapReply.LayerData[0].ImageID = new LLUUID("00000000-0000-0000-7007-000000000006"); + _server.SendPacket(MapReply, true, userInfo); + } + + /// + /// + /// + /// + /// + /// + /// + /// + public void RequestMapBlock(UserAgentInfo userInfo, int minX, int minY,int maxX,int maxY) + { + foreach (KeyValuePair RegionPair in this.Grid) + { + //check Region is inside the requested area + RegionInfo Region = RegionPair.Value; + if(((Region.X > minX) && (Region.X < maxX)) && ((Region.Y > minY) && (Region.Y < maxY))) + { + MapBlockReplyPacket MapReply = new MapBlockReplyPacket(); + MapReply.AgentData.AgentID = userInfo.AgentID; + MapReply.AgentData.Flags = 0; + MapReply.Data = new MapBlockReplyPacket.DataBlock[1]; + MapReply.Data[0] = new MapBlockReplyPacket.DataBlock(); + MapReply.Data[0].MapImageID = Region.ImageID; + MapReply.Data[0].X = Region.X; + MapReply.Data[0].Y = Region.Y; + MapReply.Data[0].WaterHeight = Region.WaterHeight; + MapReply.Data[0].Name = _enc.GetBytes( Region.Name); + MapReply.Data[0].RegionFlags = 72458694; + MapReply.Data[0].Access = 13; + MapReply.Data[0].Agents = 1; + _server.SendPacket(MapReply, true, userInfo); + } + } + + } + + /// + /// + /// + /// + /// + public void RequestTeleport(UserAgentInfo userInfo, TeleportLocationRequestPacket request) + { + if(Grid.ContainsKey(request.Info.RegionHandle)) + { + RegionInfo Region = Grid[request.Info.RegionHandle]; + libsecondlife.Packets.TeleportStartPacket TeleportStart = new TeleportStartPacket(); + TeleportStart.Info.TeleportFlags = 16; + _server.SendPacket(TeleportStart, true, userInfo); + + libsecondlife.Packets.TeleportFinishPacket Teleport = new TeleportFinishPacket(); + Teleport.Info.AgentID = userInfo.AgentID; + Teleport.Info.RegionHandle = request.Info.RegionHandle; + Teleport.Info.SimAccess = 13; + Teleport.Info.SeedCapability = new byte[0]; + + System.Net.IPAddress oIP = System.Net.IPAddress.Parse(Region.IPAddress.Address); + byte[] byteIP = oIP.GetAddressBytes(); + uint ip=(uint)byteIP[3]<<24; + ip+=(uint)byteIP[2]<<16; + ip+=(uint)byteIP[1]<<8; + ip+=(uint)byteIP[0]; + + Teleport.Info.SimIP = ip; + Teleport.Info.SimPort = Region.IPAddress.Port; + Teleport.Info.LocationID = 4; + Teleport.Info.TeleportFlags = 1 << 4;; + _server.SendPacket(Teleport, true, userInfo); + + this._agentManager.RemoveAgent(userInfo); + } + + } + + /// + /// + /// + private void LoadGrid() + { + //should connect to a space server to see what grids there are + //but for now we read static xml files + ulong CurrentHandle = 0; + bool Login = true; + + XmlDocument doc = new XmlDocument(); + + try { + doc.Load(Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, "Grid.ini" )); + } + catch ( Exception e) + { + Console.WriteLine(e.Message); + return; + } + + try + { + XmlNode root = doc.FirstChild; + if (root.Name != "Root") + throw new Exception("Error: Invalid File. Missing "); + + XmlNode nodes = root.FirstChild; + if (nodes.Name != "Grid") + throw new Exception("Error: Invalid File. first child should be "); + + if (nodes.HasChildNodes) { + foreach( XmlNode xmlnc in nodes.ChildNodes) + { + if(xmlnc.Name == "Region") + { + string xmlAttri; + RegionInfo Region = new RegionInfo(); + if(xmlnc.Attributes["Name"] != null) + { + xmlAttri = ((XmlAttribute)xmlnc.Attributes.GetNamedItem("Name")).Value; + Region.Name = xmlAttri+" \0"; + } + if(xmlnc.Attributes["ImageID"] != null) + { + xmlAttri = ((XmlAttribute)xmlnc.Attributes.GetNamedItem("ImageID")).Value; + Region.ImageID = new LLUUID(xmlAttri); + } + if(xmlnc.Attributes["IP_Address"] != null) + { + xmlAttri = ((XmlAttribute)xmlnc.Attributes.GetNamedItem("IP_Address")).Value; + Region.IPAddress.Address = xmlAttri; + } + if(xmlnc.Attributes["IP_Port"] != null) + { + xmlAttri = ((XmlAttribute)xmlnc.Attributes.GetNamedItem("IP_Port")).Value; + Region.IPAddress.Port = Convert.ToUInt16(xmlAttri); + } + if(xmlnc.Attributes["Location_X"] != null) + { + xmlAttri = ((XmlAttribute)xmlnc.Attributes.GetNamedItem("Location_X")).Value; + Region.X = Convert.ToUInt16(xmlAttri); + } + if(xmlnc.Attributes["Location_Y"] != null) + { + xmlAttri = ((XmlAttribute)xmlnc.Attributes.GetNamedItem("Location_Y")).Value; + Region.Y = Convert.ToUInt16(xmlAttri); + } + + this.Grid.Add(Region.Handle, Region); + + } + if(xmlnc.Name == "CurrentRegion") + { + + string xmlAttri; + uint Rx = 0, Ry = 0; + if(xmlnc.Attributes["RegionHandle"] != null) + { + xmlAttri = ((XmlAttribute)xmlnc.Attributes.GetNamedItem("RegionHandle")).Value; + CurrentHandle = Convert.ToUInt64(xmlAttri); + + } + else + { + if(xmlnc.Attributes["Region_X"] != null) + { + xmlAttri = ((XmlAttribute)xmlnc.Attributes.GetNamedItem("Region_X")).Value; + Rx = Convert.ToUInt32(xmlAttri); + } + if(xmlnc.Attributes["Region_Y"] != null) + { + xmlAttri = ((XmlAttribute)xmlnc.Attributes.GetNamedItem("Region_Y")).Value; + Ry = Convert.ToUInt32(xmlAttri); + } + } + if(xmlnc.Attributes["LoginServer"] != null) + { + xmlAttri = ((XmlAttribute)xmlnc.Attributes.GetNamedItem("LoginServer")).Value; + Login = Convert.ToBoolean(xmlAttri); + + } + if(CurrentHandle == 0) + { + //no RegionHandle set + //so check for Region X and Y + if((Rx > 0) && (Ry > 0)) + { + CurrentHandle = Helpers.UIntsToLong((Rx*256), (Ry*256)); + } + else + { + //seems to be no Region location set + // so set default + CurrentHandle = 1096213093147648; + } + } + } + } + + //finished loading grid, now set Globals to current region + if(CurrentHandle != 0) + { + if(Grid.ContainsKey(CurrentHandle)) + { + RegionInfo Region = Grid[CurrentHandle]; + Globals.Instance.RegionHandle = Region.Handle; + Globals.Instance.RegionName = Region.Name; + Globals.Instance.IpPort = Region.IPAddress.Port; + Globals.Instance.LoginSever = Login; + } + } + + } + } + catch ( Exception e) + { + Console.WriteLine(e.Message); + return; + } + } + } + + public class RegionInfo + { + public RegionIP IPAddress; + public string Name; + public ushort x; + public ushort y; + public ulong handle; + public LLUUID ImageID; + public uint Flags; + public byte WaterHeight; + + public ushort X + { + get + { + return(x); + } + set + { + x = value; + Handle = Helpers.UIntsToLong((((uint)x)*256), (((uint)y)*256)); + } + } + public ushort Y + { + get + { + return(y); + } + set + { + y = value; + Handle = Helpers.UIntsToLong((((uint)x)*256), (((uint)y)*256)); + } + } + public ulong Handle + { + get + { + if(handle > 0) + { + return(handle); + } + else + { + return(Helpers.UIntsToLong((((uint)x)*256), (((uint)y)*256))); + } + } + set + { + handle = value; + } + + } + + public RegionInfo() + { + this.IPAddress = new RegionIP(); + } + } + public class RegionIP + { + public string Address; + public ushort Port; + + public RegionIP() + { + + } + + } +} diff --git a/src/InventoryManager.cs b/src/InventoryManager.cs new file mode 100644 index 0000000..1df55a3 --- /dev/null +++ b/src/InventoryManager.cs @@ -0,0 +1,242 @@ +/* +Copyright (c) OpenSim project, http://osgrid.org/ + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using libsecondlife; +using libsecondlife.Packets; +using libsecondlife.AssetSystem; +using System.IO; + +namespace OpenSim +{ + /// + /// Description of InventoryManager. + /// + public class InventoryManager + { + + public Dictionary Folders; + public Dictionary Items; + private Server _server; + private System.Text.Encoding _enc = System.Text.Encoding.ASCII; + private const uint FULL_MASK_PERMISSIONS = 2147483647; + + /// + /// + /// + /// + public InventoryManager(Server server) + { + _server = server; + Folders=new Dictionary(); + Items=new Dictionary(); + } + + /// + /// + /// + /// + /// + /// + /// + public LLUUID AddToInventory(UserAgentInfo userInfo, LLUUID folderID, AssetBase asset) + { + if(this.Folders.ContainsKey(folderID)) + { + LLUUID NewItemID = LLUUID.Random(); + + InventoryItem Item = new InventoryItem(); + Item.FolderID = folderID; + Item.OwnerID = userInfo.AgentID; + Item.AssetID = asset.FullID; + Item.ItemID = NewItemID; + Item.Type = asset.Type; + Item.Name = asset.Name; + Item.Description = asset.Description; + Item.InvType = asset.InvType; + this.Items.Add(Item.ItemID, Item); + InventoryFolder Folder = Folders[Item.FolderID]; + Folder.Items.Add(Item); + return(Item.ItemID); + } + else + { + return(null); + } + } + + /// + /// + /// + /// + /// + /// + public bool CreateNewFolder(UserAgentInfo userInfo, LLUUID newFolder) + { + InventoryFolder Folder = new InventoryFolder(); + Folder.FolderID = newFolder; + Folder.OwnerID = userInfo.AgentID; + this.Folders.Add(Folder.FolderID, Folder); + + return(true); + } + + /// + /// + /// + /// + /// + public void FetchInventoryDescendents(UserAgentInfo userInfo, FetchInventoryDescendentsPacket FetchDescend) + { + if(FetchDescend.InventoryData.FetchItems) + { + if(this.Folders.ContainsKey(FetchDescend.InventoryData.FolderID)) + { + + InventoryFolder Folder = this.Folders[FetchDescend.InventoryData.FolderID]; + InventoryDescendentsPacket Descend = new InventoryDescendentsPacket(); + Descend.AgentData.AgentID = userInfo.AgentID; + Descend.AgentData.OwnerID = Folder.OwnerID; + Descend.AgentData.FolderID = FetchDescend.InventoryData.FolderID; + Descend.AgentData.Descendents = Folder.Items.Count; + Descend.AgentData.Version = Folder.Items.Count; + + Descend.ItemData = new InventoryDescendentsPacket.ItemDataBlock[Folder.Items.Count]; + for(int i = 0; i < Folder.Items.Count ; i++) + { + + InventoryItem Item=Folder.Items[i]; + Descend.ItemData[i] = new InventoryDescendentsPacket.ItemDataBlock(); + Descend.ItemData[i].ItemID = Item.ItemID; + Descend.ItemData[i].AssetID = Item.AssetID; + Descend.ItemData[i].CreatorID = Item.CreatorID; + Descend.ItemData[i].BaseMask = FULL_MASK_PERMISSIONS; + Descend.ItemData[i].CreationDate = 1000; + Descend.ItemData[i].Description = _enc.GetBytes(Item.Description+"\0"); + Descend.ItemData[i].EveryoneMask = FULL_MASK_PERMISSIONS; + Descend.ItemData[i].Flags = 1; + Descend.ItemData[i].FolderID = Item.FolderID; + Descend.ItemData[i].GroupID = new LLUUID("00000000-0000-0000-0000-000000000000"); + Descend.ItemData[i].GroupMask = FULL_MASK_PERMISSIONS; + Descend.ItemData[i].InvType = Item.InvType; + Descend.ItemData[i].Name = _enc.GetBytes(Item.Name+"\0"); + Descend.ItemData[i].NextOwnerMask = FULL_MASK_PERMISSIONS; + Descend.ItemData[i].OwnerID = Item.OwnerID; + Descend.ItemData[i].OwnerMask = FULL_MASK_PERMISSIONS; + Descend.ItemData[i].SalePrice = 100; + Descend.ItemData[i].SaleType = 0; + Descend.ItemData[i].Type = Item.Type; + Descend.ItemData[i].CRC=libsecondlife.Helpers.InventoryCRC(1000, 0, Descend.ItemData[i].InvType, Descend.ItemData[i].Type, Descend.ItemData[i].AssetID, Descend.ItemData[i].GroupID, 100, Descend.ItemData[i].OwnerID, Descend.ItemData[i].CreatorID, Descend.ItemData[i].ItemID, Descend.ItemData[i].FolderID, FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS); + } + _server.SendPacket(Descend, true, userInfo); + + } + } + else + { + Console.WriteLine("fetch subfolders"); + } + } + + /// + /// + /// + /// + public void FetchInventory(UserAgentInfo userInfo, FetchInventoryPacket FetchItems) + { + + for(int i = 0; i < FetchItems.InventoryData.Length; i++) + { + if(this.Items.ContainsKey(FetchItems.InventoryData[i].ItemID)) + { + + InventoryItem Item = Items[FetchItems.InventoryData[i].ItemID]; + FetchInventoryReplyPacket InventoryReply = new FetchInventoryReplyPacket(); + InventoryReply.AgentData.AgentID = userInfo.AgentID; + InventoryReply.InventoryData = new FetchInventoryReplyPacket.InventoryDataBlock[1]; + InventoryReply.InventoryData[0] = new FetchInventoryReplyPacket.InventoryDataBlock(); + InventoryReply.InventoryData[0].ItemID = Item.ItemID; + InventoryReply.InventoryData[0].AssetID = Item.AssetID; + InventoryReply.InventoryData[0].CreatorID = Item.CreatorID; + InventoryReply.InventoryData[0].BaseMask = FULL_MASK_PERMISSIONS; + InventoryReply.InventoryData[0].CreationDate = 1000; + InventoryReply.InventoryData[0].Description = _enc.GetBytes( Item.Description+"\0"); + InventoryReply.InventoryData[0].EveryoneMask = FULL_MASK_PERMISSIONS; + InventoryReply.InventoryData[0].Flags = 1; + InventoryReply.InventoryData[0].FolderID = Item.FolderID; + InventoryReply.InventoryData[0].GroupID = new LLUUID("00000000-0000-0000-0000-000000000000"); + InventoryReply.InventoryData[0].GroupMask = FULL_MASK_PERMISSIONS; + InventoryReply.InventoryData[0].InvType = Item.InvType; + InventoryReply.InventoryData[0].Name = _enc.GetBytes(Item.Name+"\0"); + InventoryReply.InventoryData[0].NextOwnerMask = FULL_MASK_PERMISSIONS; + InventoryReply.InventoryData[0].OwnerID = Item.OwnerID; + InventoryReply.InventoryData[0].OwnerMask = FULL_MASK_PERMISSIONS; + InventoryReply.InventoryData[0].SalePrice = 100; + InventoryReply.InventoryData[0].SaleType = 0; + InventoryReply.InventoryData[0].Type = Item.Type; + InventoryReply.InventoryData[0].CRC = libsecondlife.Helpers.InventoryCRC(1000, 0, InventoryReply.InventoryData[0].InvType, InventoryReply.InventoryData[0].Type, InventoryReply.InventoryData[0].AssetID, InventoryReply.InventoryData[0].GroupID, 100, InventoryReply.InventoryData[0].OwnerID, InventoryReply.InventoryData[0].CreatorID, InventoryReply.InventoryData[0].ItemID, InventoryReply.InventoryData[0].FolderID, FULL_MASK_PERMISSIONS, 1, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS, FULL_MASK_PERMISSIONS); + _server.SendPacket(InventoryReply, true, userInfo); + } + } + } + } + + public class InventoryFolder + { + public List Items; + //public List Subfolders; + + public LLUUID FolderID; + public LLUUID OwnerID; + public LLUUID ParentID; + + + public InventoryFolder() + { + Items = new List(); + } + + } + + public class InventoryItem + { + public LLUUID FolderID; + public LLUUID OwnerID; + public LLUUID ItemID; + public LLUUID AssetID; + public LLUUID CreatorID = LLUUID.Zero; + public sbyte InvType; + public sbyte Type; + public string Name; + public string Description; + + public InventoryItem() + { + + } + } +} diff --git a/src/Login_manager.cs b/src/Login_manager.cs new file mode 100644 index 0000000..dd741f5 --- /dev/null +++ b/src/Login_manager.cs @@ -0,0 +1,228 @@ +/* +* Copyright (c) OpenSim project, http://osgrid.org/> +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ +using Nwc.XmlRpc; +using System; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using System.Collections; +using System.Xml; +using libsecondlife; + +namespace OpenSim +{ + /// + /// Description of Login_manager. + /// + public class LoginManager + { + public LoginManager(Logon login) + { + Login=login; + } + public Logon Login; + public ushort loginPort = Globals.Instance.LoginServerPort; + public IPAddress clientAddress = IPAddress.Loopback; + public IPAddress remoteAddress = IPAddress.Any; + private Socket loginServer; + private Random RandomClass = new Random(); + private int NumClients; + + // InitializeLoginProxy: initialize the login proxy + private void InitializeLoginProxy() { + loginServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); + loginServer.Bind(new IPEndPoint(remoteAddress, loginPort)); + loginServer.Listen(1); + } + + public void Startup() + { + this.InitializeLoginProxy(); + Thread runLoginProxy = new Thread(new ThreadStart(RunLoginProxy)); + runLoginProxy.IsBackground = true; + runLoginProxy.Start(); + } + + private void RunLoginProxy() + { + try + { + for (;;) + { + Socket client = loginServer.Accept(); + IPEndPoint clientEndPoint = (IPEndPoint)client.RemoteEndPoint; + + + NetworkStream networkStream = new NetworkStream(client); + StreamReader networkReader = new StreamReader(networkStream); + StreamWriter networkWriter = new StreamWriter(networkStream); + + try + { + ProxyLogin(networkReader, networkWriter); + } + catch (Exception e) + { + Console.WriteLine(e.Message); + } + + networkWriter.Close(); + networkReader.Close(); + networkStream.Close(); + + client.Close(); + + // send any packets queued for injection + + } + } + catch (Exception e) + { + Console.WriteLine(e.Message); + Console.WriteLine(e.StackTrace); + } + } + + // ProxyLogin: proxy a login request + private void ProxyLogin(StreamReader reader, StreamWriter writer) { lock(this) { + string line; + int contentLength = 0; + + // read HTTP header + do + { + // read one line of the header + line = reader.ReadLine(); + + // check for premature EOF + if (line == null) + throw new Exception("EOF in client HTTP header"); + + // look for Content-Length + Match match = (new Regex(@"Content-Length: (\d+)$")).Match(line); + if (match.Success) + contentLength = Convert.ToInt32(match.Groups[1].Captures[0].ToString()); + } while (line != ""); + + // read the HTTP body into a buffer + char[] content = new char[contentLength]; + reader.Read(content, 0, contentLength); + //System.Text.Encoding enc = System.Text.Encoding.ASCII; + XmlRpcRequest request = (XmlRpcRequest)(new XmlRpcRequestDeserializer()).Deserialize(new String(content)); + Hashtable requestData = (Hashtable)request.Params[0]; + + string first; + string last; + LLUUID Agent; + LLUUID Session; + + //get login name + if(requestData.Contains("first")) + { + first = (string)requestData["first"]; + } + else + { + first = "test"; + } + if(requestData.Contains("last")) + { + last = (string)requestData["last"]; + } + else + { + last = "User"+NumClients.ToString(); + } + NumClients++; + + //create a agent and session LLUUID + int AgentRand = this.RandomClass.Next(1,9999); + Agent = new LLUUID("99998888-"+AgentRand.ToString("0000")+"-4f52-8ec1-0b1d5cd6aead"); + int SessionRand = this.RandomClass.Next(1,999); + Session = new LLUUID("aaaabbbb-8932-"+SessionRand.ToString("0000")+"-8664-58f53e442797"); + + + StreamReader SR; + string ResponseString = ""; + string lines; + SR=File.OpenText("new-login.dat"); + + lines=SR.ReadLine(); + + while(lines != "end-mfile") + { + + ResponseString += lines; + lines = SR.ReadLine(); + } + SR.Close(); + + XmlRpcResponse response =(XmlRpcResponse)(new XmlRpcResponseDeserializer()).Deserialize(ResponseString); + Hashtable responseData = (Hashtable)response.Value; + + responseData["agent_id"] = Agent.ToStringHyphenated(); + responseData["session_id"] = Session.ToStringHyphenated(); + ArrayList InventoryList = (ArrayList) responseData["inventory-skeleton"]; + Hashtable Inventory1 = (Hashtable)InventoryList[0]; + Hashtable Inventory2 = (Hashtable)InventoryList[1]; + LLUUID BaseFolderID = LLUUID.Random(); + LLUUID InventoryFolderID = LLUUID.Random(); + Inventory2["name"] = "Base"; + Inventory2["folder_id"] = BaseFolderID.ToStringHyphenated(); + Inventory1["folder_id"] = InventoryFolderID.ToStringHyphenated(); + + ArrayList InventoryRoot = (ArrayList) responseData["inventory-root"]; + Hashtable Inventoryroot = (Hashtable)InventoryRoot[0]; + Inventoryroot["folder_id"] = InventoryFolderID.ToStringHyphenated(); + + + //copy data to login object + lock(Login) + { + Login.First = first; + Login.Last = last; + Login.Agent = Agent; + Login.Session = Session; + Login.BaseFolder = BaseFolderID; + Login.InventoryFolder = InventoryFolderID; + } + + // forward the XML-RPC response to the client + writer.WriteLine("HTTP/1.0 200 OK"); + writer.WriteLine("Content-type: text/xml"); + writer.WriteLine(); + + XmlTextWriter responseWriter = new XmlTextWriter(writer); + XmlRpcResponseSerializer.Singleton.Serialize(responseWriter, response); + responseWriter.Close(); + } + } + } +} diff --git a/src/Main.cs b/src/Main.cs new file mode 100644 index 0000000..da926db --- /dev/null +++ b/src/Main.cs @@ -0,0 +1,138 @@ +/* +Copyright (c) OpenSim project, http://osgrid.org/ + + +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +using System; +using System.Text; +using System.IO; +using System.Threading; +using System.Net; +using System.Net.Sockets; +using System.Collections; +using System.Collections.Generic; +using libsecondlife; +using libsecondlife.Packets; +using OpenSim.world; + +namespace OpenSim +{ + /// + /// Description of MainForm. + /// + public class OpenSim_Main + { + private static OpenSim_Main sim; + public static SimConfig cfg; + public static World local_world; + private static Thread MainListener; + private static Thread PingRespponder; + public static Socket Server; + private static IPEndPoint ServerIncoming; + private static byte[] RecvBuffer = new byte[4096]; + private byte[] ZeroBuffer = new byte[8192]; + private static IPEndPoint ipeSender; + private static EndPoint epSender; + private static AsyncCallback ReceivedData; + public Dictionary ClientThreads = new Dictionary(); + + [STAThread] + public static void Main( string[] args ) + { + Console.WriteLine("OpenSim " + VersionInfo.Version + "\n"); + Console.WriteLine("Starting...\n"); + sim = new OpenSim_Main(); + sim.Startup(); + while(true) { + Thread.Sleep(1000); + } + } + + private OpenSim_Main() { + } + + private void Startup() { + // We check our local database first, then the grid for config options + Console.WriteLine("Main.cs:Startup() - Loading configuration"); + cfg = new SimConfig(); + cfg.InitConfig(); + Console.WriteLine("Main.cs:Startup() - Contacting gridserver"); + cfg.LoadFromGrid(); + + Console.WriteLine("Main.cs:Startup() - We are " + cfg.RegionName + " at " + cfg.RegionLocX.ToString() + "," + cfg.RegionLocY.ToString()); + Console.WriteLine("Initialising world"); + local_world = cfg.LoadWorld(); + + Console.WriteLine("Main.cs:Startup() - Starting up messaging system"); + MainListener = new Thread(new ThreadStart(MainServerListener)); + MainListener.Start(); + + } + + private void OnReceivedData(IAsyncResult result) { + ipeSender = new IPEndPoint(IPAddress.Any, 0); + epSender = (EndPoint)ipeSender; + Packet packet = null; + int numBytes = Server.EndReceiveFrom(result, ref epSender); + int packetEnd = numBytes - 1; + packet = Packet.BuildPacket(RecvBuffer, ref packetEnd, ZeroBuffer); + Console.Error.WriteLine(packet.ToString()); + + // This is either a new client or a packet to send to an old one + if(ClientThreads.ContainsKey(epSender)) { + ClientThreads[epSender].InPacket(packet); + } else if( packet.Type == PacketType.UseCircuitCode ) { // new client + OpenSimClient newuser = new OpenSimClient(epSender,(UseCircuitCodePacket)packet); + ClientThreads.Add(epSender, newuser); + } else { // invalid client + Console.Error.WriteLine("Main.cs:OnReceivedData() - WARNING: Got a packet from an invalid client - " + epSender.ToString()); + } + Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null); + } + + private void MainServerListener() { + Console.WriteLine("Main.cs:MainServerListener() - New thread started"); + Console.WriteLine("Main.cs:MainServerListener() - Opening UDP socket on " + cfg.IPListenAddr + ":" + cfg.IPListenPort); + + ServerIncoming = new IPEndPoint(IPAddress.Parse(cfg.IPListenAddr),cfg.IPListenPort); + Server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + Server.Bind(ServerIncoming); + + Console.WriteLine("Main.cs:MainServerListener() - UDP socket bound, getting ready to listen"); + + ipeSender = new IPEndPoint(IPAddress.Any, 0); + epSender = (EndPoint) ipeSender; + ReceivedData = new AsyncCallback(this.OnReceivedData); + Server.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null); + + Console.WriteLine("Main.cs:MainServerListener() - Listening..."); + while(true) { + Thread.Sleep(1000); + } + } + } +} diff --git a/src/OpenSimClient.cs b/src/OpenSimClient.cs new file mode 100644 index 0000000..d3f90b7 --- /dev/null +++ b/src/OpenSimClient.cs @@ -0,0 +1,339 @@ +/* +Copyright (c) OpenSim project, http://osgrid.org/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +using System; +using System.Collections; +using System.Collections.Generic; +using libsecondlife; +using libsecondlife.Packets; +using System.Net; +using System.Net.Sockets; +using System.IO; +using System.Threading; +using System.Timers; + +namespace OpenSim +{ + /// + /// Handles new client connections + /// Constructor takes a single Packet and authenticates everything + /// + public class OpenSimClient { + + public LLUUID AgentID; + public LLUUID SessionID; + public uint CircuitCode; + public world.Avatar ClientAvatar; + private UseCircuitCodePacket cirpack; + private Thread ClientThread; + private EndPoint userEP; + private BlockingQueue PacketQueue; + private Dictionary PendingAcks = new Dictionary(); + private Dictionary NeedAck = new Dictionary(); + private System.Timers.Timer AckTimer; + private uint Sequence = 0; + private object SequenceLock = new object(); + private const int MAX_APPENDED_ACKS = 10; + private const int RESEND_TIMEOUT = 4000; + private const int MAX_SEQUENCE = 0xFFFFFF; + + public void ack_pack(Packet Pack) { + //libsecondlife.Packets.PacketAckPacket ack_it = new PacketAckPacket(); + //ack_it.Packets = new PacketAckPacket.PacketsBlock[1]; + //ack_it.Packets[0] = new PacketAckPacket.PacketsBlock(); + //ack_it.Packets[0].ID = Pack.Header.ID; + //ack_it.Header.Reliable = false; + + //OutPacket(ack_it); + + if (Pack.Header.Reliable) { + lock (PendingAcks) { + uint sequence = (uint)Pack.Header.Sequence; + if (!PendingAcks.ContainsKey(sequence)) { PendingAcks[sequence] = sequence; } + } + } + } + + public void ProcessInPacket(Packet Pack) { + ack_pack(Pack); + switch(Pack.Type) { + case PacketType.CompleteAgentMovement: + ClientAvatar.CompleteMovement(OpenSim_Main.local_world); + break; + } + } + + private void ResendUnacked() + { + int now = Environment.TickCount; + + lock (NeedAck) + { + foreach (Packet packet in NeedAck.Values) + { + if (now - packet.TickCount > RESEND_TIMEOUT) + { + Console.WriteLine("Resending " + packet.Type.ToString() + " packet, " + + (now - packet.TickCount) + "ms have passed", Helpers.LogLevel.Info); + + packet.Header.Resent = true; + OutPacket(packet); + } + } + } + } + + private void SendAcks() + { + lock (PendingAcks) + { + if (PendingAcks.Count > 0) + { + if (PendingAcks.Count > 250) + { + // FIXME: Handle the odd case where we have too many pending ACKs queued up + Console.WriteLine("Too many ACKs queued up!", Helpers.LogLevel.Error); + return; + } + + Console.WriteLine("Sending PacketAck"); + + + int i = 0; + PacketAckPacket acks = new PacketAckPacket(); + acks.Packets = new PacketAckPacket.PacketsBlock[PendingAcks.Count]; + + foreach (uint ack in PendingAcks.Values) + { + acks.Packets[i] = new PacketAckPacket.PacketsBlock(); + acks.Packets[i].ID = ack; + i++; + } + + acks.Header.Reliable = false; + OutPacket(acks); + + PendingAcks.Clear(); + } + } + } + + private void AckTimer_Elapsed(object sender, ElapsedEventArgs ea) + { + SendAcks(); ResendUnacked(); + } + + public void ProcessOutPacket(Packet Pack) { + + // Keep track of when this packet was sent out + Pack.TickCount = Environment.TickCount; + + if (!Pack.Header.Resent) + { + // Set the sequence number + lock (SequenceLock) + { + if (Sequence >= MAX_SEQUENCE) + Sequence = 1; + else + Sequence++; + Pack.Header.Sequence = Sequence; + } + + if (Pack.Header.Reliable) + { + lock (NeedAck) + { + if (!NeedAck.ContainsKey(Pack.Header.Sequence)) + { + NeedAck.Add(Pack.Header.Sequence, Pack); + } + else + { + // Client.Log("Attempted to add a duplicate sequence number (" + + // packet.Header.Sequence + ") to the NeedAck dictionary for packet type " + + // packet.Type.ToString(), Helpers.LogLevel.Warning); + } + } + + // Don't append ACKs to resent packets, in case that's what was causing the + // delivery to fail + if (!Pack.Header.Resent) + { + // Append any ACKs that need to be sent out to this packet + lock (PendingAcks) + { + if (PendingAcks.Count > 0 && PendingAcks.Count < MAX_APPENDED_ACKS && + Pack.Type != PacketType.PacketAck && + Pack.Type != PacketType.LogoutRequest) + { + Pack.Header.AckList = new uint[PendingAcks.Count]; + int i = 0; + + foreach (uint ack in PendingAcks.Values) + { + Pack.Header.AckList[i] = ack; + i++; + } + + PendingAcks.Clear(); + Pack.Header.AppendedAcks = true; + } + } + } + } + } + + Console.WriteLine("OUT: \n" + Pack.ToString()); + + byte[] ZeroOutBuffer = new byte[4096]; + byte[] sendbuffer; + sendbuffer = Pack.ToBytes(); + + try { + if (Pack.Header.Zerocoded) { + int packetsize = Helpers.ZeroEncode(sendbuffer, sendbuffer.Length, ZeroOutBuffer); + OpenSim_Main.Server.SendTo(ZeroOutBuffer, packetsize, SocketFlags.None,userEP); + } else { + OpenSim_Main.Server.SendTo(sendbuffer, sendbuffer.Length, SocketFlags.None,userEP); + } + } catch (Exception) { + Console.WriteLine("OpenSimClient.cs:ProcessOutPacket() - WARNING: Socket exception occurred on connection " + userEP.ToString() + " - killing thread"); + ClientThread.Abort(); + } + + } + + public void InPacket(Packet NewPack) { + // Handle appended ACKs + if (NewPack.Header.AppendedAcks) + { + lock (NeedAck) + { + foreach (uint ack in NewPack.Header.AckList) + { + NeedAck.Remove(ack); + } + } + } + + // Handle PacketAck packets + if (NewPack.Type == PacketType.PacketAck) + { + PacketAckPacket ackPacket = (PacketAckPacket)NewPack; + + lock (NeedAck) + { + foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets) + { + NeedAck.Remove(block.ID); + } + } + } else if( ( NewPack.Type == PacketType.StartPingCheck ) ) { + //reply to pingcheck + libsecondlife.Packets.StartPingCheckPacket startPing = (libsecondlife.Packets.StartPingCheckPacket)NewPack; + libsecondlife.Packets.CompletePingCheckPacket endPing = new CompletePingCheckPacket(); + endPing.PingID.PingID = startPing.PingID.PingID; + OutPacket(endPing); + } + else + { + QueItem item = new QueItem(); + item.Packet = NewPack; + item.Incoming = true; + this.PacketQueue.Enqueue(item); + } + + } + + public void OutPacket(Packet NewPack) { + QueItem item = new QueItem(); + item.Packet = NewPack; + item.Incoming = false; + this.PacketQueue.Enqueue(item); + } + + public OpenSimClient(EndPoint remoteEP, UseCircuitCodePacket initialcirpack) { + Console.WriteLine("OpenSimClient.cs - Started up new client thread to handle incoming request"); + cirpack = initialcirpack; + userEP = remoteEP; + PacketQueue = new BlockingQueue(); + AckTimer = new System.Timers.Timer(500); + AckTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed); + AckTimer.Start(); + + Thread ClientThread = new Thread(new ThreadStart(AuthUser)); + ClientThread.IsBackground = true; + ClientThread.Start(); + } + + private void ClientLoop() { + Console.WriteLine("OpenSimClient.cs:ClientLoop() - Entered loop"); + while(true) { + QueItem nextPacket = PacketQueue.Dequeue(); + if(nextPacket.Incoming) + { + //is a incoming packet + ProcessInPacket(nextPacket.Packet); + } + else + { + //is a out going packet + ProcessOutPacket(nextPacket.Packet); + } + } + } + + private void InitNewClient() { + Console.WriteLine("OpenSimClient.cs:InitNewClient() - Adding viewer agent to world"); + OpenSim_Main.local_world.AddViewerAgent(this); + world.Entity tempent=OpenSim_Main.local_world.Entities[this.AgentID]; + this.ClientAvatar=(world.Avatar)tempent; + } + + private void AuthUser() { + Console.WriteLine("OpenSimClient.cs:AuthUser() - Authenticating new user request with grid"); + WebRequest CheckSession = WebRequest.Create(OpenSim_Main.cfg.GridURL + "/usersessions/" + OpenSim_Main.cfg.GridSendKey + "/" + cirpack.CircuitCode.ID.ToString() + "/" + cirpack.CircuitCode.Code.ToString() + "/exists"); + WebResponse GridResponse = CheckSession.GetResponse(); + StreamReader sr = new StreamReader(GridResponse.GetResponseStream()); + String grTest = sr.ReadLine(); + sr.Close(); + GridResponse.Close(); + if(grTest.Equals("1")) { // YAY! Valid login + Console.WriteLine("OpenSimClient.cs:AuthUser() - Got authenticated connection from " + userEP.ToString()); + this.AgentID=cirpack.CircuitCode.ID; + this.SessionID=cirpack.CircuitCode.SessionID; + this.CircuitCode=cirpack.CircuitCode.Code; + InitNewClient(); + ClientLoop(); + } else { // Invalid + Console.WriteLine("OpenSimClient.cs:AuthUser() - New user request denied to " + userEP.ToString()); + ClientThread.Abort(); + } + } + } + +} diff --git a/src/Physics_manager.cs b/src/Physics_manager.cs new file mode 100644 index 0000000..a813deb --- /dev/null +++ b/src/Physics_manager.cs @@ -0,0 +1,41 @@ +/* +Copyright (c) OpenSim project, http://osgrid.org/ +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +using System; + +namespace OpenSim +{ + /// + /// Description of Physics_manager. + /// + public class PhysicsManager + { + public PhysicsManager() + { + } + } +} diff --git a/src/Prim_manager.cs b/src/Prim_manager.cs new file mode 100644 index 0000000..72eae35 --- /dev/null +++ b/src/Prim_manager.cs @@ -0,0 +1,382 @@ +/* +Copyright (c) OpenSim project, http://osgrid.org/ +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +using System; +using System.Collections.Generic; +using libsecondlife; +using libsecondlife.Packets; +using libsecondlife.AssetSystem; +using System.IO; +using Axiom.MathLib; + +namespace OpenSim +{ + /// + /// Description of Prim_manager. + /// + public class PrimManager + { + private Server _server; + private uint _primCount; + + public AgentManager AgentManagement; + public libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock PrimTemplate; + public Dictionary PrimList; + + /// + /// + /// + /// + public PrimManager(Server server) + { + _server = server; + PrimList = new Dictionary (); + //this.SetupTemplates("objectupate164.dat"); + + } + + /// + /// + /// + /// + /// + /// + public void CreatePrim(UserAgentInfo userInfo, libsecondlife.LLVector3 pos1, ObjectAddPacket addPacket) + { + ObjectUpdatePacket objupdate = new ObjectUpdatePacket(); + objupdate.RegionData.RegionHandle = Globals.Instance.RegionHandle; + objupdate.RegionData.TimeDilation = 64096; + + objupdate.ObjectData = new libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock[1]; + PrimData PData = new PrimData(); + objupdate.ObjectData[0] = this.PrimTemplate; + PData.OwnerID=objupdate.ObjectData[0].OwnerID = userInfo.AgentID; + PData.PCode=objupdate.ObjectData[0].PCode = addPacket.ObjectData.PCode; + PData.PathBegin=objupdate.ObjectData[0].PathBegin = addPacket.ObjectData.PathBegin; + PData.PathEnd=objupdate.ObjectData[0].PathEnd = addPacket.ObjectData.PathEnd; + PData.PathScaleX=objupdate.ObjectData[0].PathScaleX = addPacket.ObjectData.PathScaleX; + PData.PathScaleY=objupdate.ObjectData[0].PathScaleY = addPacket.ObjectData.PathScaleY; + PData.PathShearX=objupdate.ObjectData[0].PathShearX = addPacket.ObjectData.PathShearX; + PData.PathShearY=objupdate.ObjectData[0].PathShearY = addPacket.ObjectData.PathShearY; + PData.PathSkew=objupdate.ObjectData[0].PathSkew = addPacket.ObjectData.PathSkew; + PData.ProfileBegin=objupdate.ObjectData[0].ProfileBegin = addPacket.ObjectData.ProfileBegin; + PData.ProfileEnd=objupdate.ObjectData[0].ProfileEnd = addPacket.ObjectData.ProfileEnd; + PData.Scale=objupdate.ObjectData[0].Scale = addPacket.ObjectData.Scale; + PData.PathCurve=objupdate.ObjectData[0].PathCurve = addPacket.ObjectData.PathCurve; + PData.ProfileCurve=objupdate.ObjectData[0].ProfileCurve = addPacket.ObjectData.ProfileCurve; + PData.ParentID=objupdate.ObjectData[0].ParentID = 0; + PData.ProfileHollow=objupdate.ObjectData[0].ProfileHollow = addPacket.ObjectData.ProfileHollow; + //finish off copying rest of shape data + + objupdate.ObjectData[0].ID = (uint)(702000 + _primCount); + objupdate.ObjectData[0].FullID = new LLUUID("edba7151-5857-acc5-b30b-f01efefda"+_primCount.ToString("000")); + + //update position + byte[] pb = pos1.GetBytes(); + Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 0, pb.Length); + + _primCount++; + _server.SendPacket(objupdate, true, userInfo); + + //should send to all users + foreach (KeyValuePair kp in AgentManagement.AgentList) + { + if(kp.Value.NetInfo.AgentID != userInfo.AgentID) + { + _server.SendPacket(objupdate, true, kp.Value.NetInfo); + } + } + //should store this infomation + PrimInfo NewPrim = new PrimInfo(); + NewPrim.FullID = objupdate.ObjectData[0].FullID; + NewPrim.LocalID = objupdate.ObjectData[0].ID; + NewPrim.Position = pos1; + NewPrim.Data = PData; + + this.PrimList.Add(NewPrim.FullID, NewPrim); + + //store rest of data + + } + + /// + /// + /// + /// + /// + /// + /// + /// + public void UpdatePrimPosition(UserAgentInfo userInfo, LLVector3 position, uint localID, bool setRotation, LLQuaternion rotation) + { + PrimInfo pri = null; + foreach (KeyValuePair kp in this.PrimList) + { + if(kp.Value.LocalID == localID) + { + pri = kp.Value; + } + } + if(pri == null) + { + return; + } + uint ID = pri.LocalID; + libsecondlife.LLVector3 pos2 = new LLVector3(position.X, position.Y, position.Z); + libsecondlife.LLQuaternion rotation2; + if(!setRotation) + { + pri.Position = pos2; + rotation2 = new LLQuaternion(pri.Rotation.X, pri.Rotation.Y, pri.Rotation.Z, pri.Rotation.W); + } + else + { + rotation2=new LLQuaternion(rotation.X, rotation.Y, rotation.Z, rotation.W); + pos2 = pri.Position; + pri.Rotation = rotation; + } + rotation2.W += 1; + rotation2.X += 1; + rotation2.Y += 1; + rotation2.Z += 1; + + byte[] bytes = new byte[60]; + + ImprovedTerseObjectUpdatePacket im = new ImprovedTerseObjectUpdatePacket(); + im.RegionData.RegionHandle = Globals.Instance.RegionHandle; + im.RegionData.TimeDilation = 64096; + im.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; + int i = 0; + ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); + im.ObjectData[0] = dat; + dat.TextureEntry = PrimTemplate.TextureEntry; + + bytes[i++] = (byte)(ID % 256); + bytes[i++] = (byte)((ID >> 8) % 256); + bytes[i++] = (byte)((ID >> 16) % 256); + bytes[i++] = (byte)((ID >> 24) % 256); + bytes[i++]= 0; + bytes[i++]= 0; + + byte[] pb = pos2.GetBytes(); + pri.Position = pos2; + Array.Copy(pb, 0, bytes, i, pb.Length); + i += 12; + ushort ac = 32767; + + //vel + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + + //accel + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + + ushort rw, rx,ry,rz; + rw = (ushort)(32768 * rotation2.W); + rx = (ushort)(32768 * rotation2.X); + ry = (ushort)(32768 * rotation2.Y); + rz = (ushort)(32768 * rotation2.Z); + + //rot + bytes[i++] = (byte)(rx % 256); + bytes[i++] = (byte)((rx >> 8) % 256); + bytes[i++] = (byte)(ry % 256); + bytes[i++] = (byte)((ry >> 8) % 256); + bytes[i++] = (byte)(rz % 256); + bytes[i++] = (byte)((rz >> 8) % 256); + bytes[i++] = (byte)(rw % 256); + bytes[i++] = (byte)((rw >> 8) % 256); + + //rotation vel + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + bytes[i++] = (byte)(ac % 256); + bytes[i++] = (byte)((ac >> 8) % 256); + + dat.Data=bytes; + + foreach (KeyValuePair kp in AgentManagement.AgentList) + { + if(kp.Value.NetInfo.AgentID!=userInfo.AgentID) + { + _server.SendPacket(im, true, kp.Value.NetInfo); + } + } + } + + /// + /// + /// + /// + public void SendExistingPrims(UserAgentInfo userInfo) + { + //send data for already created prims to a new joining user + } + + /// + /// + /// + /// + public void SetupTemplates(string name) + { + ObjectUpdatePacket objupdate = new ObjectUpdatePacket(); + objupdate.RegionData.RegionHandle = Globals.Instance.RegionHandle; + objupdate.RegionData.TimeDilation = 64096; + objupdate.ObjectData = new libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock[1]; + + int i = 0; + FileInfo fInfo = new FileInfo(name); + long numBytes = fInfo.Length; + FileStream fStream = new FileStream(name, FileMode.Open, FileAccess.Read); + BinaryReader br = new BinaryReader(fStream); + byte [] data1 = br.ReadBytes((int)numBytes); + br.Close(); + fStream.Close(); + + libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock objdata = new libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock(data1,ref i); + objupdate.ObjectData[0] = objdata; + this.PrimTemplate = objdata; + objdata.UpdateFlags = objdata.UpdateFlags + 12 - 16 + 32 + 256; + objdata.OwnerID = new LLUUID("00000000-0000-0000-0000-000000000000"); + //test adding a new texture to object , to test image downloading + LLObject.TextureEntry te = new LLObject.TextureEntry(objdata.TextureEntry, 0, objdata.TextureEntry.Length); + te.DefaultTexture.TextureID = new LLUUID("00000000-0000-0000-5005-000000000005"); + + LLObject.TextureEntry ntex = new LLObject.TextureEntry(new LLUUID("00000000-0000-0000-5005-000000000005")); + + objdata.TextureEntry = ntex.ToBytes(); + } + + /// + /// + /// + /// + /// + public void ReadPrimDatabase(string name, UserAgentInfo userInfo) + { + StreamReader SR; + string line; + SR=File.OpenText(name); + string [] comp = new string[10]; + string delimStr = " , "; + char [] delimiter = delimStr.ToCharArray(); + + line=SR.ReadLine(); + while(line != "end") + { + comp = line.Split(delimiter); + if(comp[0] == "ObjPack") + { + int num = Convert.ToInt32(comp[2]); + int start = Convert.ToInt32(comp[1]); + ObjectUpdatePacket objupdate = new ObjectUpdatePacket(); + objupdate.RegionData.RegionHandle = Globals.Instance.RegionHandle; + objupdate.RegionData.TimeDilation = 64096; + objupdate.ObjectData = new libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock[num]; + + // int count=0; + string data_path = System.IO.Path.Combine(System.AppDomain.CurrentDomain.BaseDirectory, @"data"); + for(int cc = 0; cc < num; cc++) + { + string filenam = System.IO.Path.Combine(data_path, @"prim_updates"+start+".dat"); + int i = 0; + //FileInfo fInfo = new FileInfo("objectupate"+start+".dat"); + FileInfo fInfo = new FileInfo(filenam); + long numBytes = fInfo.Length; + //FileStream fStream = new FileStream("objectupate"+start+".dat", FileMode.Open, FileAccess.Read); + FileStream fStream = new FileStream(filenam, FileMode.Open, FileAccess.Read); + BinaryReader br = new BinaryReader(fStream); + byte [] data1 = br.ReadBytes((int)numBytes); + br.Close(); + fStream.Close(); + + libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock objdata = new libsecondlife.Packets.ObjectUpdatePacket.ObjectDataBlock(data1, ref i); + objupdate.ObjectData[cc] = objdata; + start++; + } + _server.SendPacket(objupdate, true, userInfo); + line = SR.ReadLine(); + } + } + SR.Close(); + } + } + + public class PrimInfo + { + public LLVector3 Position; + public LLVector3 Velocity; + public LLQuaternion Rotation=LLQuaternion.Identity; + public uint LocalID; + public LLUUID FullID; + public PrimData Data; + + public PrimInfo() + { + Position=new LLVector3(0,0,0); + Velocity=new LLVector3(0,0,0); + //data=new PrimData(); + } + } + public class PrimData + { + public LLUUID OwnerID; + public byte PCode; + public byte PathBegin; + public byte PathEnd; + public byte PathScaleX; + public byte PathScaleY; + public byte PathShearX; + public byte PathShearY; + public sbyte PathSkew; + public byte ProfileBegin; + public byte ProfileEnd; + public LLVector3 Scale; + public byte PathCurve; + public byte ProfileCurve; + public uint ParentID=0; + public byte ProfileHollow; + + public bool DataBaseStorage=false; + + public PrimData() + { + + } + } +} diff --git a/src/SceneGraphManager.cs b/src/SceneGraphManager.cs new file mode 100644 index 0000000..c71ad54 --- /dev/null +++ b/src/SceneGraphManager.cs @@ -0,0 +1,40 @@ +/* +Copyright (c) OpenSim project, http://osgrid.org/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +using System; + +namespace OpenSim +{ + /// + /// Description of SceneGraphManager. + /// + public class SceneGraphManager + { + public SceneGraphManager() + { + } + } +} diff --git a/src/Script_manager.cs b/src/Script_manager.cs new file mode 100644 index 0000000..1de1d22 --- /dev/null +++ b/src/Script_manager.cs @@ -0,0 +1,103 @@ +/* + Copyright (c) OpenSim project, http://osgrid.org/ +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + */ + +using System; +using System.Collections; +//using LuaInterface; +using libsecondlife; + +namespace OpenSim +{ + /// + /// Description of Script_manager. + /// + public class ScriptManager + { + //public LuaInterface.Lua Lu; + //private ArrayList scripts; + //private prim_info current_prim; + + public ScriptManager() + { + } + + /*public void start_up (Lua lua, App ap) + { + this.Lu=lua; + //register any lua routines , like check finish script one + Lu.OpenMathLib(); + }*/ + + private void RegisterFunctions() + { + //lu.RegisterFunction( "RegisterScript",this,this.GetType().GetMethod("ScriptRegister")); + //lu.RegisterFunction( "MoveObject",this,this.GetType().GetMethod("MoveObject")); + //lu.RegisterFunction( "Say",this,this.GetType().GetMethod("Say")); + + } + + public void Call_tick(PrimInfo prim) + { + //set current prim and then call tick function in linked script + } + public void Call_touch(PrimInfo prim) + { + //set current prim and then call clicked function in linked script + + } + public void Call_on_rex(PrimInfo prim) + { + //set current prim and then call clicked function in linked script + + } + + #region Lua Functions + + public void ScriptRegister(script_object_interface script) + { + //called by scripts to register themselves + } + public void MoveObject(float x , float y, float z) + { + + } + public void Say(string message) + { + + } + #endregion + + } + + public interface script_object_interface + { + void frame_tick(); + void touch(int num); + void on_rex(int num); + } +} diff --git a/src/Second-server.csproj b/src/Second-server.csproj new file mode 100644 index 0000000..6d049ce --- /dev/null +++ b/src/Second-server.csproj @@ -0,0 +1,60 @@ + + + Exe + OpenSim + OpenSim + Debug + AnyCPU + {132A6E3E-8F2D-4BF5-BDFB-8555F53F334E} + OpenSim.Controller + + + bin\Debug\ + False + DEBUG;TRACE + True + Full + True + + + bin\Release\ + True + TRACE + False + None + False + + + + False + ..\bin\Axiom.MathLib.dll + + + False + ..\bin\libsecondlife.dll + + + False + ..\bin\log4net.dll + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/Second-server.sln b/src/Second-server.sln new file mode 100644 index 0000000..44be1db --- /dev/null +++ b/src/Second-server.sln @@ -0,0 +1,34 @@ + +Microsoft Visual Studio Solution File, Format Version 9.00 +# SharpDevelop 2.1.0.2017 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Second-server", "Second-server.csproj", "{132A6E3E-8F2D-4BF5-BDFB-8555F53F334E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|.NET 1.1 = Debug|.NET 1.1 + Debug|Any CPU = Debug|Any CPU + Release|.NET 1.1 = Release|.NET 1.1 + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {132A6E3E-8F2D-4BF5-BDFB-8555F53F334E}.Debug|.NET 1.1.ActiveCfg = Debug|Any CPU + {132A6E3E-8F2D-4BF5-BDFB-8555F53F334E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {132A6E3E-8F2D-4BF5-BDFB-8555F53F334E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {132A6E3E-8F2D-4BF5-BDFB-8555F53F334E}.Release|.NET 1.1.ActiveCfg = Release|Any CPU + {132A6E3E-8F2D-4BF5-BDFB-8555F53F334E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {132A6E3E-8F2D-4BF5-BDFB-8555F53F334E}.Release|Any CPU.Build.0 = Release|Any CPU + {D9CDEDFB-8169-4B03-B57F-0DF638F044EC}.Debug|.NET 1.1.ActiveCfg = Debug|.NET 1.1 + {D9CDEDFB-8169-4B03-B57F-0DF638F044EC}.Debug|.NET 1.1.Build.0 = Debug|.NET 1.1 + {D9CDEDFB-8169-4B03-B57F-0DF638F044EC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D9CDEDFB-8169-4B03-B57F-0DF638F044EC}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D9CDEDFB-8169-4B03-B57F-0DF638F044EC}.Release|.NET 1.1.ActiveCfg = Release|.NET 1.1 + {D9CDEDFB-8169-4B03-B57F-0DF638F044EC}.Release|.NET 1.1.Build.0 = Release|.NET 1.1 + {D9CDEDFB-8169-4B03-B57F-0DF638F044EC}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D9CDEDFB-8169-4B03-B57F-0DF638F044EC}.Release|Any CPU.Build.0 = Release|Any CPU + {132A6E3E-8F2D-4BF5-BDFB-8555F53F334E}.Debug|.NET 1.1.Build.0 = Debug|.NET 1.1 + {132A6E3E-8F2D-4BF5-BDFB-8555F53F334E}.Release|.NET 1.1.Build.0 = Release|.NET 1.1 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/Second-server.suo b/src/Second-server.suo new file mode 100644 index 0000000..4ed1adc Binary files /dev/null and b/src/Second-server.suo differ diff --git a/src/Server.cs b/src/Server.cs new file mode 100644 index 0000000..1f19bf9 --- /dev/null +++ b/src/Server.cs @@ -0,0 +1,707 @@ +/* + * Copyright (c) OpenSim project, http://osgrid.org/ +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +using System; +using System.Collections.Generic; +using libsecondlife; +using System.Collections; +using libsecondlife.Packets; +using libsecondlife.AssetSystem; +using System.Net; +using System.Net.Sockets; +using System.Timers; + +//really hacked , messy code + +namespace OpenSim +{ + /// + /// Description of Server. + /// + public interface ServerCallback + { + //should replace with delegates + void MainCallback(Packet pack, UserAgentInfo User_info); + void NewUserCallback(UserAgentInfo User_info); + void ErrorCallback(string text); + } + public class Server + { + /// A public reference to the client that this Simulator object + /// is attached to + //public SecondLife Client; + + /// The Region class that this Simulator wraps + // public Region Region; + + /// + /// Used internally to track sim disconnections, do not modify this + /// variable + /// + public bool DisconnectCandidate = false; + + /// + /// The ID number associated with this particular connection to the + /// simulator, used to emulate TCP connections. This is used + /// internally for packets that have a CircuitCode field + /// + public uint CircuitCode + { + get { return circuitCode; } + set { circuitCode = value; } + } + + /// + /// The IP address and port of the server + /// + public IPEndPoint IPEndPoint + { + get { return ipEndPoint; } + } + + /// + /// A boolean representing whether there is a working connection to the + /// simulator or not + /// + public bool Connected + { + get { return connected; } + } + + private ServerCallback CallbackObject; + private uint Sequence = 0; + private object SequenceLock = new object(); + private byte[] RecvBuffer = new byte[4096]; + private byte[] ZeroBuffer = new byte[8192]; + private byte[] ZeroOutBuffer = new byte[4096]; + private Socket Connection = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp); + private AsyncCallback ReceivedData; + private bool connected = false; + private uint circuitCode; + private IPEndPoint ipEndPoint; + private EndPoint endPoint; + private IPEndPoint ipeSender; + private EndPoint epSender; + private System.Timers.Timer AckTimer; + private Server_Settings Settings=new Server_Settings(); + public ArrayList User_agents=new ArrayList(); + + /// + /// Constructor for Simulator + /// + /// + /// + /// + /// + /// + public Server(ServerCallback s_callback) + { + + this.CallbackObject=s_callback; //should be using delegate + AckTimer = new System.Timers.Timer(Settings.NETWORK_TICK_LENGTH); + AckTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed); + + // Initialize the callback for receiving a new packet + ReceivedData = new AsyncCallback(this.OnReceivedData); + + // Client.Log("Connecting to " + ip.ToString() + ":" + port, Helpers.LogLevel.Info); + + try + { + // Create an endpoint that we will be communicating with (need it in two + // types due to .NET weirdness) + // ipEndPoint = new IPEndPoint(ip, port); + ipEndPoint = new IPEndPoint(IPAddress.Any, Globals.Instance.IpPort); + endPoint = (EndPoint)ipEndPoint; + + // Associate this simulator's socket with the given ip/port and start listening + Connection.Bind(endPoint); + ipeSender = new IPEndPoint(IPAddress.Any, 0); + //The epSender identifies the incoming clients + epSender = (EndPoint) ipeSender; + Connection.BeginReceiveFrom(RecvBuffer, 0, RecvBuffer.Length, SocketFlags.None, ref epSender, ReceivedData, null); + + // Start the ACK timer + AckTimer.Start(); + } + catch (Exception e) + { + + System.Console.WriteLine(e.Message); + } + } + + /// + /// Disconnect a Simulator + /// + public void Disconnect() + { + if (connected) + { + connected = false; + AckTimer.Stop(); + + // Send the CloseCircuit notice + CloseCircuitPacket close = new CloseCircuitPacket(); + + if (Connection.Connected) + { + try + { + // Connection.Send(close.ToBytes()); + } + catch (SocketException) + { + // There's a high probability of this failing if the network is + // disconnecting, so don't even bother logging the error + } + } + + try + { + // Shut the socket communication down + // Connection.Shutdown(SocketShutdown.Both); + } + catch (SocketException) + { + } + } + } + + /// + /// Sends a packet + /// + /// Packet to be sent + /// Increment sequence number? + public void SendPacket(Packet packet, bool incrementSequence, UserAgentInfo User_info) + { + Console.WriteLine("OUTGOING"); + Console.WriteLine(packet.ToString()); + byte[] buffer; + int bytes; + + if (!connected && packet.Type != PacketType.UseCircuitCode) + { + Console.WriteLine("Trying to send a " + packet.Type.ToString() + " packet when the socket is closed"); + + + return; + } + + /*if (packet.Header.AckList.Length > 0) + { + // Scrub any appended ACKs since all of the ACK handling is done here + packet.Header.AckList = new uint[0]; + } + packet.Header.AppendedAcks = false; + + // Keep track of when this packet was sent out + packet.TickCount = Environment.TickCount; + */ + if (incrementSequence) + { + // Set the sequence number + lock (SequenceLock) + { + if (Sequence > Settings.MAX_SEQUENCE) + Sequence = 1; + else + Sequence++; + packet.Header.Sequence = Sequence; + } + + if (packet.Header.Reliable) + { + lock (User_info.NeedAck) + { + if (!User_info.NeedAck.ContainsKey(packet.Header.Sequence)) + { + User_info.NeedAck.Add(packet.Header.Sequence, packet); + } + else + { + // Client.Log("Attempted to add a duplicate sequence number (" + + // packet.Header.Sequence + ") to the NeedAck dictionary for packet type " + + // packet.Type.ToString(), Helpers.LogLevel.Warning); + } + } + + // Don't append ACKs to resent packets, in case that's what was causing the + // delivery to fail + if (!packet.Header.Resent) + { + // Append any ACKs that need to be sent out to this packet + lock (User_info.PendingAcks) + { + if (User_info.PendingAcks.Count > 0 && User_info.PendingAcks.Count < Settings.MAX_APPENDED_ACKS && + packet.Type != PacketType.PacketAck && + packet.Type != PacketType.LogoutRequest) + { + packet.Header.AckList = new uint[User_info.PendingAcks.Count]; + int i = 0; + + foreach (uint ack in User_info.PendingAcks.Values) + { + packet.Header.AckList[i] = ack; + i++; + } + + User_info.PendingAcks.Clear(); + packet.Header.AppendedAcks = true; + } + } + } + } + } + + // Serialize the packet + buffer = packet.ToBytes(); + bytes = buffer.Length; + + try + { + // Zerocode if needed + if (packet.Header.Zerocoded) + { + lock (ZeroOutBuffer) + { + bytes = Helpers.ZeroEncode(buffer, bytes, ZeroOutBuffer); + Connection.SendTo(ZeroOutBuffer, bytes, SocketFlags.None,User_info.endpoint); + } + } + else + { + + Connection.SendTo(buffer, bytes, SocketFlags.None,User_info.endpoint); + } + } + catch (SocketException) + { + //Client.Log("Tried to send a " + packet.Type.ToString() + " on a closed socket", + // Helpers.LogLevel.Warning); + + Disconnect(); + } + } + + /// + /// Send a raw byte array payload as a packet + /// + /// The packet payload + /// Whether the second, third, and fourth bytes + /// should be modified to the current stream sequence number + /// + /// Returns Simulator Name as a String + /// + /// + public override string ToString() + { + return( " (" + ipEndPoint.ToString() + ")"); + } + + /// + /// Sends out pending acknowledgements + /// + private void SendAcks(UserAgentInfo User_info) + { + lock (User_info.PendingAcks) + { + if (connected && User_info.PendingAcks.Count > 0) + { + if (User_info.PendingAcks.Count > 250) + { + // FIXME: Handle the odd case where we have too many pending ACKs queued up + //Client.Log("Too many ACKs queued up!", Helpers.LogLevel.Error); + return; + } + + int i = 0; + PacketAckPacket acks = new PacketAckPacket(); + acks.Packets = new PacketAckPacket.PacketsBlock[User_info.PendingAcks.Count]; + + foreach (uint ack in User_info.PendingAcks.Values) + { + acks.Packets[i] = new PacketAckPacket.PacketsBlock(); + acks.Packets[i].ID = ack; + i++; + } + + acks.Header.Reliable = false; + //SendPacket(acks, true,User_info); + + User_info.PendingAcks.Clear(); + } + } + } + /// + /// Resend unacknowledged packets + /// + private void ResendUnacked(UserAgentInfo User_info) + { + if (connected) + { + int now = Environment.TickCount; + + lock (User_info.NeedAck) + { + foreach (Packet packet in User_info.NeedAck.Values) + { + if (now - packet.TickCount > Settings.RESEND_TIMEOUT) + { + // Client.Log("Resending " + packet.Type.ToString() + " packet, " + + // (now - packet.TickCount) + "ms have passed", Helpers.LogLevel.Info); + + //packet.Header.Resent = true; + // SendPacket(packet, false,User_info); + } + } + } + } + } + /// + /// Callback handler for incomming data + /// + /// + private void OnReceivedData(IAsyncResult result) + { + ipeSender = new IPEndPoint(IPAddress.Any, 0); + epSender = (EndPoint)ipeSender; + Packet packet = null; + int numBytes; + UserAgentInfo tempinfo; + + // If we're receiving data the sim connection is open + connected = true; + + // Update the disconnect flag so this sim doesn't time out + DisconnectCandidate = false; + UserAgentInfo User_info=null; + + lock (RecvBuffer) + { + // Retrieve the incoming packet + try + { + numBytes = Connection.EndReceiveFrom(result, ref epSender); + + //find user_agent_info + + int packetEnd = numBytes - 1; + packet = Packet.BuildPacket(RecvBuffer, ref packetEnd, ZeroBuffer); + + Console.WriteLine("INCOMING PACKET" + packet.TickCount.ToString() + " " + packet.Header.Sequence.ToString()); + Console.WriteLine(packet.ToString()); + libsecondlife.Packets.PacketAckPacket ack_it = new PacketAckPacket(); + ack_it.Packets = new PacketAckPacket.PacketsBlock[1]; + ack_it.Packets[0] = new PacketAckPacket.PacketsBlock(); + ack_it.Packets[0].ID = packet.Header.ID; + ack_it.Header.Reliable = false; + + tempinfo = new UserAgentInfo(); + tempinfo.endpoint = epSender; + this.SendPacket(ack_it, false, tempinfo); + if (packet.Header.Resent) + { + this.CallbackObject.ErrorCallback("resent"); + } + + if ((packet.Type == PacketType.StartPingCheck) && (packet.Header.Resent == false)) + { + //reply to pingcheck + libsecondlife.Packets.StartPingCheckPacket startping = (libsecondlife.Packets.StartPingCheckPacket)packet; + libsecondlife.Packets.CompletePingCheckPacket endping = new CompletePingCheckPacket(); + endping.PingID.PingID = startping.PingID.PingID; + endping.Header.Reliable = false; + tempinfo = new UserAgentInfo(); + tempinfo.endpoint = epSender; + this.SendPacket(endping, true, tempinfo); + } + + //should check if login/useconnection packet first + if ((packet.Type == PacketType.UseCircuitCode) && (packet.Header.Resent == false)) + { + Console.WriteLine("Got UseCircuitCode, confirming with grid..."); + UseCircuitCodePacket cir_pack=(UseCircuitCodePacket)packet; + + ArrayList requestParams = new ArrayList(); + requestParams.Add(Globals.Instance.GridSendKey); + requestParams.Add(cir_pack.CircuitCode.SessionID.ToString()); + requestParams.Add(cir_pack.CircuitCode.ID.ToString()); + + + Nwc.XmlRpc.XmlRpcRequest GridSessionInfo = new Nwc.XmlRpc.XmlRpcRequest("get_session_info",requestParams); + + Nwc.XmlRpc.XmlRpcResponse gridresponse = GridSessionInfo.Send(Globals.Instance.GridURL, 5000); + + Console.WriteLine("Processing response from grid server..."); + Hashtable gridreply = (Hashtable)gridresponse.Value; + if (gridresponse.IsFault) + { + Console.WriteLine("XML-RPC error when talking to grid: " + gridresponse.FaultString); + Connection.Disconnect(false); + } + if (((string)gridreply["agent_id"]).ToLower().Equals(cir_pack.CircuitCode.ID.ToString()) == false) + { + Console.WriteLine("Bad agent ID!"); + Connection.Disconnect(false); + } + else if (((string)gridreply["session_id"]).ToLower().Equals(cir_pack.CircuitCode.SessionID.ToString()) == false) + { + Console.WriteLine("Bad session ID!"); + Connection.Disconnect(false); + } + UserAgentInfo new_user = new UserAgentInfo(); + + new_user.AgentID = cir_pack.CircuitCode.ID; + new_user.circuitCode=cir_pack.CircuitCode.Code; + new_user.AgentID=cir_pack.CircuitCode.ID; + new_user.SessionID=cir_pack.CircuitCode.SessionID; + new_user.endpoint=epSender; + new_user.Inbox = new Queue(Settings.INBOX_SIZE); + new_user.first_name = (string)gridreply["firstname"]; + new_user.first_name = (string)gridreply["lastname"]; + + + this.CallbackObject.NewUserCallback(new_user); + this.User_agents.Add(new_user); + + } + + + UserAgentInfo temp_agent=null; + IPEndPoint send_ip=(IPEndPoint)epSender; + Console.WriteLine("incoming: address is "+send_ip.Address +"port number is: "+send_ip.Port.ToString()); + + for(int ii=0; ii Settings.MAX_PENDING_ACKS) + { + SendAcks(User_info); + } + + // Check if we already received this packet + if (User_info.Inbox.Contains(packet.Header.Sequence)) + { + //Client.Log("Received a duplicate " + packet.Type.ToString() + ", sequence=" + + // packet.Header.Sequence + ", resent=" + ((packet.Header.Resent) ? "Yes" : "No") + + // ", Inbox.Count=" + Inbox.Count + ", NeedAck.Count=" + NeedAck.Count, + // Helpers.LogLevel.Info); + + // Send an ACK for this packet immediately + + + // TESTING: Try just queuing up ACKs for resent packets instead of immediately triggering an ACK + /* lock (User_info.PendingAcks) + { + uint sequence = (uint)packet.Header.Sequence; + if (!User_info.PendingAcks.ContainsKey(sequence)) { User_info.PendingAcks[sequence] = sequence; } + }*/ + + // Avoid firing a callback twice for the same packet + this.CallbackObject.ErrorCallback("Avoiding callback"); + // this.callback_object.error("avoiding callback"); + return; + } + else + { + lock (User_info.PendingAcks) + { + uint sequence = (uint)packet.Header.Sequence; + // if (!User_info.PendingAcks.ContainsKey(sequence)) { User_info.PendingAcks[sequence] = sequence; } + } + } + } + + // Add this packet to our inbox + lock (User_info.Inbox) + { + while (User_info.Inbox.Count >= Settings.INBOX_SIZE) + { + User_info.Inbox.Dequeue(); + } + User_info.Inbox.Enqueue(packet.Header.Sequence); + } + + // Handle appended ACKs + if (packet.Header.AppendedAcks) + { + lock (User_info.NeedAck) + { + foreach (uint ack in packet.Header.AckList) + { + User_info.NeedAck.Remove(ack); + } + } + } + + // Handle PacketAck packets + if (packet.Type == PacketType.PacketAck) + { + PacketAckPacket ackPacket = (PacketAckPacket)packet; + + lock (User_info.NeedAck) + { + foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets) + { + User_info.NeedAck.Remove(block.ID); + } + } + } + + this.CallbackObject.MainCallback(packet,User_info); + + } + + private void AckTimer_Elapsed(object sender, ElapsedEventArgs ea) + { + if (connected) + { + + //TODO for each user_agent_info + for(int i=0; iThe version of libsecondlife (not the SL protocol itself) + public string VERSION = "libsecondlife 0.0.9"; + /// XML-RPC login server to connect to + public string LOGIN_SERVER = "http://www.garethnelson.com/ogs/login/"; + + /// Millisecond interval between ticks, where all ACKs are + /// sent out and the age of unACKed packets is checked + public readonly int NETWORK_TICK_LENGTH = 500; + /// The maximum value of a packet sequence number. After that + /// we assume the sequence number just rolls over? Or maybe the + /// protocol isn't able to sustain a connection past that + public readonly int MAX_SEQUENCE = 0xFFFFFF; + /// Number of milliseconds before a teleport attempt will time + /// out + public readonly int TELEPORT_TIMEOUT = 18 * 1000; + + /// Number of milliseconds before NetworkManager.Logout() will time out + public int LOGOUT_TIMEOUT = 5 * 1000; + /// Number of milliseconds for xml-rpc to timeout + public int LOGIN_TIMEOUT = 30 * 1000; + /// The maximum size of the sequence number inbox, used to + /// check for resent and/or duplicate packets + public int INBOX_SIZE = 100; + /// Milliseconds before a packet is assumed lost and resent + public int RESEND_TIMEOUT = 4000; + /// Milliseconds before the connection to a simulator is + /// assumed lost + public int SIMULATOR_TIMEOUT = 15000; + /// Maximum number of queued ACKs to be sent before SendAcks() + /// is forced + public int MAX_PENDING_ACKS = 10; + /// Maximum number of ACKs to append to a packet + public int MAX_APPENDED_ACKS = 10; + /// Cost of uploading an asset + public int UPLOAD_COST { get { return priceUpload; } } + + + private int priceUpload = 0; + + public Server_Settings() + { + + } + } + + public class UserAgentInfo + { + public EndPoint endpoint; + public LLUUID AgentID; + public LLUUID SessionID; + public uint circuitCode; + public string name; + public uint localID; + public string first_name; + public string last_name; + + public Dictionary NeedAck = new Dictionary(); + // Sequence numbers of packets we've received from the simulator + public Queue Inbox; + // ACKs that are queued up to be sent to the simulator + public Dictionary PendingAcks = new Dictionary(); + + public UserAgentInfo() + { + + } + } + +} diff --git a/src/StorageManager.cs b/src/StorageManager.cs new file mode 100644 index 0000000..05ef782 --- /dev/null +++ b/src/StorageManager.cs @@ -0,0 +1,53 @@ +/* +Copyright (c) OpenSim project, http://osgrid.org/ +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +using System; +using System.Collections.Generic; +using libsecondlife; +using System.Collections; +using libsecondlife.Packets; +using libsecondlife.AssetSystem; +using System.IO; + +namespace OpenSim +{ + /// + /// Description of StorageManager. + /// + public class StorageManager + { + public StorageManager() + { + } + } + + public class AssetStorage + { + public LLUUID Full_ID; + public byte Type; + } +} diff --git a/src/Texture_manager.cs b/src/Texture_manager.cs new file mode 100644 index 0000000..6d3f1db --- /dev/null +++ b/src/Texture_manager.cs @@ -0,0 +1,238 @@ +/* +Copyright (c) OpenSim project, http://osgrid.org/ + +* Copyright (c) , +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +using System; +using System.Collections.Generic; +using libsecondlife; +using System.Collections; +using libsecondlife.Packets; +using libsecondlife.AssetSystem; +using System.IO; + + +namespace OpenSim +{ + /// + /// Description of Texture_manager. + /// + public class TextureManager + { + public Dictionary textures; + public ArrayList requests=new ArrayList(); //should change to a generic + public ArrayList uploads=new ArrayList(); + private Server server; + + public TextureManager(Server serve) + { + server=serve; + textures=new Dictionary (); + this.initialise(); + } + + public void AddRequest(User_Agent_info user, LLUUID image_id) + { + + if(!this.textures.ContainsKey(image_id)) + { + //not found image so send back image not in data base message + ImageNotInDatabasePacket im_not=new ImageNotInDatabasePacket(); + im_not.ImageID.ID=image_id; + server.SendPacket(im_not,true,user); + return; + } + TextureImage imag=this.textures[image_id]; + TextureRequest req=new TextureRequest(); + req.RequestUser=user; + req.RequestImage=image_id; + req.image_info=imag; + + if(imag.data.LongLength>1000) //should be bigger or smaller? + { + //over 1000 bytes so split up file + req.num_packets=(int)imag.data.LongLength/1000; + req.num_packets++; + } + else + { + req.num_packets=1; + } + + this.requests.Add(req); + + } + + public void AddTexture(LLUUID image_id, string name, byte[] data) + { + + } + public void DoWork(ulong time) + { + if(this.requests.Count==0) + { + //no requests waiting + return; + } + int num; + //should be running in its own thread but for now is called by timer + if(this.requests.Count<5) + { + //lower than 5 so do all of them + num=this.requests.Count; + } + else + { + num=5; + } + TextureRequest req; + for(int i=0; i, +* All rights reserved. +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +using System; +using System.Collections.Generic; +using System.Threading; +using libsecondlife; +using libsecondlife.Packets; + +namespace OpenSim +{ + /// + /// + public class QueItem { + public QueItem() + { + } + + public Packet Packet; + public bool Incoming; + } + + + public class BlockingQueue< T > { + private Queue< T > _queue = new Queue< T >(); + private object _queueSync = new object(); + + public void Enqueue(T value) + { + lock(_queueSync) + { + _queue.Enqueue(value); + Monitor.Pulse(_queueSync); + } + } + + public T Dequeue() + { + lock(_queueSync) + { + if( _queue.Count < 1) + Monitor.Wait(_queueSync); + + return _queue.Dequeue(); + } + } + } + +} diff --git a/src/VersionInfo.cs.template b/src/VersionInfo.cs.template new file mode 100644 index 0000000..e4e1b95 --- /dev/null +++ b/src/VersionInfo.cs.template @@ -0,0 +1,37 @@ +/* +Copyright (c) OpenSim project, http://osgrid.org/ +* +* Redistribution and use in source and binary forms, with or without +* modification, are permitted provided that the following conditions are met: +* * Redistributions of source code must retain the above copyright +* notice, this list of conditions and the following disclaimer. +* * Redistributions in binary form must reproduce the above copyright +* notice, this list of conditions and the following disclaimer in the +* documentation and/or other materials provided with the distribution. +* * Neither the name of the nor the +* names of its contributors may be used to endorse or promote products +* derived from this software without specific prior written permission. +* +* THIS SOFTWARE IS PROVIDED BY ``AS IS'' AND ANY +* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +* DISCLAIMED. IN NO EVENT SHALL BE LIABLE FOR ANY +* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +using System; + +namespace OpenSim +{ + /// + /// + public class VersionInfo + { + public static string Version = "@@VERSION"; + } +} diff --git a/src/types/BitPack.cs b/src/types/BitPack.cs new file mode 100644 index 0000000..1abbcf0 --- /dev/null +++ b/src/types/BitPack.cs @@ -0,0 +1,138 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.types +{ + /* New Method + * + * 1. Get all the individual bytes and their bitlength, put them in a dictionary + * 2. Mash together when wanted. + * + * */ + public class Bits { + public byte[] data; + public int len; + } + + public class InverseBitPack + { + private List bits; + + public InverseBitPack() + { + bits = new List(); + } + } + + public class BitPack + { + private const int MAX_BITS = 8; + + private byte[] Data; + private int bytePos; + private int bitPos; + + public BitPack(byte[] data, int pos) // For libsl compatibility + { + Data = data; + bytePos = pos; + } + + public BitPack() // Encoding version + { + + } + + public void LoadData(byte[] data, int pos) { + Data = data; + bytePos = pos; + bitPos = 0; + } + + private void PackBitsArray(byte[] bits, int bitLen) + { + int offset = bitPos % MAX_BITS; + int i; + byte temp1; + byte temp2; + + for (i = 0; i < bits.Length; i++) + { + int Byte = bits[i]; + Byte <<= offset; + temp1 = (byte)(Byte & 0xFF); + temp2 = (byte)((Byte >> 8) & 0xFF); + + Data[Data.Length - 1] |= temp1; +// Data + + bitPos += bitLen; + } + } + + public float UnpackFloat() + { + byte[] output = UnpackBitsArray(32); + + if (!BitConverter.IsLittleEndian) Array.Reverse(output); + return BitConverter.ToSingle(output, 0); + } + + public int UnpackBits(int totalCount) + { + byte[] output = UnpackBitsArray(totalCount); + + if (!BitConverter.IsLittleEndian) Array.Reverse(output); + return BitConverter.ToInt32(output, 0); + } + + private byte[] UnpackBitsArray(int totalCount) + { + int count = 0; + byte[] output = new byte[4]; + int curBytePos = 0; + int curBitPos = 0; + + while (totalCount > 0) + { + if (totalCount > MAX_BITS) + { + count = MAX_BITS; + totalCount -= MAX_BITS; + } + else + { + count = totalCount; + totalCount = 0; + } + + while (count > 0) + { + // Shift the previous bits + output[curBytePos] <<= 1; + + // Grab one bit + if ((Data[bytePos] & (0x80 >> bitPos++)) != 0) + ++output[curBytePos]; + + --count; + ++curBitPos; + + if (bitPos >= MAX_BITS) + { + bitPos = 0; + ++bytePos; + } + if (curBitPos >= MAX_BITS) + { + curBitPos = 0; + ++curBytePos; + } + } + } + + return output; + } + } +} diff --git a/src/types/Mesh.cs b/src/types/Mesh.cs new file mode 100644 index 0000000..3e00c91 --- /dev/null +++ b/src/types/Mesh.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.types +{ + // TODO: This will need some performance tuning no doubt. + public class Mesh + { + public List mesh; + + public Mesh() + { + mesh = new List(); + } + + public void AddTri(Triangle tri) + { + mesh.Add(tri); + } + + public static Mesh operator +(Mesh a, Mesh b) + { + a.mesh.AddRange(b.mesh); + return a; + } + } +} diff --git a/src/types/Triangle.cs b/src/types/Triangle.cs new file mode 100644 index 0000000..8dfea6e --- /dev/null +++ b/src/types/Triangle.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Axiom.MathLib; + +namespace OpenSim.types +{ + public class Triangle + { + Vector3 a; + Vector3 b; + Vector3 c; + + public Triangle() + { + a = new Vector3(); + b = new Vector3(); + c = new Vector3(); + } + + public Triangle(Vector3 A, Vector3 B, Vector3 C) + { + a = A; + b = B; + c = C; + } + } +} diff --git a/src/world/Avatar.cs b/src/world/Avatar.cs new file mode 100644 index 0000000..863ce29 --- /dev/null +++ b/src/world/Avatar.cs @@ -0,0 +1,70 @@ +using System; +using System.Collections.Generic; +using System.Text; +using libsecondlife; +using libsecondlife.Packets; + +namespace OpenSim.world +{ + public class Avatar : Entity + { + public string firstname; + public string lastname; + public OpenSimClient ControllingClient; + + public Avatar(OpenSimClient TheClient) { + Console.WriteLine("Avatar.cs - Loading details from grid (DUMMY)"); + ControllingClient=TheClient; + } + + public void CompleteMovement(World RegionInfo) { + Console.WriteLine("Avatar.cs:CompleteMovement() - Constructing AgentMovementComplete packet"); + AgentMovementCompletePacket mov = new AgentMovementCompletePacket(); + mov.AgentData.SessionID = this.ControllingClient.SessionID; + mov.AgentData.AgentID = this.ControllingClient.AgentID; + mov.Data.RegionHandle = OpenSim_Main.cfg.RegionHandle; + // TODO - dynamicalise this stuff + mov.Data.Timestamp = 1169838966; + mov.Data.Position = new LLVector3(100f, 100f, 22f); + mov.Data.LookAt = new LLVector3(0.99f, 0.042f, 0); + + Console.WriteLine("Sending AgentMovementComplete packet"); + ControllingClient.OutPacket(mov); + } + + public void SendRegionHandshake(World RegionInfo) { + Console.WriteLine("Avatar.cs:SendRegionHandshake() - Creating empty RegionHandshake packet"); + System.Text.Encoding _enc = System.Text.Encoding.ASCII; + RegionHandshakePacket handshake = new RegionHandshakePacket(); + + Console.WriteLine("Avatar.cs:SendRegionhandshake() - Filling in RegionHandshake details"); + handshake.RegionInfo.BillableFactor = 0; + handshake.RegionInfo.IsEstateManager = false; + handshake.RegionInfo.TerrainHeightRange00 = 60; + handshake.RegionInfo.TerrainHeightRange01 = 60; + handshake.RegionInfo.TerrainHeightRange10 = 60; + handshake.RegionInfo.TerrainHeightRange11 = 60; + handshake.RegionInfo.TerrainStartHeight00 = 20; + handshake.RegionInfo.TerrainStartHeight01 = 20; + handshake.RegionInfo.TerrainStartHeight10 = 20; + handshake.RegionInfo.TerrainStartHeight11 = 20; + handshake.RegionInfo.SimAccess = 13; + handshake.RegionInfo.WaterHeight = 5; + handshake.RegionInfo.RegionFlags = 72458694; + handshake.RegionInfo.SimName = _enc.GetBytes(OpenSim_Main.cfg.RegionName + "\0"); + handshake.RegionInfo.SimOwner = new LLUUID("00000000-0000-0000-0000-000000000000"); + handshake.RegionInfo.TerrainBase0 = new LLUUID("b8d3965a-ad78-bf43-699b-bff8eca6c975"); + handshake.RegionInfo.TerrainBase1 = new LLUUID("abb783e6-3e93-26c0-248a-247666855da3"); + handshake.RegionInfo.TerrainBase2 = new LLUUID("179cdabd-398a-9b6b-1391-4dc333ba321f"); + handshake.RegionInfo.TerrainBase3 = new LLUUID("beb169c7-11ea-fff2-efe5-0f24dc881df2"); + handshake.RegionInfo.TerrainDetail0 = new LLUUID("00000000-0000-0000-0000-000000000000"); + handshake.RegionInfo.TerrainDetail1 = new LLUUID("00000000-0000-0000-0000-000000000000"); + handshake.RegionInfo.TerrainDetail2 = new LLUUID("00000000-0000-0000-0000-000000000000"); + handshake.RegionInfo.TerrainDetail3 = new LLUUID("00000000-0000-0000-0000-000000000000"); + handshake.RegionInfo.CacheID = new LLUUID("545ec0a5-5751-1026-8a0b-216e38a7ab37"); + + Console.WriteLine("Avatar.cs:SendRegionHandshake() - Sending RegionHandshake packet"); + this.ControllingClient.OutPacket(handshake); + } + } +} diff --git a/src/world/Entity.cs b/src/world/Entity.cs new file mode 100644 index 0000000..ab07fd6 --- /dev/null +++ b/src/world/Entity.cs @@ -0,0 +1,53 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Axiom.MathLib; +using OpenSim.types; + +namespace OpenSim.world +{ + public class Entity + { + protected libsecondlife.LLUUID uuid; + protected Vector3 position; + protected Vector3 velocity; + protected Quaternion rotation; + protected string name; + protected List children; + + public Entity() + { + uuid = new libsecondlife.LLUUID(); + position = new Vector3(); + velocity = new Vector3(); + rotation = new Quaternion(); + name = "(basic entity)"; + children = new List(); + } + + public virtual void update() { + // Do any per-frame updates needed that are applicable to every type of entity + foreach (Entity child in children) + { + child.update(); + } + } + + public virtual string getName() + { + return name; + } + + public virtual Mesh getMesh() + { + Mesh mesh = new Mesh(); + + foreach (Entity child in children) + { + mesh += child.getMesh(); + } + + return mesh; + } + } +} diff --git a/src/world/Primitive.cs b/src/world/Primitive.cs new file mode 100644 index 0000000..143fa55 --- /dev/null +++ b/src/world/Primitive.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Text; +using OpenSim.types; + +namespace OpenSim.world +{ + public class Primitive : Entity + { + protected float mesh_cutbegin; + protected float mesh_cutend; + + public Primitive() + { + mesh_cutbegin = 0.0f; + mesh_cutend = 1.0f; + } + + public override Mesh getMesh() + { + Mesh mesh = new Mesh(); + Triangle tri = new Triangle( + new Axiom.MathLib.Vector3(0.0f, 1.0f, 1.0f), + new Axiom.MathLib.Vector3(1.0f, 0.0f, 1.0f), + new Axiom.MathLib.Vector3(1.0f, 1.0f, 0.0f)); + + mesh.AddTri(tri); + mesh += base.getMesh(); + + return mesh; + } + } +} diff --git a/src/world/ScriptEngine.cs b/src/world/ScriptEngine.cs new file mode 100644 index 0000000..f20a08e --- /dev/null +++ b/src/world/ScriptEngine.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.world +{ + public class ScriptEngine + { + public ScriptEngine(World env) + { + } + + public void LoadScript() + { + + } + } +} diff --git a/src/world/SurfacePatch.cs b/src/world/SurfacePatch.cs new file mode 100644 index 0000000..71e4116 --- /dev/null +++ b/src/world/SurfacePatch.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.world +{ + public class SurfacePatch + { + public float[] HeightMap; + + public SurfacePatch() { + HeightMap = new float[16*16]; + + int xinc; + int yinc; + for(xinc=0; xinc<16; xinc++) for(yinc=0; yinc<16; yinc++) { + HeightMap[xinc+(yinc*16)]=100.0f; + } + + } + } +} diff --git a/src/world/World.cs b/src/world/World.cs new file mode 100644 index 0000000..cf337a8 --- /dev/null +++ b/src/world/World.cs @@ -0,0 +1,57 @@ +using System; +using libsecondlife; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.world +{ + public class World + { + public Dictionary Entities; + public SurfacePatch[] LandMap; + public ScriptEngine Scripts; + + public World() + { + Console.WriteLine("World.cs - creating new entitities instance"); + Entities = new Dictionary(); + + // We need a 16x16 array of 16m2 surface patches for a 256m2 sim + Console.WriteLine("World.cs - creating LandMap"); + LandMap = new SurfacePatch[16*16]; + int xinc; + int yinc; + for(xinc=0; xinc<16; xinc++) for(yinc=0; yinc<16; yinc++) { + LandMap[xinc+(yinc*16)]=new SurfacePatch(); + } + + Console.WriteLine("World.cs - Creating script engine instance"); + // Initialise this only after the world has loaded + Scripts = new ScriptEngine(this); + } + + public void Update() + { + foreach (libsecondlife.LLUUID UUID in Entities.Keys) + { + Entities[UUID].update(); + } + } + + public void AddViewerAgent(OpenSimClient AgentClient) { + Console.WriteLine("World.cs:AddViewerAgent() - Creating new avatar for remote viewer agent"); + Avatar NewAvatar = new Avatar(AgentClient); + Console.WriteLine("World.cs:AddViewerAgent() - Adding new avatar to world"); + this.Entities.Add(AgentClient.AgentID, NewAvatar); + Console.WriteLine("World.cs:AddViewerAgent() - Starting RegionHandshake "); + NewAvatar.SendRegionHandshake(this); + this.Update(); // will work for now, but needs to be optimised so we don't update everything in the sim for each new user + } + + public bool Backup() { + /* TODO: Save the current world entities state. */ + + return false; + } + } +} diff --git a/src/world/scripting/IScript.cs b/src/world/scripting/IScript.cs new file mode 100644 index 0000000..550594d --- /dev/null +++ b/src/world/scripting/IScript.cs @@ -0,0 +1,16 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace OpenSim.world.scripting +{ + public interface IScriptHost { + bool Register(IScript iscript); + } + public interface IScript + { + string Name{get;set;} + IScriptHost Host{get;set;} + void Show(); + } +} -- cgit v1.1