partly working chunk-based map generator (doesn't save properly, spawn is pretty...
[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, public Heightmappish
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) = 0;
104
105         // Returns InvalidPositionException if not found
106         MapBlock * getBlockNoCreate(v3s16 p);
107         // Returns NULL if not found
108         MapBlock * getBlockNoCreateNoEx(v3s16 p);
109         // Gets an existing block or creates an empty one
110         //MapBlock * getBlockCreate(v3s16 p);
111         
112         // Returns InvalidPositionException if not found
113         f32 getGroundHeight(v2s16 p, bool generate=false);
114         void setGroundHeight(v2s16 p, f32 y, bool generate=false);
115
116         // Returns InvalidPositionException if not found
117         bool isNodeUnderground(v3s16 p);
118         
119         // virtual from NodeContainer
120         bool isValidPosition(v3s16 p)
121         {
122                 v3s16 blockpos = getNodeBlockPos(p);
123                 MapBlock *blockref;
124                 try{
125                         blockref = getBlockNoCreate(blockpos);
126                 }
127                 catch(InvalidPositionException &e)
128                 {
129                         return false;
130                 }
131                 return true;
132                 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
133                 bool is_valid = blockref->isValidPosition(relpos);
134                 return is_valid;*/
135         }
136         
137         // virtual from NodeContainer
138         // throws InvalidPositionException if not found
139         MapNode getNode(v3s16 p)
140         {
141                 v3s16 blockpos = getNodeBlockPos(p);
142                 MapBlock * blockref = getBlockNoCreate(blockpos);
143                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
144
145                 return blockref->getNodeNoCheck(relpos);
146         }
147
148         // virtual from NodeContainer
149         // throws InvalidPositionException if not found
150         void setNode(v3s16 p, MapNode & n)
151         {
152                 v3s16 blockpos = getNodeBlockPos(p);
153                 MapBlock * blockref = getBlockNoCreate(blockpos);
154                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
155                 blockref->setNodeNoCheck(relpos, n);
156         }
157
158         /*MapNode getNodeGenerate(v3s16 p)
159         {
160                 v3s16 blockpos = getNodeBlockPos(p);
161                 MapBlock * blockref = getBlock(blockpos);
162                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
163
164                 return blockref->getNode(relpos);
165         }*/
166
167         /*void setNodeGenerate(v3s16 p, MapNode & n)
168         {
169                 v3s16 blockpos = getNodeBlockPos(p);
170                 MapBlock * blockref = getBlock(blockpos);
171                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
172                 blockref->setNode(relpos, n);
173         }*/
174
175         void unspreadLight(enum LightBank bank,
176                         core::map<v3s16, u8> & from_nodes,
177                         core::map<v3s16, bool> & light_sources,
178                         core::map<v3s16, MapBlock*> & modified_blocks);
179
180         void unLightNeighbors(enum LightBank bank,
181                         v3s16 pos, u8 lightwas,
182                         core::map<v3s16, bool> & light_sources,
183                         core::map<v3s16, MapBlock*> & modified_blocks);
184         
185         void spreadLight(enum LightBank bank,
186                         core::map<v3s16, bool> & from_nodes,
187                         core::map<v3s16, MapBlock*> & modified_blocks);
188         
189         void lightNeighbors(enum LightBank bank,
190                         v3s16 pos,
191                         core::map<v3s16, MapBlock*> & modified_blocks);
192
193         v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
194
195         s16 propagateSunlight(v3s16 start,
196                         core::map<v3s16, MapBlock*> & modified_blocks);
197         
198         void updateLighting(enum LightBank bank,
199                         core::map<v3s16, MapBlock*>  & a_blocks,
200                         core::map<v3s16, MapBlock*> & modified_blocks);
201                         
202         void updateLighting(core::map<v3s16, MapBlock*>  & a_blocks,
203                         core::map<v3s16, MapBlock*> & modified_blocks);
204                         
205         /*
206                 These handle lighting but not faces.
207         */
208         void addNodeAndUpdate(v3s16 p, MapNode n,
209                         core::map<v3s16, MapBlock*> &modified_blocks);
210         void removeNodeAndUpdate(v3s16 p,
211                         core::map<v3s16, MapBlock*> &modified_blocks);
212         
213 #ifndef SERVER
214         void expireMeshes(bool only_daynight_diffed);
215         
216         /*
217                 Update the faces of the given block and blocks on the
218                 leading edge.
219         */
220         void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
221         
222         // Update meshes that touch the node
223         //void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
224 #endif
225
226         /*
227                 Takes the blocks at the edges into account
228         */
229         bool dayNightDiffed(v3s16 blockpos);
230
231         //core::aabbox3d<s16> getDisplayedBlockArea();
232
233         //bool updateChangedVisibleArea();
234         
235         virtual void save(bool only_changed){assert(0);};
236
237         /*
238                 Updates usage timers
239         */
240         void timerUpdate(float dtime);
241         
242         // Takes cache into account
243         // sector mutex should be locked when calling
244         void deleteSectors(core::list<v2s16> &list, bool only_blocks);
245         
246         // Returns count of deleted sectors
247         u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
248                         core::list<v3s16> *deleted_blocks=NULL);
249
250         // For debug printing
251         virtual void PrintInfo(std::ostream &out);
252         
253         void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
254
255         /*
256                 Variables
257         */
258         
259 protected:
260
261         std::ostream &m_dout;
262
263         core::map<v2s16, MapSector*> m_sectors;
264         JMutex m_sector_mutex;
265
266         v3f m_camera_position;
267         v3f m_camera_direction;
268         JMutex m_camera_mutex;
269
270         // Be sure to set this to NULL when the cached sector is deleted 
271         MapSector *m_sector_cache;
272         v2s16 m_sector_cache_p;
273
274         WrapperHeightmap m_hwrapper;
275         
276         // Queued transforming water nodes
277         UniqueQueue<v3s16> m_transforming_liquid;
278 };
279
280 // Master heightmap parameters
281 struct HMParams
282 {
283         HMParams()
284         {
285                 blocksize = 64;
286                 randmax = "constant 70.0";
287                 randfactor = "constant 0.6";
288                 base = "linear 0 80 0";
289         }
290         s16 blocksize;
291         std::string randmax;
292         std::string randfactor;
293         std::string base;
294 };
295
296 // Map parameters
297 struct MapParams
298 {
299         MapParams()
300         {
301                 plants_amount = 1.0;
302                 ravines_amount = 1.0;
303                 //max_objects_in_block = 30;
304         }
305         float plants_amount;
306         float ravines_amount;
307         //u16 max_objects_in_block;
308 };
309
310 /*
311         ServerMap
312
313         This is the only map class that is able to generate map.
314 */
315
316 class ServerMap : public Map
317 {
318 public:
319         /*
320                 savedir: directory to which map data should be saved
321         */
322         ServerMap(std::string savedir, HMParams hmp, MapParams mp);
323         ~ServerMap();
324
325         s32 mapType() const
326         {
327                 return MAPTYPE_SERVER;
328         }
329
330         /*
331                 Map generation
332         */
333         
334         // Returns the position of the chunk where the sector is in
335         v2s16 sector_to_chunk(v2s16 sectorpos)
336         {
337                 sectorpos.X += m_chunksize / 2;
338                 sectorpos.Y += m_chunksize / 2;
339                 v2s16 chunkpos = getContainerPos(sectorpos, m_chunksize);
340                 return chunkpos;
341         }
342         
343         // Returns the position of the (0,0) sector of the chunk
344         v2s16 chunk_to_sector(v2s16 chunkpos)
345         {
346                 v2s16 sectorpos(
347                         chunkpos.X * m_chunksize,
348                         chunkpos.Y * m_chunksize
349                 );
350                 sectorpos.X -= m_chunksize / 2;
351                 sectorpos.Y -= m_chunksize / 2;
352                 return sectorpos;
353         }
354
355         /*
356                 Get a chunk.
357         */
358         MapChunk *getChunk(v2s16 chunkpos)
359         {
360                 core::map<v2s16, MapChunk*>::Node *n;
361                 n = m_chunks.find(chunkpos);
362                 if(n == NULL)
363                         return NULL;
364                 return n->getValue();
365         }
366
367         /*
368                 Generate a chunk.
369
370                 All chunks touching this one can be altered also.
371
372                 Doesn't update lighting.
373         */
374         MapChunk* generateChunkRaw(v2s16 chunkpos);
375         
376         /*
377                 Generate a chunk and its neighbors so that it won't be touched
378                 anymore.
379
380                 Doesn't update lighting.
381         */
382         MapChunk* generateChunk(v2s16 chunkpos);
383         
384         /*
385                 Generate a sector.
386                 
387                 This is mainly called by generateChunkRaw.
388         */
389         //ServerMapSector * generateSector(v2s16 p);
390         
391         /*
392                 Get a sector from somewhere.
393                 - Check memory
394                 - Check disk (loads blocks also)
395                 - Create blank one
396         */
397         ServerMapSector * createSector(v2s16 p);
398
399         /*
400                 Get a sector from somewhere.
401                 - Check memory
402                 - Check disk (loads blocks also)
403                 - Generate chunk
404         */
405         MapSector * emergeSector(v2s16 p);
406
407         MapBlock * generateBlock(
408                         v3s16 p,
409                         MapBlock *original_dummy,
410                         ServerMapSector *sector,
411                         core::map<v3s16, MapBlock*> &changed_blocks,
412                         core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
413         );
414         
415         /*
416                 Get a block from somewhere.
417                 - Memory
418                 - Create blank
419         */
420         MapBlock * createBlock(v3s16 p);
421
422         MapBlock * emergeBlock(
423                         v3s16 p,
424                         bool only_from_disk,
425                         core::map<v3s16, MapBlock*> &changed_blocks,
426                         core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
427         );
428
429 #if 0
430         /*
431                 Forcefully get a block from somewhere.
432
433                 Exceptions:
434                 - InvalidPositionException: possible if only_from_disk==true
435                 
436                 changed_blocks:
437                 - All already existing blocks that were modified are added.
438                         - If found on disk, nothing will be added.
439                         - If generated, the new block will not be included.
440
441                 lighting_invalidated_blocks:
442                 - All blocks that have heavy-to-calculate lighting changes
443                   are added.
444                         - updateLighting() should be called for these.
445                 
446                 - A block that is in changed_blocks may not be in
447                   lighting_invalidated_blocks.
448         */
449         MapBlock * emergeBlock(
450                         v3s16 p,
451                         bool only_from_disk,
452                         core::map<v3s16, MapBlock*> &changed_blocks,
453                         core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
454         );
455 #endif
456
457         /*
458                 Misc. helper functions for fiddling with directory and file
459                 names when saving
460         */
461         void createDir(std::string path);
462         void createSaveDir();
463         // returns something like "xxxxxxxx"
464         std::string getSectorSubDir(v2s16 pos);
465         // returns something like "map/sectors/xxxxxxxx"
466         std::string getSectorDir(v2s16 pos);
467         std::string createSectorDir(v2s16 pos);
468         // dirname: final directory name
469         v2s16 getSectorPos(std::string dirname);
470         v3s16 getBlockPos(std::string sectordir, std::string blockfile);
471
472         void save(bool only_changed);
473         void loadAll();
474
475         void saveMasterHeightmap();
476         void loadMasterHeightmap();
477
478         // The sector mutex should be locked when calling most of these
479         
480         // This only saves sector-specific data such as the heightmap
481         // (no MapBlocks)
482         void saveSectorMeta(ServerMapSector *sector);
483         MapSector* loadSectorMeta(std::string dirname);
484         
485         // Full load of a sector including all blocks.
486         // returns true on success, false on failure.
487         bool loadSectorFull(v2s16 p2d);
488         // If sector is not found in memory, try to load it from disk.
489         // Returns true if sector now resides in memory
490         //bool deFlushSector(v2s16 p2d);
491         
492         void saveBlock(MapBlock *block);
493         // This will generate a sector with getSector if not found.
494         void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
495
496         // Gets from master heightmap
497         void getSectorCorners(v2s16 p2d, s16 *corners);
498
499         // For debug printing
500         virtual void PrintInfo(std::ostream &out);
501
502 private:
503         // Generator parameters
504         UnlimitedHeightmap *m_heightmap;
505         MapParams m_params;
506         PointAttributeDatabase m_padb;
507
508         std::string m_savedir;
509         bool m_map_saving_enabled;
510
511         // Chunk size in MapSectors
512         s16 m_chunksize;
513         // Chunks
514         core::map<v2s16, MapChunk*> m_chunks;
515 };
516
517 /*
518         ClientMap stuff
519 */
520
521 #ifndef SERVER
522
523 struct MapDrawControl
524 {
525         MapDrawControl():
526                 range_all(false),
527                 wanted_range(50),
528                 wanted_max_blocks(0),
529                 wanted_min_range(0),
530                 blocks_drawn(0),
531                 blocks_would_have_drawn(0)
532         {
533         }
534         // Overrides limits by drawing everything
535         bool range_all;
536         // Wanted drawing range
537         float wanted_range;
538         // Maximum number of blocks to draw
539         u32 wanted_max_blocks;
540         // Blocks in this range are drawn regardless of number of blocks drawn
541         float wanted_min_range;
542         // Number of blocks rendered is written here by the renderer
543         u32 blocks_drawn;
544         // Number of blocks that would have been drawn in wanted_range
545         u32 blocks_would_have_drawn;
546 };
547
548 class Client;
549
550 /*
551         ClientMap
552         
553         This is the only map class that is able to render itself on screen.
554 */
555
556 class ClientMap : public Map, public scene::ISceneNode
557 {
558 public:
559         ClientMap(
560                         Client *client,
561                         MapDrawControl &control,
562                         scene::ISceneNode* parent,
563                         scene::ISceneManager* mgr,
564                         s32 id
565         );
566
567         ~ClientMap();
568
569         s32 mapType() const
570         {
571                 return MAPTYPE_CLIENT;
572         }
573
574         void drop()
575         {
576                 ISceneNode::drop();
577         }
578
579         /*
580                 Forcefully get a sector from somewhere
581         */
582         MapSector * emergeSector(v2s16 p);
583
584         void deSerializeSector(v2s16 p2d, std::istream &is);
585
586         /*
587                 ISceneNode methods
588         */
589
590         virtual void OnRegisterSceneNode();
591
592         virtual void render()
593         {
594                 video::IVideoDriver* driver = SceneManager->getVideoDriver();
595                 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
596                 renderMap(driver, SceneManager->getSceneNodeRenderPass());
597         }
598         
599         virtual const core::aabbox3d<f32>& getBoundingBox() const
600         {
601                 return m_box;
602         }
603
604         void renderMap(video::IVideoDriver* driver, s32 pass);
605
606         /*
607                 Methods for setting temporary modifications to nodes for
608                 drawing.
609
610                 Returns true if something changed.
611                 
612                 All blocks whose mesh could have been changed are inserted
613                 to affected_blocks.
614         */
615         bool setTempMod(v3s16 p, NodeMod mod,
616                         core::map<v3s16, MapBlock*> *affected_blocks=NULL);
617         bool clearTempMod(v3s16 p,
618                         core::map<v3s16, MapBlock*> *affected_blocks=NULL);
619         // Efficient implementation needs a cache of TempMods
620         //void clearTempMods();
621
622         // For debug printing
623         virtual void PrintInfo(std::ostream &out);
624         
625 private:
626         Client *m_client;
627         
628         core::aabbox3d<f32> m_box;
629         
630         // This is the master heightmap mesh
631         scene::SMesh *mesh;
632         JMutex mesh_mutex;
633         
634         MapDrawControl &m_control;
635 };
636
637 #endif
638
639 class MapVoxelManipulator : public VoxelManipulator
640 {
641 public:
642         MapVoxelManipulator(Map *map);
643         virtual ~MapVoxelManipulator();
644         
645         virtual void clear()
646         {
647                 VoxelManipulator::clear();
648                 m_loaded_blocks.clear();
649         }
650
651         virtual void emerge(VoxelArea a, s32 caller_id=-1);
652
653         void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
654
655 protected:
656         Map *m_map;
657         /*
658                 key = blockpos
659                 value = block existed when loaded
660         */
661         core::map<v3s16, bool> m_loaded_blocks;
662 };
663
664 class ManualMapVoxelManipulator : public MapVoxelManipulator
665 {
666 public:
667         ManualMapVoxelManipulator(Map *map);
668         virtual ~ManualMapVoxelManipulator();
669         
670         virtual void emerge(VoxelArea a, s32 caller_id=-1);
671
672         void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
673         
674         // This is much faster with big chunks of generated data
675         void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);
676
677 protected:
678         bool m_create_area;
679 };
680
681 #endif
682