aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/Config.cs259
-rw-r--r--src/OpenSimClient.cs889
-rw-r--r--src/Second-server.csproj4
-rw-r--r--src/VersionInfo.cs37
-rw-r--r--src/types/BitPack.cs138
-rw-r--r--src/world/Avatar.cs4
-rw-r--r--src/world/HeightmapGenHills.cs122
-rw-r--r--src/world/TerrainDecoder.cs683
-rw-r--r--src/world/World.cs137
9 files changed, 846 insertions, 1427 deletions
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;
36 36
37namespace OpenSim 37namespace OpenSim
38{ 38{
39 /// <summary> 39 /// <summary>
40 /// This class handles connection to the underlying database used for configuration of the region. 40 /// This class handles connection to the underlying database used for configuration of the region.
41 /// Region content is also stored by this class. The main entry point is InitConfig() which attempts to locate 41 /// Region content is also stored by this class. The main entry point is InitConfig() which attempts to locate
42 /// opensim.yap in the current working directory. If opensim.yap can not be found, default settings are loaded from 42 /// opensim.yap in the current working directory. If opensim.yap can not be found, default settings are loaded from
43 /// what is hardcoded here and then saved into opensim.yap for future startups. 43 /// what is hardcoded here and then saved into opensim.yap for future startups.
44 /// </summary> 44 /// </summary>
45 public class SimConfig 45 public class SimConfig
46 { 46 {
47 public string RegionName; 47 public string RegionName;
48 48
49 public uint RegionLocX; 49 public uint RegionLocX;
50 public uint RegionLocY; 50 public uint RegionLocY;
51 public ulong RegionHandle; 51 public ulong RegionHandle;
52 52
53 public int IPListenPort; 53 public int IPListenPort;
54 public string IPListenAddr; 54 public string IPListenAddr;
55 55
56 public bool sandbox; 56 public bool sandbox = true;
57 public string AssetURL=""; 57 public string AssetURL = String.Empty;
58 public string AssetSendKey=""; 58 public string AssetSendKey = String.Empty;
59 59
60 public string GridURL=""; 60 public string GridURL = String.Empty;
61 public string GridSendKey=""; 61 public string GridSendKey = String.Empty;
62 62
63 private IObjectContainer db; 63 private IObjectContainer db;
64 64
65 public void LoadDefaults() { 65 public void LoadDefaults()
66 string tempstring; 66 {
67 OpenSim_Main.localcons.WriteLine("Config.cs:LoadDefaults() - Please press enter to retain default or enter new settings"); 67 string tempstring;
68 68 OpenSim_Main.localcons.WriteLine("Config.cs:LoadDefaults() - Please press enter to retain default or enter new settings");
69 this.RegionName=OpenSim_Main.localcons.CmdPrompt("Name [OpenSim test]: ","OpenSim test"); 69
70 this.RegionLocX=(uint)Convert.ToInt32(OpenSim_Main.localcons.CmdPrompt("Grid Location X [997]: ","997")); 70 this.RegionName = OpenSim_Main.localcons.CmdPrompt("Name [OpenSim test]: ", "OpenSim test");
71 this.RegionLocY=(uint)Convert.ToInt32(OpenSim_Main.localcons.CmdPrompt("Grid Location Y [996]: ","996")); 71 this.RegionLocX = (uint)Convert.ToInt32(OpenSim_Main.localcons.CmdPrompt("Grid Location X [997]: ", "997"));
72 this.IPListenPort=Convert.ToInt32(OpenSim_Main.localcons.CmdPrompt("UDP port for client connections [9000]: ","9000")); 72 this.RegionLocY = (uint)Convert.ToInt32(OpenSim_Main.localcons.CmdPrompt("Grid Location Y [996]: ", "996"));
73 this.IPListenAddr=OpenSim_Main.localcons.CmdPrompt("IP Address to listen on for client connections [127.0.0.1]: ","127.0.0.1"); 73 this.IPListenPort = Convert.ToInt32(OpenSim_Main.localcons.CmdPrompt("UDP port for client connections [9000]: ", "9000"));
74 74 this.IPListenAddr = OpenSim_Main.localcons.CmdPrompt("IP Address to listen on for client connections [127.0.0.1]: ", "127.0.0.1");
75 75
76 tempstring=OpenSim_Main.localcons.CmdPrompt("Run in sandbox or grid mode? [sandbox]: ","sandbox", "sandbox", "grid"); 76 tempstring = OpenSim_Main.localcons.CmdPrompt("Run in sandbox or grid mode? [sandbox]: ", "sandbox", "sandbox", "grid");
77 if(tempstring=="grid"){ 77 this.sandbox = tempstring.Equals("sandbox");
78 this.sandbox = false; 78
79 } else if(tempstring=="sandbox"){ 79 if (!this.sandbox)
80 this.sandbox=true; 80 {
81 } 81 this.AssetURL = OpenSim_Main.localcons.CmdPrompt("Asset server URL: ");
82 82 this.AssetSendKey = OpenSim_Main.localcons.CmdPrompt("Asset server key: ");
83 if(!this.sandbox) { 83 this.GridURL = OpenSim_Main.localcons.CmdPrompt("Grid server URL: ");
84 this.AssetURL=OpenSim_Main.localcons.CmdPrompt("Asset server URL: "); 84 this.GridSendKey = OpenSim_Main.localcons.CmdPrompt("Grid server key: ");
85 this.AssetSendKey=OpenSim_Main.localcons.CmdPrompt("Asset server key: "); 85 }
86 this.GridURL=OpenSim_Main.localcons.CmdPrompt("Grid server URL: "); 86 this.RegionHandle = Helpers.UIntsToLong((RegionLocX * 256), (RegionLocY * 256));
87 this.GridSendKey=OpenSim_Main.localcons.CmdPrompt("Grid server key: "); 87 }
88 } 88
89 this.RegionHandle = Helpers.UIntsToLong((RegionLocX*256), (RegionLocY*256)); 89 public void InitConfig()
90 } 90 {
91 91 try
92 public void InitConfig() { 92 {
93 try { 93 db = Db4oFactory.OpenFile("opensim.yap");
94 db = Db4oFactory.OpenFile("opensim.yap"); 94 IObjectSet result = db.Get(typeof(SimConfig));
95 IObjectSet result = db.Get(typeof(SimConfig)); 95 if (result.Count == 1)
96 if(result.Count==1) { 96 {
97 OpenSim_Main.localcons.WriteLine("Config.cs:InitConfig() - Found a SimConfig object in the local database, loading"); 97 OpenSim_Main.localcons.WriteLine("Config.cs:InitConfig() - Found a SimConfig object in the local database, loading");
98 foreach (SimConfig cfg in result) { 98 foreach (SimConfig cfg in result)
99 this.sandbox = cfg.sandbox; 99 {
100 this.RegionName = cfg.RegionName; 100 this.sandbox = cfg.sandbox;
101 this.RegionLocX = cfg.RegionLocX; 101 this.RegionName = cfg.RegionName;
102 this.RegionLocY = cfg.RegionLocY; 102 this.RegionLocX = cfg.RegionLocX;
103 this.RegionHandle = Helpers.UIntsToLong((RegionLocX*256), (RegionLocY*256)); 103 this.RegionLocY = cfg.RegionLocY;
104 this.IPListenPort = cfg.IPListenPort; 104 this.RegionHandle = Helpers.UIntsToLong((RegionLocX * 256), (RegionLocY * 256));
105 this.IPListenAddr = cfg.IPListenAddr; 105 this.IPListenPort = cfg.IPListenPort;
106 this.AssetURL = cfg.AssetURL; 106 this.IPListenAddr = cfg.IPListenAddr;
107 this.AssetSendKey = cfg.AssetSendKey; 107 this.AssetURL = cfg.AssetURL;
108 this.GridURL = cfg.GridURL; 108 this.AssetSendKey = cfg.AssetSendKey;
109 this.GridSendKey = cfg.GridSendKey; 109 this.GridURL = cfg.GridURL;
110 } 110 this.GridSendKey = cfg.GridSendKey;
111 } else { 111 }
112 OpenSim_Main.localcons.WriteLine("Config.cs:InitConfig() - Could not find object in database, loading precompiled defaults"); 112 }
113 LoadDefaults(); 113 else
114 OpenSim_Main.localcons.WriteLine("Writing out default settings to local database"); 114 {
115 db.Set(this); 115 OpenSim_Main.localcons.WriteLine("Config.cs:InitConfig() - Could not find object in database, loading precompiled defaults");
116 } 116 LoadDefaults();
117 } catch(Exception e) { 117 OpenSim_Main.localcons.WriteLine("Writing out default settings to local database");
118 db.Close(); 118 db.Set(this);
119 OpenSim_Main.localcons.WriteLine("Config.cs:InitConfig() - Exception occured"); 119 }
120 OpenSim_Main.localcons.WriteLine(e.ToString()); 120 }
121 } 121 catch (Exception e)
122 OpenSim_Main.localcons.WriteLine("Sim settings loaded:"); 122 {
123 OpenSim_Main.localcons.WriteLine("Name: " + this.RegionName); 123 db.Close();
124 OpenSim_Main.localcons.WriteLine("Region Location: [" + this.RegionLocX.ToString() + "," + this.RegionLocY + "]"); 124 OpenSim_Main.localcons.WriteLine("Config.cs:InitConfig() - Exception occured");
125 OpenSim_Main.localcons.WriteLine("Region Handle: " + this.RegionHandle.ToString()); 125 OpenSim_Main.localcons.WriteLine(e.ToString());
126 OpenSim_Main.localcons.WriteLine("Listening on IP: " + this.IPListenAddr + ":" + this.IPListenPort); 126 }
127 OpenSim_Main.localcons.WriteLine("Sandbox Mode? " + this.sandbox.ToString()); 127 OpenSim_Main.localcons.WriteLine("Sim settings loaded:");
128 OpenSim_Main.localcons.WriteLine("Asset URL: " + this.AssetURL); 128 OpenSim_Main.localcons.WriteLine("Name: " + this.RegionName);
129 OpenSim_Main.localcons.WriteLine("Asset key: " + this.AssetSendKey); 129 OpenSim_Main.localcons.WriteLine("Region Location: [" + this.RegionLocX.ToString() + "," + this.RegionLocY + "]");
130 OpenSim_Main.localcons.WriteLine("Grid URL: " + this.GridURL); 130 OpenSim_Main.localcons.WriteLine("Region Handle: " + this.RegionHandle.ToString());
131 OpenSim_Main.localcons.WriteLine("Grid key: " + this.GridSendKey); 131 OpenSim_Main.localcons.WriteLine("Listening on IP: " + this.IPListenAddr + ":" + this.IPListenPort);
132 } 132 OpenSim_Main.localcons.WriteLine("Sandbox Mode? " + this.sandbox.ToString());
133 133 OpenSim_Main.localcons.WriteLine("Asset URL: " + this.AssetURL);
134 public World LoadWorld() { 134 OpenSim_Main.localcons.WriteLine("Asset key: " + this.AssetSendKey);
135 OpenSim_Main.localcons.WriteLine("Config.cs:LoadWorld() - Loading world...."); 135 OpenSim_Main.localcons.WriteLine("Grid URL: " + this.GridURL);
136 World blank = new World(); 136 OpenSim_Main.localcons.WriteLine("Grid key: " + this.GridSendKey);
137 OpenSim_Main.localcons.WriteLine("Config.cs:LoadWorld() - Looking for a heightmap in local DB"); 137 }
138 IObjectSet world_result = db.Get(new float[65536]); 138
139 if(world_result.Count>0) { 139 public World LoadWorld()
140 OpenSim_Main.localcons.WriteLine("Config.cs:LoadWorld() - Found a heightmap in local database, loading"); 140 {
141 blank.LandMap=(float[])world_result.Next(); 141 OpenSim_Main.localcons.WriteLine("Config.cs:LoadWorld() - Loading world....");
142 } else { 142 World blank = new World();
143 OpenSim_Main.localcons.WriteLine("Config.cs:LoadWorld() - No heightmap found, generating new one"); 143 OpenSim_Main.localcons.WriteLine("Config.cs:LoadWorld() - Looking for a heightmap in local DB");
144 for(int i =0; i < 65536; i++) { 144 IObjectSet world_result = db.Get(new float[65536]);
145 blank.LandMap[i] = 21.4989f; 145 if (world_result.Count > 0)
146 } 146 {
147 OpenSim_Main.localcons.WriteLine("Config.cs:LoadWorld() - Saving heightmap to local database"); 147 OpenSim_Main.localcons.WriteLine("Config.cs:LoadWorld() - Found a heightmap in local database, loading");
148 db.Set(blank.LandMap); 148 blank.LandMap = (float[])world_result.Next();
149 db.Commit(); 149 }
150 } 150 else
151 return blank; 151 {
152 } 152 OpenSim_Main.localcons.WriteLine("Config.cs:LoadWorld() - No heightmap found, generating new one");
153 153 HeightmapGenHills hills = new HeightmapGenHills();
154 public void LoadFromGrid() { 154 blank.LandMap = hills.GenerateHeightmap(200, 4.0f, 80.0f, false);
155 OpenSim_Main.localcons.WriteLine("Config.cs:LoadFromGrid() - dummy function, DOING ABSOLUTELY NOTHING AT ALL!!!"); 155
156 // TODO: Make this crap work 156 OpenSim_Main.localcons.WriteLine("Config.cs:LoadWorld() - Saving heightmap to local database");
157 } 157 db.Set(blank.LandMap);
158 158 db.Commit();
159 public void Shutdown() { 159 }
160 db.Close(); 160 return blank;
161 } 161 }
162 } 162
163 public void LoadFromGrid()
164 {
165 OpenSim_Main.localcons.WriteLine("Config.cs:LoadFromGrid() - dummy function, DOING ABSOLUTELY NOTHING AT ALL!!!");
166 // TODO: Make this crap work
167 }
168
169 public void Shutdown()
170 {
171 db.Close();
172 }
173 }
163} 174}
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;
37 37
38namespace OpenSim 38namespace OpenSim
39{ 39{
40 /// <summary> 40 /// <summary>
41 /// Handles new client connections 41 /// Handles new client connections
42 /// Constructor takes a single Packet and authenticates everything 42 /// Constructor takes a single Packet and authenticates everything
43 /// </summary> 43 /// </summary>
44 public class OpenSimClient { 44 public class OpenSimClient
45 45 {
46 public LLUUID AgentID; 46
47 public LLUUID SessionID; 47 public LLUUID AgentID;
48 public uint CircuitCode; 48 public LLUUID SessionID;
49 public world.Avatar ClientAvatar; 49 public uint CircuitCode;
50 private UseCircuitCodePacket cirpack; 50 public world.Avatar ClientAvatar;
51 private Thread ClientThread; 51 private UseCircuitCodePacket cirpack;
52 public EndPoint userEP; 52 private Thread ClientThread;
53 private BlockingQueue<QueItem> PacketQueue; 53 public EndPoint userEP;
54 private BlockingQueue<TransferRequestPacket> AssetRequests; 54 private BlockingQueue<QueItem> PacketQueue;
55 private Dictionary<uint, uint> PendingAcks = new Dictionary<uint, uint>(); 55 private BlockingQueue<TransferRequestPacket> AssetRequests;
56 private Dictionary<uint, Packet> NeedAck = new Dictionary<uint, Packet>(); 56 private Dictionary<uint, uint> PendingAcks = new Dictionary<uint, uint>();
57 private System.Timers.Timer AckTimer; 57 private Dictionary<uint, Packet> NeedAck = new Dictionary<uint, Packet>();
58 private uint Sequence = 0; 58 private System.Timers.Timer AckTimer;
59 private object SequenceLock = new object(); 59 private uint Sequence = 0;
60 private const int MAX_APPENDED_ACKS = 10; 60 private object SequenceLock = new object();
61 private const int RESEND_TIMEOUT = 4000; 61 private const int MAX_APPENDED_ACKS = 10;
62 private const int MAX_SEQUENCE = 0xFFFFFF; 62 private const int RESEND_TIMEOUT = 4000;
63 private Queue<uint> Inbox; 63 private const int MAX_SEQUENCE = 0xFFFFFF;
64 64 //private Queue<uint> Inbox;
65 public void ack_pack(Packet Pack) { 65
66 //libsecondlife.Packets.PacketAckPacket ack_it = new PacketAckPacket(); 66 public void ack_pack(Packet Pack)
67 //ack_it.Packets = new PacketAckPacket.PacketsBlock[1]; 67 {
68 //ack_it.Packets[0] = new PacketAckPacket.PacketsBlock(); 68 //libsecondlife.Packets.PacketAckPacket ack_it = new PacketAckPacket();
69 //ack_it.Packets[0].ID = Pack.Header.ID; 69 //ack_it.Packets = new PacketAckPacket.PacketsBlock[1];
70 //ack_it.Header.Reliable = false; 70 //ack_it.Packets[0] = new PacketAckPacket.PacketsBlock();
71 71 //ack_it.Packets[0].ID = Pack.Header.ID;
72 //OutPacket(ack_it); 72 //ack_it.Header.Reliable = false;
73 73
74 if (Pack.Header.Reliable) { 74 //OutPacket(ack_it);
75 lock (PendingAcks) { 75
76 uint sequence = (uint)Pack.Header.Sequence; 76 if (Pack.Header.Reliable)
77 if (!PendingAcks.ContainsKey(sequence)) { PendingAcks[sequence] = sequence; } 77 {
78 } 78 lock (PendingAcks)
79 } 79 {
80 } 80 uint sequence = (uint)Pack.Header.Sequence;
81 81 if (!PendingAcks.ContainsKey(sequence)) { PendingAcks[sequence] = sequence; }
82 public void AssetLoader() { 82 }
83 if(OpenSim_Main.cfg.sandbox==false) { 83 }
84 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AssetLoader() - Starting new thread"); 84 }
85 TransferRequestPacket reqPacket = AssetRequests.Dequeue(); 85
86 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AssetLoader() - Got a request, processing it"); 86 public void AssetLoader()
87 LLUUID AssetID = new LLUUID(reqPacket.TransferInfo.Params, 0); 87 {
88 WebRequest AssetLoad = WebRequest.Create(OpenSim_Main.cfg.AssetURL + "getasset/" + OpenSim_Main.cfg.AssetSendKey + "/" + AssetID + "/data"); 88 if (OpenSim_Main.cfg.sandbox == false)
89 WebResponse AssetResponse = AssetLoad.GetResponse(); 89 {
90 byte[] idata = new byte[(int)AssetResponse.ContentLength]; 90 WebResponse AssetResponse;
91 BinaryReader br = new BinaryReader(AssetResponse.GetResponseStream()); 91 byte[] idata;
92 idata = br.ReadBytes((int)AssetResponse.ContentLength); 92
93 br.Close(); 93 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AssetLoader() - Starting new thread");
94 94 TransferRequestPacket reqPacket = AssetRequests.Dequeue();
95 TransferInfoPacket Transfer = new TransferInfoPacket(); 95 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AssetLoader() - Got a request, processing it");
96 Transfer.TransferInfo.ChannelType = 2; 96 LLUUID AssetID = new LLUUID(reqPacket.TransferInfo.Params, 0);
97 Transfer.TransferInfo.Status = 0; 97
98 Transfer.TransferInfo.TargetType = 0; 98 try
99 Transfer.TransferInfo.Params = reqPacket.TransferInfo.Params; 99 {
100 Transfer.TransferInfo.Size = (int)AssetResponse.ContentLength; 100 WebRequest AssetLoad = WebRequest.Create(OpenSim_Main.cfg.AssetURL + "getasset/" + OpenSim_Main.cfg.AssetSendKey + "/" + AssetID + "/data");
101 Transfer.TransferInfo.TransferID = reqPacket.TransferInfo.TransferID; 101 AssetResponse = AssetLoad.GetResponse();
102 102 idata = new byte[(int)AssetResponse.ContentLength];
103 OutPacket(Transfer); 103 BinaryReader br = new BinaryReader(AssetResponse.GetResponseStream());
104 104 idata = br.ReadBytes((int)AssetResponse.ContentLength);
105 TransferPacketPacket TransferPacket = new TransferPacketPacket(); 105 br.Close();
106 TransferPacket.TransferData.Packet = 0; 106 }
107 TransferPacket.TransferData.ChannelType = 2; 107 catch (Exception e)
108 TransferPacket.TransferData.TransferID=reqPacket.TransferInfo.TransferID; 108 {
109 109 Console.WriteLine(e.ToString());
110 if(AssetResponse.ContentLength>1000) { 110 return;
111 byte[] chunk = new byte[1000]; 111 }
112 Array.Copy(idata,chunk,1000); 112
113 TransferPacket.TransferData.Data = chunk; 113 TransferInfoPacket Transfer = new TransferInfoPacket();
114 TransferPacket.TransferData.Status = 0; 114 Transfer.TransferInfo.ChannelType = 2;
115 OutPacket(TransferPacket); 115 Transfer.TransferInfo.Status = 0;
116 116 Transfer.TransferInfo.TargetType = 0;
117 TransferPacket = new TransferPacketPacket(); 117 Transfer.TransferInfo.Params = reqPacket.TransferInfo.Params;
118 TransferPacket.TransferData.Packet = 1; 118 Transfer.TransferInfo.Size = (int)AssetResponse.ContentLength;
119 TransferPacket.TransferData.ChannelType = 2; 119 Transfer.TransferInfo.TransferID = reqPacket.TransferInfo.TransferID;
120 TransferPacket.TransferData.TransferID = reqPacket.TransferInfo.TransferID; 120
121 byte[] chunk1 = new byte[(idata.Length-1000)]; 121 OutPacket(Transfer);
122 Array.Copy(idata, 1000, chunk1, 0, chunk1.Length); 122
123 TransferPacket.TransferData.Data = chunk1; 123 TransferPacketPacket TransferPacket = new TransferPacketPacket();
124 TransferPacket.TransferData.Status = 1; 124 TransferPacket.TransferData.Packet = 0;
125 OutPacket(TransferPacket); 125 TransferPacket.TransferData.ChannelType = 2;
126 } else { 126 TransferPacket.TransferData.TransferID = reqPacket.TransferInfo.TransferID;
127 TransferPacket.TransferData.Status = 1; 127
128 TransferPacket.TransferData.Data = idata; 128 if (AssetResponse.ContentLength > 1000)
129 OutPacket(TransferPacket); 129 {
130 } 130 byte[] chunk = new byte[1000];
131 AssetResponse.Close(); 131 Array.Copy(idata, chunk, 1000);
132 } 132 TransferPacket.TransferData.Data = chunk;
133 } 133 TransferPacket.TransferData.Status = 0;
134 134 OutPacket(TransferPacket);
135 public void Logout() { 135
136 // TODO - kill any AssetLoaders 136 TransferPacket = new TransferPacketPacket();
137 ClientThread.Abort(); 137 TransferPacket.TransferData.Packet = 1;
138 } 138 TransferPacket.TransferData.ChannelType = 2;
139 139 TransferPacket.TransferData.TransferID = reqPacket.TransferInfo.TransferID;
140 public void ProcessInPacket(Packet Pack) { 140 byte[] chunk1 = new byte[(idata.Length - 1000)];
141 ack_pack(Pack); 141 Array.Copy(idata, 1000, chunk1, 0, chunk1.Length);
142 switch(Pack.Type) { 142 TransferPacket.TransferData.Data = chunk1;
143 case PacketType.CompleteAgentMovement: 143 TransferPacket.TransferData.Status = 1;
144 ClientAvatar.CompleteMovement(OpenSim_Main.local_world); 144 OutPacket(TransferPacket);
145 ClientAvatar.SendInitialPosition(); 145 }
146 break; 146 else
147 case PacketType.RegionHandshakeReply: 147 {
148 OpenSim_Main.local_world.SendLayerData(this); 148 TransferPacket.TransferData.Status = 1;
149 break; 149 TransferPacket.TransferData.Data = idata;
150 case PacketType.AgentWearablesRequest: 150 OutPacket(TransferPacket);
151 ClientAvatar.SendInitialAppearance(); 151 }
152 break; 152 AssetResponse.Close();
153 case PacketType.TransferRequest: 153 }
154 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ProcessInPacket() - Got transfer request"); 154 }
155 // We put transfer requests into a big queue and then spawn a thread for each new one 155
156 TransferRequestPacket transfer = (TransferRequestPacket)Pack; 156 public void Logout()
157 AssetRequests.Enqueue(transfer); 157 {
158 Thread AssetLoaderThread = new Thread(new ThreadStart(AssetLoader)); 158 // TODO - kill any AssetLoaders
159 AssetLoaderThread.Start(); 159 ClientThread.Abort();
160 break; 160 }
161 case PacketType.LogoutRequest: 161
162 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ProcessInPacket() - Got a logout request"); 162 public void ProcessInPacket(Packet Pack)
163 lock(OpenSim_Main.local_world.Entities) { 163 {
164 OpenSim_Main.local_world.Entities.Remove(this.AgentID); 164 ack_pack(Pack);
165 } 165 switch (Pack.Type)
166 166 {
167 if(OpenSim_Main.cfg.sandbox==false) { 167 case PacketType.CompleteAgentMovement:
168 WebRequest DeleteSession = WebRequest.Create(OpenSim_Main.cfg.GridURL + "/usersessions/" + OpenSim_Main.cfg.GridSendKey + "/" + this.AgentID.ToString() + this.CircuitCode.ToString() + "/delete"); 168 ClientAvatar.CompleteMovement(OpenSim_Main.local_world);
169 WebResponse GridResponse = DeleteSession.GetResponse(); 169 ClientAvatar.SendInitialPosition();
170 StreamReader sr = new StreamReader(GridResponse.GetResponseStream()); 170 break;
171 String grTest = sr.ReadLine(); 171 case PacketType.RegionHandshakeReply:
172 sr.Close(); 172 OpenSim_Main.local_world.SendLayerData(this);
173 GridResponse.Close(); 173 break;
174 OpenSim_Main.localcons.WriteLine("DEBUG: " + grTest); 174 case PacketType.AgentWearablesRequest:
175 } 175 ClientAvatar.SendInitialAppearance();
176 this.ClientThread.Abort(); 176 break;
177 break; 177 case PacketType.TransferRequest:
178 case PacketType.AgentUpdate: 178 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ProcessInPacket() - Got transfer request");
179 ClientAvatar.HandleAgentUpdate((AgentUpdatePacket)Pack); 179 // We put transfer requests into a big queue and then spawn a thread for each new one
180 break; 180 TransferRequestPacket transfer = (TransferRequestPacket)Pack;
181 case PacketType.ChatFromViewer: 181 AssetRequests.Enqueue(transfer);
182 ChatFromViewerPacket inchatpack = (ChatFromViewerPacket)Pack; 182 Thread AssetLoaderThread = new Thread(new ThreadStart(AssetLoader));
183 if(Helpers.FieldToString(inchatpack.ChatData.Message)=="") break; 183 AssetLoaderThread.Start();
184 184 break;
185 System.Text.Encoding _enc = System.Text.Encoding.ASCII; 185 case PacketType.LogoutRequest:
186 libsecondlife.Packets.ChatFromSimulatorPacket reply = new ChatFromSimulatorPacket(); 186 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ProcessInPacket() - Got a logout request");
187 reply.ChatData.Audible = 1; 187 lock (OpenSim_Main.local_world.Entities)
188 reply.ChatData.Message = inchatpack.ChatData.Message; 188 {
189 reply.ChatData.ChatType = 1; 189 OpenSim_Main.local_world.Entities.Remove(this.AgentID);
190 reply.ChatData.SourceType = 1; 190 }
191 reply.ChatData.Position = this.ClientAvatar.position; 191
192 reply.ChatData.FromName = _enc.GetBytes(this.ClientAvatar.firstname + " " + this.ClientAvatar.lastname + "\0"); 192 if (OpenSim_Main.cfg.sandbox == false)
193 reply.ChatData.OwnerID = this.AgentID; 193 {
194 reply.ChatData.SourceID = this.AgentID; 194 WebRequest DeleteSession = WebRequest.Create(OpenSim_Main.cfg.GridURL + "/usersessions/" + OpenSim_Main.cfg.GridSendKey + "/" + this.AgentID.ToString() + this.CircuitCode.ToString() + "/delete");
195 195 WebResponse GridResponse = DeleteSession.GetResponse();
196 196 StreamReader sr = new StreamReader(GridResponse.GetResponseStream());
197 197 String grTest = sr.ReadLine();
198 foreach(OpenSimClient client in OpenSim_Main.sim.ClientThreads.Values) { 198 sr.Close();
199 client.OutPacket(reply); 199 GridResponse.Close();
200 } 200 OpenSim_Main.localcons.WriteLine("DEBUG: " + grTest);
201 break; 201 }
202 } 202 this.ClientThread.Abort();
203 } 203 break;
204 204 case PacketType.AgentUpdate:
205 private void ResendUnacked() 205 ClientAvatar.HandleAgentUpdate((AgentUpdatePacket)Pack);
206 { 206 break;
207 int now = Environment.TickCount; 207 case PacketType.ChatFromViewer:
208 208 ChatFromViewerPacket inchatpack = (ChatFromViewerPacket)Pack;
209 lock (NeedAck) 209 if (Helpers.FieldToString(inchatpack.ChatData.Message) == "") break;
210 { 210
211 foreach (Packet packet in NeedAck.Values) 211 System.Text.Encoding _enc = System.Text.Encoding.ASCII;
212 { 212 libsecondlife.Packets.ChatFromSimulatorPacket reply = new ChatFromSimulatorPacket();
213 if (now - packet.TickCount > RESEND_TIMEOUT) 213 reply.ChatData.Audible = 1;
214 { 214 reply.ChatData.Message = inchatpack.ChatData.Message;
215 215 reply.ChatData.ChatType = 1;
216 packet.Header.Resent = true; 216 reply.ChatData.SourceType = 1;
217 OutPacket(packet); 217 reply.ChatData.Position = this.ClientAvatar.position;
218 } 218 reply.ChatData.FromName = _enc.GetBytes(this.ClientAvatar.firstname + " " + this.ClientAvatar.lastname + "\0");
219 } 219 reply.ChatData.OwnerID = this.AgentID;
220 } 220 reply.ChatData.SourceID = this.AgentID;
221 } 221
222 222
223 private void SendAcks() 223
224 { 224 foreach (OpenSimClient client in OpenSim_Main.sim.ClientThreads.Values)
225 lock (PendingAcks) 225 {
226 { 226 client.OutPacket(reply);
227 if (PendingAcks.Count > 0) 227 }
228 { 228 break;
229 if (PendingAcks.Count > 250) 229 }
230 { 230 }
231 return; 231
232 } 232 private void ResendUnacked()
233 233 {
234 234 int now = Environment.TickCount;
235 235
236 int i = 0; 236 lock (NeedAck)
237 PacketAckPacket acks = new PacketAckPacket(); 237 {
238 acks.Packets = new PacketAckPacket.PacketsBlock[PendingAcks.Count]; 238 foreach (Packet packet in NeedAck.Values)
239 239 {
240 foreach (uint ack in PendingAcks.Values) 240 if (now - packet.TickCount > RESEND_TIMEOUT)
241 { 241 {
242 acks.Packets[i] = new PacketAckPacket.PacketsBlock(); 242
243 acks.Packets[i].ID = ack; 243 packet.Header.Resent = true;
244 i++; 244 OutPacket(packet);
245 } 245 }
246 246 }
247 acks.Header.Reliable = false; 247 }
248 OutPacket(acks); 248 }
249 249
250 PendingAcks.Clear(); 250 private void SendAcks()
251 } 251 {
252 } 252 lock (PendingAcks)
253 } 253 {
254 254 if (PendingAcks.Count > 0)
255 private void AckTimer_Elapsed(object sender, ElapsedEventArgs ea) 255 {
256 { 256 if (PendingAcks.Count > 250)
257 SendAcks(); 257 {
258 ResendUnacked(); 258 return;
259 } 259 }
260 260
261 public void ProcessOutPacket(Packet Pack) { 261
262 262
263 // Keep track of when this packet was sent out 263 int i = 0;
264 Pack.TickCount = Environment.TickCount; 264 PacketAckPacket acks = new PacketAckPacket();
265 265 acks.Packets = new PacketAckPacket.PacketsBlock[PendingAcks.Count];
266 if (!Pack.Header.Resent) 266
267 { 267 foreach (uint ack in PendingAcks.Values)
268 // Set the sequence number 268 {
269 lock (SequenceLock) 269 acks.Packets[i] = new PacketAckPacket.PacketsBlock();
270 { 270 acks.Packets[i].ID = ack;
271 if (Sequence >= MAX_SEQUENCE) 271 i++;
272 Sequence = 1; 272 }
273 else 273
274 Sequence++; 274 acks.Header.Reliable = false;
275 Pack.Header.Sequence = Sequence; 275 OutPacket(acks);
276 } 276
277 277 PendingAcks.Clear();
278 if (Pack.Header.Reliable) //DIRTY HACK 278 }
279 { 279 }
280 lock (NeedAck) 280 }
281 { 281
282 if (!NeedAck.ContainsKey(Pack.Header.Sequence)) 282 private void AckTimer_Elapsed(object sender, ElapsedEventArgs ea)
283 { 283 {
284 NeedAck.Add(Pack.Header.Sequence, Pack); 284 SendAcks();
285 } 285 ResendUnacked();
286 else 286 }
287 { 287
288 // Client.Log("Attempted to add a duplicate sequence number (" + 288 public void ProcessOutPacket(Packet Pack)
289 // packet.Header.Sequence + ") to the NeedAck dictionary for packet type " + 289 {
290 // packet.Type.ToString(), Helpers.LogLevel.Warning); 290
291 } 291 // Keep track of when this packet was sent out
292 } 292 Pack.TickCount = Environment.TickCount;
293 293
294 // Don't append ACKs to resent packets, in case that's what was causing the 294 if (!Pack.Header.Resent)
295 // delivery to fail 295 {
296 if (!Pack.Header.Resent) 296 // Set the sequence number
297 { 297 lock (SequenceLock)
298 // Append any ACKs that need to be sent out to this packet 298 {
299 lock (PendingAcks) 299 if (Sequence >= MAX_SEQUENCE)
300 { 300 Sequence = 1;
301 if (PendingAcks.Count > 0 && PendingAcks.Count < MAX_APPENDED_ACKS && 301 else
302 Pack.Type != PacketType.PacketAck && 302 Sequence++;
303 Pack.Type != PacketType.LogoutRequest) 303 Pack.Header.Sequence = Sequence;
304 { 304 }
305 Pack.Header.AckList = new uint[PendingAcks.Count]; 305
306 int i = 0; 306 if (Pack.Header.Reliable) //DIRTY HACK
307 307 {
308 foreach (uint ack in PendingAcks.Values) 308 lock (NeedAck)
309 { 309 {
310 Pack.Header.AckList[i] = ack; 310 if (!NeedAck.ContainsKey(Pack.Header.Sequence))
311 i++; 311 {
312 } 312 NeedAck.Add(Pack.Header.Sequence, Pack);
313 313 }
314 PendingAcks.Clear(); 314 else
315 Pack.Header.AppendedAcks = true; 315 {
316 } 316 // Client.Log("Attempted to add a duplicate sequence number (" +
317 } 317 // packet.Header.Sequence + ") to the NeedAck dictionary for packet type " +
318 } 318 // packet.Type.ToString(), Helpers.LogLevel.Warning);
319 } 319 }
320 } 320 }
321 321
322 322 // Don't append ACKs to resent packets, in case that's what was causing the
323 byte[] ZeroOutBuffer = new byte[4096]; 323 // delivery to fail
324 byte[] sendbuffer; 324 if (!Pack.Header.Resent)
325 sendbuffer = Pack.ToBytes(); 325 {
326 326 // Append any ACKs that need to be sent out to this packet
327 try { 327 lock (PendingAcks)
328 if (Pack.Header.Zerocoded) { 328 {
329 int packetsize = Helpers.ZeroEncode(sendbuffer, sendbuffer.Length, ZeroOutBuffer); 329 if (PendingAcks.Count > 0 && PendingAcks.Count < MAX_APPENDED_ACKS &&
330 OpenSim_Main.Server.SendTo(ZeroOutBuffer, packetsize, SocketFlags.None,userEP); 330 Pack.Type != PacketType.PacketAck &&
331 } else { 331 Pack.Type != PacketType.LogoutRequest)
332 OpenSim_Main.Server.SendTo(sendbuffer, sendbuffer.Length, SocketFlags.None,userEP); 332 {
333 } 333 Pack.Header.AckList = new uint[PendingAcks.Count];
334 } catch (Exception) { 334 int i = 0;
335 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ProcessOutPacket() - WARNING: Socket exception occurred on connection " + userEP.ToString() + " - killing thread"); 335
336 ClientThread.Abort(); 336 foreach (uint ack in PendingAcks.Values)
337 } 337 {
338 338 Pack.Header.AckList[i] = ack;
339 } 339 i++;
340 340 }
341 public void InPacket(Packet NewPack) { 341
342 // Handle appended ACKs 342 PendingAcks.Clear();
343 if (NewPack.Header.AppendedAcks) 343 Pack.Header.AppendedAcks = true;
344 { 344 }
345 lock (NeedAck) 345 }
346 { 346 }
347 foreach (uint ack in NewPack.Header.AckList) 347 }
348 { 348 }
349 OpenSim_Main.localcons.WriteLine("Got appended ack: "+ack); 349
350 NeedAck.Remove(ack); 350
351 } 351 byte[] ZeroOutBuffer = new byte[4096];
352 } 352 byte[] sendbuffer;
353 } 353 sendbuffer = Pack.ToBytes();
354 354
355 // Handle PacketAck packets 355 try
356 if (NewPack.Type == PacketType.PacketAck) 356 {
357 { 357 if (Pack.Header.Zerocoded)
358 PacketAckPacket ackPacket = (PacketAckPacket)NewPack; 358 {
359 359 int packetsize = Helpers.ZeroEncode(sendbuffer, sendbuffer.Length, ZeroOutBuffer);
360 lock (NeedAck) 360 OpenSim_Main.Server.SendTo(ZeroOutBuffer, packetsize, SocketFlags.None, userEP);
361 { 361 }
362 foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets) 362 else
363 { 363 {
364 NeedAck.Remove(block.ID); 364 OpenSim_Main.Server.SendTo(sendbuffer, sendbuffer.Length, SocketFlags.None, userEP);
365 } 365 }
366 } 366 }
367 } else if( ( NewPack.Type == PacketType.StartPingCheck ) ) { 367 catch (Exception)
368 //reply to pingcheck 368 {
369 libsecondlife.Packets.StartPingCheckPacket startPing = (libsecondlife.Packets.StartPingCheckPacket)NewPack; 369 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ProcessOutPacket() - WARNING: Socket exception occurred on connection " + userEP.ToString() + " - killing thread");
370 libsecondlife.Packets.CompletePingCheckPacket endPing = new CompletePingCheckPacket(); 370 ClientThread.Abort();
371 endPing.PingID.PingID = startPing.PingID.PingID; 371 }
372 OutPacket(endPing); 372
373 } 373 }
374 else 374
375 { 375 public void InPacket(Packet NewPack)
376 QueItem item = new QueItem(); 376 {
377 item.Packet = NewPack; 377 // Handle appended ACKs
378 item.Incoming = true; 378 if (NewPack.Header.AppendedAcks)
379 this.PacketQueue.Enqueue(item); 379 {
380 } 380 lock (NeedAck)
381 381 {
382 } 382 foreach (uint ack in NewPack.Header.AckList)
383 383 {
384 public void OutPacket(Packet NewPack) { 384 OpenSim_Main.localcons.WriteLine("Got appended ack: " + ack);
385 QueItem item = new QueItem(); 385 NeedAck.Remove(ack);
386 item.Packet = NewPack; 386 }
387 item.Incoming = false; 387 }
388 this.PacketQueue.Enqueue(item); 388 }
389 } 389
390 390 // Handle PacketAck packets
391 public OpenSimClient(EndPoint remoteEP, UseCircuitCodePacket initialcirpack) { 391 if (NewPack.Type == PacketType.PacketAck)
392 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs - Started up new client thread to handle incoming request"); 392 {
393 cirpack = initialcirpack; 393 PacketAckPacket ackPacket = (PacketAckPacket)NewPack;
394 userEP = remoteEP; 394
395 PacketQueue = new BlockingQueue<QueItem>(); 395 lock (NeedAck)
396 AssetRequests = new BlockingQueue<TransferRequestPacket>(); 396 {
397 AckTimer = new System.Timers.Timer(500); 397 foreach (PacketAckPacket.PacketsBlock block in ackPacket.Packets)
398 AckTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed); 398 {
399 AckTimer.Start(); 399 NeedAck.Remove(block.ID);
400 400 }
401 ClientThread = new Thread(new ThreadStart(AuthUser)); 401 }
402 ClientThread.IsBackground = true; 402 }
403 ClientThread.Start(); 403 else if ((NewPack.Type == PacketType.StartPingCheck))
404 } 404 {
405 405 //reply to pingcheck
406 private void ClientLoop() { 406 libsecondlife.Packets.StartPingCheckPacket startPing = (libsecondlife.Packets.StartPingCheckPacket)NewPack;
407 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ClientLoop() - Entered loop"); 407 libsecondlife.Packets.CompletePingCheckPacket endPing = new CompletePingCheckPacket();
408 while(true) { 408 endPing.PingID.PingID = startPing.PingID.PingID;
409 QueItem nextPacket = PacketQueue.Dequeue(); 409 OutPacket(endPing);
410 if(nextPacket.Incoming) 410 }
411 { 411 else
412 //is a incoming packet 412 {
413 ProcessInPacket(nextPacket.Packet); 413 QueItem item = new QueItem();
414 } 414 item.Packet = NewPack;
415 else 415 item.Incoming = true;
416 { 416 this.PacketQueue.Enqueue(item);
417 //is a out going packet 417 }
418 ProcessOutPacket(nextPacket.Packet); 418
419 } 419 }
420 } 420
421 } 421 public void OutPacket(Packet NewPack)
422 422 {
423 private void InitNewClient() { 423 QueItem item = new QueItem();
424 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:InitNewClient() - Adding viewer agent to world"); 424 item.Packet = NewPack;
425 OpenSim_Main.local_world.AddViewerAgent(this); 425 item.Incoming = false;
426 world.Entity tempent=OpenSim_Main.local_world.Entities[this.AgentID]; 426 this.PacketQueue.Enqueue(item);
427 this.ClientAvatar=(world.Avatar)tempent; 427 }
428 } 428
429 429 public OpenSimClient(EndPoint remoteEP, UseCircuitCodePacket initialcirpack)
430 private void AuthUser() { 430 {
431 if(OpenSim_Main.cfg.sandbox==false) { 431 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs - Started up new client thread to handle incoming request");
432 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AuthUser() - Authenticating new user request with grid"); 432 cirpack = initialcirpack;
433 WebRequest CheckSession = WebRequest.Create(OpenSim_Main.cfg.GridURL + "/usersessions/" + OpenSim_Main.cfg.GridSendKey + "/" + cirpack.CircuitCode.ID.ToString() + "/" + cirpack.CircuitCode.Code.ToString() + "/exists"); 433 userEP = remoteEP;
434 OpenSim_Main.localcons.WriteLine(OpenSim_Main.cfg.GridURL); 434 PacketQueue = new BlockingQueue<QueItem>();
435 WebResponse GridResponse = CheckSession.GetResponse(); 435 AssetRequests = new BlockingQueue<TransferRequestPacket>();
436 StreamReader sr = new StreamReader(GridResponse.GetResponseStream()); 436 AckTimer = new System.Timers.Timer(500);
437 String grTest = sr.ReadLine(); 437 AckTimer.Elapsed += new ElapsedEventHandler(AckTimer_Elapsed);
438 sr.Close(); 438 AckTimer.Start();
439 GridResponse.Close(); 439
440 if(String.IsNullOrEmpty(grTest) || grTest.Equals("1")) { // YAY! Valid login 440 ClientThread = new Thread(new ThreadStart(AuthUser));
441 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AuthUser() - Got authenticated connection from " + userEP.ToString()); 441 ClientThread.IsBackground = true;
442 this.AgentID=cirpack.CircuitCode.ID; 442 ClientThread.Start();
443 this.SessionID=cirpack.CircuitCode.SessionID; 443 }
444 this.CircuitCode=cirpack.CircuitCode.Code; 444
445 InitNewClient(); 445 private void ClientLoop()
446 ClientLoop(); 446 {
447 } else { // Invalid 447 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:ClientLoop() - Entered loop");
448 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AuthUser() - New user request denied to " + userEP.ToString()); 448 while (true)
449 ClientThread.Abort(); 449 {
450 } 450 QueItem nextPacket = PacketQueue.Dequeue();
451 } else { 451 if (nextPacket.Incoming)
452 this.AgentID=cirpack.CircuitCode.ID; 452 {
453 this.SessionID=cirpack.CircuitCode.SessionID; 453 //is a incoming packet
454 this.CircuitCode=cirpack.CircuitCode.Code; 454 ProcessInPacket(nextPacket.Packet);
455 InitNewClient(); 455 }
456 ClientLoop(); 456 else
457 } 457 {
458 } 458 //is a out going packet
459 } 459 ProcessOutPacket(nextPacket.Packet);
460 }
461 }
462 }
463
464 private void InitNewClient()
465 {
466 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:InitNewClient() - Adding viewer agent to world");
467 OpenSim_Main.local_world.AddViewerAgent(this);
468 world.Entity tempent = OpenSim_Main.local_world.Entities[this.AgentID];
469 this.ClientAvatar = (world.Avatar)tempent;
470 }
471
472 private void AuthUser()
473 {
474 if (OpenSim_Main.cfg.sandbox == false)
475 {
476 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AuthUser() - Authenticating new user request with grid");
477 WebRequest CheckSession = WebRequest.Create(OpenSim_Main.cfg.GridURL + "/usersessions/" + OpenSim_Main.cfg.GridSendKey + "/" + cirpack.CircuitCode.ID.ToString() + "/" + cirpack.CircuitCode.Code.ToString() + "/exists");
478 OpenSim_Main.localcons.WriteLine(OpenSim_Main.cfg.GridURL);
479 WebResponse GridResponse = CheckSession.GetResponse();
480 StreamReader sr = new StreamReader(GridResponse.GetResponseStream());
481 String grTest = sr.ReadLine();
482 sr.Close();
483 GridResponse.Close();
484 if (String.IsNullOrEmpty(grTest) || grTest.Equals("1"))
485 { // YAY! Valid login
486 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AuthUser() - Got authenticated connection from " + userEP.ToString());
487 this.AgentID = cirpack.CircuitCode.ID;
488 this.SessionID = cirpack.CircuitCode.SessionID;
489 this.CircuitCode = cirpack.CircuitCode.Code;
490 InitNewClient();
491 ClientLoop();
492 }
493 else
494 { // Invalid
495 OpenSim_Main.localcons.WriteLine("OpenSimClient.cs:AuthUser() - New user request denied to " + userEP.ToString());
496 ClientThread.Abort();
497 }
498 }
499 else
500 {
501 this.AgentID = cirpack.CircuitCode.ID;
502 this.SessionID = cirpack.CircuitCode.SessionID;
503 this.CircuitCode = cirpack.CircuitCode.Code;
504 InitNewClient();
505 ClientLoop();
506 }
507 }
508 }
460 509
461} 510}
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 @@
46 <Compile Include="Config.cs" /> 46 <Compile Include="Config.cs" />
47 <Compile Include="Main.cs" /> 47 <Compile Include="Main.cs" />
48 <Compile Include="OpenSimClient.cs" /> 48 <Compile Include="OpenSimClient.cs" />
49 <Compile Include="types\BitPack.cs" /> 49 <Compile Include="ServerConsole.cs" />
50 <Compile Include="types\Mesh.cs" /> 50 <Compile Include="types\Mesh.cs" />
51 <Compile Include="types\Triangle.cs" /> 51 <Compile Include="types\Triangle.cs" />
52 <Compile Include="Util.cs" /> 52 <Compile Include="Util.cs" />
53 <Compile Include="VersionInfo.cs" /> 53 <Compile Include="VersionInfo.cs" />
54 <Compile Include="world\Avatar.cs" /> 54 <Compile Include="world\Avatar.cs" />
55 <Compile Include="world\Entity.cs" /> 55 <Compile Include="world\Entity.cs" />
56 <Compile Include="world\HeightmapGenHills.cs" />
56 <Compile Include="world\PhysicsEngine.cs" /> 57 <Compile Include="world\PhysicsEngine.cs" />
57 <Compile Include="world\Primitive.cs" /> 58 <Compile Include="world\Primitive.cs" />
58 <Compile Include="world\ScriptEngine.cs" /> 59 <Compile Include="world\ScriptEngine.cs" />
59 <Compile Include="world\scripting\IScript.cs" /> 60 <Compile Include="world\scripting\IScript.cs" />
60 <Compile Include="world\SurfacePatch.cs" /> 61 <Compile Include="world\SurfacePatch.cs" />
61 <Compile Include="world\TerrainDecoder.cs" />
62 <Compile Include="world\World.cs" /> 62 <Compile Include="world\World.cs" />
63 </ItemGroup> 63 </ItemGroup>
64 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" /> 64 <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.Targets" />
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 @@
1/*
2Copyright (c) OpenSim project, http://osgrid.org/
3*
4* Redistribution and use in source and binary forms, with or without
5* modification, are permitted provided that the following conditions are met:
6* * Redistributions of source code must retain the above copyright
7* notice, this list of conditions and the following disclaimer.
8* * Redistributions in binary form must reproduce the above copyright
9* notice, this list of conditions and the following disclaimer in the
10* documentation and/or other materials provided with the distribution.
11* * Neither the name of the <organization> nor the
12* names of its contributors may be used to endorse or promote products
13* derived from this software without specific prior written permission.
14*
15* THIS SOFTWARE IS PROVIDED BY <copyright holder> ``AS IS'' AND ANY
16* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18* DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
19* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*/
26
27using System;
28
29namespace OpenSim
30{
31 /// <summary>
32 /// </summary>
33 public class VersionInfo
34 {
35 public static string Version = "0.0.1-unofficial";
36 }
37}
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 @@
1using System;
2using System.Collections.Generic;
3using System.Text;
4
5namespace OpenSim.types
6{
7 /* New Method
8 *
9 * 1. Get all the individual bytes and their bitlength, put them in a dictionary
10 * 2. Mash together when wanted.
11 *
12 * */
13 public class Bits {
14 public byte[] data;
15 public int len;
16 }
17
18 public class InverseBitPack
19 {
20 private List<Bits> bits;
21
22 public InverseBitPack()
23 {
24 bits = new List<Bits>();
25 }
26 }
27
28 public class BitPack
29 {
30 private const int MAX_BITS = 8;
31
32 private byte[] Data;
33 private int bytePos;
34 private int bitPos;
35
36 public BitPack(byte[] data, int pos) // For libsl compatibility
37 {
38 Data = data;
39 bytePos = pos;
40 }
41
42 public BitPack() // Encoding version
43 {
44
45 }
46
47 public void LoadData(byte[] data, int pos) {
48 Data = data;
49 bytePos = pos;
50 bitPos = 0;
51 }
52
53 private void PackBitsArray(byte[] bits, int bitLen)
54 {
55 int offset = bitPos % MAX_BITS;
56 int i;
57 byte temp1;
58 byte temp2;
59
60 for (i = 0; i < bits.Length; i++)
61 {
62 int Byte = bits[i];
63 Byte <<= offset;
64 temp1 = (byte)(Byte & 0xFF);
65 temp2 = (byte)((Byte >> 8) & 0xFF);
66
67 Data[Data.Length - 1] |= temp1;
68// Data
69
70 bitPos += bitLen;
71 }
72 }
73
74 public float UnpackFloat()
75 {
76 byte[] output = UnpackBitsArray(32);
77
78 if (!BitConverter.IsLittleEndian) Array.Reverse(output);
79 return BitConverter.ToSingle(output, 0);
80 }
81
82 public int UnpackBits(int totalCount)
83 {
84 byte[] output = UnpackBitsArray(totalCount);
85
86 if (!BitConverter.IsLittleEndian) Array.Reverse(output);
87 return BitConverter.ToInt32(output, 0);
88 }
89
90 private byte[] UnpackBitsArray(int totalCount)
91 {
92 int count = 0;
93 byte[] output = new byte[4];
94 int curBytePos = 0;
95 int curBitPos = 0;
96
97 while (totalCount > 0)
98 {
99 if (totalCount > MAX_BITS)
100 {
101 count = MAX_BITS;
102 totalCount -= MAX_BITS;
103 }
104 else
105 {
106 count = totalCount;
107 totalCount = 0;
108 }
109
110 while (count > 0)
111 {
112 // Shift the previous bits
113 output[curBytePos] <<= 1;
114
115 // Grab one bit
116 if ((Data[bytePos] & (0x80 >> bitPos++)) != 0)
117 ++output[curBytePos];
118
119 --count;
120 ++curBitPos;
121
122 if (bitPos >= MAX_BITS)
123 {
124 bitPos = 0;
125 ++bytePos;
126 }
127 if (curBitPos >= MAX_BITS)
128 {
129 curBitPos = 0;
130 ++curBytePos;
131 }
132 }
133 }
134
135 return output;
136 }
137 }
138}
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
226 handshake.RegionInfo.TerrainStartHeight10 = 10; 226 handshake.RegionInfo.TerrainStartHeight10 = 10;
227 handshake.RegionInfo.TerrainStartHeight11 = 10; 227 handshake.RegionInfo.TerrainStartHeight11 = 10;
228 handshake.RegionInfo.SimAccess = 13; 228 handshake.RegionInfo.SimAccess = 13;
229 handshake.RegionInfo.WaterHeight = 5; 229 handshake.RegionInfo.WaterHeight = 20.0f;
230 handshake.RegionInfo.RegionFlags = 72458694; 230 handshake.RegionInfo.RegionFlags = 72458694; // TODO: WTF sirs? Use an enum!
231 handshake.RegionInfo.SimName = _enc.GetBytes(OpenSim_Main.cfg.RegionName + "\0"); 231 handshake.RegionInfo.SimName = _enc.GetBytes(OpenSim_Main.cfg.RegionName + "\0");
232 handshake.RegionInfo.SimOwner = new LLUUID("00000000-0000-0000-0000-000000000000"); 232 handshake.RegionInfo.SimOwner = new LLUUID("00000000-0000-0000-0000-000000000000");
233 handshake.RegionInfo.TerrainBase0 = new LLUUID("b8d3965a-ad78-bf43-699b-bff8eca6c975"); 233 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 @@
1using System;
2
3namespace libsecondlife
4{
5 public class HeightmapGenHills
6 {
7 private Random Rand = new Random();
8 private int NumHills;
9 private float HillMin;
10 private float HillMax;
11 private bool Island;
12 private float[] heightmap;
13
14 public float[] GenerateHeightmap(int numHills, float hillMin, float hillMax, bool island)
15 {
16 NumHills = numHills;
17 HillMin = hillMin;
18 HillMax = hillMax;
19 Island = island;
20
21 heightmap = new float[256 * 256];
22
23 for (int i = 0; i < numHills; i++)
24 {
25 AddHill();
26 }
27
28 Normalize();
29
30 return heightmap;
31 }
32
33 private void AddHill()
34 {
35 float x, y;
36 float radius = RandomRange(HillMin, HillMax);
37
38 if (Island)
39 {
40 // Which direction from the center of the map the hill is placed
41 float theta = RandomRange(0, 6.28f);
42
43 // How far from the center of the map to place the hill. The radius
44 // is subtracted from the range to prevent any part of the hill from
45 // reaching the edge of the map
46 float distance = RandomRange(radius / 2.0f, 128.0f - radius);
47
48 x = 128.0f + (float)Math.Cos(theta) * distance;
49 y = 128.0f + (float)Math.Sin(theta) * distance;
50 }
51 else
52 {
53 x = RandomRange(-radius, 256.0f + radius);
54 y = RandomRange(-radius, 256.0f + radius);
55 }
56
57 float radiusSq = radius * radius;
58 float distSq;
59 float height;
60
61 int xMin = (int)(x - radius) - 1;
62 int xMax = (int)(x + radius) + 1;
63 if (xMin < 0) xMin = 0;
64 if (xMax > 255) xMax = 255;
65
66 int yMin = (int)(y - radius) - 1;
67 int yMax = (int)(y + radius) + 1;
68 if (yMin < 0) yMin = 0;
69 if (yMax > 255) yMax = 255;
70
71 // Loop through each affected cell and determine the height at that point
72 for (int v = yMin; v <= yMax; ++v)
73 {
74 float fv = (float)v;
75
76 for (int h = xMin; h <= xMax; ++h)
77 {
78 float fh = (float)h;
79
80 // Determine how far from the center of this hill this point is
81 distSq = (x - fh) * (x - fh) + (y - fv) * (y - fv);
82 height = radiusSq - distSq;
83
84 // Don't add negative hill values
85 if (height > 0.0f) heightmap[h + v * 256] += height;
86 }
87 }
88 }
89
90 private void Normalize()
91 {
92 float min = heightmap[0];
93 float max = heightmap[0];
94
95 for (int x = 0; x < 256; x++)
96 {
97 for (int y = 0; y < 256; y++)
98 {
99 if (heightmap[x + y * 256] < min) min = heightmap[x + y * 256];
100 if (heightmap[x + y * 256] > max) max = heightmap[x + y * 256];
101 }
102 }
103
104 // Avoid a rare divide by zero
105 if (min != max)
106 {
107 for (int x = 0; x < 256; x++)
108 {
109 for (int y = 0; y < 256; y++)
110 {
111 heightmap[x + y * 256] = ((heightmap[x + y * 256] - min) / (max - min)) * (HillMax - HillMin);
112 }
113 }
114 }
115 }
116
117 private float RandomRange(float min, float max)
118 {
119 return (float)Rand.NextDouble() * (max - min) + min;
120 }
121 }
122}
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 @@
1/*
2* Copyright (c) OpenSim project, http://sim.opensecondlife.org/
3*
4* Redistribution and use in source and binary forms, with or without
5* modification, are permitted provided that the following conditions are met:
6* * Redistributions of source code must retain the above copyright
7* notice, this list of conditions and the following disclaimer.
8* * Redistributions in binary form must reproduce the above copyright
9* notice, this list of conditions and the following disclaimer in the
10* documentation and/or other materials provided with the distribution.
11* * Neither the name of the <organization> nor the
12* names of its contributors may be used to endorse or promote products
13* derived from this software without specific prior written permission.
14*
15* THIS SOFTWARE IS PROVIDED BY <copyright holder> ``AS IS'' AND ANY
16* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18* DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
19* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25*
26*/
27
28using System;
29using System.Collections.Generic;
30//using libsecondlife;
31using libsecondlife.Packets;
32
33namespace OpenSim
34{
35 /// <summary>
36 /// Description of TerrainDecoder.
37 /// </summary>
38 public class TerrainDecode
39 {
40
41 public enum LayerType : byte
42 {
43 Land = 0x4C,
44 Water = 0x57,
45 Wind = 0x37,
46 Cloud = 0x38
47 }
48
49 public struct GroupHeader
50 {
51 public int Stride;
52 public int PatchSize;
53 public LayerType Type;
54 }
55
56 public struct PatchHeader
57 {
58 public float DCOffset;
59 public int Range;
60 public int QuantWBits;
61 public int PatchIDs;
62 public uint WordBits;
63 }
64
65 public class Patch
66 {
67 public float[] Heightmap;
68 }
69
70
71 /// <summary>
72 ///
73 /// </summary>
74 /// <param name="simulator"></param>
75 /// <param name="x"></param>
76 /// <param name="y"></param>
77 /// <param name="width"></param>
78 /// <param name="data"></param>
79 // public delegate void LandPatchCallback(Simulator simulator, int x, int y, int width, float[] data);
80
81
82 /// <summary>
83 ///
84 /// </summary>
85 //public event LandPatchCallback OnLandPatch;
86
87 private Random RandomClass = new Random();
88
89 private const byte END_OF_PATCHES = 97;
90 private const int PATCHES_PER_EDGE = 16;
91 private const float OO_SQRT2 = 0.7071067811865475244008443621049f;
92
93 //private SecondLife Client;
94 private Dictionary<ulong, Patch[]> SimPatches = new Dictionary<ulong, Patch[]>();
95 private float[] DequantizeTable16 = new float[16 * 16];
96 private float[] DequantizeTable32 = new float[32 * 32];
97 private float[] ICosineTable16 = new float[16 * 16];
98 private float[] ICosineTable32 = new float[32 * 32];
99 private int[] DeCopyMatrix16 = new int[16 * 16];
100 private int[] DeCopyMatrix32 = new int[32 * 32];
101
102
103 /// <summary>
104 ///
105 /// </summary>
106 /// <param name="client"></param>
107 public TerrainDecode()
108 {
109
110 // Initialize the decompression tables
111 BuildDequantizeTable16();
112 BuildDequantizeTable32();
113 SetupICosines16();
114 SetupICosines32();
115 BuildDecopyMatrix16();
116 BuildDecopyMatrix32();
117
118 }
119
120
121 private void BuildDequantizeTable16()
122 {
123 for (int j = 0; j < 16; j++)
124 {
125 for (int i = 0; i < 16; i++)
126 {
127 DequantizeTable16[j * 16 + i] = 1.0f + 2.0f * (float)(i + j);
128 }
129 }
130 }
131
132 private void BuildDequantizeTable32()
133 {
134 for (int j = 0; j < 32; j++)
135 {
136 for (int i = 0; i < 32; i++)
137 {
138 DequantizeTable32[j * 32 + i] = 1.0f + 2.0f * (float)(i + j);
139 }
140 }
141 }
142
143 private void SetupICosines16()
144 {
145 const float hposz = (float)Math.PI * 0.5f / 16.0f;
146
147 for (int u = 0; u < 16; u++)
148 {
149 for (int n = 0; n < 16; n++)
150 {
151 ICosineTable16[u * 16 + n] = (float)Math.Cos((2.0f * (float)n + 1.0f) * (float)u * hposz);
152 }
153 }
154 }
155
156 private void SetupICosines32()
157 {
158 const float hposz = (float)Math.PI * 0.5f / 32.0f;
159
160 for (int u = 0; u < 32; u++)
161 {
162 for (int n = 0; n < 32; n++)
163 {
164 ICosineTable32[u * 32 + n] = (float)Math.Cos((2.0f * (float)n + 1.0f) * (float)u * hposz);
165 }
166 }
167 }
168
169 private void BuildDecopyMatrix16()
170 {
171 bool diag = false;
172 bool right = true;
173 int i = 0;
174 int j = 0;
175 int count = 0;
176
177 while (i < 16 && j < 16)
178 {
179 DeCopyMatrix16[j * 16 + i] = count++;
180
181 if (!diag)
182 {
183 if (right)
184 {
185 if (i < 16 - 1) i++;
186 else j++;
187
188 right = false;
189 diag = true;
190 }
191 else
192 {
193 if (j < 16 - 1) j++;
194 else i++;
195
196 right = true;
197 diag = true;
198 }
199 }
200 else
201 {
202 if (right)
203 {
204 i++;
205 j--;
206 if (i == 16 - 1 || j == 0) diag = false;
207 }
208 else
209 {
210 i--;
211 j++;
212 if (j == 16 - 1 || i == 0) diag = false;
213 }
214 }
215 }
216 }
217
218 private void BuildDecopyMatrix32()
219 {
220 bool diag = false;
221 bool right = true;
222 int i = 0;
223 int j = 0;
224 int count = 0;
225
226 while (i < 32 && j < 32)
227 {
228 DeCopyMatrix32[j * 32 + i] = count++;
229
230 if (!diag)
231 {
232 if (right)
233 {
234 if (i < 32 - 1) i++;
235 else j++;
236
237 right = false;
238 diag = true;
239 }
240 else
241 {
242 if (j < 32 - 1) j++;
243 else i++;
244
245 right = true;
246 diag = true;
247 }
248 }
249 else
250 {
251 if (right)
252 {
253 i++;
254 j--;
255 if (i == 32 - 1 || j == 0) diag = false;
256 }
257 else
258 {
259 i--;
260 j++;
261 if (j == 32 - 1 || i == 0) diag = false;
262 }
263 }
264 }
265 }
266
267 private void EncodePatchHeader(BitPacker bitpack, PatchHeader header)
268 {
269 bitpack.PackBits(header.QuantWBits,8);
270
271 if (header.QuantWBits == END_OF_PATCHES)
272 return;
273
274 bitpack.PackFloat(header.DCOffset);
275 bitpack.PackBits(header.Range,16);
276 bitpack.PackBits(header.PatchIDs,10);
277
278 }
279
280 public void DCTLine16(float[] In, float[] Out, int line)
281 {
282 int N =16;
283 int lineSize = line * 16;
284
285 for(int k = 0; k < N;k++)
286 {
287 float sum = 0.0f;
288 for(int n = 0; n < N; n++)
289 {
290 float num = (float)(Math.PI*k*(2.0f*n+1)/(2*N));
291 float cosine = (float)Math.Cos(num);
292 float product = In[lineSize +n] * cosine;
293 sum += product;
294 }
295
296 float alpha;
297 if(k == 0)
298 {
299 alpha = (float)(1.0f/Math.Sqrt(2));
300 }
301 else
302 {
303 alpha = 1;
304 }
305 Out[lineSize + k] =(float)( sum * alpha );
306
307 }
308 }
309 public void DCTColumn16(float[] In, float[] Out, int Column)
310 {
311 int N =16;
312 int uSize;
313
314 for(int k = 0; k < N; k++){
315 float sum = 0.0f;
316 for(int n = 0; n < N; n++)
317 {
318 uSize = n * 16;
319 float num = (float)(Math.PI*k*(2.0f*n+1)/(2*N));
320 float cosine = (float)Math.Cos(num);
321 float product = In[uSize + Column] * cosine;
322 sum += product;
323 }
324
325 float alpha;
326 if(k == 0)
327 {
328 alpha = (float)(1.0f/Math.Sqrt(2));
329 }
330 else
331 {
332 alpha = 1;
333 }
334 Out[16 * k + Column] = (float)( sum * alpha * (2.0f /N));
335
336 }
337 }
338
339 private void EncodePatch(int[] patches, BitPacker bitpack, int size)
340 {
341 int lastnum =0;
342 for(int n = 0; n < size * size; n++)
343 {
344 if(patches[n]!=0)
345 lastnum=n;
346 }
347 for (int n = 0; n < lastnum+1; n++)
348 {
349 if(patches[n] != 0)
350 {
351 bitpack.PackBits(1,1); //value or EOB
352 bitpack.PackBits(1,1); //value
353 if(patches[n] > 0)
354 {
355
356 bitpack.PackBits(0,1); // positive
357 bitpack.PackBits(patches[n],13);
358
359 }
360 else
361 {
362 bitpack.PackBits(1,1); // negative
363
364 int temp = patches[n] * -1;
365 bitpack.PackBits(temp,13);
366
367 }
368 }
369 else
370 {
371 bitpack.PackBits(0,1); // no value
372 }
373 }
374
375 bitpack.PackBits(1,1); //value or EOB
376 bitpack.PackBits(0,1); // EOB
377 }
378
379 public int[] CompressPatch(float[] patches)
380 {
381 int size = 16;
382 float[] block = new float[size * size];
383 int[] output = new int[size * size];
384 int prequant = (139 >> 4) + 2;
385 int quantize = 1 << prequant;
386 float ooq = 1.0f / (float)quantize;
387 float mult = ooq * (float)1;
388 float addval = mult * (float)(1 << (prequant - 1)) + 20.4989f;
389
390 if (size == 16)
391 {
392 for (int n = 0; n < 16 * 16; n++)
393 {
394 block[n] = (float)((patches[n] - addval)/ mult);
395 }
396
397 float[] ftemp = new float[32 * 32];
398
399 for (int o = 0; o < 16; o++)
400 this.DCTColumn16(block, ftemp, o);
401 for (int o = 0; o < 16; o++)
402 this.DCTLine16(ftemp, block, o);
403 }
404
405 for (int j = 0; j < block.Length; j++)
406 {
407 output[DeCopyMatrix16[j]] = (int)(block[j] / DequantizeTable16[j]);
408 }
409
410 return output;
411 }
412
413 public Packet CreateLayerPacket(float[] heightmap, int minX, int minY, int maxX, int maxY)
414 {
415 //int minX = 0, maxX = 2, minY = 0, maxY = 1; //these should be passed to this function
416 LayerDataPacket layer = new LayerDataPacket();
417 byte[] Encoded = new byte[2048];
418 layer.LayerID.Type = 76;
419 GroupHeader header = new GroupHeader();
420 header.Stride = 264;
421 header.PatchSize = 16;
422 header.Type = LayerType.Land;
423 BitPacker newpack = new BitPacker(Encoded,0);
424 newpack.PackBits(header.Stride,16);
425 newpack.PackBits(header.PatchSize,8);
426 newpack.PackBits((int)header.Type,8);
427
428
429 float[] height;
430 for(int y = minY; y< maxY; y++)
431 {
432 for(int x = minX ; x < maxX ; x++)
433 {
434 height = new float[256];
435 Array.Copy(heightmap, (4096 *y) +(x *256), height, 0, 256);
436
437 this.CreatePatch(height, newpack, x, y);
438 }
439 }
440
441 PatchHeader headers = new PatchHeader();
442 headers.QuantWBits = END_OF_PATCHES;
443 this.EncodePatchHeader(newpack, headers);
444
445 int lastused=0;
446 for(int i = 0; i < 2048 ; i++)
447 {
448 if(Encoded[i] !=0)
449 lastused = i;
450 }
451
452 byte[] data = new byte[lastused+1];
453 Array.Copy(Encoded, data, lastused+1);
454 layer.LayerData.Data =data;
455
456 return(layer);
457 }
458 public void CreatePatch(float[] heightmap, BitPacker newpack, int x, int y)
459 {
460 PatchHeader header = new PatchHeader();
461 header.DCOffset = 20.4989f;
462 header.QuantWBits = 139;
463 header.Range = 1;
464 header.PatchIDs = (y & 0x1F);
465 header.PatchIDs += x <<5 ;
466
467 this.EncodePatchHeader(newpack, header);
468
469 int[] newpatch = this.CompressPatch(heightmap);
470 this.EncodePatch(newpatch, newpack, 16);
471
472 }
473 }
474
475 //***************************************************
476 public class BitPacker
477 {
478 private const int MAX_BITS = 8;
479
480 private byte[] Data;
481 public int bytePos;
482 public int bitPos;
483
484 /// <summary>
485 /// Default constructor, initialize the bit packer / bit unpacker
486 /// with a byte array and starting position
487 /// </summary>
488 /// <param name="data">Byte array to pack bits in to or unpack from</param>
489 /// <param name="pos">Starting position in the byte array</param>
490 public BitPacker(byte[] data, int pos)
491 {
492 Data = data;
493 bytePos = pos;
494 }
495
496 /// <summary>
497 /// Pack a floating point value in to the data
498 /// </summary>
499 /// <param name="data">Floating point value to pack</param>
500 public void PackFloat(float data)
501 {
502 byte[] input = BitConverter.GetBytes(data);
503 PackBitArray(input, 32);
504 }
505
506 /// <summary>
507 /// Pack part or all of an integer in to the data
508 /// </summary>
509 /// <param name="data">Integer containing the data to pack</param>
510 /// <param name="totalCount">Number of bits of the integer to pack</param>
511 public void PackBits(int data, int totalCount)
512 {
513 byte[] input = BitConverter.GetBytes(data);
514 PackBitArray(input, totalCount);
515 }
516
517 /// <summary>
518 /// Unpacking a floating point value from the data
519 /// </summary>
520 /// <returns>Unpacked floating point value</returns>
521 public float UnpackFloat()
522 {
523 byte[] output = UnpackBitsArray(32);
524
525 if (!BitConverter.IsLittleEndian) Array.Reverse(output);
526 return BitConverter.ToSingle(output, 0);
527 }
528
529 /// <summary>
530 /// Unpack a variable number of bits from the data in to integer format
531 /// </summary>
532 /// <param name="totalCount">Number of bits to unpack</param>
533 /// <returns>An integer containing the unpacked bits</returns>
534 /// <remarks>This function is only useful up to 32 bits</remarks>
535 public int UnpackBits(int totalCount)
536 {
537 byte[] output = UnpackBitsArray(totalCount);
538
539 if (!BitConverter.IsLittleEndian) Array.Reverse(output);
540 return BitConverter.ToInt32(output, 0);
541 }
542
543 private void PackBitArray(byte[] data, int totalCount)
544 {
545 int count = 0;
546 int curBytePos = 0;
547 int curBitPos = 0;
548
549 while (totalCount > 0)
550 {
551 if (totalCount > (MAX_BITS ))
552 {
553 count = MAX_BITS ;
554 totalCount -= MAX_BITS ;
555 }
556 else
557 {
558 count = totalCount;
559 totalCount = 0;
560 }
561
562 while (count > 0)
563 {
564 switch(count)
565 {
566 case 1:
567 if ((data[curBytePos] & (0x01)) != 0)
568 {
569 Data[bytePos] |= (byte)(0x80 >> bitPos);
570 }
571 break;
572 case 2:
573 if ((data[curBytePos] & (0x02)) != 0)
574 {
575 Data[bytePos] |= (byte)(0x80 >> bitPos);
576 }
577 break;
578 case 3:
579 if ((data[curBytePos] & (0x04)) != 0)
580 {
581 Data[bytePos] |= (byte)(0x80 >> bitPos);
582 }
583 break;
584 case 4:
585 if ((data[curBytePos] & (0x08)) != 0)
586 {
587 Data[bytePos] |= (byte)(0x80 >> bitPos);
588 }
589 break;
590 case 5:
591 if ((data[curBytePos] & (0x10)) != 0)
592 {
593 Data[bytePos] |= (byte)(0x80 >> bitPos);
594 }
595 break;
596 case 6:
597 if ((data[curBytePos] & (0x20)) != 0)
598 {
599 Data[bytePos] |= (byte)(0x80 >> bitPos);
600 }
601 break;
602 case 7:
603 if ((data[curBytePos] & (0x40)) != 0)
604 {
605 Data[bytePos] |= (byte)(0x80 >> bitPos);
606 }
607 break;
608 case 8:
609 if ((data[curBytePos] & (0x80)) != 0)
610 {
611 Data[bytePos] |= (byte)(0x80 >> bitPos);
612 }
613 break;
614 }
615
616 bitPos++;
617 --count;
618 ++curBitPos;
619
620 if (bitPos >= MAX_BITS)
621 {
622 bitPos = 0;
623 ++bytePos;
624 }
625 if (curBitPos >= MAX_BITS)
626 {
627 curBitPos = 0;
628 ++curBytePos;
629 }
630 }
631 }
632 }
633
634
635 private byte[] UnpackBitsArray(int totalCount)
636 {
637 int count = 0;
638 byte[] output = new byte[4];
639 int curBytePos = 0;
640 int curBitPos = 0;
641
642 while (totalCount > 0)
643 {
644 if (totalCount > MAX_BITS)
645 {
646 count = MAX_BITS;
647 totalCount -= MAX_BITS;
648 }
649 else
650 {
651 count = totalCount;
652 totalCount = 0;
653 }
654
655 while (count > 0)
656 {
657 // Shift the previous bits
658 output[curBytePos] <<= 1;
659
660 // Grab one bit
661 if ((Data[bytePos] & (0x80 >> bitPos++)) != 0)
662 ++output[curBytePos];
663
664 --count;
665 ++curBitPos;
666
667 if (bitPos >= MAX_BITS)
668 {
669 bitPos = 0;
670 ++bytePos;
671 }
672 if (curBitPos >= MAX_BITS)
673 {
674 curBitPos = 0;
675 ++curBytePos;
676 }
677 }
678 }
679
680 return output;
681 }
682 }
683}
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 @@
1using System; 1using System;
2using System.Threading; 2using System.Threading;
3using libsecondlife;
4using libsecondlife.Packets;
5using System.Collections.Generic; 3using System.Collections.Generic;
6using System.Text; 4using System.Text;
5using libsecondlife;
6using libsecondlife.Packets;
7 7
8namespace OpenSim.world 8namespace OpenSim.world
9{ 9{
@@ -12,77 +12,98 @@ namespace OpenSim.world
12 public Dictionary<libsecondlife.LLUUID, Entity> Entities; 12 public Dictionary<libsecondlife.LLUUID, Entity> Entities;
13 public float[] LandMap; 13 public float[] LandMap;
14 public ScriptEngine Scripts; 14 public ScriptEngine Scripts;
15 public TerrainDecode terrainengine = new TerrainDecode(); 15 public uint _localNumber = 0;
16 public uint _localNumber=0; 16 public PhysicsEngine physics;
17 public PhysicsEngine physics; 17
18 18 private libsecondlife.TerrainManager TerrainManager;
19 private Random Rand = new Random(); 19 private Random Rand = new Random();
20 20
21 public World() 21 public World()
22 { 22 {
23 OpenSim_Main.localcons.WriteLine("World.cs - creating new entitities instance"); 23 OpenSim_Main.localcons.WriteLine("World.cs - creating new entitities instance");
24 Entities = new Dictionary<libsecondlife.LLUUID, Entity>(); 24 Entities = new Dictionary<libsecondlife.LLUUID, Entity>();
25
26 OpenSim_Main.localcons.WriteLine("World.cs - creating LandMap");
27 TerrainManager = new TerrainManager(new SecondLife());
28 }
25 29
26 OpenSim_Main.localcons.WriteLine("World.cs - creating LandMap"); 30 public void InitLoop()
27 terrainengine = new TerrainDecode(); 31 {
28 LandMap = new float[65536]; 32 OpenSim_Main.localcons.WriteLine("World.cs:StartLoop() - Initialising physics");
29 33 this.physics = new PhysicsEngine();
34 physics.Startup();
30 } 35 }
31 36
32 public void InitLoop() { 37 public void DoStuff()
33 OpenSim_Main.localcons.WriteLine("World.cs:StartLoop() - Initialising physics"); 38 {
34 this.physics = new PhysicsEngine(); 39 lock (this)
35 physics.Startup(); 40 {
36 } 41 physics.DoStuff(this);
37 42 this.Update();
38 public void DoStuff() { 43 }
39 lock(this) { 44 }
40 physics.DoStuff(this);
41 this.Update();
42 }
43 }
44 45
45 public void Update() { 46 public void Update()
47 {
46 foreach (libsecondlife.LLUUID UUID in Entities.Keys) 48 foreach (libsecondlife.LLUUID UUID in Entities.Keys)
47 { 49 {
48 if(Entities[UUID].needupdate) { 50 if (Entities[UUID].needupdate)
49 Entities[UUID].update(); 51 {
50 52 Entities[UUID].update();
51 if(Entities[UUID] is Avatar) { 53
52 Avatar avatar=(Avatar)Entities[UUID]; 54 if (Entities[UUID] is Avatar)
53 if((avatar.oldpos!=avatar.position) || (avatar.oldvel!=avatar.velocity) || avatar.walking) { 55 {
54 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = Entities[UUID].CreateTerseBlock(); 56 Avatar avatar = (Avatar)Entities[UUID];
55 foreach(OpenSimClient client in OpenSim_Main.sim.ClientThreads.Values) { 57 if ((avatar.oldpos != avatar.position) || (avatar.oldvel != avatar.velocity) || avatar.walking)
56 ImprovedTerseObjectUpdatePacket terse = new ImprovedTerseObjectUpdatePacket(); 58 {
57 terse.RegionData.RegionHandle = OpenSim_Main.cfg.RegionHandle; // FIXME 59 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = Entities[UUID].CreateTerseBlock();
58 terse.RegionData.TimeDilation = 0; 60 foreach (OpenSimClient client in OpenSim_Main.sim.ClientThreads.Values)
59 terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; 61 {
60 terse.ObjectData[0] = terseBlock; 62 ImprovedTerseObjectUpdatePacket terse = new ImprovedTerseObjectUpdatePacket();
61 client.OutPacket(terse); 63 terse.RegionData.RegionHandle = OpenSim_Main.cfg.RegionHandle; // FIXME
62 } 64 terse.RegionData.TimeDilation = 0;
63 }} 65 terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1];
64 } 66 terse.ObjectData[0] = terseBlock;
67 client.OutPacket(terse);
68 }
69 }
70 }
71 }
65 } 72 }
66 } 73 }
67 74
68 public void SendLayerData(OpenSimClient RemoteClient) { 75 public void SendLayerData(OpenSimClient RemoteClient)
69 for(int x=0; x<16; x=x+4) for(int y=0; y<16; y++){ 76 {
70 Packet layerpack=this.terrainengine.CreateLayerPacket(LandMap, x,y,x+4,y+1); 77 int[] patches = new int[4];
71 RemoteClient.OutPacket(layerpack);
72 }
73 }
74 78
75 public void AddViewerAgent(OpenSimClient AgentClient) { 79 for (int y = 0; y < 16; y++)
76 OpenSim_Main.localcons.WriteLine("World.cs:AddViewerAgent() - Creating new avatar for remote viewer agent"); 80 {
77 Avatar NewAvatar = new Avatar(AgentClient); 81 for (int x = 0; x < 16; x = x + 4)
78 OpenSim_Main.localcons.WriteLine("World.cs:AddViewerAgent() - Adding new avatar to world"); 82 {
79 this.Entities.Add(AgentClient.AgentID, NewAvatar); 83 patches[0] = x + 0 + y * 16;
80 OpenSim_Main.localcons.WriteLine("World.cs:AddViewerAgent() - Starting RegionHandshake "); 84 patches[1] = x + 1 + y * 16;
81 NewAvatar.SendRegionHandshake(this); 85 patches[2] = x + 2 + y * 16;
82 this.Update(); // will work for now, but needs to be optimised so we don't update everything in the sim for each new user 86 patches[3] = x + 3 + y * 16;
83 }
84 87
85 public bool Backup() { 88 Packet layerpack = TerrainManager.CreateLandPacket(LandMap, patches);
89 RemoteClient.OutPacket(layerpack);
90 }
91 }
92 }
93
94 public void AddViewerAgent(OpenSimClient AgentClient)
95 {
96 OpenSim_Main.localcons.WriteLine("World.cs:AddViewerAgent() - Creating new avatar for remote viewer agent");
97 Avatar NewAvatar = new Avatar(AgentClient);
98 OpenSim_Main.localcons.WriteLine("World.cs:AddViewerAgent() - Adding new avatar to world");
99 this.Entities.Add(AgentClient.AgentID, NewAvatar);
100 OpenSim_Main.localcons.WriteLine("World.cs:AddViewerAgent() - Starting RegionHandshake ");
101 NewAvatar.SendRegionHandshake(this);
102 this.Update(); // will work for now, but needs to be optimised so we don't update everything in the sim for each new user
103 }
104
105 public bool Backup()
106 {
86 /* TODO: Save the current world entities state. */ 107 /* TODO: Save the current world entities state. */
87 108
88 return false; 109 return false;