partly working chunk-based map generator (doesn't save properly, spawn is pretty random)

pull/1/head
Perttu Ahola 2011-02-01 03:06:02 +02:00
parent be851871cd
commit 6e196c2ce4
13 changed files with 1370 additions and 126 deletions

View File

@ -5,6 +5,7 @@
IrrlichtWrapper::IrrlichtWrapper(IrrlichtDevice *device) IrrlichtWrapper::IrrlichtWrapper(IrrlichtDevice *device)
{ {
m_running = true;
m_main_thread = get_current_thread_id(); m_main_thread = get_current_thread_id();
m_device_mutex.Init(); m_device_mutex.Init();
m_device = device; m_device = device;
@ -35,6 +36,11 @@ void IrrlichtWrapper::Run()
} }
} }
void IrrlichtWrapper::Shutdown(bool shutdown)
{
m_running = !shutdown;
}
textureid_t IrrlichtWrapper::getTextureId(const std::string &name) textureid_t IrrlichtWrapper::getTextureId(const std::string &name)
{ {
u32 id = m_namecache.getId(name); u32 id = m_namecache.getId(name);
@ -73,6 +79,10 @@ video::ITexture* IrrlichtWrapper::getTexture(const TextureSpec &spec)
} }
else else
{ {
// If irrlicht has shut down, just return NULL
if(m_running == false)
return NULL;
// We're gonna ask the result to be put into here // We're gonna ask the result to be put into here
ResultQueue<TextureSpec, video::ITexture*, u8, u8> result_queue; ResultQueue<TextureSpec, video::ITexture*, u8, u8> result_queue;

View File

@ -132,11 +132,15 @@ public:
/* /*
These are called from the main thread These are called from the main thread
*/ */
IrrlichtWrapper(IrrlichtDevice *device); IrrlichtWrapper(IrrlichtDevice *device);
// Run queued tasks // Run queued tasks
void Run(); void Run();
// Shutdown wrapper; this disables queued texture fetching
void Shutdown(bool shutdown);
/* /*
These are called from other threads These are called from other threads
*/ */
@ -182,6 +186,8 @@ private:
Members Members
*/ */
bool m_running;
// The id of the thread that can (and has to) use irrlicht directly // The id of the thread that can (and has to) use irrlicht directly
threadid_t m_main_thread; threadid_t m_main_thread;

View File

@ -296,7 +296,10 @@ FEATURE: The map could be generated procedually:
- Lighting would not have to be necessarily calculated until - Lighting would not have to be necessarily calculated until
the blocks are actually needed - it would be quite fast the blocks are actually needed - it would be quite fast
- Something like 64*64*16 MapBlocks? - Something like 64*64*16 MapBlocks?
- TODO: Separate lighting and block generation - No, MapSectors. And as much as it is efficient to do,
64x64 might be too much.
- FIXME: This is currently halfway done and the generator is
fairly broken
* Make the stone level with a heightmap * Make the stone level with a heightmap
* Carve out stuff in the stone * Carve out stuff in the stone
* Dump dirt all around, and simulate it falling off steep * Dump dirt all around, and simulate it falling off steep
@ -311,16 +314,25 @@ FEATURE: The map could be generated procedually:
parameter field is free for this. parameter field is free for this.
- Simulate rock falling from cliffs when water has removed - Simulate rock falling from cliffs when water has removed
enough solid rock from the bottom enough solid rock from the bottom
TODO: Lazy lighting updates:
- Set updateLighting to ignore MapBlocks with expired lighting,
except the blocks specified to it
- When a MapBlock is generated, lighting expires in all blocks
touching it (26 blocks + self)
- When a lighting-wise valid MapBlock is needed and lighting of it
has expired, what to do?
Doing now: Doing now:
---------- ----------
# maybe done
* not done
* Remove all kinds of systems that are made redundant by the new map
generator
- Sector heightmaps? At least they should be made redundant.
- Sector objects
* Do something about AttributeDatabase/List being too slow
* Save chunk metadata on disk
* Change water side textures so that buggy water doesn't look bad
* Make server find the spawning place from the real map data, not from
the heightmap
* only_from_disk doesn't work that well anymore
* Make the generator to run in background and not blocking block
placement and transfer
* Fix the strange mineral occurences
====================================================================== ======================================================================
@ -1886,6 +1898,9 @@ int main(int argc, char *argv[])
*/ */
{ {
// This is set to true at the end of the scope
g_irrlicht->Shutdown(false);
/* /*
Draw "Loading" screen Draw "Loading" screen
*/ */
@ -3017,6 +3032,14 @@ int main(int argc, char *argv[])
delete quick_inventory; delete quick_inventory;
/*
Disable texture fetches and other stuff that is queued
to be processed by the main loop.
This has to be done before client goes out of scope.
*/
g_irrlicht->Shutdown(true);
} // client and server are deleted at this point } // client and server are deleted at this point
} //try } //try

File diff suppressed because it is too large Load Diff

View File

@ -93,6 +93,8 @@ public:
MapSector * getSectorNoGenerateNoEx(v2s16 p2d); MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
// On failure throws InvalidPositionException // On failure throws InvalidPositionException
MapSector * getSectorNoGenerate(v2s16 p2d); MapSector * getSectorNoGenerate(v2s16 p2d);
// Gets an existing sector or creates an empty one
//MapSector * getSectorCreate(v2s16 p2d);
/* /*
This is overloaded by ClientMap and ServerMap to allow This is overloaded by ClientMap and ServerMap to allow
@ -104,6 +106,8 @@ public:
MapBlock * getBlockNoCreate(v3s16 p); MapBlock * getBlockNoCreate(v3s16 p);
// Returns NULL if not found // Returns NULL if not found
MapBlock * getBlockNoCreateNoEx(v3s16 p); MapBlock * getBlockNoCreateNoEx(v3s16 p);
// Gets an existing block or creates an empty one
//MapBlock * getBlockCreate(v3s16 p);
// Returns InvalidPositionException if not found // Returns InvalidPositionException if not found
f32 getGroundHeight(v2s16 p, bool generate=false); f32 getGroundHeight(v2s16 p, bool generate=false);
@ -382,12 +386,20 @@ public:
This is mainly called by generateChunkRaw. This is mainly called by generateChunkRaw.
*/ */
ServerMapSector * generateSector(v2s16 p); //ServerMapSector * generateSector(v2s16 p);
/* /*
Get a sector from somewhere. Get a sector from somewhere.
- Check memory - Check memory
- Check disk - Check disk (loads blocks also)
- Create blank one
*/
ServerMapSector * createSector(v2s16 p);
/*
Get a sector from somewhere.
- Check memory
- Check disk (loads blocks also)
- Generate chunk - Generate chunk
*/ */
MapSector * emergeSector(v2s16 p); MapSector * emergeSector(v2s16 p);
@ -400,6 +412,13 @@ public:
core::map<v3s16, MapBlock*> &lighting_invalidated_blocks core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
); );
/*
Get a block from somewhere.
- Memory
- Create blank
*/
MapBlock * createBlock(v3s16 p);
MapBlock * emergeBlock( MapBlock * emergeBlock(
v3s16 p, v3s16 p,
bool only_from_disk, bool only_from_disk,
@ -636,10 +655,8 @@ public:
protected: protected:
Map *m_map; Map *m_map;
/* /*
NOTE: This might be used or not key = blockpos
bool is dummy value value = block existed when loaded
SUGG: How 'bout an another VoxelManipulator for storing the
information about which block is loaded?
*/ */
core::map<v3s16, bool> m_loaded_blocks; core::map<v3s16, bool> m_loaded_blocks;
}; };
@ -654,7 +671,11 @@ public:
void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max); void initialEmerge(v3s16 blockpos_min, v3s16 blockpos_max);
// This is much faster with big chunks of generated data
void blitBackAll(core::map<v3s16, MapBlock*> * modified_blocks);
protected: protected:
bool m_create_area;
}; };
#endif #endif

