From 0b6f8a02a7d0927031bf812429770d6ecc5f483a Mon Sep 17 00:00:00 2001 From: jhurliman Date: Wed, 7 Mar 2007 05:09:18 +0000 Subject: [PATCH] * Updating libsecondlife.dll to the latest version with a working LayerData function * Reformatting some source files * Adding a try/catch sanity check around a phoning home check to osgrid.org * Updating the MSVC project file * Converted LayerData generation to use the functions built in to libsecondlife * Removing unused BitPack.cs and TerrainDecoder.cs files * Added a basic terrain generator (hills algorithm) --- bin/libsecondlife.dll | Bin 2338816 -> 2338816 bytes src/Config.cs | 249 +++++----- src/OpenSimClient.cs | 851 +++++++++++++++++---------------- src/Second-server.csproj | 4 +- src/VersionInfo.cs | 37 ++ src/types/BitPack.cs | 138 ------ src/world/Avatar.cs | 4 +- src/world/HeightmapGenHills.cs | 122 +++++ src/world/TerrainDecoder.cs | 683 -------------------------- src/world/World.cs | 139 +++--- 10 files changed, 823 insertions(+), 1404 deletions(-) create mode 100644 src/VersionInfo.cs delete mode 100644 src/types/BitPack.cs create mode 100644 src/world/HeightmapGenHills.cs delete mode 100644 src/world/TerrainDecoder.cs diff --git a/bin/libsecondlife.dll b/bin/libsecondlife.dll index c0c1f9c7972b1a6ab9933e6e56b1acc91ac04551..89d692a3243c9c653f4d3cdc627abad19a60cd1e 100755 GIT binary patch delta 29992 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 delta 29903 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 Bq-g*E diff --git a/src/Config.cs b/src/Config.cs index 90753efa37..9bb92962d0 100644 --- a/src/Config.cs +++ b/src/Config.cs @@ -36,128 +36,139 @@ 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 bool sandbox; - public string AssetURL=""; - public string AssetSendKey=""; - - public string GridURL=""; - public string GridSendKey=""; + /// + /// 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; - private IObjectContainer db; - - public void LoadDefaults() { - string tempstring; - OpenSim_Main.localcons.WriteLine("Config.cs:LoadDefaults() - Please press enter to retain default or enter new settings"); - - this.RegionName=OpenSim_Main.localcons.CmdPrompt("Name [OpenSim test]: ","OpenSim test"); - this.RegionLocX=(uint)Convert.ToInt32(OpenSim_Main.localcons.CmdPrompt("Grid Location X [997]: ","997")); - this.RegionLocY=(uint)Convert.ToInt32(OpenSim_Main.localcons.CmdPrompt("Grid Location Y [996]: ","996")); - this.IPListenPort=Convert.ToInt32(OpenSim_Main.localcons.CmdPrompt("UDP port for client connections [9000]: ","9000")); - this.IPListenAddr=OpenSim_Main.localcons.CmdPrompt("IP Address to listen on for client connections [127.0.0.1]: ","127.0.0.1"); - - - tempstring=OpenSim_Main.localcons.CmdPrompt("Run in sandbox or grid mode? [sandbox]: ","sandbox", "sandbox", "grid"); - if(tempstring=="grid"){ - this.sandbox = false; - } else if(tempstring=="sandbox"){ - this.sandbox=true; - } + public uint RegionLocX; + public uint RegionLocY; + public ulong RegionHandle; - if(!this.sandbox) { - this.AssetURL=OpenSim_Main.localcons.CmdPrompt("Asset server URL: "); - this.AssetSendKey=OpenSim_Main.localcons.CmdPrompt("Asset server key: "); - this.GridURL=OpenSim_Main.localcons.CmdPrompt("Grid server URL: "); - this.GridSendKey=OpenSim_Main.localcons.CmdPrompt("Grid server key: "); - } - this.RegionHandle = Helpers.UIntsToLong((RegionLocX*256), (RegionLocY*256)); - } + public int IPListenPort; + public string IPListenAddr; - public void InitConfig() { - try { - db = Db4oFactory.OpenFile("opensim.yap"); - IObjectSet result = db.Get(typeof(SimConfig)); - if(result.Count==1) { - OpenSim_Main.localcons.WriteLine("Config.cs:InitConfig() - Found a SimConfig object in the local database, loading"); - foreach (SimConfig cfg in result) { - this.sandbox = cfg.sandbox; - 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 { - OpenSim_Main.localcons.WriteLine("Config.cs:InitConfig() - Could not find object in database, loading precompiled defaults"); - LoadDefaults(); - OpenSim_Main.localcons.WriteLine("Writing out default settings to local database"); - db.Set(this); - } - } catch(Exception e) { - db.Close(); - OpenSim_Main.localcons.WriteLine("Config.cs:InitConfig() - Exception occured"); - OpenSim_Main.localcons.WriteLine(e.ToString()); - } - OpenSim_Main.localcons.WriteLine("Sim settings loaded:"); - OpenSim_Main.localcons.WriteLine("Name: " + this.RegionName); - OpenSim_Main.localcons.WriteLine("Region Location: [" + this.RegionLocX.ToString() + "," + this.RegionLocY + "]"); - OpenSim_Main.localcons.WriteLine("Region Handle: " + this.RegionHandle.ToString()); - OpenSim_Main.localcons.WriteLine("Listening on IP: " + this.IPListenAddr + ":" + this.IPListenPort); - OpenSim_Main.localcons.WriteLine("Sandbox Mode? " + this.sandbox.ToString()); - OpenSim_Main.localcons.WriteLine("Asset URL: " + this.AssetURL); - OpenSim_Main.localcons.WriteLine("Asset key: " + this.AssetSendKey); - OpenSim_Main.localcons.WriteLine("Grid URL: " + this.GridURL); - OpenSim_Main.localcons.WriteLine("Grid key: " + this.GridSendKey); - } - - public World LoadWorld() { - OpenSim_Main.localcons.WriteLine("Config.cs:LoadWorld() - Loading world...."); - World blank = new World(); - OpenSim_Main.localcons.WriteLine("Config.cs:LoadWorld() - Looking for a heightmap in local DB"); - IObjectSet world_result = db.Get(new float[65536]); - if(world_result.Count>0) { - OpenSim_Main.localcons.WriteLine("Config.cs:LoadWorld() - Found a heightmap in local database, loading"); - blank.LandMap=(float[])world_result.Next(); - } else { - OpenSim_Main.localcons.WriteLine("Config.cs:LoadWorld() - No heightmap found, generating new one"); - for(int i =0; i < 65536; i++) { - blank.LandMap[i] = 21.4989f; - } - OpenSim_Main.localcons.WriteLine("Config.cs:LoadWorld() - Saving heightmap to local database"); - db.Set(blank.LandMap); - db.Commit(); - } - return blank; - } + public bool sandbox = true; + public string AssetURL = String.Empty; + public string AssetSendKey = String.Empty; - public void LoadFromGrid() { - OpenSim_Main.localcons.WriteLine("Config.cs:LoadFromGrid() - dummy function, DOING ABSOLUTELY NOTHING AT ALL!!!"); - // TODO: Make this crap work - } + public string GridURL = String.Empty; + public string GridSendKey = String.Empty; - public void Shutdown() { - db.Close(); - } - } + private IObjectContainer db; + + public void LoadDefaults() + { + string tempstring; + OpenSim_Main.localcons.WriteLine("Config.cs:LoadDefaults() - Please press enter to retain default or enter new settings"); + + this.RegionName = OpenSim_Main.localcons.CmdPrompt("Name [OpenSim test]: ", "OpenSim test"); + this.RegionLocX = (uint)Convert.ToInt32(OpenSim_Main.localcons.CmdPrompt("Grid Location X [997]: ", "997")); + this.RegionLocY = (uint)Convert.ToInt32(OpenSim_Main.localcons.CmdPrompt("Grid Location Y [996]: ", "996")); + this.IPListenPort = Convert.ToInt32(OpenSim_Main.localcons.CmdPrompt("UDP port for client connections [9000]: ", "9000")); + this.IPListenAddr = OpenSim_Main.localcons.CmdPrompt("IP Address to listen on for client connections [127.0.0.1]: ", "127.0.0.1"); + + tempstring = OpenSim_Main.localcons.CmdPrompt("Run in sandbox or grid mode? [sandbox]: ", "sandbox", "sandbox", "grid"); + this.sandbox = tempstring.Equals("sandbox"); + + if (!this.sandbox) + { + this.AssetURL = OpenSim_Main.localcons.CmdPrompt("Asset server URL: "); + this.AssetSendKey = OpenSim_Main.localcons.CmdPrompt("Asset server key: "); + this.GridURL = OpenSim_Main.localcons.CmdPrompt("Grid server URL: "); + this.GridSendKey = OpenSim_Main.localcons.CmdPrompt("Grid server key: "); + } + this.RegionHandle = Helpers.UIntsToLong((RegionLocX * 256), (RegionLocY * 256)); + } + + public void InitConfig() + { + try + { + db = Db4oFactory.OpenFile("opensim.yap"); + IObjectSet result = db.Get(typeof(SimConfig)); + if (result.Count == 1) + { + OpenSim_Main.localcons.WriteLine("Config.cs:InitConfig() - Found a SimConfig object in the local database, loading"); + foreach (SimConfig cfg in result) + { + this.sandbox = cfg.sandbox; + 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 + { + OpenSim_Main.localcons.WriteLine("Config.cs:InitConfig() - Could not find object in database, loading precompiled defaults"); + LoadDefaults(); + OpenSim_Main.localcons.WriteLine("Writing out default settings to local database"); + db.Set(this); + } + } + catch (Exception e) + { + db.Close(); + OpenSim_Main.localcons.WriteLine("Config.cs:InitConfig() - Exception occured"); + OpenSim_Main.localcons.WriteLine(e.ToString()); + } + OpenSim_Main.localcons.WriteLine("Sim settings loaded:"); + OpenSim_Main.localcons.WriteLine("Name: " + this.RegionName); + OpenSim_Main.localcons.WriteLine("Region Location: [" + this.RegionLocX.ToString() + "," + this.RegionLocY + "]"); + OpenSim_Main.localcons.WriteLine("Region Handle: " + this.RegionHandle.ToString()); + OpenSim_Main.localcons.WriteLine("Listening on IP: " + this.IPListenAddr + ":" + this.IPListenPort); + OpenSim_Main.localcons.WriteLine("Sandbox Mode? " + this.sandbox.ToString()); + OpenSim_Main.localcons.WriteLine("Asset URL: " + this.AssetURL); + OpenSim_Main.localcons.WriteLine("Asset key: " + this.AssetSendKey); + OpenSim_Main.localcons.WriteLine("Grid URL: " + this.GridURL); + OpenSim_Main.localcons.WriteLine("Grid key: " + this.GridSendKey); + } + + public World LoadWorld() + { + OpenSim_Main.localcons.WriteLine("Config.cs:LoadWorld() - Loading world...."); + World blank = new World(); + OpenSim_Main.localcons.WriteLine("Config.cs:LoadWorld() - Looking for a heightmap in local DB"); + IObjectSet world_result = db.Get(new float[65536]); + if (world_result.Count > 0) + { + OpenSim_Main.localcons.WriteLine("Config.cs:LoadWorld() - Found a heightmap in local database, loading"); + blank.LandMap = (float[])world_result.Next(); + } + else + { + OpenSim_Main.localcons.WriteLine("Config.cs:LoadWorld() - No heightmap found, generating new one"); + HeightmapGenHills hills = new HeightmapGenHills(); + blank.LandMap = hills.GenerateHeightmap(200, 4.0f, 80.0f, false); + + OpenSim_Main.localcons.WriteLine("Config.cs:LoadWorld() - Saving heightmap to local database"); + db.Set(blank.LandMap); + db.Commit(); + } + return blank; + } + + public void LoadFromGrid() + { + OpenSim_Main.localcons.WriteLine("Config.cs:LoadFromGrid() - dummy function, DOING ABSOLUTELY NOTHING AT ALL!!!"); + // TODO: Make this crap work + } + + public void Shutdown() + { + db.Close(); + } + } } diff --git a/src/OpenSimClient.cs b/src/OpenSimClient.cs index 655ebfe9a7..497df000c8 100644 --- a/src/OpenSimClient.cs +++ b/src/OpenSimClient.cs @@ -37,425 +37,474 @@ 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; - public EndPoint userEP; - private BlockingQueue PacketQueue; - private BlockingQueue AssetRequests; - 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; - private Queue Inbox; - - 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; + /// + /// Handles new client connections + /// Constructor takes a single Packet and authenticates everything + /// + public class OpenSimClient + { - //OutPacket(ack_it); - - if (Pack.Header.Reliable) { - lock (PendingAcks) { - uint sequence = (uint)Pack.Header.Sequence; - if (!PendingAcks.ContainsKey(sequence)) { PendingAcks[sequence] = sequence; } - } - } - } - - public void AssetLoader() { - if(OpenSim_Main.cfg.sandbox==false) { - OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AssetLoader() - Starting new thread"); - TransferRequestPacket reqPacket = AssetRequests.Dequeue(); - OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AssetLoader() - Got a request, processing it"); - LLUUID AssetID = new LLUUID(reqPacket.TransferInfo.Params, 0); - WebRequest AssetLoad = WebRequest.Create(OpenSim_Main.cfg.AssetURL + "getasset/" + OpenSim_Main.cfg.AssetSendKey + "/" + AssetID + "/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(); - - TransferInfoPacket Transfer = new TransferInfoPacket(); - Transfer.TransferInfo.ChannelType = 2; - Transfer.TransferInfo.Status = 0; - Transfer.TransferInfo.TargetType = 0; - Transfer.TransferInfo.Params = reqPacket.TransferInfo.Params; - Transfer.TransferInfo.Size = (int)AssetResponse.ContentLength; - Transfer.TransferInfo.TransferID = reqPacket.TransferInfo.TransferID; - - OutPacket(Transfer); - - TransferPacketPacket TransferPacket = new TransferPacketPacket(); - TransferPacket.TransferData.Packet = 0; - TransferPacket.TransferData.ChannelType = 2; - TransferPacket.TransferData.TransferID=reqPacket.TransferInfo.TransferID; - - if(AssetResponse.ContentLength>1000) { - byte[] chunk = new byte[1000]; - Array.Copy(idata,chunk,1000); - TransferPacket.TransferData.Data = chunk; - TransferPacket.TransferData.Status = 0; - OutPacket(TransferPacket); - - TransferPacket = new TransferPacketPacket(); - TransferPacket.TransferData.Packet = 1; - TransferPacket.TransferData.ChannelType = 2; - TransferPacket.TransferData.TransferID = reqPacket.TransferInfo.TransferID; - byte[] chunk1 = new byte[(idata.Length-1000)]; - Array.Copy(idata, 1000, chunk1, 0, chunk1.Length); - TransferPacket.TransferData.Data = chunk1; - TransferPacket.TransferData.Status = 1; - OutPacket(TransferPacket); - } else { - TransferPacket.TransferData.Status = 1; - TransferPacket.TransferData.Data = idata; - OutPacket(TransferPacket); - } - AssetResponse.Close(); - } - } - - public void Logout() { - // TODO - kill any AssetLoaders - ClientThread.Abort(); - } - - public void ProcessInPacket(Packet Pack) { - ack_pack(Pack); - switch(Pack.Type) { - case PacketType.CompleteAgentMovement: - ClientAvatar.CompleteMovement(OpenSim_Main.local_world); - ClientAvatar.SendInitialPosition(); - break; - case PacketType.RegionHandshakeReply: - OpenSim_Main.local_world.SendLayerData(this); - break; - case PacketType.AgentWearablesRequest: - ClientAvatar.SendInitialAppearance(); - break; - case PacketType.TransferRequest: - OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ProcessInPacket() - Got transfer request"); - // We put transfer requests into a big queue and then spawn a thread for each new one - TransferRequestPacket transfer = (TransferRequestPacket)Pack; - AssetRequests.Enqueue(transfer); - Thread AssetLoaderThread = new Thread(new ThreadStart(AssetLoader)); - AssetLoaderThread.Start(); - break; - case PacketType.LogoutRequest: - OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ProcessInPacket() - Got a logout request"); - lock(OpenSim_Main.local_world.Entities) { - OpenSim_Main.local_world.Entities.Remove(this.AgentID); - } - - if(OpenSim_Main.cfg.sandbox==false) { - WebRequest DeleteSession = WebRequest.Create(OpenSim_Main.cfg.GridURL + "/usersessions/" + OpenSim_Main.cfg.GridSendKey + "/" + this.AgentID.ToString() + this.CircuitCode.ToString() + "/delete"); - WebResponse GridResponse = DeleteSession.GetResponse(); - StreamReader sr = new StreamReader(GridResponse.GetResponseStream()); - String grTest = sr.ReadLine(); - sr.Close(); - GridResponse.Close(); - OpenSim_Main.localcons.WriteLine("DEBUG: " + grTest); - } - this.ClientThread.Abort(); - break; - case PacketType.AgentUpdate: - ClientAvatar.HandleAgentUpdate((AgentUpdatePacket)Pack); - break; - case PacketType.ChatFromViewer: - ChatFromViewerPacket inchatpack = (ChatFromViewerPacket)Pack; - if(Helpers.FieldToString(inchatpack.ChatData.Message)=="") break; + public LLUUID AgentID; + public LLUUID SessionID; + public uint CircuitCode; + public world.Avatar ClientAvatar; + private UseCircuitCodePacket cirpack; + private Thread ClientThread; + public EndPoint userEP; + private BlockingQueue PacketQueue; + private BlockingQueue AssetRequests; + 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; + //private Queue Inbox; - System.Text.Encoding _enc = System.Text.Encoding.ASCII; - libsecondlife.Packets.ChatFromSimulatorPacket reply = new ChatFromSimulatorPacket(); - reply.ChatData.Audible = 1; - reply.ChatData.Message = inchatpack.ChatData.Message; - reply.ChatData.ChatType = 1; - reply.ChatData.SourceType = 1; - reply.ChatData.Position = this.ClientAvatar.position; - reply.ChatData.FromName = _enc.GetBytes(this.ClientAvatar.firstname + " " + this.ClientAvatar.lastname + "\0"); - reply.ChatData.OwnerID = this.AgentID; - reply.ChatData.SourceID = this.AgentID; - + 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 AssetLoader() + { + if (OpenSim_Main.cfg.sandbox == false) + { + WebResponse AssetResponse; + byte[] idata; + + OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AssetLoader() - Starting new thread"); + TransferRequestPacket reqPacket = AssetRequests.Dequeue(); + OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AssetLoader() - Got a request, processing it"); + LLUUID AssetID = new LLUUID(reqPacket.TransferInfo.Params, 0); + + try + { + WebRequest AssetLoad = WebRequest.Create(OpenSim_Main.cfg.AssetURL + "getasset/" + OpenSim_Main.cfg.AssetSendKey + "/" + AssetID + "/data"); + AssetResponse = AssetLoad.GetResponse(); + idata = new byte[(int)AssetResponse.ContentLength]; + BinaryReader br = new BinaryReader(AssetResponse.GetResponseStream()); + idata = br.ReadBytes((int)AssetResponse.ContentLength); + br.Close(); + } + catch (Exception e) + { + Console.WriteLine(e.ToString()); + return; + } + + TransferInfoPacket Transfer = new TransferInfoPacket(); + Transfer.TransferInfo.ChannelType = 2; + Transfer.TransferInfo.Status = 0; + Transfer.TransferInfo.TargetType = 0; + Transfer.TransferInfo.Params = reqPacket.TransferInfo.Params; + Transfer.TransferInfo.Size = (int)AssetResponse.ContentLength; + Transfer.TransferInfo.TransferID = reqPacket.TransferInfo.TransferID; + + OutPacket(Transfer); + + TransferPacketPacket TransferPacket = new TransferPacketPacket(); + TransferPacket.TransferData.Packet = 0; + TransferPacket.TransferData.ChannelType = 2; + TransferPacket.TransferData.TransferID = reqPacket.TransferInfo.TransferID; + + if (AssetResponse.ContentLength > 1000) + { + byte[] chunk = new byte[1000]; + Array.Copy(idata, chunk, 1000); + TransferPacket.TransferData.Data = chunk; + TransferPacket.TransferData.Status = 0; + OutPacket(TransferPacket); + + TransferPacket = new TransferPacketPacket(); + TransferPacket.TransferData.Packet = 1; + TransferPacket.TransferData.ChannelType = 2; + TransferPacket.TransferData.TransferID = reqPacket.TransferInfo.TransferID; + byte[] chunk1 = new byte[(idata.Length - 1000)]; + Array.Copy(idata, 1000, chunk1, 0, chunk1.Length); + TransferPacket.TransferData.Data = chunk1; + TransferPacket.TransferData.Status = 1; + OutPacket(TransferPacket); + } + else + { + TransferPacket.TransferData.Status = 1; + TransferPacket.TransferData.Data = idata; + OutPacket(TransferPacket); + } + AssetResponse.Close(); + } + } + + public void Logout() + { + // TODO - kill any AssetLoaders + ClientThread.Abort(); + } + + public void ProcessInPacket(Packet Pack) + { + ack_pack(Pack); + switch (Pack.Type) + { + case PacketType.CompleteAgentMovement: + ClientAvatar.CompleteMovement(OpenSim_Main.local_world); + ClientAvatar.SendInitialPosition(); + break; + case PacketType.RegionHandshakeReply: + OpenSim_Main.local_world.SendLayerData(this); + break; + case PacketType.AgentWearablesRequest: + ClientAvatar.SendInitialAppearance(); + break; + case PacketType.TransferRequest: + OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ProcessInPacket() - Got transfer request"); + // We put transfer requests into a big queue and then spawn a thread for each new one + TransferRequestPacket transfer = (TransferRequestPacket)Pack; + AssetRequests.Enqueue(transfer); + Thread AssetLoaderThread = new Thread(new ThreadStart(AssetLoader)); + AssetLoaderThread.Start(); + break; + case PacketType.LogoutRequest: + OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ProcessInPacket() - Got a logout request"); + lock (OpenSim_Main.local_world.Entities) + { + OpenSim_Main.local_world.Entities.Remove(this.AgentID); + } + + if (OpenSim_Main.cfg.sandbox == false) + { + WebRequest DeleteSession = WebRequest.Create(OpenSim_Main.cfg.GridURL + "/usersessions/" + OpenSim_Main.cfg.GridSendKey + "/" + this.AgentID.ToString() + this.CircuitCode.ToString() + "/delete"); + WebResponse GridResponse = DeleteSession.GetResponse(); + StreamReader sr = new StreamReader(GridResponse.GetResponseStream()); + String grTest = sr.ReadLine(); + sr.Close(); + GridResponse.Close(); + OpenSim_Main.localcons.WriteLine("DEBUG: " + grTest); + } + this.ClientThread.Abort(); + break; + case PacketType.AgentUpdate: + ClientAvatar.HandleAgentUpdate((AgentUpdatePacket)Pack); + break; + case PacketType.ChatFromViewer: + ChatFromViewerPacket inchatpack = (ChatFromViewerPacket)Pack; + if (Helpers.FieldToString(inchatpack.ChatData.Message) == "") break; + + System.Text.Encoding _enc = System.Text.Encoding.ASCII; + libsecondlife.Packets.ChatFromSimulatorPacket reply = new ChatFromSimulatorPacket(); + reply.ChatData.Audible = 1; + reply.ChatData.Message = inchatpack.ChatData.Message; + reply.ChatData.ChatType = 1; + reply.ChatData.SourceType = 1; + reply.ChatData.Position = this.ClientAvatar.position; + reply.ChatData.FromName = _enc.GetBytes(this.ClientAvatar.firstname + " " + this.ClientAvatar.lastname + "\0"); + reply.ChatData.OwnerID = this.AgentID; + reply.ChatData.SourceID = this.AgentID; - foreach(OpenSimClient client in OpenSim_Main.sim.ClientThreads.Values) { - client.OutPacket(reply); - } - break; - } - } - private void ResendUnacked() - { - int now = Environment.TickCount; + foreach (OpenSimClient client in OpenSim_Main.sim.ClientThreads.Values) + { + client.OutPacket(reply); + } + break; + } + } - lock (NeedAck) - { - foreach (Packet packet in NeedAck.Values) - { - if (now - packet.TickCount > RESEND_TIMEOUT) - { + private void ResendUnacked() + { + int now = Environment.TickCount; - packet.Header.Resent = true; - OutPacket(packet); - } - } - } - } + lock (NeedAck) + { + foreach (Packet packet in NeedAck.Values) + { + if (now - packet.TickCount > RESEND_TIMEOUT) + { - private void SendAcks() - { - lock (PendingAcks) - { - if (PendingAcks.Count > 0) - { - if (PendingAcks.Count > 250) - { - return; - } - - + packet.Header.Resent = true; + OutPacket(packet); + } + } + } + } - 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) //DIRTY HACK - { - 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; - } - } - } - } - } + private void SendAcks() + { + lock (PendingAcks) + { + if (PendingAcks.Count > 0) + { + if (PendingAcks.Count > 250) + { + return; + } - 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) { - OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ProcessOutPacket() - WARNING: Socket exception occurred on connection " + userEP.ToString() + " - killing thread"); - ClientThread.Abort(); - } - - } + int i = 0; + PacketAckPacket acks = new PacketAckPacket(); + acks.Packets = new PacketAckPacket.PacketsBlock[PendingAcks.Count]; - public void InPacket(Packet NewPack) { - // Handle appended ACKs - if (NewPack.Header.AppendedAcks) - { - lock (NeedAck) - { - foreach (uint ack in NewPack.Header.AckList) - { - OpenSim_Main.localcons.WriteLine("Got appended ack: "+ack); - NeedAck.Remove(ack); - } - } - } + foreach (uint ack in PendingAcks.Values) + { + acks.Packets[i] = new PacketAckPacket.PacketsBlock(); + acks.Packets[i].ID = ack; + i++; + } - // Handle PacketAck packets - if (NewPack.Type == PacketType.PacketAck) - { - PacketAckPacket ackPacket = (PacketAckPacket)NewPack; + acks.Header.Reliable = false; + OutPacket(acks); - 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); - } - - } + PendingAcks.Clear(); + } + } + } - public void OutPacket(Packet NewPack) { - QueItem item = new QueItem(); - item.Packet = NewPack; - item.Incoming = false; - this.PacketQueue.Enqueue(item); - } + private void AckTimer_Elapsed(object sender, ElapsedEventArgs ea) + { + SendAcks(); + ResendUnacked(); + } - public OpenSimClient(EndPoint remoteEP, UseCircuitCodePacket initialcirpack) { - OpenSim_Main.localcons.WriteLine("OpenSimClient.cs - Started up new client thread to handle incoming request"); - cirpack = initialcirpack; - userEP = remoteEP; - PacketQueue = new BlockingQueue(); - AssetRequests = new BlockingQueue(); - AckTimer = new System.Timers.Timer(500); - AckTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed); - AckTimer.Start(); + public void ProcessOutPacket(Packet Pack) + { - ClientThread = new Thread(new ThreadStart(AuthUser)); - ClientThread.IsBackground = true; - ClientThread.Start(); - } - - private void ClientLoop() { - OpenSim_Main.localcons.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); - } - } - } + // Keep track of when this packet was sent out + Pack.TickCount = Environment.TickCount; - private void InitNewClient() { - OpenSim_Main.localcons.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() { - if(OpenSim_Main.cfg.sandbox==false) { - OpenSim_Main.localcons.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"); - OpenSim_Main.localcons.WriteLine(OpenSim_Main.cfg.GridURL); - WebResponse GridResponse = CheckSession.GetResponse(); - StreamReader sr = new StreamReader(GridResponse.GetResponseStream()); - String grTest = sr.ReadLine(); - sr.Close(); - GridResponse.Close(); - if(String.IsNullOrEmpty(grTest) || grTest.Equals("1")) { // YAY! Valid login - OpenSim_Main.localcons.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 - OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AuthUser() - New user request denied to " + userEP.ToString()); - ClientThread.Abort(); - } - } else { - this.AgentID=cirpack.CircuitCode.ID; - this.SessionID=cirpack.CircuitCode.SessionID; - this.CircuitCode=cirpack.CircuitCode.Code; - InitNewClient(); - ClientLoop(); - } - } - } + 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) //DIRTY HACK + { + 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; + } + } + } + } + } + + + 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) + { + OpenSim_Main.localcons.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) + { + OpenSim_Main.localcons.WriteLine("Got appended ack: " + ack); + 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) + { + OpenSim_Main.localcons.WriteLine("OpenSimClient.cs - Started up new client thread to handle incoming request"); + cirpack = initialcirpack; + userEP = remoteEP; + PacketQueue = new BlockingQueue(); + AssetRequests = new BlockingQueue(); + AckTimer = new System.Timers.Timer(500); + AckTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed); + AckTimer.Start(); + + ClientThread = new Thread(new ThreadStart(AuthUser)); + ClientThread.IsBackground = true; + ClientThread.Start(); + } + + private void ClientLoop() + { + OpenSim_Main.localcons.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() + { + OpenSim_Main.localcons.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() + { + if (OpenSim_Main.cfg.sandbox == false) + { + OpenSim_Main.localcons.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"); + OpenSim_Main.localcons.WriteLine(OpenSim_Main.cfg.GridURL); + WebResponse GridResponse = CheckSession.GetResponse(); + StreamReader sr = new StreamReader(GridResponse.GetResponseStream()); + String grTest = sr.ReadLine(); + sr.Close(); + GridResponse.Close(); + if (String.IsNullOrEmpty(grTest) || grTest.Equals("1")) + { // YAY! Valid login + OpenSim_Main.localcons.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 + OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AuthUser() - New user request denied to " + userEP.ToString()); + ClientThread.Abort(); + } + } + else + { + this.AgentID = cirpack.CircuitCode.ID; + this.SessionID = cirpack.CircuitCode.SessionID; + this.CircuitCode = cirpack.CircuitCode.Code; + InitNewClient(); + ClientLoop(); + } + } + } } diff --git a/src/Second-server.csproj b/src/Second-server.csproj index 304f6660c4..8d55e06e04 100644 --- a/src/Second-server.csproj +++ b/src/Second-server.csproj @@ -46,19 +46,19 @@ - + + - diff --git a/src/VersionInfo.cs b/src/VersionInfo.cs new file mode 100644 index 0000000000..14581eeeb9 --- /dev/null +++ b/src/VersionInfo.cs @@ -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 = "0.0.1-unofficial"; + } +} diff --git a/src/types/BitPack.cs b/src/types/BitPack.cs deleted file mode 100644 index 1abbcf012e..0000000000 --- a/src/types/BitPack.cs +++ /dev/null @@ -1,138 +0,0 @@ -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/world/Avatar.cs b/src/world/Avatar.cs index 26b2002b3a..9d8d7d2322 100644 --- a/src/world/Avatar.cs +++ b/src/world/Avatar.cs @@ -226,8 +226,8 @@ namespace OpenSim.world handshake.RegionInfo.TerrainStartHeight10 = 10; handshake.RegionInfo.TerrainStartHeight11 = 10; handshake.RegionInfo.SimAccess = 13; - handshake.RegionInfo.WaterHeight = 5; - handshake.RegionInfo.RegionFlags = 72458694; + handshake.RegionInfo.WaterHeight = 20.0f; + handshake.RegionInfo.RegionFlags = 72458694; // TODO: WTF sirs? Use an enum! 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"); diff --git a/src/world/HeightmapGenHills.cs b/src/world/HeightmapGenHills.cs new file mode 100644 index 0000000000..12af005b0e --- /dev/null +++ b/src/world/HeightmapGenHills.cs @@ -0,0 +1,122 @@ +using System; + +namespace libsecondlife +{ + public class HeightmapGenHills + { + private Random Rand = new Random(); + private int NumHills; + private float HillMin; + private float HillMax; + private bool Island; + private float[] heightmap; + + public float[] GenerateHeightmap(int numHills, float hillMin, float hillMax, bool island) + { + NumHills = numHills; + HillMin = hillMin; + HillMax = hillMax; + Island = island; + + heightmap = new float[256 * 256]; + + for (int i = 0; i < numHills; i++) + { + AddHill(); + } + + Normalize(); + + return heightmap; + } + + private void AddHill() + { + float x, y; + float radius = RandomRange(HillMin, HillMax); + + if (Island) + { + // Which direction from the center of the map the hill is placed + float theta = RandomRange(0, 6.28f); + + // How far from the center of the map to place the hill. The radius + // is subtracted from the range to prevent any part of the hill from + // reaching the edge of the map + float distance = RandomRange(radius / 2.0f, 128.0f - radius); + + x = 128.0f + (float)Math.Cos(theta) * distance; + y = 128.0f + (float)Math.Sin(theta) * distance; + } + else + { + x = RandomRange(-radius, 256.0f + radius); + y = RandomRange(-radius, 256.0f + radius); + } + + float radiusSq = radius * radius; + float distSq; + float height; + + int xMin = (int)(x - radius) - 1; + int xMax = (int)(x + radius) + 1; + if (xMin < 0) xMin = 0; + if (xMax > 255) xMax = 255; + + int yMin = (int)(y - radius) - 1; + int yMax = (int)(y + radius) + 1; + if (yMin < 0) yMin = 0; + if (yMax > 255) yMax = 255; + + // Loop through each affected cell and determine the height at that point + for (int v = yMin; v <= yMax; ++v) + { + float fv = (float)v; + + for (int h = xMin; h <= xMax; ++h) + { + float fh = (float)h; + + // Determine how far from the center of this hill this point is + distSq = (x - fh) * (x - fh) + (y - fv) * (y - fv); + height = radiusSq - distSq; + + // Don't add negative hill values + if (height > 0.0f) heightmap[h + v * 256] += height; + } + } + } + + private void Normalize() + { + float min = heightmap[0]; + float max = heightmap[0]; + + for (int x = 0; x < 256; x++) + { + for (int y = 0; y < 256; y++) + { + if (heightmap[x + y * 256] < min) min = heightmap[x + y * 256]; + if (heightmap[x + y * 256] > max) max = heightmap[x + y * 256]; + } + } + + // Avoid a rare divide by zero + if (min != max) + { + for (int x = 0; x < 256; x++) + { + for (int y = 0; y < 256; y++) + { + heightmap[x + y * 256] = ((heightmap[x + y * 256] - min) / (max - min)) * (HillMax - HillMin); + } + } + } + } + + private float RandomRange(float min, float max) + { + return (float)Rand.NextDouble() * (max - min) + min; + } + } +} diff --git a/src/world/TerrainDecoder.cs b/src/world/TerrainDecoder.cs deleted file mode 100644 index 1a3482611f..0000000000 --- a/src/world/TerrainDecoder.cs +++ /dev/null @@ -1,683 +0,0 @@ -/* -* Copyright (c) OpenSim project, http://sim.opensecondlife.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; - -namespace OpenSim -{ - /// - /// Description of TerrainDecoder. - /// - public class TerrainDecode - { - - public enum LayerType : byte - { - Land = 0x4C, - Water = 0x57, - Wind = 0x37, - Cloud = 0x38 - } - - public struct GroupHeader - { - public int Stride; - public int PatchSize; - public LayerType Type; - } - - public struct PatchHeader - { - public float DCOffset; - public int Range; - public int QuantWBits; - public int PatchIDs; - public uint WordBits; - } - - public class Patch - { - public float[] Heightmap; - } - - - /// - /// - /// - /// - /// - /// - /// - /// - // public delegate void LandPatchCallback(Simulator simulator, int x, int y, int width, float[] data); - - - /// - /// - /// - //public event LandPatchCallback OnLandPatch; - - private Random RandomClass = new Random(); - - private const byte END_OF_PATCHES = 97; - private const int PATCHES_PER_EDGE = 16; - private const float OO_SQRT2 = 0.7071067811865475244008443621049f; - - //private SecondLife Client; - private Dictionary SimPatches = new Dictionary(); - private float[] DequantizeTable16 = new float[16 * 16]; - private float[] DequantizeTable32 = new float[32 * 32]; - private float[] ICosineTable16 = new float[16 * 16]; - private float[] ICosineTable32 = new float[32 * 32]; - private int[] DeCopyMatrix16 = new int[16 * 16]; - private int[] DeCopyMatrix32 = new int[32 * 32]; - - - /// - /// - /// - /// - public TerrainDecode() - { - - // Initialize the decompression tables - BuildDequantizeTable16(); - BuildDequantizeTable32(); - SetupICosines16(); - SetupICosines32(); - BuildDecopyMatrix16(); - BuildDecopyMatrix32(); - - } - - - private void BuildDequantizeTable16() - { - for (int j = 0; j < 16; j++) - { - for (int i = 0; i < 16; i++) - { - DequantizeTable16[j * 16 + i] = 1.0f + 2.0f * (float)(i + j); - } - } - } - - private void BuildDequantizeTable32() - { - for (int j = 0; j < 32; j++) - { - for (int i = 0; i < 32; i++) - { - DequantizeTable32[j * 32 + i] = 1.0f + 2.0f * (float)(i + j); - } - } - } - - private void SetupICosines16() - { - const float hposz = (float)Math.PI * 0.5f / 16.0f; - - for (int u = 0; u < 16; u++) - { - for (int n = 0; n < 16; n++) - { - ICosineTable16[u * 16 + n] = (float)Math.Cos((2.0f * (float)n + 1.0f) * (float)u * hposz); - } - } - } - - private void SetupICosines32() - { - const float hposz = (float)Math.PI * 0.5f / 32.0f; - - for (int u = 0; u < 32; u++) - { - for (int n = 0; n < 32; n++) - { - ICosineTable32[u * 32 + n] = (float)Math.Cos((2.0f * (float)n + 1.0f) * (float)u * hposz); - } - } - } - - private void BuildDecopyMatrix16() - { - bool diag = false; - bool right = true; - int i = 0; - int j = 0; - int count = 0; - - while (i < 16 && j < 16) - { - DeCopyMatrix16[j * 16 + i] = count++; - - if (!diag) - { - if (right) - { - if (i < 16 - 1) i++; - else j++; - - right = false; - diag = true; - } - else - { - if (j < 16 - 1) j++; - else i++; - - right = true; - diag = true; - } - } - else - { - if (right) - { - i++; - j--; - if (i == 16 - 1 || j == 0) diag = false; - } - else - { - i--; - j++; - if (j == 16 - 1 || i == 0) diag = false; - } - } - } - } - - private void BuildDecopyMatrix32() - { - bool diag = false; - bool right = true; - int i = 0; - int j = 0; - int count = 0; - - while (i < 32 && j < 32) - { - DeCopyMatrix32[j * 32 + i] = count++; - - if (!diag) - { - if (right) - { - if (i < 32 - 1) i++; - else j++; - - right = false; - diag = true; - } - else - { - if (j < 32 - 1) j++; - else i++; - - right = true; - diag = true; - } - } - else - { - if (right) - { - i++; - j--; - if (i == 32 - 1 || j == 0) diag = false; - } - else - { - i--; - j++; - if (j == 32 - 1 || i == 0) diag = false; - } - } - } - } - - private void EncodePatchHeader(BitPacker bitpack, PatchHeader header) - { - bitpack.PackBits(header.QuantWBits,8); - - if (header.QuantWBits == END_OF_PATCHES) - return; - - bitpack.PackFloat(header.DCOffset); - bitpack.PackBits(header.Range,16); - bitpack.PackBits(header.PatchIDs,10); - - } - - public void DCTLine16(float[] In, float[] Out, int line) - { - int N =16; - int lineSize = line * 16; - - for(int k = 0; k < N;k++) - { - float sum = 0.0f; - for(int n = 0; n < N; n++) - { - float num = (float)(Math.PI*k*(2.0f*n+1)/(2*N)); - float cosine = (float)Math.Cos(num); - float product = In[lineSize +n] * cosine; - sum += product; - } - - float alpha; - if(k == 0) - { - alpha = (float)(1.0f/Math.Sqrt(2)); - } - else - { - alpha = 1; - } - Out[lineSize + k] =(float)( sum * alpha ); - - } - } - public void DCTColumn16(float[] In, float[] Out, int Column) - { - int N =16; - int uSize; - - for(int k = 0; k < N; k++){ - float sum = 0.0f; - for(int n = 0; n < N; n++) - { - uSize = n * 16; - float num = (float)(Math.PI*k*(2.0f*n+1)/(2*N)); - float cosine = (float)Math.Cos(num); - float product = In[uSize + Column] * cosine; - sum += product; - } - - float alpha; - if(k == 0) - { - alpha = (float)(1.0f/Math.Sqrt(2)); - } - else - { - alpha = 1; - } - Out[16 * k + Column] = (float)( sum * alpha * (2.0f /N)); - - } - } - - private void EncodePatch(int[] patches, BitPacker bitpack, int size) - { - int lastnum =0; - for(int n = 0; n < size * size; n++) - { - if(patches[n]!=0) - lastnum=n; - } - for (int n = 0; n < lastnum+1; n++) - { - if(patches[n] != 0) - { - bitpack.PackBits(1,1); //value or EOB - bitpack.PackBits(1,1); //value - if(patches[n] > 0) - { - - bitpack.PackBits(0,1); // positive - bitpack.PackBits(patches[n],13); - - } - else - { - bitpack.PackBits(1,1); // negative - - int temp = patches[n] * -1; - bitpack.PackBits(temp,13); - - } - } - else - { - bitpack.PackBits(0,1); // no value - } - } - - bitpack.PackBits(1,1); //value or EOB - bitpack.PackBits(0,1); // EOB - } - - public int[] CompressPatch(float[] patches) - { - int size = 16; - float[] block = new float[size * size]; - int[] output = new int[size * size]; - int prequant = (139 >> 4) + 2; - int quantize = 1 << prequant; - float ooq = 1.0f / (float)quantize; - float mult = ooq * (float)1; - float addval = mult * (float)(1 << (prequant - 1)) + 20.4989f; - - if (size == 16) - { - for (int n = 0; n < 16 * 16; n++) - { - block[n] = (float)((patches[n] - addval)/ mult); - } - - float[] ftemp = new float[32 * 32]; - - for (int o = 0; o < 16; o++) - this.DCTColumn16(block, ftemp, o); - for (int o = 0; o < 16; o++) - this.DCTLine16(ftemp, block, o); - } - - for (int j = 0; j < block.Length; j++) - { - output[DeCopyMatrix16[j]] = (int)(block[j] / DequantizeTable16[j]); - } - - return output; - } - - public Packet CreateLayerPacket(float[] heightmap, int minX, int minY, int maxX, int maxY) - { - //int minX = 0, maxX = 2, minY = 0, maxY = 1; //these should be passed to this function - LayerDataPacket layer = new LayerDataPacket(); - byte[] Encoded = new byte[2048]; - layer.LayerID.Type = 76; - GroupHeader header = new GroupHeader(); - header.Stride = 264; - header.PatchSize = 16; - header.Type = LayerType.Land; - BitPacker newpack = new BitPacker(Encoded,0); - newpack.PackBits(header.Stride,16); - newpack.PackBits(header.PatchSize,8); - newpack.PackBits((int)header.Type,8); - - - float[] height; - for(int y = minY; y< maxY; y++) - { - for(int x = minX ; x < maxX ; x++) - { - height = new float[256]; - Array.Copy(heightmap, (4096 *y) +(x *256), height, 0, 256); - - this.CreatePatch(height, newpack, x, y); - } - } - - PatchHeader headers = new PatchHeader(); - headers.QuantWBits = END_OF_PATCHES; - this.EncodePatchHeader(newpack, headers); - - int lastused=0; - for(int i = 0; i < 2048 ; i++) - { - if(Encoded[i] !=0) - lastused = i; - } - - byte[] data = new byte[lastused+1]; - Array.Copy(Encoded, data, lastused+1); - layer.LayerData.Data =data; - - return(layer); - } - public void CreatePatch(float[] heightmap, BitPacker newpack, int x, int y) - { - PatchHeader header = new PatchHeader(); - header.DCOffset = 20.4989f; - header.QuantWBits = 139; - header.Range = 1; - header.PatchIDs = (y & 0x1F); - header.PatchIDs += x <<5 ; - - this.EncodePatchHeader(newpack, header); - - int[] newpatch = this.CompressPatch(heightmap); - this.EncodePatch(newpatch, newpack, 16); - - } - } - - //*************************************************** - public class BitPacker - { - private const int MAX_BITS = 8; - - private byte[] Data; - public int bytePos; - public int bitPos; - - /// - /// Default constructor, initialize the bit packer / bit unpacker - /// with a byte array and starting position - /// - /// Byte array to pack bits in to or unpack from - /// Starting position in the byte array - public BitPacker(byte[] data, int pos) - { - Data = data; - bytePos = pos; - } - - /// - /// Pack a floating point value in to the data - /// - /// Floating point value to pack - public void PackFloat(float data) - { - byte[] input = BitConverter.GetBytes(data); - PackBitArray(input, 32); - } - - /// - /// Pack part or all of an integer in to the data - /// - /// Integer containing the data to pack - /// Number of bits of the integer to pack - public void PackBits(int data, int totalCount) - { - byte[] input = BitConverter.GetBytes(data); - PackBitArray(input, totalCount); - } - - /// - /// Unpacking a floating point value from the data - /// - /// Unpacked floating point value - public float UnpackFloat() - { - byte[] output = UnpackBitsArray(32); - - if (!BitConverter.IsLittleEndian) Array.Reverse(output); - return BitConverter.ToSingle(output, 0); - } - - /// - /// Unpack a variable number of bits from the data in to integer format - /// - /// Number of bits to unpack - /// An integer containing the unpacked bits - /// This function is only useful up to 32 bits - public int UnpackBits(int totalCount) - { - byte[] output = UnpackBitsArray(totalCount); - - if (!BitConverter.IsLittleEndian) Array.Reverse(output); - return BitConverter.ToInt32(output, 0); - } - - private void PackBitArray(byte[] data, int totalCount) - { - int count = 0; - 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) - { - switch(count) - { - case 1: - if ((data[curBytePos] & (0x01)) != 0) - { - Data[bytePos] |= (byte)(0x80 >> bitPos); - } - break; - case 2: - if ((data[curBytePos] & (0x02)) != 0) - { - Data[bytePos] |= (byte)(0x80 >> bitPos); - } - break; - case 3: - if ((data[curBytePos] & (0x04)) != 0) - { - Data[bytePos] |= (byte)(0x80 >> bitPos); - } - break; - case 4: - if ((data[curBytePos] & (0x08)) != 0) - { - Data[bytePos] |= (byte)(0x80 >> bitPos); - } - break; - case 5: - if ((data[curBytePos] & (0x10)) != 0) - { - Data[bytePos] |= (byte)(0x80 >> bitPos); - } - break; - case 6: - if ((data[curBytePos] & (0x20)) != 0) - { - Data[bytePos] |= (byte)(0x80 >> bitPos); - } - break; - case 7: - if ((data[curBytePos] & (0x40)) != 0) - { - Data[bytePos] |= (byte)(0x80 >> bitPos); - } - break; - case 8: - if ((data[curBytePos] & (0x80)) != 0) - { - Data[bytePos] |= (byte)(0x80 >> bitPos); - } - break; - } - - bitPos++; - --count; - ++curBitPos; - - if (bitPos >= MAX_BITS) - { - bitPos = 0; - ++bytePos; - } - if (curBitPos >= MAX_BITS) - { - curBitPos = 0; - ++curBytePos; - } - } - } - } - - - 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/world/World.cs b/src/world/World.cs index 83788cd2fa..158ddc2a1c 100644 --- a/src/world/World.cs +++ b/src/world/World.cs @@ -1,9 +1,9 @@ using System; using System.Threading; -using libsecondlife; -using libsecondlife.Packets; using System.Collections.Generic; using System.Text; +using libsecondlife; +using libsecondlife.Packets; namespace OpenSim.world { @@ -12,77 +12,98 @@ namespace OpenSim.world public Dictionary Entities; public float[] LandMap; public ScriptEngine Scripts; - public TerrainDecode terrainengine = new TerrainDecode(); - public uint _localNumber=0; - public PhysicsEngine physics; - + public uint _localNumber = 0; + public PhysicsEngine physics; + + private libsecondlife.TerrainManager TerrainManager; private Random Rand = new Random(); public World() { - OpenSim_Main.localcons.WriteLine("World.cs - creating new entitities instance"); - Entities = new Dictionary(); + OpenSim_Main.localcons.WriteLine("World.cs - creating new entitities instance"); + Entities = new Dictionary(); - OpenSim_Main.localcons.WriteLine("World.cs - creating LandMap"); - terrainengine = new TerrainDecode(); - LandMap = new float[65536]; - + OpenSim_Main.localcons.WriteLine("World.cs - creating LandMap"); + TerrainManager = new TerrainManager(new SecondLife()); } - public void InitLoop() { - OpenSim_Main.localcons.WriteLine("World.cs:StartLoop() - Initialising physics"); - this.physics = new PhysicsEngine(); - physics.Startup(); - } - - public void DoStuff() { - lock(this) { - physics.DoStuff(this); - this.Update(); - } - } + public void InitLoop() + { + OpenSim_Main.localcons.WriteLine("World.cs:StartLoop() - Initialising physics"); + this.physics = new PhysicsEngine(); + physics.Startup(); + } - public void Update() { - foreach (libsecondlife.LLUUID UUID in Entities.Keys) + public void DoStuff() + { + lock (this) { - if(Entities[UUID].needupdate) { - Entities[UUID].update(); - - if(Entities[UUID] is Avatar) { - Avatar avatar=(Avatar)Entities[UUID]; - if((avatar.oldpos!=avatar.position) || (avatar.oldvel!=avatar.velocity) || avatar.walking) { - ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = Entities[UUID].CreateTerseBlock(); - foreach(OpenSimClient client in OpenSim_Main.sim.ClientThreads.Values) { - ImprovedTerseObjectUpdatePacket terse = new ImprovedTerseObjectUpdatePacket(); - terse.RegionData.RegionHandle = OpenSim_Main.cfg.RegionHandle; // FIXME - terse.RegionData.TimeDilation = 0; - terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; - terse.ObjectData[0] = terseBlock; - client.OutPacket(terse); - } - }} - } + physics.DoStuff(this); + this.Update(); } } - public void SendLayerData(OpenSimClient RemoteClient) { - for(int x=0; x<16; x=x+4) for(int y=0; y<16; y++){ - Packet layerpack=this.terrainengine.CreateLayerPacket(LandMap, x,y,x+4,y+1); - RemoteClient.OutPacket(layerpack); - } - } + public void Update() + { + foreach (libsecondlife.LLUUID UUID in Entities.Keys) + { + if (Entities[UUID].needupdate) + { + Entities[UUID].update(); - public void AddViewerAgent(OpenSimClient AgentClient) { - OpenSim_Main.localcons.WriteLine("World.cs:AddViewerAgent() - Creating new avatar for remote viewer agent"); - Avatar NewAvatar = new Avatar(AgentClient); - OpenSim_Main.localcons.WriteLine("World.cs:AddViewerAgent() - Adding new avatar to world"); - this.Entities.Add(AgentClient.AgentID, NewAvatar); - OpenSim_Main.localcons.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 - } + if (Entities[UUID] is Avatar) + { + Avatar avatar = (Avatar)Entities[UUID]; + if ((avatar.oldpos != avatar.position) || (avatar.oldvel != avatar.velocity) || avatar.walking) + { + ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = Entities[UUID].CreateTerseBlock(); + foreach (OpenSimClient client in OpenSim_Main.sim.ClientThreads.Values) + { + ImprovedTerseObjectUpdatePacket terse = new ImprovedTerseObjectUpdatePacket(); + terse.RegionData.RegionHandle = OpenSim_Main.cfg.RegionHandle; // FIXME + terse.RegionData.TimeDilation = 0; + terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; + terse.ObjectData[0] = terseBlock; + client.OutPacket(terse); + } + } + } + } + } + } - public bool Backup() { + public void SendLayerData(OpenSimClient RemoteClient) + { + int[] patches = new int[4]; + + for (int y = 0; y < 16; y++) + { + for (int x = 0; x < 16; x = x + 4) + { + patches[0] = x + 0 + y * 16; + patches[1] = x + 1 + y * 16; + patches[2] = x + 2 + y * 16; + patches[3] = x + 3 + y * 16; + + Packet layerpack = TerrainManager.CreateLandPacket(LandMap, patches); + RemoteClient.OutPacket(layerpack); + } + } + } + + public void AddViewerAgent(OpenSimClient AgentClient) + { + OpenSim_Main.localcons.WriteLine("World.cs:AddViewerAgent() - Creating new avatar for remote viewer agent"); + Avatar NewAvatar = new Avatar(AgentClient); + OpenSim_Main.localcons.WriteLine("World.cs:AddViewerAgent() - Adding new avatar to world"); + this.Entities.Add(AgentClient.AgentID, NewAvatar); + OpenSim_Main.localcons.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;