source: binary-improvements/7dtd-server-fixes/src/MapRendering/MapRendering.cs@ 141

Last change on this file since 141 was 140, checked in by alloc, 10 years ago

Fixes

File size: 8.1 KB
RevLine 
[130]1using System;
2using System.Collections.Generic;
3using System.IO;
4using System.Threading;
5using UnityEngine;
6
7namespace AllocsFixes.MapRendering
8{
9 public class MapRendering
10 {
11 private static MapRendering instance;
12
13 public static MapRendering Instance {
14 get {
15 if (instance == null) {
16 instance = new MapRendering ();
17 }
18 return instance;
19 }
20 }
21
22 private RegionFileManager rfm;
[136]23 private Texture2D fullMapTexture = null;
[130]24 private MapRenderBlockBuffer[] zoomLevelBuffers = new MapRenderBlockBuffer[Constants.ZOOMLEVELS];
25 private Color[] chunkColors = new Color[Constants.MAP_CHUNK_SIZE * Constants.MAP_CHUNK_SIZE];
[132]26 private System.Timers.Timer chunkSaveTimer = new System.Timers.Timer (500);
[130]27 private bool renderingFullMap = false;
[140]28 public static bool renderingEnabled = true;
[130]29
30 private MapRendering ()
31 {
32 Constants.MAP_DIRECTORY = StaticDirectories.GetSaveGameDir () + "/map";
33
34 for (int i = 0; i < Constants.ZOOMLEVELS; i++) {
35 zoomLevelBuffers [i] = new MapRenderBlockBuffer (i);
36 }
37
38 chunkSaveTimer.AutoReset = false;
39 chunkSaveTimer.Elapsed += new System.Timers.ElapsedEventHandler (SaveAllBlockMaps);
40 }
41
42 public static void RenderSingleChunk (Chunk chunk)
43 {
[140]44 if (renderingEnabled) {
45 ThreadPool.QueueUserWorkItem ((o) =>
46 {
47 try {
48 if (!Instance.renderingFullMap) {
49 Chunk c = (Chunk)o;
50 Vector3i cPos = c.GetWorldPos ();
51 Vector2i cPos2 = new Vector2i (cPos.x / Constants.MAP_CHUNK_SIZE, cPos.z / Constants.MAP_CHUNK_SIZE);
52 Instance.RenderChunk (c, cPos2);
53 Instance.chunkSaveTimer.Stop ();
54 Instance.chunkSaveTimer.Start ();
55 }
56 } catch (Exception e) {
57 Log.Out ("Exception in MapRendering.RenderSingleChunk(): " + e);
[130]58 }
[140]59 }, chunk);
60 }
[130]61 }
62
63 public void RenderFullMap ()
64 {
65 MicroStopwatch microStopwatch = new MicroStopwatch ();
66
[132]67 string regionSaveDir = StaticDirectories.GetSaveGameRegionDir ();
68 rfm = new RegionFileManager (regionSaveDir, regionSaveDir, 1, false);
69
[130]70 if (Directory.Exists (Constants.MAP_DIRECTORY))
71 Directory.Delete (Constants.MAP_DIRECTORY, true);
72
73 renderingFullMap = true;
74
75 Vector2i minChunk, maxChunk;
76 Vector2i minPos, maxPos;
77 int widthChunks, heightChunks, widthPix, heightPix;
78 getWorldExtent (out minChunk, out maxChunk, out minPos, out maxPos, out widthChunks, out heightChunks, out widthPix, out heightPix);
79
[135]80 Log.Out (String.Format ("RenderMap: min: {0}, max: {1}, minPos: {2}, maxPos: {3}, w/h: {4}/{5}, wP/hP: {6}/{7}",
81 minChunk.ToString (), maxChunk.ToString (),
82 minPos.ToString (), maxPos.ToString (),
83 widthChunks, heightChunks,
[136]84 widthPix, heightPix)
85 );
[135]86
[136]87 if (widthPix <= 8000 && heightPix <= 8000)
88 fullMapTexture = new Texture2D (widthPix, heightPix);
[130]89
90 Vector2i curFullMapPos;
91 Vector2i curChunkPos;
92 for (curFullMapPos.x = 0; curFullMapPos.x < widthPix; curFullMapPos.x += Constants.MAP_CHUNK_SIZE) {
93 for (curFullMapPos.y = 0; curFullMapPos.y < heightPix; curFullMapPos.y += Constants.MAP_CHUNK_SIZE) {
94 curChunkPos.x = (curFullMapPos.x / Constants.MAP_CHUNK_SIZE) + minChunk.x;
95 curChunkPos.y = (curFullMapPos.y / Constants.MAP_CHUNK_SIZE) + minChunk.y;
96
97 RenderChunk (curChunkPos, curFullMapPos);
98 }
99 Log.Out (String.Format ("RenderMap: {0}/{1} ({2}%)", curFullMapPos.x, widthPix, (int)((float)curFullMapPos.x / widthPix * 100)));
100 }
101 SaveAllBlockMaps (null, null);
102
[132]103 rfm = null;
104
[136]105 if (fullMapTexture != null) {
106 byte[] array = fullMapTexture.EncodeToPNG ();
107 File.WriteAllBytes (Constants.MAP_DIRECTORY + "/map.png", array);
108 Texture2D.Destroy (fullMapTexture);
109 fullMapTexture = null;
110 }
[130]111
112 renderingFullMap = false;
113
114 Log.Out ("Generating map took: " + microStopwatch.ElapsedMilliseconds + " ms");
115 Log.Out ("World extent: " + minPos + " - " + maxPos);
116 }
117
118 private int saveCount = 0;
[140]119 private long renderCount = 0;
[130]120
121 private void SaveAllBlockMaps (object source, System.Timers.ElapsedEventArgs e)
122 {
123 Monitor.Enter (zoomLevelBuffers);
124 try {
[140]125 Log.Out ("------- SaveAllBlockMaps " + ++saveCount + " - " + renderCount);
[130]126 for (int i = 0; i < Constants.ZOOMLEVELS; i++) {
[135]127 zoomLevelBuffers [i].SaveBlock ();
[130]128 }
129 } finally {
130 Monitor.Exit (zoomLevelBuffers);
131 }
132 }
133
134 private bool RenderChunk (Vector2i chunkPos, Vector2i fullMapPos = default(Vector2i))
135 {
136 long chunkKey = WorldChunkCache.MakeChunkKey (chunkPos.x, chunkPos.y);
137 if (rfm.ContainsChunkSync (chunkKey)) {
138 Chunk chunk = rfm.GetChunkSync (chunkKey);
139 return RenderChunk (chunk, chunkPos, fullMapPos);
140 }
141 return false;
142 }
143
144 private bool RenderChunk (Chunk chunk, Vector2i chunkPos, Vector2i fullMapPos = default(Vector2i))
145 {
146 Monitor.Enter (zoomLevelBuffers);
147 try {
[140]148 renderCount++;
[130]149 ushort[] mapColors = chunk.GetMapColors ();
150 if (mapColors != null) {
151 Vector2i block, blockOffset;
152 getBlockNumber (chunkPos, out block, out blockOffset, Constants.MAP_BLOCK_TO_CHUNK_DIV, Constants.MAP_CHUNK_SIZE);
153
154 for (int i_colors = 0; i_colors < mapColors.Length; i_colors++) {
155 chunkColors [i_colors] = shortColorToColor (mapColors [i_colors]);
156 }
157
[135]158 zoomLevelBuffers [Constants.ZOOMLEVELS - 1].LoadBlock (block);
159 zoomLevelBuffers [Constants.ZOOMLEVELS - 1].SetPart (blockOffset, Constants.MAP_CHUNK_SIZE, chunkColors);
[130]160
[136]161 if (renderingFullMap && fullMapTexture != null)
[130]162 fullMapTexture.SetPixels (fullMapPos.x, fullMapPos.y, Constants.MAP_CHUNK_SIZE, Constants.MAP_CHUNK_SIZE, chunkColors);
163
164 RenderZoomLevel (Constants.ZOOMLEVELS - 1, block);
165
166 return true;
167 }
168 return false;
169 } finally {
170 Monitor.Exit (zoomLevelBuffers);
171 }
172 }
173
174 private void RenderZoomLevel (int level, Vector2i innerBlock)
175 {
176 if (level > 0) {
177 Vector2i block, blockOffset;
[135]178 getBlockNumber (innerBlock, out block, out blockOffset, 2, Constants.MAP_BLOCK_SIZE / 2);
[130]179
[135]180 zoomLevelBuffers [level - 1].LoadBlock (block);
181 zoomLevelBuffers [level - 1].SetPart (blockOffset, Constants.MAP_BLOCK_SIZE / 2, zoomLevelBuffers [level].GetHalfScaled ());
[130]182
183 RenderZoomLevel (level - 1, block);
184 }
185 }
186
187 private void getBlockNumber (Vector2i innerPos, out Vector2i block, out Vector2i blockOffset, int scaleFactor, int offsetSize)
188 {
189 block.x = ((innerPos.x + 16777216) / scaleFactor) - (16777216 / scaleFactor);
190 block.y = ((innerPos.y + 16777216) / scaleFactor) - (16777216 / scaleFactor);
191 blockOffset.x = ((innerPos.x + 16777216) % scaleFactor) * offsetSize;
192 blockOffset.y = ((innerPos.y + 16777216) % scaleFactor) * offsetSize;
193 }
194
195 private void getWorldExtent (out Vector2i minChunk, out Vector2i maxChunk,
196 out Vector2i minPos, out Vector2i maxPos,
197 out int widthChunks, out int heightChunks,
198 out int widthPix, out int heightPix)
199 {
200 long[] keys = rfm.GetAllChunkKeys ();
201 int minX = Int32.MaxValue;
202 int minY = Int32.MaxValue;
203 int maxX = Int32.MinValue;
204 int maxY = Int32.MinValue;
205 foreach (long key in keys) {
206 int x = WorldChunkCache.extractX (key);
207 int y = WorldChunkCache.extractZ (key);
208
209 if (x < minX)
210 minX = x;
211 if (x > maxX)
212 maxX = x;
213 if (y < minY)
214 minY = y;
215 if (y > maxY)
216 maxY = y;
217 }
218
219 minChunk.x = minX;
220 minChunk.y = minY;
221
222 maxChunk.x = maxX;
223 maxChunk.y = maxY;
224
225 minPos.x = minX * Constants.MAP_CHUNK_SIZE;
226 minPos.y = minY * Constants.MAP_CHUNK_SIZE;
227
228 maxPos.x = maxX * Constants.MAP_CHUNK_SIZE;
229 maxPos.y = maxY * Constants.MAP_CHUNK_SIZE;
230
231 widthChunks = maxX - minX + 1;
232 heightChunks = maxY - minY + 1;
233
234 widthPix = widthChunks * Constants.MAP_CHUNK_SIZE;
235 heightPix = heightChunks * Constants.MAP_CHUNK_SIZE;
236 }
237
238 private Color32 shortColorToColor32 (ushort col)
239 {
240 return new Color32 ((byte)((float)(col >> 10 & 31) / 31f * 255f), (byte)((float)(col >> 5 & 31) / 31f * 255f), (byte)((float)(col & 31) / 31f * 255f), 255);
241 }
242
243 private Color shortColorToColor (ushort col)
244 {
245 return new Color (((float)(col >> 10 & 31) / 31f), ((float)(col >> 5 & 31) / 31f), ((float)(col & 31) / 31f), 255);
246 }
247
248 }
249}
Note: See TracBrowser for help on using the repository browser.