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

Last change on this file since 133 was 132, checked in by alloc, 10 years ago

Fixes: Source cleanups

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