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