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

Last change on this file since 132 was 132, checked in by alloc, 6 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.