From 0b6f8a02a7d0927031bf812429770d6ecc5f483a Mon Sep 17 00:00:00 2001 From: jhurliman Date: Wed, 7 Mar 2007 05:09:18 +0000 Subject: * 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) --- src/Config.cs | 259 ++++++------ src/OpenSimClient.cs | 889 ++++++++++++++++++++++------------------- 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 | 137 ++++--- 9 files changed, 846 insertions(+), 1427 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 (limited to 'src') diff --git a/src/Config.cs b/src/Config.cs index 90753ef..9bb9296 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=""; - - 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; - } - - 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"); - 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 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(); - } - } + /// + /// 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 = true; + public string AssetURL = String.Empty; + public string AssetSendKey = String.Empty; + + public string GridURL = String.Empty; + public string GridSendKey = String.Empty; + + 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 655ebfe..497df00 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; - - //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; - - 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; - - lock (NeedAck) - { - foreach (Packet packet in NeedAck.Values) - { - if (now - packet.TickCount > RESEND_TIMEOUT) - { - - packet.Header.Resent = true; - OutPacket(packet); - } - } - } - } - - private void SendAcks() - { - lock (PendingAcks) - { - if (PendingAcks.Count > 0) - { - if (PendingAcks.Count > 250) - { - return; - } - - - - 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; - } - } - } - } - } - - - 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(); - } - } - } + /// + /// 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; + + //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; + + lock (NeedAck) + { + foreach (Packet packet in NeedAck.Values) + { + if (now - packet.TickCount > RESEND_TIMEOUT) + { + + packet.Header.Resent = true; + OutPacket(packet); + } + } + } + } + + private void SendAcks() + { + lock (PendingAcks) + { + if (PendingAcks.Count > 0) + { + if (PendingAcks.Count > 250) + { + return; + } + + + + 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; + } + } + } + } + } + + + 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 304f666..8d55e06 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 0000000..14581ee --- /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 1abbcf0..0000000 --- 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 26b2002..9d8d7d2 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 0000000..12af005 --- /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 1a34826..0000000 --- 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 83788cd..158ddc2 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"); + TerrainManager = new TerrainManager(new SecondLife()); + } - OpenSim_Main.localcons.WriteLine("World.cs - creating LandMap"); - terrainengine = new TerrainDecode(); - LandMap = new float[65536]; - + public void InitLoop() + { + OpenSim_Main.localcons.WriteLine("World.cs:StartLoop() - Initialising physics"); + this.physics = new PhysicsEngine(); + physics.Startup(); } - 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 DoStuff() + { + lock (this) + { + physics.DoStuff(this); + this.Update(); + } + } - public void Update() { + public void Update() + { foreach (libsecondlife.LLUUID UUID in Entities.Keys) { - 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); - } - }} - } + 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); + } + } + } + } } } - 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 SendLayerData(OpenSimClient RemoteClient) + { + int[] patches = new int[4]; - 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 - } + 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; - public bool Backup() { + 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; -- cgit v1.1