...and the map part of that
[oweals/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 <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 #include "nodemetadata.h"
43
44 /*
45         Temporarily exposed map generator stuff
46         Should only be used for testing
47 */
48
49 double base_rock_level_2d(u64 seed, v2s16 p);
50
51 /*
52         MapEditEvent
53 */
54
55 #define MAPTYPE_BASE 0
56 #define MAPTYPE_SERVER 1
57 #define MAPTYPE_CLIENT 2
58
59 enum MapEditEventType{
60         // Node added (changed from air or something else to something)
61         MEET_ADDNODE,
62         // Node removed (changed to air)
63         MEET_REMOVENODE,
64         // Node metadata of block changed (not knowing which node exactly)
65         // p stores block coordinate
66         MEET_BLOCK_NODE_METADATA_CHANGED,
67         // Anything else
68         MEET_OTHER
69 };
70
71 struct MapEditEvent
72 {
73         MapEditEventType type;
74         v3s16 p;
75         MapNode n;
76         core::map<v3s16, bool> modified_blocks;
77         u16 already_known_by_peer;
78
79         MapEditEvent():
80                 type(MEET_OTHER),
81                 already_known_by_peer(0)
82         {
83         }
84         
85         MapEditEvent * clone()
86         {
87                 MapEditEvent *event = new MapEditEvent();
88                 event->type = type;
89                 event->p = p;
90                 event->n = n;
91                 for(core::map<v3s16, bool>::Iterator
92                                 i = modified_blocks.getIterator();
93                                 i.atEnd()==false; i++)
94                 {
95                         v3s16 p = i.getNode()->getKey();
96                         bool v = i.getNode()->getValue();
97                         event->modified_blocks.insert(p, v);
98                 }
99                 return event;
100         }
101 };
102
103 class MapEventReceiver
104 {
105 public:
106         // event shall be deleted by caller after the call.
107         virtual void onMapEditEvent(MapEditEvent *event) = 0;
108 };
109
110 class Map : public NodeContainer
111 {
112 public:
113
114         Map(std::ostream &dout);
115         virtual ~Map();
116
117         virtual u16 nodeContainerId() const
118         {
119                 return NODECONTAINER_ID_MAP;
120         }
121
122         virtual s32 mapType() const
123         {
124                 return MAPTYPE_BASE;
125         }
126         
127         /*
128                 Drop (client) or delete (server) the map.
129         */
130         virtual void drop()
131         {
132                 delete this;
133         }
134
135         void addEventReceiver(MapEventReceiver *event_receiver);
136         void removeEventReceiver(MapEventReceiver *event_receiver);
137         // event shall be deleted by caller after the call.
138         void dispatchEvent(MapEditEvent *event);
139
140         // On failure returns NULL
141         MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
142         // On failure returns NULL
143         MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
144         // On failure throws InvalidPositionException
145         MapSector * getSectorNoGenerate(v2s16 p2d);
146         // Gets an existing sector or creates an empty one
147         //MapSector * getSectorCreate(v2s16 p2d);
148
149         /*
150                 This is overloaded by ClientMap and ServerMap to allow
151                 their differing fetch methods.
152         */
153         virtual MapSector * emergeSector(v2s16 p){ return NULL; }
154         virtual MapSector * emergeSector(v2s16 p,
155                         core::map<v3s16, MapBlock*> &changed_blocks){ return NULL; }
156
157         // Returns InvalidPositionException if not found
158         MapBlock * getBlockNoCreate(v3s16 p);
159         // Returns NULL if not found
160         MapBlock * getBlockNoCreateNoEx(v3s16 p);
161         // Gets an existing block or creates an empty one
162         //MapBlock * getBlockCreate(v3s16 p);
163         
164         // Returns InvalidPositionException if not found
165         bool isNodeUnderground(v3s16 p);
166         
167         // virtual from NodeContainer
168         bool isValidPosition(v3s16 p)
169         {
170                 v3s16 blockpos = getNodeBlockPos(p);
171                 MapBlock *blockref;
172                 try{
173                         blockref = getBlockNoCreate(blockpos);
174                 }
175                 catch(InvalidPositionException &e)
176                 {
177                         return false;
178                 }
179                 return true;
180                 /*v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
181                 bool is_valid = blockref->isValidPosition(relpos);
182                 return is_valid;*/
183         }
184         
185         // virtual from NodeContainer
186         // throws InvalidPositionException if not found
187         MapNode getNode(v3s16 p)
188         {
189                 v3s16 blockpos = getNodeBlockPos(p);
190                 MapBlock * blockref = getBlockNoCreate(blockpos);
191                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
192
193                 return blockref->getNodeNoCheck(relpos);
194         }
195
196         // virtual from NodeContainer
197         // throws InvalidPositionException if not found
198         void setNode(v3s16 p, MapNode & n)
199         {
200                 v3s16 blockpos = getNodeBlockPos(p);
201                 MapBlock * blockref = getBlockNoCreate(blockpos);
202                 v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
203                 blockref->setNodeNoCheck(relpos, n);
204         }
205         
206         // Returns a CONTENT_IGNORE node if not found
207         MapNode getNodeNoEx(v3s16 p)
208         {
209                 try{
210                         v3s16 blockpos = getNodeBlockPos(p);
211                         MapBlock * blockref = getBlockNoCreate(blockpos);
212                         v3s16 relpos = p - blockpos*MAP_BLOCKSIZE;
213
214                         return blockref->getNodeNoCheck(relpos);
215                 }
216                 catch(InvalidPositionException &e)
217                 {
218                         return MapNode(CONTENT_IGNORE);
219                 }
220         }
221
222         void unspreadLight(enum LightBank bank,
223                         core::map<v3s16, u8> & from_nodes,
224                         core::map<v3s16, bool> & light_sources,
225                         core::map<v3s16, MapBlock*> & modified_blocks);
226
227         void unLightNeighbors(enum LightBank bank,
228                         v3s16 pos, u8 lightwas,
229                         core::map<v3s16, bool> & light_sources,
230                         core::map<v3s16, MapBlock*> & modified_blocks);
231         
232         void spreadLight(enum LightBank bank,
233                         core::map<v3s16, bool> & from_nodes,
234                         core::map<v3s16, MapBlock*> & modified_blocks);
235         
236         void lightNeighbors(enum LightBank bank,
237                         v3s16 pos,
238                         core::map<v3s16, MapBlock*> & modified_blocks);
239
240         v3s16 getBrightestNeighbour(enum LightBank bank, v3s16 p);
241
242         s16 propagateSunlight(v3s16 start,
243                         core::map<v3s16, MapBlock*> & modified_blocks);
244         
245         void updateLighting(enum LightBank bank,
246                         core::map<v3s16, MapBlock*>  & a_blocks,
247                         core::map<v3s16, MapBlock*> & modified_blocks);
248                         
249         void updateLighting(core::map<v3s16, MapBlock*>  & a_blocks,
250                         core::map<v3s16, MapBlock*> & modified_blocks);
251                         
252         /*
253                 These handle lighting but not faces.
254         */
255         void addNodeAndUpdate(v3s16 p, MapNode n,
256                         core::map<v3s16, MapBlock*> &modified_blocks);
257         void removeNodeAndUpdate(v3s16 p,
258                         core::map<v3s16, MapBlock*> &modified_blocks);
259
260         /*
261                 Wrappers for the latter ones.
262                 These emit events.
263                 Return true if succeeded, false if not.
264         */
265         bool addNodeWithEvent(v3s16 p, MapNode n);
266         bool removeNodeWithEvent(v3s16 p);
267         
268         /*
269                 Takes the blocks at the edges into account
270         */
271         bool dayNightDiffed(v3s16 blockpos);
272
273         //core::aabbox3d<s16> getDisplayedBlockArea();
274
275         //bool updateChangedVisibleArea();
276         
277         virtual void save(bool only_changed){assert(0);};
278
279         /*
280                 Updates usage timers
281         */
282         void timerUpdate(float dtime);
283         
284         // Takes cache into account
285         // sector mutex should be locked when calling
286         void deleteSectors(core::list<v2s16> &list, bool only_blocks);
287         
288         // Returns count of deleted sectors
289         u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
290                         core::list<v3s16> *deleted_blocks=NULL);
291
292         // For debug printing
293         virtual void PrintInfo(std::ostream &out);
294         
295         void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
296
297         /*
298                 Node metadata
299                 These are basically coordinate wrappers to MapBlock
300         */
301         
302         NodeMetadata* getNodeMetadata(v3s16 p);
303         void setNodeMetadata(v3s16 p, NodeMetadata *meta);
304         void removeNodeMetadata(v3s16 p);
305         void nodeMetadataStep(float dtime,
306                         core::map<v3s16, MapBlock*> &changed_blocks);
307         
308         /*
309                 Misc.
310         */
311         core::map<v2s16, MapSector*> *getSectorsPtr(){return &m_sectors;}
312
313         /*
314                 Variables
315         */
316         
317 protected:
318
319         std::ostream &m_dout;
320
321         core::map<MapEventReceiver*, bool> m_event_receivers;
322         
323         core::map<v2s16, MapSector*> m_sectors;
324         //JMutex m_sector_mutex;
325
326         // Be sure to set this to NULL when the cached sector is deleted 
327         MapSector *m_sector_cache;
328         v2s16 m_sector_cache_p;
329
330         // Queued transforming water nodes
331         UniqueQueue<v3s16> m_transforming_liquid;
332 };
333
334 /*
335         ServerMap
336
337         This is the only map class that is able to generate map.
338 */
339
340 struct ChunkMakeData;
341
342 class ServerMap : public Map
343 {
344 public:
345         /*
346                 savedir: directory to which map data should be saved
347         */
348         ServerMap(std::string savedir);
349         ~ServerMap();
350
351         s32 mapType() const
352         {
353                 return MAPTYPE_SERVER;
354         }
355
356         /*
357                 Map generation
358         */
359         
360         // Returns the position of the chunk where the sector is in
361         v2s16 sector_to_chunk(v2s16 sectorpos)
362         {
363                 if(m_chunksize == 0)
364                         return v2s16(0,0);
365                 sectorpos.X += m_chunksize / 2;
366                 sectorpos.Y += m_chunksize / 2;
367                 v2s16 chunkpos = getContainerPos(sectorpos, m_chunksize);
368                 return chunkpos;
369         }
370         
371         // Returns the position of the (0,0) sector of the chunk
372         v2s16 chunk_to_sector(v2s16 chunkpos)
373         {
374                 if(m_chunksize == 0)
375                         return v2s16(0,0);
376                 v2s16 sectorpos(
377                         chunkpos.X * m_chunksize,
378                         chunkpos.Y * m_chunksize
379                 );
380                 sectorpos.X -= m_chunksize / 2;
381                 sectorpos.Y -= m_chunksize / 2;
382                 return sectorpos;
383         }
384
385         /*
386                 Get a chunk.
387         */
388         MapChunk *getChunk(v2s16 chunkpos)
389         {
390                 core::map<v2s16, MapChunk*>::Node *n;
391                 n = m_chunks.find(chunkpos);
392                 if(n == NULL)
393                         return NULL;
394                 return n->getValue();
395         }
396
397         /*
398                 True if the chunk and its neighbors are fully generated.
399                 It means the chunk will not be touched in the future by the
400                 generator. If false, generateChunk will make it true.
401         */
402         bool chunkNonVolatile(v2s16 chunkpos)
403         {
404                 if(m_chunksize == 0)
405                         return true;
406                 
407                 /*for(s16 x=-1; x<=1; x++)
408                 for(s16 y=-1; y<=1; y++)*/
409                 s16 x=0;
410                 s16 y=0;
411                 {
412                         v2s16 chunkpos0 = chunkpos + v2s16(x,y);
413                         MapChunk *chunk = getChunk(chunkpos);
414                         if(chunk == NULL)
415                                 return false;
416                         if(chunk->getGenLevel() != GENERATED_FULLY)
417                                 return false;
418                 }
419                 return true;
420         }
421         
422         /*
423                 Returns true if any chunk is marked as modified
424         */
425         bool anyChunkModified()
426         {
427                 for(core::map<v2s16, MapChunk*>::Iterator
428                                 i = m_chunks.getIterator();
429                                 i.atEnd()==false; i++)
430                 {
431                         v2s16 p = i.getNode()->getKey();
432                         MapChunk *chunk = i.getNode()->getValue();
433                         if(chunk->isModified())
434                                 return true;
435                 }
436                 return false;
437         }
438
439         void setChunksNonModified()
440         {
441                 for(core::map<v2s16, MapChunk*>::Iterator
442                                 i = m_chunks.getIterator();
443                                 i.atEnd()==false; i++)
444                 {
445                         v2s16 p = i.getNode()->getKey();
446                         MapChunk *chunk = i.getNode()->getValue();
447                         chunk->setModified(false);
448                 }
449         }
450
451         /*
452                 Chunks are generated by using these and makeChunk().
453         */
454         void initChunkMake(ChunkMakeData &data, v2s16 chunkpos);
455         MapChunk* finishChunkMake(ChunkMakeData &data,
456                         core::map<v3s16, MapBlock*> &changed_blocks);
457
458         /*
459                 Generate a chunk.
460
461                 All chunks touching this one can be altered also.
462         */
463         /*MapChunk* generateChunkRaw(v2s16 chunkpos,
464                         core::map<v3s16, MapBlock*> &changed_blocks,
465                         bool force=false);*/
466         
467         /*
468                 Generate a chunk and its neighbors so that it won't be touched
469                 anymore.
470         */
471         /*MapChunk* generateChunk(v2s16 chunkpos,
472                         core::map<v3s16, MapBlock*> &changed_blocks);*/
473         
474         /*
475                 Generate a sector.
476                 
477                 This is mainly called by generateChunkRaw.
478         */
479         //ServerMapSector * generateSector(v2s16 p);
480         
481         /*
482                 Get a sector from somewhere.
483                 - Check memory
484                 - Check disk (loads blocks also)
485                 - Create blank one
486         */
487         ServerMapSector * createSector(v2s16 p);
488
489         /*
490                 Get a sector from somewhere.
491                 - Check memory
492                 - Check disk (loads blocks also)
493                 - Generate chunk
494         */
495         /*MapSector * emergeSector(v2s16 p,
496                         core::map<v3s16, MapBlock*> &changed_blocks);*/
497         
498         /*MapSector * emergeSector(v2s16 p)
499         {
500                 core::map<v3s16, MapBlock*> changed_blocks;
501                 return emergeSector(p, changed_blocks);
502         }*/
503
504         MapBlock * generateBlock(
505                         v3s16 p,
506                         MapBlock *original_dummy,
507                         ServerMapSector *sector,
508                         core::map<v3s16, MapBlock*> &changed_blocks,
509                         core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
510         );
511         
512         /*
513                 Get a block from somewhere.
514                 - Memory
515                 - Create blank
516         */
517         MapBlock * createBlock(v3s16 p);
518         
519         /*
520                 only_from_disk, changed_blocks and lighting_invalidated_blocks
521                 are not properly used by the new map generator.
522         */
523         MapBlock * emergeBlock(
524                         v3s16 p,
525                         bool only_from_disk,
526                         core::map<v3s16, MapBlock*> &changed_blocks,
527                         core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
528         );
529
530 #if 0
531         /*
532                 Forcefully get a block from somewhere.
533
534                 Exceptions:
535                 - InvalidPositionException: possible if only_from_disk==true
536                 
537                 changed_blocks:
538                 - All already existing blocks that were modified are added.
539                         - If found on disk, nothing will be added.
540                         - If generated, the new block will not be included.
541
542                 lighting_invalidated_blocks:
543                 - All blocks that have heavy-to-calculate lighting changes
544                   are added.
545                         - updateLighting() should be called for these.
546                 
547                 - A block that is in changed_blocks may not be in
548                   lighting_invalidated_blocks.
549         */
550         MapBlock * emergeBlock(
551                         v3s16 p,
552                         bool only_from_disk,
553                         core::map<v3s16, MapBlock*> &changed_blocks,
554                         core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
555         );
556 #endif
557         
558         // Helper for placing objects on ground level
559         s16 findGroundLevel(v2s16 p2d);
560
561         /*
562                 Misc. helper functions for fiddling with directory and file
563                 names when saving
564         */
565         void createDirs(std::string path);
566         // returns something like "map/sectors/xxxxxxxx"
567         std::string getSectorDir(v2s16 pos, int layout = 2);
568         // dirname: final directory name
569         v2s16 getSectorPos(std::string dirname);
570         v3s16 getBlockPos(std::string sectordir, std::string blockfile);
571
572         void save(bool only_changed);
573         //void loadAll();
574         
575         // Saves map seed and possibly other stuff
576         void saveMapMeta();
577         void loadMapMeta();
578         
579         void saveChunkMeta();
580         void loadChunkMeta();
581         
582         // The sector mutex should be locked when calling most of these
583         
584         // This only saves sector-specific data such as the heightmap
585         // (no MapBlocks)
586         // DEPRECATED? Sectors have no metadata anymore.
587         void saveSectorMeta(ServerMapSector *sector);
588         MapSector* loadSectorMeta(std::string dirname, bool save_after_load);
589         
590         // Full load of a sector including all blocks.
591         // returns true on success, false on failure.
592         bool loadSectorFull(v2s16 p2d);
593         // If sector is not found in memory, try to load it from disk.
594         // Returns true if sector now resides in memory
595         //bool deFlushSector(v2s16 p2d);
596         
597         void saveBlock(MapBlock *block);
598         // This will generate a sector with getSector if not found.
599         void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load=false);
600
601         // For debug printing
602         virtual void PrintInfo(std::ostream &out);
603
604         bool isSavingEnabled(){ return m_map_saving_enabled; }
605
606         u64 getSeed(){ return m_seed; }
607
608 private:
609         // Seed used for all kinds of randomness
610         u64 m_seed;
611
612         std::string m_savedir;
613         bool m_map_saving_enabled;
614
615         // Chunk size in MapSectors
616         // If 0, chunks are disabled.
617         s16 m_chunksize;
618         // Chunks
619         core::map<v2s16, MapChunk*> m_chunks;
620
621         /*
622                 Metadata is re-written on disk only if this is true.
623                 This is reset to false when written on disk.
624         */
625         bool m_map_metadata_changed;
626 };
627
628 /*
629         ClientMap stuff
630 */
631
632 #ifndef SERVER
633
634 struct MapDrawControl
635 {
636         MapDrawControl():
637                 range_all(false),
638                 wanted_range(50),
639                 wanted_max_blocks(0),
640                 wanted_min_range(0),
641                 blocks_drawn(0),
642                 blocks_would_have_drawn(0)
643         {
644         }
645         // Overrides limits by drawing everything
646         bool range_all;
647         // Wanted drawing range
648         float wanted_range;
649         // Maximum number of blocks to draw
650         u32 wanted_max_blocks;
651         // Blocks in this range are drawn regardless of number of blocks drawn
652         float wanted_min_range;
653         // Number of blocks rendered is written here by the renderer
654         u32 blocks_drawn;
655         // Number of blocks that would have been drawn in wanted_range
656         u32 blocks_would_have_drawn;
657 };
658
659 class Client;
660
661 /*
662         ClientMap
663         
664         This is the only map class that is able to render itself on screen.
665 */
666
667 class ClientMap : public Map, public scene::ISceneNode
668 {
669 public:
670         ClientMap(
671                         Client *client,
672                         MapDrawControl &control,
673                         scene::ISceneNode* parent,
674                         scene::ISceneManager* mgr,
675                         s32 id
676         );
677
678         ~ClientMap();
679
680         s32 mapType() const
681         {
682                 return MAPTYPE_CLIENT;
683         }
684
685         void drop()
686         {
687                 ISceneNode::drop();
688         }
689
690         void updateCamera(v3f pos, v3f dir)
691         {
692                 JMutexAutoLock lock(m_camera_mutex);
693                 m_camera_position = pos;
694                 m_camera_direction = dir;
695         }
696
697         /*
698                 Forcefully get a sector from somewhere
699         */
700         MapSector * emergeSector(v2s16 p);
701
702         void deSerializeSector(v2s16 p2d, std::istream &is);
703
704         /*
705                 ISceneNode methods
706         */
707
708         virtual void OnRegisterSceneNode();
709
710         virtual void render()
711         {
712                 video::IVideoDriver* driver = SceneManager->getVideoDriver();
713                 driver->setTransform(video::ETS_WORLD, AbsoluteTransformation);
714                 renderMap(driver, SceneManager->getSceneNodeRenderPass());
715         }
716         
717         virtual const core::aabbox3d<f32>& getBoundingBox() const
718         {
719                 return m_box;
720         }
721
722         void renderMap(video::IVideoDriver* driver, s32 pass);
723
724         /*
725                 Methods for setting temporary modifications to nodes for
726                 drawing.
727
728                 Returns true if something changed.
729                 
730                 All blocks whose mesh could have been changed are inserted
731                 to affected_blocks.
732         */
733         bool setTempMod(v3s16 p, NodeMod mod,
734                         core::map<v3s16, MapBlock*> *affected_blocks=NULL);
735         bool clearTempMod(v3s16 p,
736                         core::map<v3s16, MapBlock*> *affected_blocks=NULL);
737         // Efficient implementation needs a cache of TempMods
738         //void clearTempMods();
739
740         void expireMeshes(bool only_daynight_diffed);
741         
742         /*
743                 Update the faces of the given block and blocks on the
744                 leading edge.
745         */
746         void updateMeshes(v3s16 blockpos, u32 daynight_ratio);
747         
748         // Update meshes that touch the node
749         //void updateNodeMeshes(v3s16 nodepos, u32 daynight_ratio);
750
751         // For debug printing
752         virtual void PrintInfo(std::ostream &out);
753         
754 private:
755         Client *m_client;
756         
757         core::aabbox3d<f32> m_box;
758         
759         // This is the master heightmap mesh
760         //scene::SMesh *mesh;
761         //JMutex mesh_mutex;
762         
763         MapDrawControl &m_control;
764
765         v3f m_camera_position;
766         v3f m_camera_direction;
767         JMutex m_camera_mutex;
768
769 };
770
771 #endif
772
773 class MapVoxelManipulator : public VoxelManipulator
774 {
775 public:
776         MapVoxelManipulator(Map *map);
777         virtual ~MapVoxelManipulator();
778         
779         virtual void clear()
780         {
781                 VoxelManipulator::clear();
782                 m_loaded_blocks.clear();
783         }
784
785         virtual void emerge(VoxelArea a, s32 caller_id=-1);
786
787         void blitBack(core::map<v3s16, MapBlock*> & modified_blocks);
788
789 protected:
790         Map *m_map;
791         /*
792                 key = blockpos
793                 value = block existed when loaded
794         */
795         core::map<v3s16, bool> m_loaded_blocks;
796 };
797
798 class ManualMapVoxelManipulator : public MapVoxelManipulator
799 {
800 public:
801         ManualMapVoxelManipulator(Map *map);
802         virtual ~ManualMapVoxelManipulator();
803
804         void setMap(Map *map)
805         {m_map = map;}
806         
807         virtual void emerge(VoxelArea a, s32 caller_id=-1);
808
809         void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
810         
811         // This is much faster with big chunks of generated data
812         void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);
813
814 protected:
815         bool m_create_area;
816 };
817
818 struct ChunkMakeData
819 {
820         bool no_op;
821         ManualMapVoxelManipulator vmanip;
822         u64 seed;
823         v2s16 chunkpos;
824         s16 y_blocks_min;
825         s16 y_blocks_max;
826         v2s16 sectorpos_base;
827         s16 sectorpos_base_size;
828         v2s16 sectorpos_bigbase;
829         s16 sectorpos_bigbase_size;
830         s16 max_spread_amount;
831         UniqueQueue<v3s16> transforming_liquid;
832
833         ChunkMakeData():
834                 no_op(false),
835                 vmanip(NULL),
836                 seed(0)
837         {}
838 };
839
840 void makeChunk(ChunkMakeData *data);
841
842 #endif
843