corrade-vassal – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * Copyright (c) 2006-2014, openmetaverse.org
3 * All rights reserved.
4 *
5 * - Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * - Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 * - Neither the name of the openmetaverse.org nor the names
11 * of its contributors may be used to endorse or promote products derived from
12 * this software without specific prior written permission.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
15 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 * POSSIBILITY OF SUCH DAMAGE.
25 */
26  
27 using System;
28 using System.Collections.Generic;
29 using OpenMetaverse.Packets;
30  
31 namespace OpenMetaverse
32 {
33 public class TerrainManager
34 {
35 #region EventHandling
36 /// <summary>The event subscribers. null if no subcribers</summary>
37 private EventHandler<LandPatchReceivedEventArgs> m_LandPatchReceivedEvent;
38  
39 /// <summary>Raises the LandPatchReceived event</summary>
40 /// <param name="e">A LandPatchReceivedEventArgs object containing the
41 /// data returned from the simulator</param>
42 protected virtual void OnLandPatchReceived(LandPatchReceivedEventArgs e)
43 {
44 EventHandler<LandPatchReceivedEventArgs> handler = m_LandPatchReceivedEvent;
45 if (handler != null)
46 handler(this, e);
47 }
48  
49 /// <summary>Thread sync lock object</summary>
50 private readonly object m_LandPatchReceivedLock = new object();
51  
52 /// <summary>Raised when the simulator responds sends </summary>
53 public event EventHandler<LandPatchReceivedEventArgs> LandPatchReceived
54 {
55 add { lock (m_LandPatchReceivedLock) { m_LandPatchReceivedEvent += value; } }
56 remove { lock (m_LandPatchReceivedLock) { m_LandPatchReceivedEvent -= value; } }
57 }
58 #endregion
59  
60 private GridClient Client;
61  
62 /// <summary>
63 /// Default constructor
64 /// </summary>
65 /// <param name="client"></param>
66 public TerrainManager(GridClient client)
67 {
68 Client = client;
69 Client.Network.RegisterCallback(PacketType.LayerData, LayerDataHandler);
70 }
71  
72 private void DecompressLand(Simulator simulator, BitPack bitpack, TerrainPatch.GroupHeader group)
73 {
74 int x;
75 int y;
76 int[] patches = new int[32 * 32];
77 int count = 0;
78  
79 while (true)
80 {
81 TerrainPatch.Header header = TerrainCompressor.DecodePatchHeader(bitpack);
82  
83 if (header.QuantWBits == TerrainCompressor.END_OF_PATCHES)
84 break;
85  
86 x = header.X;
87 y = header.Y;
88  
89 if (x >= TerrainCompressor.PATCHES_PER_EDGE || y >= TerrainCompressor.PATCHES_PER_EDGE)
90 {
91 Logger.Log(String.Format(
92 "Invalid LayerData land packet, x={0}, y={1}, dc_offset={2}, range={3}, quant_wbits={4}, patchids={5}, count={6}",
93 x, y, header.DCOffset, header.Range, header.QuantWBits, header.PatchIDs, count),
94 Helpers.LogLevel.Warning, Client);
95 return;
96 }
97  
98 // Decode this patch
99 TerrainCompressor.DecodePatch(patches, bitpack, header, group.PatchSize);
100  
101 // Decompress this patch
102 float[] heightmap = TerrainCompressor.DecompressPatch(patches, header, group);
103  
104 count++;
105  
106 try { OnLandPatchReceived(new LandPatchReceivedEventArgs(simulator, x, y, group.PatchSize, heightmap)); }
107 catch (Exception e) { Logger.Log(e.Message, Helpers.LogLevel.Error, Client, e); }
108  
109 if (Client.Settings.STORE_LAND_PATCHES)
110 {
111 TerrainPatch patch = new TerrainPatch();
112 patch.Data = heightmap;
113 patch.X = x;
114 patch.Y = y;
115 simulator.Terrain[y * 16 + x] = patch;
116 }
117 }
118 }
119  
120 private void DecompressWind(Simulator simulator, BitPack bitpack, TerrainPatch.GroupHeader group)
121 {
122 int[] patches = new int[32 * 32];
123  
124 // Ignore the simulator stride value
125 group.Stride = group.PatchSize;
126  
127 // Each wind packet contains the wind speeds and direction for the entire simulator
128 // stored as two float arrays. The first array is the X value of the wind speed at
129 // each 16x16m block, second is the Y value.
130 // wind_speed = distance(x,y to 0,0)
131 // wind_direction = vec2(x,y)
132  
133 // X values
134 TerrainPatch.Header header = TerrainCompressor.DecodePatchHeader(bitpack);
135 TerrainCompressor.DecodePatch(patches, bitpack, header, group.PatchSize);
136 float[] xvalues = TerrainCompressor.DecompressPatch(patches, header, group);
137  
138 // Y values
139 header = TerrainCompressor.DecodePatchHeader(bitpack);
140 TerrainCompressor.DecodePatch(patches, bitpack, header, group.PatchSize);
141 float[] yvalues = TerrainCompressor.DecompressPatch(patches, header, group);
142  
143 if (simulator.Client.Settings.STORE_LAND_PATCHES)
144 {
145 for (int i = 0; i < 256; i++)
146 simulator.WindSpeeds[i] = new Vector2(xvalues[i], yvalues[i]);
147 }
148 }
149  
150 private void DecompressCloud(Simulator simulator, BitPack bitpack, TerrainPatch.GroupHeader group)
151 {
152 // FIXME:
153 }
154  
155 private void LayerDataHandler(object sender, PacketReceivedEventArgs e)
156 {
157 LayerDataPacket layer = (LayerDataPacket)e.Packet;
158 BitPack bitpack = new BitPack(layer.LayerData.Data, 0);
159 TerrainPatch.GroupHeader header = new TerrainPatch.GroupHeader();
160 TerrainPatch.LayerType type = (TerrainPatch.LayerType)layer.LayerID.Type;
161  
162 // Stride
163 header.Stride = bitpack.UnpackBits(16);
164 // Patch size
165 header.PatchSize = bitpack.UnpackBits(8);
166 // Layer type
167 header.Type = (TerrainPatch.LayerType)bitpack.UnpackBits(8);
168  
169 switch (type)
170 {
171 case TerrainPatch.LayerType.Land:
172 if (m_LandPatchReceivedEvent != null || Client.Settings.STORE_LAND_PATCHES)
173 DecompressLand(e.Simulator, bitpack, header);
174 break;
175 case TerrainPatch.LayerType.Water:
176 Logger.Log("Got a Water LayerData packet, implement me!", Helpers.LogLevel.Error, Client);
177 break;
178 case TerrainPatch.LayerType.Wind:
179 DecompressWind(e.Simulator, bitpack, header);
180 break;
181 case TerrainPatch.LayerType.Cloud:
182 DecompressCloud(e.Simulator, bitpack, header);
183 break;
184 default:
185 Logger.Log("Unrecognized LayerData type " + type.ToString(), Helpers.LogLevel.Warning, Client);
186 break;
187 }
188 }
189 }
190  
191 #region EventArgs classes
192 // <summary>Provides data for LandPatchReceived</summary>
193 public class LandPatchReceivedEventArgs : EventArgs
194 {
195 private readonly Simulator m_Simulator;
196 private readonly int m_X;
197 private readonly int m_Y;
198 private readonly int m_PatchSize;
199 private readonly float[] m_HeightMap;
200  
201 /// <summary>Simulator from that sent tha data</summary>
202 public Simulator Simulator { get { return m_Simulator; } }
203 /// <summary>Sim coordinate of the patch</summary>
204 public int X { get { return m_X; } }
205 /// <summary>Sim coordinate of the patch</summary>
206 public int Y { get { return m_Y; } }
207 /// <summary>Size of tha patch</summary>
208 public int PatchSize { get { return m_PatchSize; } }
209 /// <summary>Heightmap for the patch</summary>
210 public float[] HeightMap { get { return m_HeightMap; } }
211  
212 public LandPatchReceivedEventArgs(Simulator simulator, int x, int y, int patchSize, float[] heightMap)
213 {
214 this.m_Simulator = simulator;
215 this.m_X = x;
216 this.m_Y = y;
217 this.m_PatchSize = patchSize;
218 this.m_HeightMap = heightMap;
219 }
220 }
221 #endregion
222 }