]> git.lizzy.rs Git - dragonfireclient.git/blob - src/map.h
comments
[dragonfireclient.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
44 #define MAPTYPE_BASE 0
45 #define MAPTYPE_SERVER 1
46 #define MAPTYPE_CLIENT 2
47
48 class Map : public NodeContainer, public Heightmappish
49 {
50 public:
51
52         Map(std::ostream &dout);
53         virtual ~Map();
54
55         virtual u16 nodeContainerId() const
56         {
57                 return NODECONTAINER_ID_MAP;
58         }
59
60         virtual s32 mapType() const
61         {
62                 return MAPTYPE_BASE;
63         }
64
65         virtual void drop()
66         {
67                 delete this;
68         }
69
70         void updateCamera(v3f pos, v3f dir)
71         {
72                 JMutexAutoLock lock(m_camera_mutex);
73                 m_camera_position = pos;
74                 m_camera_direction = dir;
75         }
76
77         static core::aabbox3d<f32> getNodeBox(v3s16 p)
78         {
79                 return core::aabbox3d<f32>(
80                         (float)p.X * BS - 0.5*BS,
81                         (float)p.Y * BS - 0.5*BS,
82                         (float)p.Z * BS - 0.5*BS,
83                         (float)p.X * BS + 0.5*BS,
84                         (float)p.Y * BS + 0.5*BS,
85                         (float)p.Z * BS + 0.5*BS
86                 );
87         }
88
89         //bool sectorExists(v2s16 p);
90         MapSector * getSectorNoGenerate(v2s16 p2d);
91         /*
92                 This is overloaded by ClientMap and ServerMap to allow
93                 their differing fetch methods.
94         */
95         virtual MapSector * emergeSector(v2s16 p) = 0;
96
97         // Returns InvalidPositionException if not found
98         MapBlock * getBlockNoCreate(v3s16 p);
99         // Returns NULL if not found
100         MapBlock * getBlockNoCreateNoEx(v3s16 p);
101         
102         // Returns InvalidPositionException if not found
103         f32 getGroundHeight(v2s16 p, bool generate=false);
104         void setGroundHeight(v2s16 p, f32 y, bool generate=false);
105
106         // Returns InvalidPositionException if not found
107         bool isNodeUnderground(v3s16 p);
108         
109         // virtual from NodeContainer
110         bool isValidPosition(v3s16 p)
111         {
112                 v3s16 blockpos = getNodeBlockPos(p);
113                 MapBlock *blockref;
114                 try{
115                         blockref = getBlockNoCreate(blockpos);
116                 }
117                 catch(InvalidPositionException &e)
118                 {
119                         return false;
120                 }
121                 return true;
122                 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
123                 bool is_valid = blockref->isValidPosition(relpos);
124                 return is_valid;*/
125         }
126         
127         // virtual from NodeContainer
128         // throws InvalidPositionException if not found
129         MapNode getNode(v3s16 p)
130         {
131                 v3s16 blockpos = getNodeBlockPos(p);
132                 MapBlock * blockref = getBlockNoCreate(blockpos);
133                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
134
135                 return blockref->getNodeNoCheck(relpos);
136         }
137
138         // virtual from NodeContainer
139         // throws InvalidPositionException if not found
140         void setNode(v3s16 p, MapNode & n)
141         {
142                 v3s16 blockpos = getNodeBlockPos(p);
143                 MapBlock * blockref = getBlockNoCreate(blockpos);
144                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
145                 blockref->setNodeNoCheck(relpos, n);
146         }
147
148         /*MapNode getNodeGenerate(v3s16 p)
149         {
150                 v3s16 blockpos = getNodeBlockPos(p);
151                 MapBlock * blockref = getBlock(blockpos);
152                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
153
154                 return blockref->getNode(relpos);
155         }*/
156
157         /*void setNodeGenerate(v3s16 p, MapNode & n)
158         {
159                 v3s16 blockpos = getNodeBlockPos(p);
160                 MapBlock * blockref = getBlock(blockpos);
161                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
162                 blockref->setNode(relpos, n);
163         }*/
164
165         void unspreadLight(enum LightBank bank,
166                         core::map<v3s16, u8> & from_nodes,
167                         core::map<v3s16, bool> & light_sources,
168                         core::map<v3s16, MapBlock*> & modified_blocks);
169
170         void unLightNeighbors(enum LightBank bank,
171                         v3s16 pos, u8 lightwas,
172                         core::map<v3s16, bool> & light_sources,
173                         core::map<v3s16, MapBlock*> & modified_blocks);
174         
175         void spreadLight(enum LightBank bank,
176                         core::map<v3s16, bool> & from_nodes,
177                         core::map<v3s16, MapBlock*> & modified_blocks);
178         
179         void lightNeighbors(enum LightBank bank,
180                         v3s16 pos,
181                         core::map<v3s16, MapBlock*> & modified_blocks);
182
183         v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
184
185         s16 propagateSunlight(v3s16 start,
186                         core::map<v3s16, MapBlock*> & modified_blocks);
187         
188         void updateLighting(enum LightBank bank,
189                         core::map<v3s16, MapBlock*>  & a_blocks,
190                         core::map<v3s16, MapBlock*> & modified_blocks);
191                         
192         void updateLighting(core::map<v3s16, MapBlock*>  & a_blocks,
193                         core::map<v3s16, MapBlock*> & modified_blocks);
194                         
195         /*
196                 These handle lighting but not faces.
197         */
198         void addNodeAndUpdate(v3s16 p, MapNode n,
199                         core::map<v3s16, MapBlock*> &modified_blocks);
200         void removeNodeAndUpdate(v3s16 p,
201                         core::map<v3s16, MapBlock*> &modified_blocks);
202         
203 #ifndef SERVER
204         void expireMeshes(bool only_daynight_diffed);
205         
206         /*
207                 Update the faces of the given block and blocks on the
208                 leading edge.
209         */
210         void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
211         
212         // Update meshes that touch the node
213         //void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
214 #endif
215
216         /*
217                 Takes the blocks at the edges into account
218         */
219         bool dayNightDiffed(v3s16 blockpos);
220
221         //core::aabbox3d<s16> getDisplayedBlockArea();
222
223         //bool updateChangedVisibleArea();
224         
225         virtual void save(bool only_changed){assert(0);};
226
227         /*
228                 Updates usage timers
229         */
230         void timerUpdate(float dtime);
231         
232         // Takes cache into account
233         // sector mutex should be locked when calling
234         void deleteSectors(core::list<v2s16> &list, bool only_blocks);
235         
236         // Returns count of deleted sectors
237         u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
238                         core::list<v3s16> *deleted_blocks=NULL);
239
240         // For debug printing
241         virtual void PrintInfo(std::ostream &out);
242         
243         void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
244
245         /*
246                 Variables
247         */
248         
249 protected:
250
251         std::ostream &m_dout;
252
253         core::map<v2s16, MapSector*> m_sectors;
254         JMutex m_sector_mutex;
255
256         v3f m_camera_position;
257         v3f m_camera_direction;
258         JMutex m_camera_mutex;
259
260         // Be sure to set this to NULL when the cached sector is deleted 
261         MapSector *m_sector_cache;
262         v2s16 m_sector_cache_p;
263
264         WrapperHeightmap m_hwrapper;
265         
266         // Queued transforming water nodes
267         UniqueQueue<v3s16> m_transforming_liquid;
268 };
269
270 // Master heightmap parameters
271 struct HMParams
272 {
273         HMParams()
274         {
275                 blocksize = 64;
276                 randmax = "constant 70.0";
277                 randfactor = "constant 0.6";
278                 base = "linear 0 80 0";
279         }
280         s16 blocksize;
281         std::string randmax;
282         std::string randfactor;
283         std::string base;
284 };
285
286 // Map parameters
287 struct MapParams
288 {
289         MapParams()
290         {
291                 plants_amount = 1.0;
292                 ravines_amount = 1.0;
293                 //max_objects_in_block = 30;
294         }
295         float plants_amount;
296         float ravines_amount;
297         //u16 max_objects_in_block;
298 };
299
300 /*
301         ServerMap
302
303         This is the only map class that is able to generate map.
304 */
305
306 class ServerMap : public Map
307 {
308 public:
309         /*
310                 savedir: directory to which map data should be saved
311         */
312         ServerMap(std::string savedir, HMParams hmp, MapParams mp);
313         ~ServerMap();
314
315         s32 mapType() const
316         {
317                 return MAPTYPE_SERVER;
318         }
319
320         /*
321                 Forcefully get a sector from somewhere
322         */
323         MapSector * emergeSector(v2s16 p);
324         /*
325                 Forcefully get a block from somewhere.
326
327                 Exceptions:
328                 - InvalidPositionException: possible if only_from_disk==true
329                 
330                 changed_blocks:
331                 - All already existing blocks that were modified are added.
332                         - If found on disk, nothing will be added.
333                         - If generated, the new block will not be included.
334
335                 lighting_invalidated_blocks:
336                 - All blocks that have heavy-to-calculate lighting changes
337                   are added.
338                         - updateLighting() should be called for these.
339                 
340                 - A block that is in changed_blocks may not be in
341                   lighting_invalidated_blocks.
342         */
343         MapBlock * emergeBlock(
344                         v3s16 p,
345                         bool only_from_disk,
346                         core::map<v3s16, MapBlock*> &changed_blocks,
347                         core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
348         );
349
350         void createDir(std::string path);
351         void createSaveDir();
352         // returns something like "xxxxxxxx"
353         std::string getSectorSubDir(v2s16 pos);
354         // returns something like "map/sectors/xxxxxxxx"
355         std::string getSectorDir(v2s16 pos);
356         std::string createSectorDir(v2s16 pos);
357         // dirname: final directory name
358         v2s16 getSectorPos(std::string dirname);
359         v3s16 getBlockPos(std::string sectordir, std::string blockfile);
360
361         void save(bool only_changed);
362         void loadAll();
363
364         void saveMasterHeightmap();
365         void loadMasterHeightmap();
366
367         // The sector mutex should be locked when calling most of these
368         
369         // This only saves sector-specific data such as the heightmap
370         // (no MapBlocks)
371         void saveSectorMeta(ServerMapSector *sector);
372         MapSector* loadSectorMeta(std::string dirname);
373         
374         // Full load of a sector including all blocks.
375         // returns true on success, false on failure.
376         bool loadSectorFull(v2s16 p2d);
377         // If sector is not found in memory, try to load it from disk.
378         // Returns true if sector now resides in memory
379         //bool deFlushSector(v2s16 p2d);
380         
381         void saveBlock(MapBlock *block);
382         // This will generate a sector with getSector if not found.
383         void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector);
384
385         // Gets from master heightmap
386         void getSectorCorners(v2s16 p2d, s16 *corners);
387
388         // For debug printing
389         virtual void PrintInfo(std::ostream &out);
390
391 private:
392         // Generator parameters
393         UnlimitedHeightmap *m_heightmap;
394         MapParams m_params;
395         PointAttributeDatabase m_padb;
396
397         std::string m_savedir;
398         bool m_map_saving_enabled;
399 };
400
401 #ifndef SERVER
402
403 struct MapDrawControl
404 {
405         MapDrawControl():
406                 range_all(false),
407                 wanted_range(50),
408                 wanted_max_blocks(0),
409                 wanted_min_range(0),
410                 blocks_drawn(0),
411                 blocks_would_have_drawn(0)
412         {
413         }
414         // Overrides limits by drawing everything
415         bool range_all;
416         // Wanted drawing range
417         float wanted_range;
418         // Maximum number of blocks to draw
419         u32 wanted_max_blocks;
420         // Blocks in this range are drawn regardless of number of blocks drawn
421         float wanted_min_range;
422         // Number of blocks rendered is written here by the renderer
423         u32 blocks_drawn;
424         // Number of blocks that would have been drawn in wanted_range
425         u32 blocks_would_have_drawn;
426 };
427
428 class Client;
429
430 /*
431         ClientMap
432         
433         This is the only map class that is able to render itself on screen.
434 */
435
436 class ClientMap : public Map, public scene::ISceneNode
437 {
438 public:
439         ClientMap(
440                         Client *client,
441                         MapDrawControl &control,
442                         scene::ISceneNode* parent,
443                         scene::ISceneManager* mgr,
444                         s32 id
445         );
446
447         ~ClientMap();
448
449         s32 mapType() const
450         {
451                 return MAPTYPE_CLIENT;
452         }
453
454         void drop()
455         {
456                 ISceneNode::drop();
457         }
458
459         /*
460                 Forcefully get a sector from somewhere
461         */
462         MapSector * emergeSector(v2s16 p);
463
464         void deSerializeSector(v2s16 p2d, std::istream &is);
465
466         /*
467                 ISceneNode methods
468         */
469
470         virtual void OnRegisterSceneNode();
471
472         virtual void render()
473         {
474                 video::IVideoDriver* driver = SceneManager->getVideoDriver();
475                 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
476                 renderMap(driver, SceneManager->getSceneNodeRenderPass());
477         }
478         
479         virtual const core::aabbox3d<f32>& getBoundingBox() const
480         {
481                 return m_box;
482         }
483
484         void renderMap(video::IVideoDriver* driver, s32 pass);
485
486         /*
487                 Methods for setting temporary modifications to nodes for
488                 drawing.
489
490                 Returns true if something changed.
491                 
492                 All blocks whose mesh could have been changed are inserted
493                 to affected_blocks.
494         */
495         bool setTempMod(v3s16 p, NodeMod mod,
496                         core::map<v3s16, MapBlock*> *affected_blocks=NULL);
497         bool clearTempMod(v3s16 p,
498                         core::map<v3s16, MapBlock*> *affected_blocks=NULL);
499         // Efficient implementation needs a cache of TempMods
500         //void clearTempMods();
501
502         // For debug printing
503         virtual void PrintInfo(std::ostream &out);
504         
505 private:
506         Client *m_client;
507         
508         core::aabbox3d<f32> m_box;
509         
510         // This is the master heightmap mesh
511         scene::SMesh *mesh;
512         JMutex mesh_mutex;
513         
514         MapDrawControl &m_control;
515 };
516
517 #endif
518
519 class MapVoxelManipulator : public VoxelManipulator
520 {
521 public:
522         MapVoxelManipulator(Map *map);
523         virtual ~MapVoxelManipulator();
524         
525         virtual void clear()
526         {
527                 VoxelManipulator::clear();
528                 m_loaded_blocks.clear();
529         }
530
531         virtual void emerge(VoxelArea a, s32 caller_id=-1);
532
533         void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
534
535 protected:
536         Map *m_map;
537         /*
538                 NOTE: This might be used or not
539                 bool is dummy value
540                 SUGG: How 'bout an another VoxelManipulator for storing the
541                       information about which block is loaded?
542         */
543         core::map<v3s16, bool> m_loaded_blocks;
544 };
545
546 class ManualMapVoxelManipulator : public MapVoxelManipulator
547 {
548 public:
549         ManualMapVoxelManipulator(Map *map);
550         virtual ~ManualMapVoxelManipulator();
551         
552         virtual void emerge(VoxelArea a, s32 caller_id=-1);
553
554         void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
555
556 protected:
557 };
558
559 #endif
560