View File

@ -1309,10 +1309,21 @@ void MapBlock::copyTo(VoxelManipulator &dst)
v3s16 data_size(MAP_BLOCKSIZE, MAP_BLOCKSIZE, MAP_BLOCKSIZE); v3s16 data_size(MAP_BLOCKSIZE, MAP_BLOCKSIZE, MAP_BLOCKSIZE);
VoxelArea data_area(v3s16(0,0,0), data_size - v3s16(1,1,1)); VoxelArea data_area(v3s16(0,0,0), data_size - v3s16(1,1,1));
// Copy from data to VoxelManipulator
dst.copyFrom(data, data_area, v3s16(0,0,0), dst.copyFrom(data, data_area, v3s16(0,0,0),
getPosRelative(), data_size); getPosRelative(), data_size);
} }
void MapBlock::copyFrom(VoxelManipulator &dst)
{
v3s16 data_size(MAP_BLOCKSIZE, MAP_BLOCKSIZE, MAP_BLOCKSIZE);
VoxelArea data_area(v3s16(0,0,0), data_size - v3s16(1,1,1));
// Copy from VoxelManipulator to data
dst.copyTo(data, data_area, v3s16(0,0,0),
getPosRelative(), data_size);
}
void MapBlock::stepObjects(float dtime, bool server, u32 daynight_ratio) void MapBlock::stepObjects(float dtime, bool server, u32 daynight_ratio)
{ {
/* /*

View File

@ -426,6 +426,8 @@ public:
// Copies data to VoxelManipulator to getPosRelative() // Copies data to VoxelManipulator to getPosRelative()
void copyTo(VoxelManipulator &dst); void copyTo(VoxelManipulator &dst);
// Copies data from VoxelManipulator getPosRelative()
void copyFrom(VoxelManipulator &dst);
/* /*
MapBlockObject stuff MapBlockObject stuff

View File

@ -438,6 +438,14 @@ struct MapNode
param2 = a_param2; param2 = a_param2;
} }
/*MapNode & operator=(const MapNode &other)
{
d = other.d;
param = other.param;
param2 = other.param2;
return *this;
}*/
bool operator==(const MapNode &other) bool operator==(const MapNode &other)
{ {
return (d == other.d return (d == other.d

View File

@ -570,10 +570,15 @@ ServerMapSector* ServerMapSector::deSerialize(
if(n != NULL) if(n != NULL)
{ {
dstream<<"deSerializing existent sectors not supported " dstream<<"WARNING: deSerializing existent sectors not supported "
"at the moment, because code hasn't been tested." "at the moment, because code hasn't been tested."
<<std::endl; <<std::endl;
assert(0);
//assert(0);
MapSector *sector = n->getValue();
assert(sector->getId() == MAPSECTOR_SERVER);
return (ServerMapSector*)sector;
// NOTE: At least hm_split mismatch would have to be checked // NOTE: At least hm_split mismatch would have to be checked
//sector = n->getValue(); //sector = n->getValue();

View File

@ -606,6 +606,15 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
{ {
block_is_invalid = true; block_is_invalid = true;
} }
v2s16 p2d(p.X, p.Z);
ServerMap *map = (ServerMap*)(&server->m_env.getMap());
v2s16 chunkpos = map->sector_to_chunk(p2d);
MapChunk *chunk = map->getChunk(chunkpos);
if(chunk == NULL)
block_is_invalid = true;
else if(chunk->getIsVolatile() == true)
block_is_invalid = true;
} }
/* /*
@ -3258,7 +3267,8 @@ Player *Server::emergePlayer(const char *name, const char *password,
player->setPosition(intToFloat(v3s16( player->setPosition(intToFloat(v3s16(
nodepos.X, nodepos.X,
groundheight + 1, //groundheight + 1,
groundheight + 15,
nodepos.Y nodepos.Y
))); )));

View File

@ -207,6 +207,10 @@ public:
{ {
return ptr == t; return ptr == t;
} }
T & operator[](unsigned int i)
{
return ptr[i];
}
private: private:
void drop() void drop()
{ {
@ -572,6 +576,15 @@ inline bool isInArea(v2s16 p, s16 d)
); );
} }
inline bool isInArea(v3s16 p, v3s16 d)
{
return (
p.X >= 0 && p.X < d.X &&
p.Y >= 0 && p.Y < d.Y &&
p.Z >= 0 && p.Z < d.Z
);
}
inline s16 rangelim(s16 i, s16 min, s16 max) inline s16 rangelim(s16 i, s16 min, s16 max)
{ {
if(i < min) if(i < min)
@ -1459,6 +1472,13 @@ int myrand(void);
void mysrand(unsigned seed); void mysrand(unsigned seed);
#define MYRAND_MAX 32767 #define MYRAND_MAX 32767
inline int myrand_range(int min, int max)
{
if(min >= max)
return max;
return (myrand()%(max-min+1))+min;
}
/* /*
Some kind of a thing that stores attributes related to Some kind of a thing that stores attributes related to
coordinate points coordinate points

View File

@ -41,7 +41,6 @@ VoxelManipulator::VoxelManipulator():
m_data(NULL), m_data(NULL),
m_flags(NULL) m_flags(NULL)
{ {
m_disable_water_climb = false;
} }
VoxelManipulator::~VoxelManipulator() VoxelManipulator::~VoxelManipulator()
@ -221,6 +220,22 @@ void VoxelManipulator::copyFrom(MapNode *src, VoxelArea src_area,
} }
} }
void VoxelManipulator::copyTo(MapNode *dst, VoxelArea dst_area,
v3s16 dst_pos, v3s16 from_pos, v3s16 size)
{
for(s16 z=0; z<size.Z; z++)
for(s16 y=0; y<size.Y; y++)
{
s32 i_dst = dst_area.index(dst_pos.X, dst_pos.Y+y, dst_pos.Z+z);
s32 i_local = m_area.index(from_pos.X, from_pos.Y+y, from_pos.Z+z);
memcpy(&dst[i_dst], &m_data[i_local], size.X*sizeof(MapNode));
}
}
/*
Algorithms
-----------------------------------------------------
*/
void VoxelManipulator::clearFlag(u8 flags) void VoxelManipulator::clearFlag(u8 flags)
{ {
@ -541,7 +556,7 @@ void VoxelManipulator::spreadLight(enum LightBank bank, v3s16 p)
Lights neighbors of from_nodes, collects all them and then Lights neighbors of from_nodes, collects all them and then
goes on recursively. goes on recursively.
NOTE: This is faster in small areas but will overflow the NOTE: This is faster on small areas but will overflow the
stack on large areas. Thus it is not used. stack on large areas. Thus it is not used.
*/ */
void VoxelManipulator::spreadLight(enum LightBank bank, void VoxelManipulator::spreadLight(enum LightBank bank,

View File

@ -263,6 +263,30 @@ public:
return index(p.X, p.Y, p.Z); return index(p.X, p.Y, p.Z);
} }
// Translate index in the X coordinate
void add_x(const v3s16 &extent, u32 &i, s16 a)
{
i += a;
}
// Translate index in the Y coordinate
void add_y(const v3s16 &extent, u32 &i, s16 a)
{
i += a * extent.X;
}
// Translate index in the Z coordinate
void add_z(const v3s16 &extent, u32 &i, s16 a)
{
i += a * extent.X*extent.Y;
}
// Translate index in space
void add_p(const v3s16 &extent, u32 &i, v3s16 a)
{
i += a.Z*extent.X*extent.Y + a.Y*extent.X + a.X;
}
/*
Print method for debugging
*/
void print(std::ostream &o) const void print(std::ostream &o) const
{ {
v3s16 e = getExtent(); v3s16 e = getExtent();
@ -395,6 +419,10 @@ public:
void copyFrom(MapNode *src, VoxelArea src_area, void copyFrom(MapNode *src, VoxelArea src_area,
v3s16 from_pos, v3s16 to_pos, v3s16 size); v3s16 from_pos, v3s16 to_pos, v3s16 size);
// Copy data
void copyTo(MapNode *dst, VoxelArea dst_area,
v3s16 dst_pos, v3s16 from_pos, v3s16 size);
/* /*
Algorithms Algorithms
*/ */