]> git.lizzy.rs Git - minetest.git/blob - src/map.h
map unloading is now a whole lot better
[minetest.git] / src / map.h
1 /*
2 Minetest-c55
3 Copyright (C) 2010-2011 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 <jmutexautolock.h>
25 #include <jthread.h>
26 #include <iostream>
27
28 #include "common_irrlicht.h"
29 #include "mapnode.h"
30 #include "mapblock_nodemod.h"
31 #include "constants.h"
32 #include "voxel.h"
33
34 class MapSector;
35 class ServerMapSector;
36 class ClientMapSector;
37 class MapBlock;
38 class NodeMetadata;
39
40 namespace mapgen{
41         struct BlockMakeData;
42 };
43
44 /*
45         MapEditEvent
46 */
47
48 #define MAPTYPE_BASE 0
49 #define MAPTYPE_SERVER 1
50 #define MAPTYPE_CLIENT 2
51
52 enum MapEditEventType{
53         // Node added (changed from air or something else to something)
54         MEET_ADDNODE,
55         // Node removed (changed to air)
56         MEET_REMOVENODE,
57         // Node metadata of block changed (not knowing which node exactly)
58         // p stores block coordinate
59         MEET_BLOCK_NODE_METADATA_CHANGED,
60         // Anything else
61         MEET_OTHER
62 };
63
64 struct MapEditEvent
65 {
66         MapEditEventType type;
67         v3s16 p;
68         MapNode n;
69         core::map<v3s16, bool> modified_blocks;
70         u16 already_known_by_peer;
71
72         MapEditEvent():
73                 type(MEET_OTHER),
74                 already_known_by_peer(0)
75         {
76         }
77         
78         MapEditEvent * clone()
79         {
80                 MapEditEvent *event = new MapEditEvent();
81                 event->type = type;
82                 event->p = p;
83                 event->n = n;
84                 for(core::map<v3s16, bool>::Iterator
85                                 i = modified_blocks.getIterator();
86                                 i.atEnd()==false; i++)
87                 {
88                         v3s16 p = i.getNode()->getKey();
89                         bool v = i.getNode()->getValue();
90                         event->modified_blocks.insert(p, v);
91                 }
92                 return event;
93         }
94 };
95
96 class MapEventReceiver
97 {
98 public:
99         // event shall be deleted by caller after the call.
100         virtual void onMapEditEvent(MapEditEvent *event) = 0;
101 };
102
103 class Map /*: public NodeContainer*/
104 {
105 public:
106
107         Map(std::ostream &dout);
108         virtual ~Map();
109
110         /*virtual u16 nodeContainerId() const
111         {
112                 return NODECONTAINER_ID_MAP;
113         }*/
114
115         virtual s32 mapType() const
116         {
117                 return MAPTYPE_BASE;
118         }
119         
120         /*
121                 Drop (client) or delete (server) the map.
122         */
123         virtual void drop()
124         {
125                 delete this;
126         }
127
128         void addEventReceiver(MapEventReceiver *event_receiver);
129         void removeEventReceiver(MapEventReceiver *event_receiver);
130         // event shall be deleted by caller after the call.
131         void dispatchEvent(MapEditEvent *event);
132
133         // On failure returns NULL
134         MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
135         // Same as the above (there exists no lock anymore)
136         MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
137         // On failure throws InvalidPositionException
138         MapSector * getSectorNoGenerate(v2s16 p2d);
139         // Gets an existing sector or creates an empty one
140         //MapSector * getSectorCreate(v2s16 p2d);
141
142         /*
143                 This is overloaded by ClientMap and ServerMap to allow
144                 their differing fetch methods.
145         */
146         virtual MapSector * emergeSector(v2s16 p){ return NULL; }
147         virtual MapSector * emergeSector(v2s16 p,
148                         core::map<v3s16, MapBlock*> &changed_blocks){ return NULL; }
149
150         // Returns InvalidPositionException if not found
151         MapBlock * getBlockNoCreate(v3s16 p);
152         // Returns NULL if not found
153         MapBlock * getBlockNoCreateNoEx(v3s16 p);
154         
155         // Returns InvalidPositionException if not found
156         bool isNodeUnderground(v3s16 p);
157         
158         bool isValidPosition(v3s16 p);
159         
160         // throws InvalidPositionException if not found
161         MapNode getNode(v3s16 p);
162
163         // throws InvalidPositionException if not found
164         void setNode(v3s16 p, MapNode & n);
165         
166         // Returns a CONTENT_IGNORE node if not found
167         MapNode getNodeNoEx(v3s16 p);
168
169         void unspreadLight(enum LightBank bank,
170                         core::map<v3s16, u8> & from_nodes,
171                         core::map<v3s16, bool> & light_sources,
172                         core::map<v3s16, MapBlock*> & modified_blocks);
173
174         void unLightNeighbors(enum LightBank bank,
175                         v3s16 pos, u8 lightwas,
176                         core::map<v3s16, bool> & light_sources,
177                         core::map<v3s16, MapBlock*> & modified_blocks);
178         
179         void spreadLight(enum LightBank bank,
180                         core::map<v3s16, bool> & from_nodes,
181                         core::map<v3s16, MapBlock*> & modified_blocks);
182         
183         void lightNeighbors(enum LightBank bank,
184                         v3s16 pos,
185                         core::map<v3s16, MapBlock*> & modified_blocks);
186
187         v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
188
189         s16 propagateSunlight(v3s16 start,
190                         core::map<v3s16, MapBlock*> & modified_blocks);
191         
192         void updateLighting(enum LightBank bank,
193                         core::map<v3s16, MapBlock*>  & a_blocks,
194                         core::map<v3s16, MapBlock*> & modified_blocks);
195                         
196         void updateLighting(core::map<v3s16, MapBlock*>  & a_blocks,
197                         core::map<v3s16, MapBlock*> & modified_blocks);
198                         
199         /*
200                 These handle lighting but not faces.
201         */
202         void addNodeAndUpdate(v3s16 p, MapNode n,
203                         core::map<v3s16, MapBlock*> &modified_blocks);
204         void removeNodeAndUpdate(v3s16 p,
205                         core::map<v3s16, MapBlock*> &modified_blocks);
206
207         /*
208                 Wrappers for the latter ones.
209                 These emit events.
210                 Return true if succeeded, false if not.
211         */
212         bool addNodeWithEvent(v3s16 p, MapNode n);
213         bool removeNodeWithEvent(v3s16 p);
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         // Server implements this.
227         // Client leaves it as no-op.
228         virtual void saveBlock(MapBlock *block){};
229
230         /*
231                 Updates usage timers and unloads unused blocks and sectors.
232                 Saves modified blocks before unloading on MAPTYPE_SERVER.
233         */
234         void timerUpdate(float dtime, float unload_timeout,
235                         core::list<v3s16> *unloaded_blocks=NULL);
236                 
237         // Deletes sectors and their blocks from memory
238         // Takes cache into account
239         // If deleted sector is in sector cache, clears cache
240         void deleteSectors(core::list<v2s16> &list);
241
242 #if 0
243         /*
244                 Unload unused data
245                 = flush changed to disk and delete from memory, if usage timer of
246                   block is more than timeout
247         */
248         void unloadUnusedData(float timeout,
249                         core::list<v3s16> *deleted_blocks=NULL);
250 #endif
251
252         // For debug printing. Prints "Map: ", "ServerMap: " or "ClientMap: "
253         virtual void PrintInfo(std::ostream &out);
254         
255         void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
256
257         /*
258                 Node metadata
259                 These are basically coordinate wrappers to MapBlock
260         */
261         
262         NodeMetadata* getNodeMetadata(v3s16 p);
263         void setNodeMetadata(v3s16 p, NodeMetadata *meta);
264         void removeNodeMetadata(v3s16 p);
265         void nodeMetadataStep(float dtime,
266                         core::map<v3s16, MapBlock*> &changed_blocks);
267         
268         /*
269                 Misc.
270         */
271         core::map<v2s16, MapSector*> *getSectorsPtr(){return &m_sectors;}
272
273         /*
274                 Variables
275         */
276         
277 protected:
278
279         std::ostream &m_dout;
280
281         core::map<MapEventReceiver*, bool> m_event_receivers;
282         
283         core::map<v2s16, MapSector*> m_sectors;
284
285         // Be sure to set this to NULL when the cached sector is deleted 
286         MapSector *m_sector_cache;
287         v2s16 m_sector_cache_p;
288
289         // Queued transforming water nodes
290         UniqueQueue<v3s16> m_transforming_liquid;
291 };
292
293 /*
294         ServerMap
295
296         This is the only map class that is able to generate map.
297 */
298
299 class ServerMap : public Map
300 {
301 public:
302         /*
303                 savedir: directory to which map data should be saved
304         */
305         ServerMap(std::string savedir);
306         ~ServerMap();
307
308         s32 mapType() const
309         {
310                 return MAPTYPE_SERVER;
311         }
312
313         /*
314                 Get a sector from somewhere.
315                 - Check memory
316                 - Check disk (doesn't load blocks)
317                 - Create blank one
318         */
319         ServerMapSector * createSector(v2s16 p);
320
321         /*
322                 Blocks are generated by using these and makeBlock().
323         */
324         void initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos);
325         MapBlock* finishBlockMake(mapgen::BlockMakeData *data,
326                         core::map<v3s16, MapBlock*> &changed_blocks);
327         
328         // A non-threaded wrapper to the above
329         MapBlock * generateBlock(
330                         v3s16 p,
331                         core::map<v3s16, MapBlock*> &modified_blocks
332         );
333         
334         /*
335                 Get a block from somewhere.
336                 - Memory
337                 - Create blank
338         */
339         MapBlock * createBlock(v3s16 p);
340
341 #if 0
342         /*
343                 NOTE: This comment might be outdated
344                 
345                 Forcefully get a block from somewhere.
346
347                 InvalidPositionException possible if only_from_disk==true
348                 
349                 Parameters:
350                 changed_blocks: Blocks that have been modified
351         */
352         MapBlock * emergeBlock(
353                         v3s16 p,
354                         bool only_from_disk,
355                         core::map<v3s16, MapBlock*> &changed_blocks,
356                         core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
357         );
358 #endif
359         
360         // Helper for placing objects on ground level
361         s16 findGroundLevel(v2s16 p2d);
362
363         /*
364                 Misc. helper functions for fiddling with directory and file
365                 names when saving
366         */
367         void createDirs(std::string path);
368         // returns something like "map/sectors/xxxxxxxx"
369         std::string getSectorDir(v2s16 pos, int layout = 2);
370         // dirname: final directory name
371         v2s16 getSectorPos(std::string dirname);
372         v3s16 getBlockPos(std::string sectordir, std::string blockfile);
373         static std::string getBlockFilename(v3s16 p);
374
375         void save(bool only_changed);
376         //void loadAll();
377         
378         // Saves map seed and possibly other stuff
379         void saveMapMeta();
380         void loadMapMeta();
381         
382         /*void saveChunkMeta();
383         void loadChunkMeta();*/
384         
385         // The sector mutex should be locked when calling most of these
386         
387         // This only saves sector-specific data such as the heightmap
388         // (no MapBlocks)
389         // DEPRECATED? Sectors have no metadata anymore.
390         void saveSectorMeta(ServerMapSector *sector);
391         MapSector* loadSectorMeta(std::string dirname, bool save_after_load);
392         bool loadSectorMeta(v2s16 p2d);
393         
394         // Full load of a sector including all blocks.
395         // returns true on success, false on failure.
396         bool loadSectorFull(v2s16 p2d);
397         // If sector is not found in memory, try to load it from disk.
398         // Returns true if sector now resides in memory
399         //bool deFlushSector(v2s16 p2d);
400         
401         void saveBlock(MapBlock *block);
402         // This will generate a sector with getSector if not found.
403         void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load=false);
404         MapBlock* loadBlock(v3s16 p);
405
406         // For debug printing
407         virtual void PrintInfo(std::ostream &out);
408
409         bool isSavingEnabled(){ return m_map_saving_enabled; }
410
411         u64 getSeed(){ return m_seed; }
412
413 private:
414         // Seed used for all kinds of randomness
415         u64 m_seed;
416
417         std::string m_savedir;
418         bool m_map_saving_enabled;
419
420 #if 0
421         // Chunk size in MapSectors
422         // If 0, chunks are disabled.
423         s16 m_chunksize;
424         // Chunks
425         core::map<v2s16, MapChunk*> m_chunks;
426 #endif
427
428         /*
429                 Metadata is re-written on disk only if this is true.
430                 This is reset to false when written on disk.
431         */
432         bool m_map_metadata_changed;
433 };
434
435 /*
436         ClientMap stuff
437 */
438
439 #ifndef SERVER
440
441 struct MapDrawControl
442 {
443         MapDrawControl():
444                 range_all(false),
445                 wanted_range(50),
446                 wanted_max_blocks(0),
447                 wanted_min_range(0),
448                 blocks_drawn(0),
449                 blocks_would_have_drawn(0)
450         {
451         }
452         // Overrides limits by drawing everything
453         bool range_all;
454         // Wanted drawing range
455         float wanted_range;
456         // Maximum number of blocks to draw
457         u32 wanted_max_blocks;
458         // Blocks in this range are drawn regardless of number of blocks drawn
459         float wanted_min_range;
460         // Number of blocks rendered is written here by the renderer
461         u32 blocks_drawn;
462         // Number of blocks that would have been drawn in wanted_range
463         u32 blocks_would_have_drawn;
464 };
465
466 class Client;
467
468 /*
469         ClientMap
470         
471         This is the only map class that is able to render itself on screen.
472 */
473
474 class ClientMap : public Map, public scene::ISceneNode
475 {
476 public:
477         ClientMap(
478                         Client *client,
479                         MapDrawControl &control,
480                         scene::ISceneNode* parent,
481                         scene::ISceneManager* mgr,
482                         s32 id
483         );
484
485         ~ClientMap();
486
487         s32 mapType() const
488         {
489                 return MAPTYPE_CLIENT;
490         }
491
492         void drop()
493         {
494                 ISceneNode::drop();
495         }
496
497         void updateCamera(v3f pos, v3f dir)
498         {
499                 JMutexAutoLock lock(m_camera_mutex);
500                 m_camera_position = pos;
501                 m_camera_direction = dir;
502         }
503
504         /*
505                 Forcefully get a sector from somewhere
506         */
507         MapSector * emergeSector(v2s16 p);
508
509         //void deSerializeSector(v2s16 p2d, std::istream &is);
510
511         /*
512                 ISceneNode methods
513         */
514
515         virtual void OnRegisterSceneNode();
516
517         virtual void render()
518         {
519                 video::IVideoDriver* driver = SceneManager->getVideoDriver();
520                 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
521                 renderMap(driver, SceneManager->getSceneNodeRenderPass());
522         }
523         
524         virtual const core::aabbox3d<f32>& getBoundingBox() const
525         {
526                 return m_box;
527         }
528
529         void renderMap(video::IVideoDriver* driver, s32 pass);
530
531         /*
532                 Methods for setting temporary modifications to nodes for
533                 drawing.
534
535                 Returns true if something changed.
536                 
537                 All blocks whose mesh could have been changed are inserted
538                 to affected_blocks.
539         */
540         bool setTempMod(v3s16 p, NodeMod mod,
541                         core::map<v3s16, MapBlock*> *affected_blocks=NULL);
542         bool clearTempMod(v3s16 p,
543                         core::map<v3s16, MapBlock*> *affected_blocks=NULL);
544         // Efficient implementation needs a cache of TempMods
545         //void clearTempMods();
546
547         void expireMeshes(bool only_daynight_diffed);
548         
549         /*
550                 Update the faces of the given block and blocks on the
551                 leading edge.
552         */
553         void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
554         
555         // Update meshes that touch the node
556         //void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
557
558         // For debug printing
559         virtual void PrintInfo(std::ostream &out);
560         
561         // Check if sector was drawn on last render()
562         bool sectorWasDrawn(v2s16 p)
563         {
564                 return (m_last_drawn_sectors.find(p) != NULL);
565         }
566         
567 private:
568         Client *m_client;
569         
570         core::aabbox3d<f32> m_box;
571         
572         // This is the master heightmap mesh
573         //scene::SMesh *mesh;
574         //JMutex mesh_mutex;
575         
576         MapDrawControl &m_control;
577
578         v3f m_camera_position;
579         v3f m_camera_direction;
580         JMutex m_camera_mutex;
581         
582         core::map<v2s16, bool> m_last_drawn_sectors;
583 };
584
585 #endif
586
587 class MapVoxelManipulator : public VoxelManipulator
588 {
589 public:
590         MapVoxelManipulator(Map *map);
591         virtual ~MapVoxelManipulator();
592         
593         virtual void clear()
594         {
595                 VoxelManipulator::clear();
596                 m_loaded_blocks.clear();
597         }
598
599         virtual void emerge(VoxelArea a, s32 caller_id=-1);
600
601         void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
602
603 protected:
604         Map *m_map;
605         /*
606                 key = blockpos
607                 value = block existed when loaded
608         */
609         core::map<v3s16, bool> m_loaded_blocks;
610 };
611
612 class ManualMapVoxelManipulator : public MapVoxelManipulator
613 {
614 public:
615         ManualMapVoxelManipulator(Map *map);
616         virtual ~ManualMapVoxelManipulator();
617
618         void setMap(Map *map)
619         {m_map = map;}
620         
621         virtual void emerge(VoxelArea a, s32 caller_id=-1);
622
623         void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
624         
625         // This is much faster with big chunks of generated data
626         void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);
627
628 protected:
629         bool m_create_area;
630 };
631
632 #endif
633