work-in-progress texture atlas optimization
[oweals/minetest.git] / src / map.h
1 /*
2 Minetest-c55
3 Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with this program; if not, write to the Free Software Foundation, Inc.,
17 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20 #ifndef MAP_HEADER
21 #define MAP_HEADER
22
23 #include <jmutex.h>
24 #include <jthread.h>
25 #include <iostream>
26 #include <malloc.h>
27
28 #ifdef _WIN32
29         #include <windows.h>
30         #define sleep_s(x) Sleep((x*1000))
31 #else
32         #include <unistd.h>
33         #define sleep_s(x) sleep(x)
34 #endif
35
36 #include "common_irrlicht.h"
37 //#include "heightmap.h"
38 #include "mapnode.h"
39 #include "mapblock.h"
40 #include "mapsector.h"
41 #include "constants.h"
42 #include "voxel.h"
43 #include "mapchunk.h"
44
45 #define MAPTYPE_BASE 0
46 #define MAPTYPE_SERVER 1
47 #define MAPTYPE_CLIENT 2
48
49 class Map : public NodeContainer
50 {
51 public:
52
53         Map(std::ostream &dout);
54         virtual ~Map();
55
56         virtual u16 nodeContainerId() const
57         {
58                 return NODECONTAINER_ID_MAP;
59         }
60
61         virtual s32 mapType() const
62         {
63                 return MAPTYPE_BASE;
64         }
65
66         virtual void drop()
67         {
68                 delete this;
69         }
70
71         void updateCamera(v3f pos, v3f dir)
72         {
73                 JMutexAutoLock lock(m_camera_mutex);
74                 m_camera_position = pos;
75                 m_camera_direction = dir;
76         }
77
78         static core::aabbox3d<f32> getNodeBox(v3s16 p)
79         {
80                 return core::aabbox3d<f32>(
81                         (float)p.X * BS - 0.5*BS,
82                         (float)p.Y * BS - 0.5*BS,
83                         (float)p.Z * BS - 0.5*BS,
84                         (float)p.X * BS + 0.5*BS,
85                         (float)p.Y * BS + 0.5*BS,
86                         (float)p.Z * BS + 0.5*BS
87                 );
88         }
89         
90         // On failure returns NULL
91         MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
92         // On failure returns NULL
93         MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
94         // On failure throws InvalidPositionException
95         MapSector * getSectorNoGenerate(v2s16 p2d);
96         // Gets an existing sector or creates an empty one
97         //MapSector * getSectorCreate(v2s16 p2d);
98
99         /*
100                 This is overloaded by ClientMap and ServerMap to allow
101                 their differing fetch methods.
102         */
103         virtual MapSector * emergeSector(v2s16 p){ return NULL; }
104         virtual MapSector * emergeSector(v2s16 p,
105                         core::map<v3s16, MapBlock*> &changed_blocks){ return NULL; }
106
107         // Returns InvalidPositionException if not found
108         MapBlock * getBlockNoCreate(v3s16 p);
109         // Returns NULL if not found
110         MapBlock * getBlockNoCreateNoEx(v3s16 p);
111         // Gets an existing block or creates an empty one
112         //MapBlock * getBlockCreate(v3s16 p);
113         
114         // Returns InvalidPositionException if not found
115         f32 getGroundHeight(v2s16 p, bool generate=false);
116         void setGroundHeight(v2s16 p, f32 y, bool generate=false);
117
118         // Returns InvalidPositionException if not found
119         bool isNodeUnderground(v3s16 p);
120         
121         // virtual from NodeContainer
122         bool isValidPosition(v3s16 p)
123         {
124                 v3s16 blockpos = getNodeBlockPos(p);
125                 MapBlock *blockref;
126                 try{
127                         blockref = getBlockNoCreate(blockpos);
128                 }
129                 catch(InvalidPositionException &e)
130                 {
131                         return false;
132                 }
133                 return true;
134                 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
135                 bool is_valid = blockref->isValidPosition(relpos);
136                 return is_valid;*/
137         }
138         
139         // virtual from NodeContainer
140         // throws InvalidPositionException if not found
141         MapNode getNode(v3s16 p)
142         {
143                 v3s16 blockpos = getNodeBlockPos(p);
144                 MapBlock * blockref = getBlockNoCreate(blockpos);
145                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
146
147                 return blockref->getNodeNoCheck(relpos);
148         }
149
150         // virtual from NodeContainer
151         // throws InvalidPositionException if not found
152         void setNode(v3s16 p, MapNode & n)
153         {
154                 v3s16 blockpos = getNodeBlockPos(p);
155                 MapBlock * blockref = getBlockNoCreate(blockpos);
156                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
157                 blockref->setNodeNoCheck(relpos, n);
158         }
159
160         /*MapNode getNodeGenerate(v3s16 p)
161         {
162                 v3s16 blockpos = getNodeBlockPos(p);
163                 MapBlock * blockref = getBlock(blockpos);
164                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
165
166                 return blockref->getNode(relpos);
167         }*/
168
169         /*void setNodeGenerate(v3s16 p, MapNode & n)
170         {
171                 v3s16 blockpos = getNodeBlockPos(p);
172                 MapBlock * blockref = getBlock(blockpos);
173                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
174                 blockref->setNode(relpos, n);
175         }*/
176
177         void unspreadLight(enum LightBank bank,
178                         core::map<v3s16, u8> & from_nodes,
179                         core::map<v3s16, bool> & light_sources,
180                         core::map<v3s16, MapBlock*> & modified_blocks);
181
182         void unLightNeighbors(enum LightBank bank,
183                         v3s16 pos, u8 lightwas,
184                         core::map<v3s16, bool> & light_sources,
185                         core::map<v3s16, MapBlock*> & modified_blocks);
186         
187         void spreadLight(enum LightBank bank,
188                         core::map<v3s16, bool> & from_nodes,
189                         core::map<v3s16, MapBlock*> & modified_blocks);
190         
191         void lightNeighbors(enum LightBank bank,
192                         v3s16 pos,
193                         core::map<v3s16, MapBlock*> & modified_blocks);
194
195         v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
196
197         s16 propagateSunlight(v3s16 start,
198                         core::map<v3s16, MapBlock*> & modified_blocks);
199         
200         void updateLighting(enum LightBank bank,
201                         core::map<v3s16, MapBlock*>  & a_blocks,
202                         core::map<v3s16, MapBlock*> & modified_blocks);
203                         
204         void updateLighting(core::map<v3s16, MapBlock*>  & a_blocks,
205                         core::map<v3s16, MapBlock*> & modified_blocks);
206                         
207         /*
208                 These handle lighting but not faces.
209         */
210         void addNodeAndUpdate(v3s16 p, MapNode n,
211                         core::map<v3s16, MapBlock*> &modified_blocks);
212         void removeNodeAndUpdate(v3s16 p,
213                         core::map<v3s16, MapBlock*> &modified_blocks);
214         
215 #ifndef SERVER
216         void expireMeshes(bool only_daynight_diffed);
217         
218         /*
219                 Update the faces of the given block and blocks on the
220                 leading edge.
221         */
222         void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
223         
224         // Update meshes that touch the node
225         //void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
226 #endif
227
228         /*
229                 Takes the blocks at the edges into account
230         */
231         bool dayNightDiffed(v3s16 blockpos);
232
233         //core::aabbox3d<s16> getDisplayedBlockArea();
234
235         //bool updateChangedVisibleArea();
236         
237         virtual void save(bool only_changed){assert(0);};
238
239         /*
240                 Updates usage timers
241         */
242         void timerUpdate(float dtime);
243         
244         // Takes cache into account
245         // sector mutex should be locked when calling
246         void deleteSectors(core::list<v2s16> &list, bool only_blocks);
247         
248         // Returns count of deleted sectors
249         u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
250                         core::list<v3s16> *deleted_blocks=NULL);
251
252         // For debug printing
253         virtual void PrintInfo(std::ostream &out);
254         
255         void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
256
257         /*
258                 Variables
259         */
260         
261 protected:
262
263         std::ostream &m_dout;
264
265         core::map<v2s16, MapSector*> m_sectors;
266         JMutex m_sector_mutex;
267
268         v3f m_camera_position;
269         v3f m_camera_direction;
270         JMutex m_camera_mutex;
271
272         // Be sure to set this to NULL when the cached sector is deleted 
273         MapSector *m_sector_cache;
274         v2s16 m_sector_cache_p;
275
276         //WrapperHeightmap m_hwrapper;
277         
278         // Queued transforming water nodes
279         UniqueQueue<v3s16> m_transforming_liquid;
280 };
281
282 /*
283         ServerMap
284
285         This is the only map class that is able to generate map.
286 */
287
288 class ServerMap : public Map
289 {
290 public:
291         /*
292                 savedir: directory to which map data should be saved
293         */
294         ServerMap(std::string savedir);
295         ~ServerMap();
296
297         s32 mapType() const
298         {
299                 return MAPTYPE_SERVER;
300         }
301
302         /*
303                 Map generation
304         */
305         
306         // Returns the position of the chunk where the sector is in
307         v2s16 sector_to_chunk(v2s16 sectorpos)
308         {
309                 sectorpos.X += m_chunksize / 2;
310                 sectorpos.Y += m_chunksize / 2;
311                 v2s16 chunkpos = getContainerPos(sectorpos, m_chunksize);
312                 return chunkpos;
313         }
314         
315         // Returns the position of the (0,0) sector of the chunk
316         v2s16 chunk_to_sector(v2s16 chunkpos)
317         {
318                 v2s16 sectorpos(
319                         chunkpos.X * m_chunksize,
320                         chunkpos.Y * m_chunksize
321                 );
322                 sectorpos.X -= m_chunksize / 2;
323                 sectorpos.Y -= m_chunksize / 2;
324                 return sectorpos;
325         }
326
327         /*
328                 Get a chunk.
329         */
330         MapChunk *getChunk(v2s16 chunkpos)
331         {
332                 core::map<v2s16, MapChunk*>::Node *n;
333                 n = m_chunks.find(chunkpos);
334                 if(n == NULL)
335                         return NULL;
336                 return n->getValue();
337         }
338
339         /*
340                 True if the chunk and its neighbors are fully generated.
341                 It means the chunk will not be touched in the future by the
342                 generator. If false, generateChunk will make it true.
343         */
344         bool chunkNonVolatile(v2s16 chunkpos)
345         {
346                 /*for(s16 x=-1; x<=1; x++)
347                 for(s16 y=-1; y<=1; y++)*/
348                 s16 x=0;
349                 s16 y=0;
350                 {
351                         v2s16 chunkpos0 = chunkpos + v2s16(x,y);
352                         MapChunk *chunk = getChunk(chunkpos);
353                         if(chunk == NULL)
354                                 return false;
355                         if(chunk->getGenLevel() != GENERATED_FULLY)
356                                 return false;
357                 }
358                 return true;
359         }
360
361         /*
362                 Generate a chunk.
363
364                 All chunks touching this one can be altered also.
365         */
366         MapChunk* generateChunkRaw(v2s16 chunkpos,
367                         core::map<v3s16, MapBlock*> &changed_blocks);
368         
369         /*
370                 Generate a chunk and its neighbors so that it won't be touched
371                 anymore.
372         */
373         MapChunk* generateChunk(v2s16 chunkpos,
374                         core::map<v3s16, MapBlock*> &changed_blocks);
375         
376         /*
377                 Generate a sector.
378                 
379                 This is mainly called by generateChunkRaw.
380         */
381         //ServerMapSector * generateSector(v2s16 p);
382         
383         /*
384                 Get a sector from somewhere.
385                 - Check memory
386                 - Check disk (loads blocks also)
387                 - Create blank one
388         */
389         ServerMapSector * createSector(v2s16 p);
390
391         /*
392                 Get a sector from somewhere.
393                 - Check memory
394                 - Check disk (loads blocks also)
395                 - Generate chunk
396         */
397         MapSector * emergeSector(v2s16 p,
398                         core::map<v3s16, MapBlock*> &changed_blocks);
399         
400         MapSector * emergeSector(v2s16 p)
401         {
402                 core::map<v3s16, MapBlock*> changed_blocks;
403                 return emergeSector(p, changed_blocks);
404         }
405
406         MapBlock * generateBlock(
407                         v3s16 p,
408                         MapBlock *original_dummy,
409                         ServerMapSector *sector,
410                         core::map<v3s16, MapBlock*> &changed_blocks,
411                         core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
412         );
413         
414         /*
415                 Get a block from somewhere.
416                 - Memory
417                 - Create blank
418         */
419         MapBlock * createBlock(v3s16 p);
420         
421         /*
422                 only_from_disk, changed_blocks and lighting_invalidated_blocks
423                 are not properly used by the new map generator.
424         */
425         MapBlock * emergeBlock(
426                         v3s16 p,
427                         bool only_from_disk,
428                         core::map<v3s16, MapBlock*> &changed_blocks,
429                         core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
430         );
431
432 #if 0
433         /*
434                 Forcefully get a block from somewhere.
435
436                 Exceptions:
437                 - InvalidPositionException: possible if only_from_disk==true
438                 
439                 changed_blocks:
440                 - All already existing blocks that were modified are added.
441                         - If found on disk, nothing will be added.
442                         - If generated, the new block will not be included.
443
444                 lighting_invalidated_blocks:
445                 - All blocks that have heavy-to-calculate lighting changes
446                   are added.
447                         - updateLighting() should be called for these.
448                 
449                 - A block that is in changed_blocks may not be in
450                   lighting_invalidated_blocks.
451         */
452         MapBlock * emergeBlock(
453                         v3s16 p,
454                         bool only_from_disk,
455                         core::map<v3s16, MapBlock*> &changed_blocks,
456                         core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
457         );
458 #endif
459
460         /*
461                 Misc. helper functions for fiddling with directory and file
462                 names when saving
463         */
464         void createDir(std::string path);
465         void createSaveDir();
466         // returns something like "xxxxxxxx"
467         std::string getSectorSubDir(v2s16 pos);
468         // returns something like "map/sectors/xxxxxxxx"
469         std::string getSectorDir(v2s16 pos);
470         std::string createSectorDir(v2s16 pos);
471         // dirname: final directory name
472         v2s16 getSectorPos(std::string dirname);
473         v3s16 getBlockPos(std::string sectordir, std::string blockfile);
474
475         void save(bool only_changed);
476         void loadAll();
477         
478         // TODO
479         void saveMapMeta();
480         void loadMapMeta();
481         
482         // TODO
483         void saveChunkMeta();
484         void loadChunkMeta();
485         
486         // DEPRECATED
487         void saveMasterHeightmap();
488         void loadMasterHeightmap();
489
490         // The sector mutex should be locked when calling most of these
491         
492         // This only saves sector-specific data such as the heightmap
493         // (no MapBlocks)
494         // DEPRECATED? Sectors have no metadata anymore.
495         void saveSectorMeta(ServerMapSector *sector);
496         MapSector* loadSectorMeta(std::string dirname);
497         
498         // Full load of a sector including all blocks.
499         // returns true on success, false on failure.
500         bool loadSectorFull(v2s16 p2d);
501         // If sector is not found in memory, try to load it from disk.
502         // Returns true if sector now resides in memory
503         //bool deFlushSector(v2s16 p2d);
504         
505         void saveBlock(MapBlock *block);
506         // This will generate a sector with getSector if not found.
507         void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
508
509         // Gets from master heightmap
510         // DEPRECATED?
511         void getSectorCorners(v2s16 p2d, s16 *corners);
512
513         // For debug printing
514         virtual void PrintInfo(std::ostream &out);
515
516         bool isSavingEnabled(){ return m_map_saving_enabled; }
517
518 private:
519         // Seed used for all kinds of randomness
520         u64 m_seed;
521
522         std::string m_savedir;
523         bool m_map_saving_enabled;
524
525         // Chunk size in MapSectors
526         s16 m_chunksize;
527         // Chunks
528         core::map<v2s16, MapChunk*> m_chunks;
529 };
530
531 /*
532         ClientMap stuff
533 */
534
535 #ifndef SERVER
536
537 struct MapDrawControl
538 {
539         MapDrawControl():
540                 range_all(false),
541                 wanted_range(50),
542                 wanted_max_blocks(0),
543                 wanted_min_range(0),
544                 blocks_drawn(0),
545                 blocks_would_have_drawn(0)
546         {
547         }
548         // Overrides limits by drawing everything
549         bool range_all;
550         // Wanted drawing range
551         float wanted_range;
552         // Maximum number of blocks to draw
553         u32 wanted_max_blocks;
554         // Blocks in this range are drawn regardless of number of blocks drawn
555         float wanted_min_range;
556         // Number of blocks rendered is written here by the renderer
557         u32 blocks_drawn;
558         // Number of blocks that would have been drawn in wanted_range
559         u32 blocks_would_have_drawn;
560 };
561
562 class Client;
563
564 /*
565         ClientMap
566         
567         This is the only map class that is able to render itself on screen.
568 */
569
570 class ClientMap : public Map, public scene::ISceneNode
571 {
572 public:
573         ClientMap(
574                         Client *client,
575                         MapDrawControl &control,
576                         scene::ISceneNode* parent,
577                         scene::ISceneManager* mgr,
578                         s32 id
579         );
580
581         ~ClientMap();
582
583         s32 mapType() const
584         {
585                 return MAPTYPE_CLIENT;
586         }
587
588         void drop()
589         {
590                 ISceneNode::drop();
591         }
592
593         /*
594                 Forcefully get a sector from somewhere
595         */
596         MapSector * emergeSector(v2s16 p);
597
598         void deSerializeSector(v2s16 p2d, std::istream &is);
599
600         /*
601                 ISceneNode methods
602         */
603
604         virtual void OnRegisterSceneNode();
605
606         virtual void render()
607         {
608                 video::IVideoDriver* driver = SceneManager->getVideoDriver();
609                 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
610                 renderMap(driver, SceneManager->getSceneNodeRenderPass());
611         }
612         
613         virtual const core::aabbox3d<f32>& getBoundingBox() const
614         {
615                 return m_box;
616         }
617
618         void renderMap(video::IVideoDriver* driver, s32 pass);
619
620         /*
621                 Methods for setting temporary modifications to nodes for
622                 drawing.
623
624                 Returns true if something changed.
625                 
626                 All blocks whose mesh could have been changed are inserted
627                 to affected_blocks.
628         */
629         bool setTempMod(v3s16 p, NodeMod mod,
630                         core::map<v3s16, MapBlock*> *affected_blocks=NULL);
631         bool clearTempMod(v3s16 p,
632                         core::map<v3s16, MapBlock*> *affected_blocks=NULL);
633         // Efficient implementation needs a cache of TempMods
634         //void clearTempMods();
635
636         // For debug printing
637         virtual void PrintInfo(std::ostream &out);
638         
639 private:
640         Client *m_client;
641         
642         core::aabbox3d<f32> m_box;
643         
644         // This is the master heightmap mesh
645         //scene::SMesh *mesh;
646         //JMutex mesh_mutex;
647         
648         MapDrawControl &m_control;
649 };
650
651 #endif
652
653 class MapVoxelManipulator : public VoxelManipulator
654 {
655 public:
656         MapVoxelManipulator(Map *map);
657         virtual ~MapVoxelManipulator();
658         
659         virtual void clear()
660         {
661                 VoxelManipulator::clear();
662                 m_loaded_blocks.clear();
663         }
664
665         virtual void emerge(VoxelArea a, s32 caller_id=-1);
666
667         void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
668
669 protected:
670         Map *m_map;
671         /*
672                 key = blockpos
673                 value = block existed when loaded
674         */
675         core::map<v3s16, bool> m_loaded_blocks;
676 };
677
678 class ManualMapVoxelManipulator : public MapVoxelManipulator
679 {
680 public:
681         ManualMapVoxelManipulator(Map *map);
682         virtual ~ManualMapVoxelManipulator();
683         
684         virtual void emerge(VoxelArea a, s32 caller_id=-1);
685
686         void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
687         
688         // This is much faster with big chunks of generated data
689         void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);
690
691 protected:
692         bool m_create_area;
693 };
694
695 #endif
696