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

This commit is contained in:
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)
{
m_running = true;
m_main_thread = get_current_thread_id();
m_device_mutex.Init();
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)
{
u32 id = m_namecache.getId(name);
@ -73,6 +79,10 @@ video::ITexture* IrrlichtWrapper::getTexture(const TextureSpec &spec)
}
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
ResultQueue<TextureSpec, video::ITexture*, u8, u8> result_queue;

View File

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

View File

@ -288,7 +288,7 @@ FEATURE: Map generator version 2
where some minerals are found
- Create a system that allows a huge amount of different "map
generator modules/filters"
FEATURE: The map could be generated procedually:
- This would need the map to be generated in larger pieces
- How large? How do they connect to each other?
@ -296,7 +296,10 @@ FEATURE: The map could be generated procedually:
- Lighting would not have to be necessarily calculated until
the blocks are actually needed - it would be quite fast
- 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
* Carve out stuff in the stone
* 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.
- Simulate rock falling from cliffs when water has removed
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:
----------
# 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
*/
@ -3017,6 +3032,14 @@ int main(int argc, char *argv[])
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
} //try

File diff suppressed because it is too large Load Diff

View File

@ -93,6 +93,8 @@ public:
MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
// On failure throws InvalidPositionException
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
@ -104,6 +106,8 @@ public:
MapBlock * getBlockNoCreate(v3s16 p);
// Returns NULL if not found
MapBlock * getBlockNoCreateNoEx(v3s16 p);
// Gets an existing block or creates an empty one
//MapBlock * getBlockCreate(v3s16 p);
// Returns InvalidPositionException if not found
f32 getGroundHeight(v2s16 p, bool generate=false);
@ -382,12 +386,20 @@ public:
This is mainly called by generateChunkRaw.
*/
ServerMapSector * generateSector(v2s16 p);
//ServerMapSector * generateSector(v2s16 p);
/*
Get a sector from somewhere.
- Check memory
- Check disk (loads blocks also)
- Create blank one
*/
ServerMapSector * createSector(v2s16 p);
/*
Get a sector from somewhere.
- Check memory
- Check disk
- Check disk (loads blocks also)
- Generate chunk
*/
MapSector * emergeSector(v2s16 p);
@ -399,6 +411,13 @@ public:
core::map<v3s16, MapBlock*> &changed_blocks,
core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
);
/*
Get a block from somewhere.
- Memory
- Create blank
*/
MapBlock * createBlock(v3s16 p);
MapBlock * emergeBlock(
v3s16 p,
@ -636,10 +655,8 @@ public:
protected:
Map *m_map;
/*
NOTE: This might be used or not
bool is dummy value
SUGG: How 'bout an another VoxelManipulator for storing the
information about which block is loaded?
key = blockpos
value = block existed when loaded
*/
core::map<v3s16, bool> m_loaded_blocks;
};
@ -653,8 +670,12 @@ public:
virtual void emerge(VoxelArea a, s32 caller_id=-1);
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:
bool m_create_area;
};
#endif

View File

@ -1309,10 +1309,21 @@ void MapBlock::copyTo(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 data to VoxelManipulator
dst.copyFrom(data, data_area, v3s16(0,0,0),
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)
{
/*

View File

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

View File

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

View File

@ -570,10 +570,15 @@ ServerMapSector* ServerMapSector::deSerialize(
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."
<<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
//sector = n->getValue();

View File

@ -606,6 +606,15 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
{
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(
nodepos.X,
groundheight + 1,
//groundheight + 1,
groundheight + 15,
nodepos.Y
)));

View File

@ -207,6 +207,10 @@ public:
{
return ptr == t;
}
T & operator[](unsigned int i)
{
return ptr[i];
}
private:
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)
{
if(i < min)
@ -1459,6 +1472,13 @@ int myrand(void);
void mysrand(unsigned seed);
#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
coordinate points

View File

@ -41,7 +41,6 @@ VoxelManipulator::VoxelManipulator():
m_data(NULL),
m_flags(NULL)
{
m_disable_water_climb = false;
}
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)
{
@ -541,7 +556,7 @@ void VoxelManipulator::spreadLight(enum LightBank bank, v3s16 p)
Lights neighbors of from_nodes, collects all them and then
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.
*/
void VoxelManipulator::spreadLight(enum LightBank bank,

View File

@ -262,7 +262,31 @@ public:
{
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
{
v3s16 e = getExtent();
@ -394,6 +418,10 @@ public:
*/
void copyFrom(MapNode *src, VoxelArea src_area,
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