New map generator added (and SQLite, messed up the commits at that time...) (import from temporary git repo)
This commit is contained in:
parent
47e4eda4bb
commit
7538b4c620
|
@ -1,4 +1,5 @@
|
|||
map/*
|
||||
world/*
|
||||
CMakeFiles/*
|
||||
src/CMakeFiles/*
|
||||
src/Makefile
|
||||
|
|
|
@ -131,6 +131,7 @@ include_directories(
|
|||
${CMAKE_BUILD_TYPE}
|
||||
${PNG_INCLUDE_DIR}
|
||||
"${PROJECT_SOURCE_DIR}/jthread"
|
||||
"${PROJECT_SOURCE_DIR}/sqlite"
|
||||
)
|
||||
|
||||
set(EXECUTABLE_OUTPUT_PATH ../bin)
|
||||
|
@ -149,6 +150,7 @@ if(BUILD_CLIENT)
|
|||
${PLATFORM_LIBS}
|
||||
${CLIENT_PLATFORM_LIBS}
|
||||
jthread
|
||||
sqlite3
|
||||
)
|
||||
endif(BUILD_CLIENT)
|
||||
|
||||
|
@ -159,6 +161,7 @@ if(BUILD_SERVER)
|
|||
${ZLIB_LIBRARIES}
|
||||
${PLATFORM_LIBS}
|
||||
jthread
|
||||
sqlite3
|
||||
)
|
||||
endif(BUILD_SERVER)
|
||||
|
||||
|
@ -249,5 +252,6 @@ endif(BUILD_SERVER)
|
|||
# Subdirectories
|
||||
|
||||
add_subdirectory(jthread)
|
||||
add_subdirectory(sqlite)
|
||||
|
||||
#end
|
||||
|
|
|
@ -220,12 +220,12 @@ void Client::step(float dtime)
|
|||
g_settings.getFloat("client_delete_unused_sectors_timeout");
|
||||
|
||||
// Delete sector blocks
|
||||
/*u32 num = m_env.getMap().deleteUnusedSectors
|
||||
/*u32 num = m_env.getMap().unloadUnusedData
|
||||
(delete_unused_sectors_timeout,
|
||||
true, &deleted_blocks);*/
|
||||
|
||||
// Delete whole sectors
|
||||
u32 num = m_env.getMap().deleteUnusedSectors
|
||||
u32 num = m_env.getMap().unloadUnusedData
|
||||
(delete_unused_sectors_timeout,
|
||||
false, &deleted_blocks);
|
||||
|
||||
|
@ -722,7 +722,6 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
*/
|
||||
//dstream<<"Updating"<<std::endl;
|
||||
block->deSerialize(istr, ser_version);
|
||||
//block->setChangedFlag();
|
||||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
|
@ -733,7 +732,6 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
block = new MapBlock(&m_env.getMap(), p);
|
||||
block->deSerialize(istr, ser_version);
|
||||
sector->insertBlock(block);
|
||||
//block->setChangedFlag();
|
||||
|
||||
//DEBUG
|
||||
/*NodeMod mod;
|
||||
|
@ -744,27 +742,6 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
block->setTempMod(v3s16(8,8,8), mod);
|
||||
block->setTempMod(v3s16(8,7,8), mod);
|
||||
block->setTempMod(v3s16(8,6,8), mod);*/
|
||||
#if 0
|
||||
/*
|
||||
Add some coulds
|
||||
Well, this is a dumb way to do it, they should just
|
||||
be drawn as separate objects. But the looks of them
|
||||
can be tested this way.
|
||||
*/
|
||||
if(p.Y == 3)
|
||||
{
|
||||
NodeMod mod;
|
||||
mod.type = NODEMOD_CHANGECONTENT;
|
||||
mod.param = CONTENT_CLOUD;
|
||||
v3s16 p2;
|
||||
p2.Y = 8;
|
||||
for(p2.X=3; p2.X<=13; p2.X++)
|
||||
for(p2.Z=3; p2.Z<=13; p2.Z++)
|
||||
{
|
||||
block->setTempMod(p2, mod);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} //envlock
|
||||
|
||||
|
@ -796,6 +773,9 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
|
||||
//m_env.getClientMap().updateMeshes(block->getPos(), getDayNightRatio());
|
||||
|
||||
/*
|
||||
Add it to mesh update queue and set it to be acknowledged after update.
|
||||
*/
|
||||
addUpdateMeshTaskWithEdge(p, true);
|
||||
}
|
||||
else if(command == TOCLIENT_PLAYERPOS)
|
||||
|
|
|
@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "content_mapblock.h"
|
||||
#include "content_mapnode.h"
|
||||
#include "main.h" // For g_settings and g_texturesource
|
||||
#include "mineral.h"
|
||||
|
||||
#ifndef SERVER
|
||||
// Create a cuboid.
|
||||
|
@ -129,6 +130,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||
bool new_style_water = g_settings.getBool("new_style_water");
|
||||
bool new_style_leaves = g_settings.getBool("new_style_leaves");
|
||||
//bool smooth_lighting = g_settings.getBool("smooth_lighting");
|
||||
bool invisible_stone = g_settings.getBool("invisible_stone");
|
||||
|
||||
float node_water_level = 1.0;
|
||||
if(new_style_water)
|
||||
|
@ -178,6 +180,14 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||
g_texturesource->getTextureId("wood.png"));
|
||||
material_wood.setTexture(0, pa_wood.atlas);
|
||||
|
||||
// General ground material for special output
|
||||
// Texture is modified just before usage
|
||||
video::SMaterial material_general;
|
||||
material_general.setFlag(video::EMF_LIGHTING, false);
|
||||
material_general.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||
material_general.setFlag(video::EMF_FOG_ENABLE, true);
|
||||
material_general.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||
|
||||
for(s16 z=0; z<MAP_BLOCKSIZE; z++)
|
||||
for(s16 y=0; y<MAP_BLOCKSIZE; y++)
|
||||
for(s16 x=0; x<MAP_BLOCKSIZE; x++)
|
||||
|
@ -824,6 +834,88 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
|
|||
}
|
||||
|
||||
}
|
||||
#if 1
|
||||
/*
|
||||
Add stones with minerals if stone is invisible
|
||||
*/
|
||||
else if(n.d == CONTENT_STONE && invisible_stone && n.getMineral() != MINERAL_NONE)
|
||||
{
|
||||
for(u32 j=0; j<6; j++)
|
||||
{
|
||||
// NOTE: Hopefully g_6dirs[j] is the right direction...
|
||||
v3s16 dir = g_6dirs[j];
|
||||
/*u8 l = 0;
|
||||
MapNode n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + dir);
|
||||
if(content_features(n2.d).param_type == CPT_LIGHT)
|
||||
l = decode_light(n2.getLightBlend(data->m_daynight_ratio));
|
||||
else
|
||||
l = 255;*/
|
||||
u8 l = 255;
|
||||
video::SColor c(255,l,l,l);
|
||||
|
||||
// Get the right texture
|
||||
TileSpec ts = n.getTile(dir);
|
||||
AtlasPointer ap = ts.texture;
|
||||
material_general.setTexture(0, ap.atlas);
|
||||
|
||||
video::S3DVertex vertices[4] =
|
||||
{
|
||||
/*video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, 0,1),
|
||||
video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, 1,1),
|
||||
video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, 1,0),
|
||||
video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c, 0,0),*/
|
||||
video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c,
|
||||
ap.x0(), ap.y1()),
|
||||
video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c,
|
||||
ap.x1(), ap.y1()),
|
||||
video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c,
|
||||
ap.x1(), ap.y0()),
|
||||
video::S3DVertex(-BS/2,BS/2,BS/2, 0,0,0, c,
|
||||
ap.x0(), ap.y0()),
|
||||
};
|
||||
|
||||
if(j == 0)
|
||||
{
|
||||
for(u16 i=0; i<4; i++)
|
||||
vertices[i].Pos.rotateXZBy(0);
|
||||
}
|
||||
else if(j == 1)
|
||||
{
|
||||
for(u16 i=0; i<4; i++)
|
||||
vertices[i].Pos.rotateXZBy(180);
|
||||
}
|
||||
else if(j == 2)
|
||||
{
|
||||
for(u16 i=0; i<4; i++)
|
||||
vertices[i].Pos.rotateXZBy(-90);
|
||||
}
|
||||
else if(j == 3)
|
||||
{
|
||||
for(u16 i=0; i<4; i++)
|
||||
vertices[i].Pos.rotateXZBy(90);
|
||||
}
|
||||
else if(j == 4)
|
||||
{
|
||||
for(u16 i=0; i<4; i++)
|
||||
vertices[i].Pos.rotateYZBy(-90);
|
||||
}
|
||||
else if(j == 5)
|
||||
{
|
||||
for(u16 i=0; i<4; i++)
|
||||
vertices[i].Pos.rotateYZBy(90);
|
||||
}
|
||||
|
||||
for(u16 i=0; i<4; i++)
|
||||
{
|
||||
vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
|
||||
}
|
||||
|
||||
u16 indices[] = {0,1,2,2,3,0};
|
||||
// Add to mesh collector
|
||||
collector.append(material_general, vertices, 4, indices, 6);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ void content_mapnode_init()
|
|||
// Read some settings
|
||||
bool new_style_water = g_settings.getBool("new_style_water");
|
||||
bool new_style_leaves = g_settings.getBool("new_style_leaves");
|
||||
bool invisible_stone = g_settings.getBool("invisible_stone");
|
||||
|
||||
u8 i;
|
||||
ContentFeatures *f = NULL;
|
||||
|
@ -48,6 +49,8 @@ void content_mapnode_init()
|
|||
f->is_ground_content = true;
|
||||
f->dug_item = std::string("MaterialItem ")+itos(CONTENT_COBBLE)+" 1";
|
||||
setStoneLikeDiggingProperties(f->digging_properties, 1.0);
|
||||
if(invisible_stone)
|
||||
f->solidness = 0; // For debugging, hides regular stone
|
||||
|
||||
i = CONTENT_GRASS;
|
||||
f = &content_features(i);
|
||||
|
@ -81,11 +84,21 @@ void content_mapnode_init()
|
|||
i = CONTENT_SAND;
|
||||
f = &content_features(i);
|
||||
f->setAllTextures("sand.png");
|
||||
f->setInventoryTextureCube("sand.png", "sand.png", "sand.png");
|
||||
f->param_type = CPT_MINERAL;
|
||||
f->is_ground_content = true;
|
||||
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
||||
setDirtLikeDiggingProperties(f->digging_properties, 1.0);
|
||||
|
||||
i = CONTENT_GRAVEL;
|
||||
f = &content_features(i);
|
||||
f->setAllTextures("gravel.png");
|
||||
f->setInventoryTextureCube("gravel.png", "gravel.png", "gravel.png");
|
||||
f->param_type = CPT_MINERAL;
|
||||
f->is_ground_content = true;
|
||||
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
||||
setDirtLikeDiggingProperties(f->digging_properties, 1.75);
|
||||
|
||||
i = CONTENT_TREE;
|
||||
f = &content_features(i);
|
||||
f->setAllTextures("tree.png");
|
||||
|
@ -146,6 +159,7 @@ void content_mapnode_init()
|
|||
i = CONTENT_WOOD;
|
||||
f = &content_features(i);
|
||||
f->setAllTextures("wood.png");
|
||||
f->setInventoryTextureCube("wood.png", "wood.png", "wood.png");
|
||||
f->is_ground_content = true;
|
||||
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
||||
setWoodLikeDiggingProperties(f->digging_properties, 0.75);
|
||||
|
@ -153,6 +167,7 @@ void content_mapnode_init()
|
|||
i = CONTENT_MESE;
|
||||
f = &content_features(i);
|
||||
f->setAllTextures("mese.png");
|
||||
f->setInventoryTextureCube("mese.png", "mese.png", "mese.png");
|
||||
f->is_ground_content = true;
|
||||
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
||||
setStoneLikeDiggingProperties(f->digging_properties, 0.5);
|
||||
|
@ -160,6 +175,7 @@ void content_mapnode_init()
|
|||
i = CONTENT_CLOUD;
|
||||
f = &content_features(i);
|
||||
f->setAllTextures("cloud.png");
|
||||
f->setInventoryTextureCube("cloud.png", "cloud.png", "cloud.png");
|
||||
f->is_ground_content = true;
|
||||
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
||||
|
||||
|
@ -190,7 +206,8 @@ void content_mapnode_init()
|
|||
|
||||
i = CONTENT_WATERSOURCE;
|
||||
f = &content_features(i);
|
||||
f->setInventoryTexture("water.png");
|
||||
//f->setInventoryTexture("water.png");
|
||||
f->setInventoryTextureCube("water.png", "water.png", "water.png");
|
||||
if(new_style_water)
|
||||
{
|
||||
f->solidness = 0; // drawn separately, makes no faces
|
||||
|
@ -229,7 +246,7 @@ void content_mapnode_init()
|
|||
f->wall_mounted = true;
|
||||
f->air_equivalent = true;
|
||||
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
||||
f->light_source = LIGHT_MAX;
|
||||
f->light_source = LIGHT_MAX-1;
|
||||
f->digging_properties.set("", DiggingProperties(true, 0.0, 0));
|
||||
|
||||
i = CONTENT_SIGN_WALL;
|
||||
|
@ -280,7 +297,16 @@ void content_mapnode_init()
|
|||
f->param_type = CPT_NONE;
|
||||
f->is_ground_content = true;
|
||||
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
||||
setStoneLikeDiggingProperties(f->digging_properties, 1.0);
|
||||
setStoneLikeDiggingProperties(f->digging_properties, 0.9);
|
||||
|
||||
i = CONTENT_MOSSYCOBBLE;
|
||||
f = &content_features(i);
|
||||
f->setAllTextures("mossycobble.png");
|
||||
f->setInventoryTextureCube("mossycobble.png", "mossycobble.png", "mossycobble.png");
|
||||
f->param_type = CPT_NONE;
|
||||
f->is_ground_content = true;
|
||||
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
|
||||
setStoneLikeDiggingProperties(f->digging_properties, 0.8);
|
||||
|
||||
i = CONTENT_STEEL;
|
||||
f = &content_features(i);
|
||||
|
|
|
@ -48,6 +48,8 @@ void content_mapnode_init();
|
|||
#define CONTENT_STEEL 19
|
||||
#define CONTENT_GLASS 20
|
||||
#define CONTENT_FENCE 21
|
||||
#define CONTENT_MOSSYCOBBLE 22
|
||||
#define CONTENT_GRAVEL 23
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -69,6 +69,7 @@ void set_default_settings()
|
|||
g_settings.setDefault("invert_mouse", "false");
|
||||
g_settings.setDefault("enable_farmesh", "false");
|
||||
g_settings.setDefault("enable_clouds", "true");
|
||||
g_settings.setDefault("invisible_stone", "false");
|
||||
|
||||
// Server stuff
|
||||
g_settings.setDefault("enable_experimental", "false");
|
||||
|
@ -81,8 +82,8 @@ void set_default_settings()
|
|||
|
||||
g_settings.setDefault("objectdata_interval", "0.2");
|
||||
g_settings.setDefault("active_object_range", "2");
|
||||
g_settings.setDefault("max_simultaneous_block_sends_per_client", "1");
|
||||
//g_settings.setDefault("max_simultaneous_block_sends_per_client", "2");
|
||||
//g_settings.setDefault("max_simultaneous_block_sends_per_client", "1");
|
||||
g_settings.setDefault("max_simultaneous_block_sends_per_client", "2");
|
||||
g_settings.setDefault("max_simultaneous_block_sends_server_total", "8");
|
||||
g_settings.setDefault("max_block_send_distance", "8");
|
||||
g_settings.setDefault("max_block_generate_distance", "8");
|
||||
|
|
|
@ -579,6 +579,64 @@ void spawnRandomObjects(MapBlock *block)
|
|||
}
|
||||
#endif
|
||||
|
||||
void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
|
||||
{
|
||||
// Get time difference
|
||||
u32 dtime_s = 0;
|
||||
u32 stamp = block->getTimestamp();
|
||||
if(m_game_time > stamp && stamp != BLOCK_TIMESTAMP_UNDEFINED)
|
||||
dtime_s = m_game_time - block->getTimestamp();
|
||||
dtime_s += additional_dtime;
|
||||
|
||||
// Set current time as timestamp (and let it set ChangedFlag)
|
||||
block->setTimestamp(m_game_time);
|
||||
|
||||
//dstream<<"Block is "<<dtime_s<<" seconds old."<<std::endl;
|
||||
|
||||
// Activate stored objects
|
||||
activateObjects(block);
|
||||
|
||||
// Run node metadata
|
||||
bool changed = block->m_node_metadata.step((float)dtime_s);
|
||||
if(changed)
|
||||
{
|
||||
MapEditEvent event;
|
||||
event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
|
||||
event.p = block->getPos();
|
||||
m_map->dispatchEvent(&event);
|
||||
|
||||
block->setChangedFlag();
|
||||
}
|
||||
|
||||
// TODO: Do something
|
||||
// TODO: Implement usage of ActiveBlockModifier
|
||||
|
||||
// Here's a quick demonstration
|
||||
v3s16 p0;
|
||||
for(p0.X=0; p0.X<MAP_BLOCKSIZE; p0.X++)
|
||||
for(p0.Y=0; p0.Y<MAP_BLOCKSIZE; p0.Y++)
|
||||
for(p0.Z=0; p0.Z<MAP_BLOCKSIZE; p0.Z++)
|
||||
{
|
||||
v3s16 p = p0 + block->getPosRelative();
|
||||
MapNode n = block->getNodeNoEx(p0);
|
||||
// Test something:
|
||||
// Convert all mud under proper day lighting to grass
|
||||
if(n.d == CONTENT_MUD)
|
||||
{
|
||||
if(dtime_s > 300)
|
||||
{
|
||||
MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0));
|
||||
if(content_features(n_top.d).air_equivalent &&
|
||||
n_top.getLight(LIGHTBANK_DAY) >= 13)
|
||||
{
|
||||
n.d = CONTENT_GRASS;
|
||||
m_map->addNodeWithEvent(p, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ServerEnvironment::step(float dtime)
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
@ -715,60 +773,8 @@ void ServerEnvironment::step(float dtime)
|
|||
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
|
||||
if(block==NULL)
|
||||
continue;
|
||||
|
||||
// Get time difference
|
||||
u32 dtime_s = 0;
|
||||
u32 stamp = block->getTimestamp();
|
||||
if(m_game_time > stamp && stamp != BLOCK_TIMESTAMP_UNDEFINED)
|
||||
dtime_s = m_game_time - block->getTimestamp();
|
||||
|
||||
// Set current time as timestamp (and let it set ChangedFlag)
|
||||
block->setTimestamp(m_game_time);
|
||||
|
||||
//dstream<<"Block is "<<dtime_s<<" seconds old."<<std::endl;
|
||||
|
||||
// Activate stored objects
|
||||
activateObjects(block);
|
||||
|
||||
// Run node metadata
|
||||
bool changed = block->m_node_metadata.step((float)dtime_s);
|
||||
if(changed)
|
||||
{
|
||||
MapEditEvent event;
|
||||
event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
|
||||
event.p = p;
|
||||
m_map->dispatchEvent(&event);
|
||||
|
||||
block->setChangedFlag();
|
||||
}
|
||||
|
||||
// TODO: Do something
|
||||
// TODO: Implement usage of ActiveBlockModifier
|
||||
|
||||
// Here's a quick demonstration
|
||||
v3s16 p0;
|
||||
for(p0.X=0; p0.X<MAP_BLOCKSIZE; p0.X++)
|
||||
for(p0.Y=0; p0.Y<MAP_BLOCKSIZE; p0.Y++)
|
||||
for(p0.Z=0; p0.Z<MAP_BLOCKSIZE; p0.Z++)
|
||||
{
|
||||
v3s16 p = p0 + block->getPosRelative();
|
||||
MapNode n = block->getNodeNoEx(p0);
|
||||
// Test something:
|
||||
// Convert all mud under proper day lighting to grass
|
||||
if(n.d == CONTENT_MUD)
|
||||
{
|
||||
if(dtime_s > 300)
|
||||
{
|
||||
MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0));
|
||||
if(content_features(n_top.d).air_equivalent &&
|
||||
n_top.getLight(LIGHTBANK_DAY) >= 13)
|
||||
{
|
||||
n.d = CONTENT_GRASS;
|
||||
m_map->addNodeWithEvent(p, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
activateBlock(block);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -867,6 +873,22 @@ void ServerEnvironment::step(float dtime)
|
|||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
Convert grass into mud if under something else than air
|
||||
*/
|
||||
else if(n.d == CONTENT_GRASS)
|
||||
{
|
||||
//if(myrand()%20 == 0)
|
||||
{
|
||||
MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0));
|
||||
if(n_top.d != CONTENT_AIR
|
||||
&& n_top.d != CONTENT_IGNORE)
|
||||
{
|
||||
n.d = CONTENT_MUD;
|
||||
m_map->addNodeWithEvent(p, n);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -197,6 +197,12 @@ public:
|
|||
*/
|
||||
ActiveObjectMessage getActiveObjectMessage();
|
||||
|
||||
/*
|
||||
Activate objects and dynamically modify for the dtime determined
|
||||
from timestamp and additional_dtime
|
||||
*/
|
||||
void activateBlock(MapBlock *block, u32 additional_dtime=0);
|
||||
|
||||
/*
|
||||
ActiveBlockModifiers (TODO)
|
||||
-------------------------------------------
|
||||
|
|
|
@ -33,8 +33,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
Temporarily exposed map generator stuff
|
||||
Should only be used for testing
|
||||
*/
|
||||
extern double base_rock_level_2d(u64 seed, v2s16 p);
|
||||
extern double get_mud_add_amount(u64 seed, v2s16 p);
|
||||
//extern double base_rock_level_2d(u64 seed, v2s16 p);
|
||||
//extern double get_mud_add_amount(u64 seed, v2s16 p);
|
||||
extern s16 find_ground_level_from_noise(u64 seed, v2s16 p2d, s16 precision);
|
||||
extern bool get_have_sand(u64 seed, v2s16 p2d);
|
||||
extern double tree_amount_2d(u64 seed, v2s16 p);
|
||||
|
||||
|
@ -126,8 +127,11 @@ HeightPoint ground_height(u64 seed, v2s16 p2d)
|
|||
if(n)
|
||||
return n->getValue();
|
||||
HeightPoint hp;
|
||||
hp.gh = BS*base_rock_level_2d(seed, p2d);
|
||||
hp.ma = BS*get_mud_add_amount(seed, p2d);
|
||||
s16 level = find_ground_level_from_noise(seed, p2d, 3);
|
||||
hp.gh = (level-4)*BS;
|
||||
hp.ma = (4)*BS;
|
||||
/*hp.gh = BS*base_rock_level_2d(seed, p2d);
|
||||
hp.ma = BS*get_mud_add_amount(seed, p2d);*/
|
||||
hp.have_sand = get_have_sand(seed, p2d);
|
||||
if(hp.gh > BS*WATER_LEVEL)
|
||||
hp.tree_amount = tree_amount_2d(seed, p2d);
|
||||
|
@ -136,7 +140,7 @@ HeightPoint ground_height(u64 seed, v2s16 p2d)
|
|||
// No mud has been added if mud amount is less than 1
|
||||
if(hp.ma < 1.0*BS)
|
||||
hp.ma = 0.0;
|
||||
hp.gh -= BS*3; // Lower a bit so that it is not that much in the way
|
||||
//hp.gh -= BS*3; // Lower a bit so that it is not that much in the way
|
||||
g_heights[p2d] = hp;
|
||||
return hp;
|
||||
}
|
||||
|
|
11
src/main.cpp
11
src/main.cpp
|
@ -186,6 +186,11 @@ TODO: Better control of draw_control.wanted_max_blocks
|
|||
TODO: Further investigate the use of GPU lighting in addition to the
|
||||
current one
|
||||
|
||||
TODO: Artificial (night) light could be more yellow colored than sunlight.
|
||||
- This is technically doable.
|
||||
- Also the actual colors of the textures could be made less colorful
|
||||
in the dark but it's a bit more difficult.
|
||||
|
||||
SUGG: Somehow make the night less colorful
|
||||
|
||||
Configuration:
|
||||
|
@ -361,6 +366,12 @@ Fixes to the current release:
|
|||
Stuff to do after release:
|
||||
---------------------------
|
||||
|
||||
Doing currently:
|
||||
----------------
|
||||
|
||||
TODO: Use MapBlock::resetUsageTimer() in appropriate places
|
||||
(on client and server)
|
||||
|
||||
======================================================================
|
||||
|
||||
*/
|
||||
|
|
4453
src/map.cpp
4453
src/map.cpp
File diff suppressed because it is too large
Load Diff
218
src/map.h
218
src/map.h
|
@ -132,7 +132,7 @@ public:
|
|||
|
||||
// On failure returns NULL
|
||||
MapSector * getSectorNoGenerateNoExNoLock(v2s16 p2d);
|
||||
// On failure returns NULL
|
||||
// Same as the above (there exists no lock anymore)
|
||||
MapSector * getSectorNoGenerateNoEx(v2s16 p2d);
|
||||
// On failure throws InvalidPositionException
|
||||
MapSector * getSectorNoGenerate(v2s16 p2d);
|
||||
|
@ -268,6 +268,9 @@ public:
|
|||
//bool updateChangedVisibleArea();
|
||||
|
||||
virtual void save(bool only_changed){assert(0);};
|
||||
|
||||
// Server implements this
|
||||
virtual void saveBlock(MapBlock *block){};
|
||||
|
||||
/*
|
||||
Updates usage timers
|
||||
|
@ -279,7 +282,7 @@ public:
|
|||
void deleteSectors(core::list<v2s16> &list, bool only_blocks);
|
||||
|
||||
// Returns count of deleted sectors
|
||||
u32 deleteUnusedSectors(float timeout, bool only_blocks=false,
|
||||
u32 unloadUnusedData(float timeout, bool only_blocks=false,
|
||||
core::list<v3s16> *deleted_blocks=NULL);
|
||||
|
||||
// For debug printing
|
||||
|
@ -330,7 +333,9 @@ protected:
|
|||
This is the only map class that is able to generate map.
|
||||
*/
|
||||
|
||||
struct ChunkMakeData;
|
||||
//struct ChunkMakeData;
|
||||
|
||||
struct BlockMakeData;
|
||||
|
||||
class ServerMap : public Map
|
||||
{
|
||||
|
@ -346,160 +351,25 @@ public:
|
|||
return MAPTYPE_SERVER;
|
||||
}
|
||||
|
||||
/*
|
||||
Map generation
|
||||
*/
|
||||
|
||||
// Returns the position of the chunk where the sector is in
|
||||
v2s16 sector_to_chunk(v2s16 sectorpos)
|
||||
{
|
||||
if(m_chunksize == 0)
|
||||
return v2s16(0,0);
|
||||
sectorpos.X += m_chunksize / 2;
|
||||
sectorpos.Y += m_chunksize / 2;
|
||||
v2s16 chunkpos = getContainerPos(sectorpos, m_chunksize);
|
||||
return chunkpos;
|
||||
}
|
||||
|
||||
// Returns the position of the (0,0) sector of the chunk
|
||||
v2s16 chunk_to_sector(v2s16 chunkpos)
|
||||
{
|
||||
if(m_chunksize == 0)
|
||||
return v2s16(0,0);
|
||||
v2s16 sectorpos(
|
||||
chunkpos.X * m_chunksize,
|
||||
chunkpos.Y * m_chunksize
|
||||
);
|
||||
sectorpos.X -= m_chunksize / 2;
|
||||
sectorpos.Y -= m_chunksize / 2;
|
||||
return sectorpos;
|
||||
}
|
||||
|
||||
/*
|
||||
Get a chunk.
|
||||
*/
|
||||
MapChunk *getChunk(v2s16 chunkpos)
|
||||
{
|
||||
core::map<v2s16, MapChunk*>::Node *n;
|
||||
n = m_chunks.find(chunkpos);
|
||||
if(n == NULL)
|
||||
return NULL;
|
||||
return n->getValue();
|
||||
}
|
||||
|
||||
/*
|
||||
True if the chunk and its neighbors are fully generated.
|
||||
It means the chunk will not be touched in the future by the
|
||||
generator. If false, generateChunk will make it true.
|
||||
*/
|
||||
bool chunkNonVolatile(v2s16 chunkpos)
|
||||
{
|
||||
if(m_chunksize == 0)
|
||||
return true;
|
||||
|
||||
/*for(s16 x=-1; x<=1; x++)
|
||||
for(s16 y=-1; y<=1; y++)*/
|
||||
s16 x=0;
|
||||
s16 y=0;
|
||||
{
|
||||
v2s16 chunkpos0 = chunkpos + v2s16(x,y);
|
||||
MapChunk *chunk = getChunk(chunkpos);
|
||||
if(chunk == NULL)
|
||||
return false;
|
||||
if(chunk->getGenLevel() != GENERATED_FULLY)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
Returns true if any chunk is marked as modified
|
||||
*/
|
||||
bool anyChunkModified()
|
||||
{
|
||||
for(core::map<v2s16, MapChunk*>::Iterator
|
||||
i = m_chunks.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
{
|
||||
v2s16 p = i.getNode()->getKey();
|
||||
MapChunk *chunk = i.getNode()->getValue();
|
||||
if(chunk->isModified())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void setChunksNonModified()
|
||||
{
|
||||
for(core::map<v2s16, MapChunk*>::Iterator
|
||||
i = m_chunks.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
{
|
||||
v2s16 p = i.getNode()->getKey();
|
||||
MapChunk *chunk = i.getNode()->getValue();
|
||||
chunk->setModified(false);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Chunks are generated by using these and makeChunk().
|
||||
*/
|
||||
void initChunkMake(ChunkMakeData &data, v2s16 chunkpos);
|
||||
MapChunk* finishChunkMake(ChunkMakeData &data,
|
||||
core::map<v3s16, MapBlock*> &changed_blocks);
|
||||
|
||||
/*
|
||||
Generate a chunk.
|
||||
|
||||
All chunks touching this one can be altered also.
|
||||
*/
|
||||
/*MapChunk* generateChunkRaw(v2s16 chunkpos,
|
||||
core::map<v3s16, MapBlock*> &changed_blocks,
|
||||
bool force=false);*/
|
||||
|
||||
/*
|
||||
Generate a chunk and its neighbors so that it won't be touched
|
||||
anymore.
|
||||
*/
|
||||
/*MapChunk* generateChunk(v2s16 chunkpos,
|
||||
core::map<v3s16, MapBlock*> &changed_blocks);*/
|
||||
|
||||
/*
|
||||
Generate a sector.
|
||||
|
||||
This is mainly called by generateChunkRaw.
|
||||
*/
|
||||
//ServerMapSector * generateSector(v2s16 p);
|
||||
|
||||
/*
|
||||
Get a sector from somewhere.
|
||||
- Check memory
|
||||
- Check disk (loads blocks also)
|
||||
- Check disk (doesn't load blocks)
|
||||
- Create blank one
|
||||
*/
|
||||
ServerMapSector * createSector(v2s16 p);
|
||||
|
||||
/*
|
||||
Get a sector from somewhere.
|
||||
- Check memory
|
||||
- Check disk (loads blocks also)
|
||||
- Generate chunk
|
||||
Blocks are generated by using these and makeBlock().
|
||||
*/
|
||||
/*MapSector * emergeSector(v2s16 p,
|
||||
core::map<v3s16, MapBlock*> &changed_blocks);*/
|
||||
void initBlockMake(BlockMakeData *data, v3s16 blockpos);
|
||||
MapBlock* finishBlockMake(BlockMakeData *data,
|
||||
core::map<v3s16, MapBlock*> &changed_blocks);
|
||||
|
||||
/*MapSector * emergeSector(v2s16 p)
|
||||
{
|
||||
core::map<v3s16, MapBlock*> changed_blocks;
|
||||
return emergeSector(p, changed_blocks);
|
||||
}*/
|
||||
|
||||
// A non-threaded wrapper to the above
|
||||
MapBlock * generateBlock(
|
||||
v3s16 p,
|
||||
MapBlock *original_dummy,
|
||||
ServerMapSector *sector,
|
||||
core::map<v3s16, MapBlock*> &changed_blocks,
|
||||
core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
|
||||
core::map<v3s16, MapBlock*> &modified_blocks
|
||||
);
|
||||
|
||||
/*
|
||||
|
@ -508,37 +378,17 @@ public:
|
|||
- Create blank
|
||||
*/
|
||||
MapBlock * createBlock(v3s16 p);
|
||||
|
||||
/*
|
||||
only_from_disk, changed_blocks and lighting_invalidated_blocks
|
||||
are not properly used by the new map generator.
|
||||
*/
|
||||
MapBlock * emergeBlock(
|
||||
v3s16 p,
|
||||
bool only_from_disk,
|
||||
core::map<v3s16, MapBlock*> &changed_blocks,
|
||||
core::map<v3s16, MapBlock*> &lighting_invalidated_blocks
|
||||
);
|
||||
|
||||
#if 0
|
||||
/*
|
||||
NOTE: This comment might be outdated
|
||||
|
||||
Forcefully get a block from somewhere.
|
||||
|
||||
Exceptions:
|
||||
- InvalidPositionException: possible if only_from_disk==true
|
||||
InvalidPositionException possible if only_from_disk==true
|
||||
|
||||
changed_blocks:
|
||||
- All already existing blocks that were modified are added.
|
||||
- If found on disk, nothing will be added.
|
||||
- If generated, the new block will not be included.
|
||||
|
||||
lighting_invalidated_blocks:
|
||||
- All blocks that have heavy-to-calculate lighting changes
|
||||
are added.
|
||||
- updateLighting() should be called for these.
|
||||
|
||||
- A block that is in changed_blocks may not be in
|
||||
lighting_invalidated_blocks.
|
||||
Parameters:
|
||||
changed_blocks: Blocks that have been modified
|
||||
*/
|
||||
MapBlock * emergeBlock(
|
||||
v3s16 p,
|
||||
|
@ -561,6 +411,7 @@ public:
|
|||
// dirname: final directory name
|
||||
v2s16 getSectorPos(std::string dirname);
|
||||
v3s16 getBlockPos(std::string sectordir, std::string blockfile);
|
||||
static std::string getBlockFilename(v3s16 p);
|
||||
|
||||
void save(bool only_changed);
|
||||
//void loadAll();
|
||||
|
@ -569,8 +420,8 @@ public:
|
|||
void saveMapMeta();
|
||||
void loadMapMeta();
|
||||
|
||||
void saveChunkMeta();
|
||||
void loadChunkMeta();
|
||||
/*void saveChunkMeta();
|
||||
void loadChunkMeta();*/
|
||||
|
||||
// The sector mutex should be locked when calling most of these
|
||||
|
||||
|
@ -579,6 +430,7 @@ public:
|
|||
// DEPRECATED? Sectors have no metadata anymore.
|
||||
void saveSectorMeta(ServerMapSector *sector);
|
||||
MapSector* loadSectorMeta(std::string dirname, bool save_after_load);
|
||||
bool loadSectorMeta(v2s16 p2d);
|
||||
|
||||
// Full load of a sector including all blocks.
|
||||
// returns true on success, false on failure.
|
||||
|
@ -590,6 +442,7 @@ public:
|
|||
void saveBlock(MapBlock *block);
|
||||
// This will generate a sector with getSector if not found.
|
||||
void loadBlock(std::string sectordir, std::string blockfile, MapSector *sector, bool save_after_load=false);
|
||||
MapBlock* loadBlock(v3s16 p);
|
||||
|
||||
// For debug printing
|
||||
virtual void PrintInfo(std::ostream &out);
|
||||
|
@ -605,11 +458,13 @@ private:
|
|||
std::string m_savedir;
|
||||
bool m_map_saving_enabled;
|
||||
|
||||
#if 0
|
||||
// Chunk size in MapSectors
|
||||
// If 0, chunks are disabled.
|
||||
s16 m_chunksize;
|
||||
// Chunks
|
||||
core::map<v2s16, MapChunk*> m_chunks;
|
||||
#endif
|
||||
|
||||
/*
|
||||
Metadata is re-written on disk only if this is true.
|
||||
|
@ -815,6 +670,7 @@ protected:
|
|||
bool m_create_area;
|
||||
};
|
||||
|
||||
#if 0
|
||||
struct ChunkMakeData
|
||||
{
|
||||
bool no_op;
|
||||
|
@ -838,6 +694,24 @@ struct ChunkMakeData
|
|||
};
|
||||
|
||||
void makeChunk(ChunkMakeData *data);
|
||||
#endif
|
||||
|
||||
struct BlockMakeData
|
||||
{
|
||||
bool no_op;
|
||||
ManualMapVoxelManipulator vmanip;
|
||||
u64 seed;
|
||||
v3s16 blockpos;
|
||||
UniqueQueue<v3s16> transforming_liquid;
|
||||
|
||||
BlockMakeData():
|
||||
no_op(false),
|
||||
vmanip(NULL),
|
||||
seed(0)
|
||||
{}
|
||||
};
|
||||
|
||||
void makeBlock(BlockMakeData *data);
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -31,13 +31,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
MapBlock::MapBlock(NodeContainer *parent, v3s16 pos, bool dummy):
|
||||
m_parent(parent),
|
||||
m_pos(pos),
|
||||
changed(true),
|
||||
m_modified(MOD_STATE_WRITE_NEEDED),
|
||||
is_underground(false),
|
||||
m_lighting_expired(true),
|
||||
m_day_night_differs(false),
|
||||
//m_not_fully_generated(false),
|
||||
m_generated(false),
|
||||
m_objects(this),
|
||||
m_timestamp(BLOCK_TIMESTAMP_UNDEFINED)
|
||||
m_timestamp(BLOCK_TIMESTAMP_UNDEFINED),
|
||||
m_usage_timer(BLOCK_TIMESTAMP_UNDEFINED)
|
||||
{
|
||||
data = NULL;
|
||||
if(dummy == false)
|
||||
|
@ -241,7 +242,7 @@ bool MapBlock::propagateSunlight(core::map<v3s16, bool> & light_sources,
|
|||
// Check if node above block has sunlight
|
||||
try{
|
||||
MapNode n = getNodeParent(v3s16(x, MAP_BLOCKSIZE, z));
|
||||
if(n.getLight(LIGHTBANK_DAY) != LIGHT_SUN)
|
||||
if(n.d == CONTENT_IGNORE || n.getLight(LIGHTBANK_DAY) != LIGHT_SUN)
|
||||
{
|
||||
no_sunlight = true;
|
||||
}
|
||||
|
@ -593,6 +594,11 @@ void MapBlock::serialize(std::ostream &os, u8 version)
|
|||
flags |= 0x02;
|
||||
if(m_lighting_expired)
|
||||
flags |= 0x04;
|
||||
if(version >= 18)
|
||||
{
|
||||
if(m_generated == false)
|
||||
flags |= 0x08;
|
||||
}
|
||||
os.write((char*)&flags, 1);
|
||||
|
||||
u32 nodecount = MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE;
|
||||
|
@ -668,6 +674,12 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
|
|||
setLightingExpired(true);
|
||||
}
|
||||
|
||||
// These have no "generated" field
|
||||
if(version < 18)
|
||||
{
|
||||
m_generated = true;
|
||||
}
|
||||
|
||||
// These have no compression
|
||||
if(version <= 3 || version == 5 || version == 6)
|
||||
{
|
||||
|
@ -749,6 +761,8 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
|
|||
is_underground = (flags & 0x01) ? true : false;
|
||||
m_day_night_differs = (flags & 0x02) ? true : false;
|
||||
m_lighting_expired = (flags & 0x04) ? true : false;
|
||||
if(version >= 18)
|
||||
m_generated = (flags & 0x08) ? false : true;
|
||||
|
||||
// Uncompress data
|
||||
std::ostringstream os(std::ios_base::binary);
|
||||
|
|
125
src/mapblock.h
125
src/mapblock.h
|
@ -51,6 +51,36 @@ enum{
|
|||
FACE_LEFT
|
||||
};*/
|
||||
|
||||
enum ModifiedState
|
||||
{
|
||||
// Has not been modified.
|
||||
MOD_STATE_CLEAN = 0,
|
||||
MOD_RESERVED1 = 1,
|
||||
// Has been modified, and will be saved when being unloaded.
|
||||
MOD_STATE_WRITE_AT_UNLOAD = 2,
|
||||
MOD_RESERVED3 = 3,
|
||||
// Has been modified, and will be saved as soon as possible.
|
||||
MOD_STATE_WRITE_NEEDED = 4,
|
||||
MOD_RESERVED5 = 5,
|
||||
};
|
||||
|
||||
// NOTE: If this is enabled, set MapBlock to be initialized with
|
||||
// CONTENT_IGNORE.
|
||||
/*enum BlockGenerationStatus
|
||||
{
|
||||
// Completely non-generated (filled with CONTENT_IGNORE).
|
||||
BLOCKGEN_UNTOUCHED=0,
|
||||
// Trees or similar might have been blitted from other blocks to here.
|
||||
// Otherwise, the block contains CONTENT_IGNORE
|
||||
BLOCKGEN_FROM_NEIGHBORS=2,
|
||||
// Has been generated, but some neighbors might put some stuff in here
|
||||
// when they are generated.
|
||||
// Does not contain any CONTENT_IGNORE
|
||||
BLOCKGEN_SELF_GENERATED=4,
|
||||
// The block and all its neighbors have been generated
|
||||
BLOCKGEN_FULLY_GENERATED=6
|
||||
};*/
|
||||
|
||||
enum
|
||||
{
|
||||
NODECONTAINER_ID_MAPBLOCK,
|
||||
|
@ -106,9 +136,10 @@ public:
|
|||
u32 l = MAP_BLOCKSIZE * MAP_BLOCKSIZE * MAP_BLOCKSIZE;
|
||||
data = new MapNode[l];
|
||||
for(u32 i=0; i<l; i++){
|
||||
data[i] = MapNode();
|
||||
//data[i] = MapNode();
|
||||
data[i] = MapNode(CONTENT_IGNORE);
|
||||
}
|
||||
setChangedFlag();
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -130,19 +161,43 @@ public:
|
|||
modified, so that the block is saved and possibly not deleted from
|
||||
memory.
|
||||
*/
|
||||
// DEPRECATED, use *Modified()
|
||||
void setChangedFlag()
|
||||
{
|
||||
changed = true;
|
||||
//dstream<<"Deprecated setChangedFlag() called"<<std::endl;
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
}
|
||||
// DEPRECATED, use *Modified()
|
||||
void resetChangedFlag()
|
||||
{
|
||||
changed = false;
|
||||
//dstream<<"Deprecated resetChangedFlag() called"<<std::endl;
|
||||
resetModified();
|
||||
}
|
||||
// DEPRECATED, use *Modified()
|
||||
bool getChangedFlag()
|
||||
{
|
||||
return changed;
|
||||
//dstream<<"Deprecated getChangedFlag() called"<<std::endl;
|
||||
if(getModified() == MOD_STATE_CLEAN)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// m_modified methods
|
||||
void raiseModified(u32 mod)
|
||||
{
|
||||
m_modified = MYMAX(m_modified, mod);
|
||||
}
|
||||
u32 getModified()
|
||||
{
|
||||
return m_modified;
|
||||
}
|
||||
void resetModified()
|
||||
{
|
||||
m_modified = MOD_STATE_CLEAN;
|
||||
}
|
||||
|
||||
// is_underground getter/setter
|
||||
bool getIsUnderground()
|
||||
{
|
||||
return is_underground;
|
||||
|
@ -150,7 +205,7 @@ public:
|
|||
void setIsUnderground(bool a_is_underground)
|
||||
{
|
||||
is_underground = a_is_underground;
|
||||
setChangedFlag();
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
}
|
||||
|
||||
#ifndef SERVER
|
||||
|
@ -168,22 +223,22 @@ public:
|
|||
void setLightingExpired(bool expired)
|
||||
{
|
||||
m_lighting_expired = expired;
|
||||
setChangedFlag();
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
}
|
||||
bool getLightingExpired()
|
||||
{
|
||||
return m_lighting_expired;
|
||||
}
|
||||
|
||||
/*bool isFullyGenerated()
|
||||
bool isGenerated()
|
||||
{
|
||||
return !m_not_fully_generated;
|
||||
return m_generated;
|
||||
}
|
||||
void setFullyGenerated(bool b)
|
||||
void setGenerated(bool b)
|
||||
{
|
||||
setChangedFlag();
|
||||
m_not_fully_generated = !b;
|
||||
}*/
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
m_generated = b;
|
||||
}
|
||||
|
||||
bool isValid()
|
||||
{
|
||||
|
@ -261,7 +316,7 @@ public:
|
|||
if(y < 0 || y >= MAP_BLOCKSIZE) throw InvalidPositionException();
|
||||
if(z < 0 || z >= MAP_BLOCKSIZE) throw InvalidPositionException();
|
||||
data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x] = n;
|
||||
setChangedFlag();
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
}
|
||||
|
||||
void setNode(v3s16 p, MapNode & n)
|
||||
|
@ -290,7 +345,7 @@ public:
|
|||
if(data == NULL)
|
||||
throw InvalidPositionException();
|
||||
data[z*MAP_BLOCKSIZE*MAP_BLOCKSIZE + y*MAP_BLOCKSIZE + x] = n;
|
||||
setChangedFlag();
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
}
|
||||
|
||||
void setNodeNoCheck(v3s16 p, MapNode & n)
|
||||
|
@ -376,26 +431,26 @@ public:
|
|||
{
|
||||
m_objects.update(is, version, smgr, daynight_ratio);
|
||||
|
||||
setChangedFlag();
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
}
|
||||
void clearObjects()
|
||||
{
|
||||
m_objects.clear();
|
||||
|
||||
setChangedFlag();
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
}
|
||||
void addObject(MapBlockObject *object)
|
||||
throw(ContainerFullException, AlreadyExistsException)
|
||||
{
|
||||
m_objects.add(object);
|
||||
|
||||
setChangedFlag();
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
}
|
||||
void removeObject(s16 id)
|
||||
{
|
||||
m_objects.remove(id);
|
||||
|
||||
setChangedFlag();
|
||||
raiseModified(MOD_STATE_WRITE_NEEDED);
|
||||
}
|
||||
MapBlockObject * getObject(s16 id)
|
||||
{
|
||||
|
@ -505,7 +560,7 @@ public:
|
|||
void setTimestamp(u32 time)
|
||||
{
|
||||
m_timestamp = time;
|
||||
setChangedFlag();
|
||||
raiseModified(MOD_STATE_WRITE_AT_UNLOAD);
|
||||
}
|
||||
void setTimestampNoChangedFlag(u32 time)
|
||||
{
|
||||
|
@ -515,6 +570,22 @@ public:
|
|||
{
|
||||
return m_timestamp;
|
||||
}
|
||||
|
||||
/*
|
||||
See m_usage_timer
|
||||
*/
|
||||
void resetUsageTimer()
|
||||
{
|
||||
m_usage_timer = 0;
|
||||
}
|
||||
void incrementUsageTimer(float dtime)
|
||||
{
|
||||
m_usage_timer += dtime;
|
||||
}
|
||||
u32 getUsageTimer()
|
||||
{
|
||||
return m_usage_timer;
|
||||
}
|
||||
|
||||
/*
|
||||
Serialization
|
||||
|
@ -581,10 +652,10 @@ private:
|
|||
|
||||
/*
|
||||
- On the server, this is used for telling whether the
|
||||
block has been changed from the one on disk.
|
||||
block has been modified from the one on disk.
|
||||
- On the client, this is used for nothing.
|
||||
*/
|
||||
bool changed;
|
||||
u32 m_modified;
|
||||
|
||||
/*
|
||||
When propagating sunlight and the above block doesn't exist,
|
||||
|
@ -607,6 +678,8 @@ private:
|
|||
|
||||
// Whether day and night lighting differs
|
||||
bool m_day_night_differs;
|
||||
|
||||
bool m_generated;
|
||||
|
||||
// DEPRECATED
|
||||
MapBlockObjectList m_objects;
|
||||
|
@ -630,6 +703,12 @@ private:
|
|||
Value BLOCK_TIMESTAMP_UNDEFINED=0xffffffff means there is no timestamp.
|
||||
*/
|
||||
u32 m_timestamp;
|
||||
|
||||
/*
|
||||
When the block is accessed, this is set to 0.
|
||||
Map will unload the block when this reaches a timeout.
|
||||
*/
|
||||
float m_usage_timer;
|
||||
};
|
||||
|
||||
inline bool blockpos_over_limit(v3s16 p)
|
||||
|
|
|
@ -24,7 +24,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
|
||||
MapSector::MapSector(NodeContainer *parent, v2s16 pos):
|
||||
differs_from_disk(true),
|
||||
usage_timer(0.0),
|
||||
m_parent(parent),
|
||||
m_pos(pos),
|
||||
m_block_cache(NULL)
|
||||
|
|
|
@ -203,13 +203,6 @@ public:
|
|||
// Basically, this should be changed to true in every setter method
|
||||
bool differs_from_disk;
|
||||
|
||||
// Counts seconds from last usage.
|
||||
// Sector can be deleted from memory after some time of inactivity.
|
||||
// NOTE: It has to be made very sure no other thread is accessing
|
||||
// the sector and it doesn't remain in any cache when
|
||||
// deleting it.
|
||||
float usage_timer;
|
||||
|
||||
protected:
|
||||
|
||||
// The pile of MapBlocks
|
||||
|
|
111
src/noise.cpp
111
src/noise.cpp
|
@ -222,6 +222,49 @@ double noise3d_perlin_abs(double x, double y, double z, int seed,
|
|||
return a;
|
||||
}
|
||||
|
||||
// -1->0, 0->1, 1->0
|
||||
double contour(double v)
|
||||
{
|
||||
v = fabs(v);
|
||||
if(v >= 1.0)
|
||||
return 0.0;
|
||||
return (1.0-v);
|
||||
}
|
||||
|
||||
double noise3d_param(const NoiseParams ¶m, double x, double y, double z)
|
||||
{
|
||||
double s = param.pos_scale;
|
||||
x /= s;
|
||||
y /= s;
|
||||
z /= s;
|
||||
|
||||
if(param.type == NOISE_PERLIN)
|
||||
{
|
||||
return param.noise_scale*noise3d_perlin(x,y,z, param.seed,
|
||||
param.octaves,
|
||||
param.persistence);
|
||||
}
|
||||
else if(param.type == NOISE_PERLIN_ABS)
|
||||
{
|
||||
return param.noise_scale*noise3d_perlin_abs(x,y,z, param.seed,
|
||||
param.octaves,
|
||||
param.persistence);
|
||||
}
|
||||
else if(param.type == NOISE_PERLIN_CONTOUR)
|
||||
{
|
||||
return contour(param.noise_scale*noise3d_perlin(x,y,z,
|
||||
param.seed, param.octaves,
|
||||
param.persistence));
|
||||
}
|
||||
else if(param.type == NOISE_PERLIN_CONTOUR_FLIP_YZ)
|
||||
{
|
||||
return contour(param.noise_scale*noise3d_perlin(x,z,y,
|
||||
param.seed, param.octaves,
|
||||
param.persistence));
|
||||
}
|
||||
else assert(0);
|
||||
}
|
||||
|
||||
/*
|
||||
NoiseBuffer
|
||||
*/
|
||||
|
@ -246,8 +289,7 @@ void NoiseBuffer::clear()
|
|||
m_size_z = 0;
|
||||
}
|
||||
|
||||
void NoiseBuffer::create(int seed, int octaves, double persistence,
|
||||
double pos_scale,
|
||||
void NoiseBuffer::create(const NoiseParams ¶m,
|
||||
double first_x, double first_y, double first_z,
|
||||
double last_x, double last_y, double last_z,
|
||||
double samplelength_x, double samplelength_y, double samplelength_z)
|
||||
|
@ -265,22 +307,54 @@ void NoiseBuffer::create(int seed, int octaves, double persistence,
|
|||
m_size_y = (last_y - m_start_y)/samplelength_y + 2;
|
||||
m_size_z = (last_z - m_start_z)/samplelength_z + 2;
|
||||
|
||||
/*dstream<<"m_size_x="<<m_size_x<<", m_size_y="<<m_size_y
|
||||
<<", m_size_z="<<m_size_z<<std::endl;*/
|
||||
|
||||
m_data = new double[m_size_x*m_size_y*m_size_z];
|
||||
|
||||
for(int x=0; x<m_size_x; x++)
|
||||
for(int y=0; y<m_size_y; y++)
|
||||
for(int z=0; z<m_size_z; z++)
|
||||
{
|
||||
double xd = (m_start_x + (double)x*m_samplelength_x)/pos_scale;
|
||||
double yd = (m_start_y + (double)y*m_samplelength_y)/pos_scale;
|
||||
double zd = (m_start_z + (double)z*m_samplelength_z)/pos_scale;
|
||||
intSet(x,y,z, noise3d_perlin(xd,yd,zd,seed,octaves,persistence));
|
||||
double xd = (m_start_x + (double)x*m_samplelength_x);
|
||||
double yd = (m_start_y + (double)y*m_samplelength_y);
|
||||
double zd = (m_start_z + (double)z*m_samplelength_z);
|
||||
double a = noise3d_param(param, xd,yd,zd);
|
||||
intSet(x,y,z, a);
|
||||
}
|
||||
}
|
||||
|
||||
void NoiseBuffer::multiply(const NoiseParams ¶m)
|
||||
{
|
||||
assert(m_data != NULL);
|
||||
|
||||
for(int x=0; x<m_size_x; x++)
|
||||
for(int y=0; y<m_size_y; y++)
|
||||
for(int z=0; z<m_size_z; z++)
|
||||
{
|
||||
double xd = (m_start_x + (double)x*m_samplelength_x);
|
||||
double yd = (m_start_y + (double)y*m_samplelength_y);
|
||||
double zd = (m_start_z + (double)z*m_samplelength_z);
|
||||
double a = noise3d_param(param, xd,yd,zd);
|
||||
intMultiply(x,y,z, a);
|
||||
}
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
void NoiseBuffer::create(int seed, int octaves, double persistence,
|
||||
bool abs,
|
||||
double first_x, double first_y, double first_z,
|
||||
double last_x, double last_y, double last_z,
|
||||
double samplelength_x, double samplelength_y, double samplelength_z)
|
||||
{
|
||||
NoiseParams param;
|
||||
param.type = abs ? NOISE_PERLIN_ABS : NOISE_PERLIN;
|
||||
param.seed = seed;
|
||||
param.octaves = octaves;
|
||||
param.persistence = persistence;
|
||||
|
||||
create(param, first_x, first_y, first_z,
|
||||
last_x, last_y, last_z,
|
||||
samplelength_x, samplelength_y, samplelength_z);
|
||||
}
|
||||
|
||||
void NoiseBuffer::intSet(int x, int y, int z, double d)
|
||||
{
|
||||
int i = m_size_x*m_size_y*z + m_size_x*y + x;
|
||||
|
@ -289,6 +363,14 @@ void NoiseBuffer::intSet(int x, int y, int z, double d)
|
|||
m_data[i] = d;
|
||||
}
|
||||
|
||||
void NoiseBuffer::intMultiply(int x, int y, int z, double d)
|
||||
{
|
||||
int i = m_size_x*m_size_y*z + m_size_x*y + x;
|
||||
assert(i >= 0);
|
||||
assert(i < m_size_x*m_size_y*m_size_z);
|
||||
m_data[i] = m_data[i] * d;
|
||||
}
|
||||
|
||||
double NoiseBuffer::intGet(int x, int y, int z)
|
||||
{
|
||||
int i = m_size_x*m_size_y*z + m_size_x*y + x;
|
||||
|
@ -326,3 +408,14 @@ double NoiseBuffer::get(double x, double y, double z)
|
|||
return triLinearInterpolation(v000,v100,v010,v110,v001,v101,v011,v111,xl,yl,zl);
|
||||
}
|
||||
|
||||
/*bool NoiseBuffer::contains(double x, double y, double z)
|
||||
{
|
||||
x -= m_start_x;
|
||||
y -= m_start_y;
|
||||
z -= m_start_z;
|
||||
x /= m_samplelength_x;
|
||||
y /= m_samplelength_y;
|
||||
z /= m_samplelength_z;
|
||||
if(x <= 0.0 || x >= m_size_x)
|
||||
}*/
|
||||
|
||||
|
|
42
src/noise.h
42
src/noise.h
|
@ -41,6 +41,38 @@ double noise3d_perlin(double x, double y, double z, int seed,
|
|||
double noise3d_perlin_abs(double x, double y, double z, int seed,
|
||||
int octaves, double persistence);
|
||||
|
||||
enum NoiseType
|
||||
{
|
||||
NOISE_PERLIN,
|
||||
NOISE_PERLIN_ABS,
|
||||
NOISE_PERLIN_CONTOUR,
|
||||
NOISE_PERLIN_CONTOUR_FLIP_YZ
|
||||
};
|
||||
|
||||
struct NoiseParams
|
||||
{
|
||||
NoiseType type;
|
||||
int seed;
|
||||
int octaves;
|
||||
double persistence;
|
||||
double pos_scale;
|
||||
double noise_scale; // Useful for contour noises
|
||||
|
||||
NoiseParams(NoiseType type_=NOISE_PERLIN, int seed_=0,
|
||||
int octaves_=3, double persistence_=0.5,
|
||||
double pos_scale_=100.0, double noise_scale_=1.0):
|
||||
type(type_),
|
||||
seed(seed_),
|
||||
octaves(octaves_),
|
||||
persistence(persistence_),
|
||||
pos_scale(pos_scale_),
|
||||
noise_scale(noise_scale_)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
double noise3d_param(const NoiseParams ¶m, double x, double y, double z);
|
||||
|
||||
class NoiseBuffer
|
||||
{
|
||||
public:
|
||||
|
@ -48,15 +80,23 @@ public:
|
|||
~NoiseBuffer();
|
||||
|
||||
void clear();
|
||||
void create(const NoiseParams ¶m,
|
||||
double first_x, double first_y, double first_z,
|
||||
double last_x, double last_y, double last_z,
|
||||
double samplelength_x, double samplelength_y, double samplelength_z);
|
||||
void multiply(const NoiseParams ¶m);
|
||||
// Deprecated
|
||||
void create(int seed, int octaves, double persistence,
|
||||
double pos_scale,
|
||||
bool abs,
|
||||
double first_x, double first_y, double first_z,
|
||||
double last_x, double last_y, double last_z,
|
||||
double samplelength_x, double samplelength_y, double samplelength_z);
|
||||
|
||||
void intSet(int x, int y, int z, double d);
|
||||
void intMultiply(int x, int y, int z, double d);
|
||||
double intGet(int x, int y, int z);
|
||||
double get(double x, double y, double z);
|
||||
//bool contains(double x, double y, double z);
|
||||
|
||||
private:
|
||||
double *m_data;
|
||||
|
|
|
@ -53,11 +53,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
15: StaticObjects
|
||||
16: larger maximum size of node metadata, and compression
|
||||
17: MapBlocks contain timestamp
|
||||
18: sqlite/new generator/whatever
|
||||
*/
|
||||
// This represents an uninitialized or invalid format
|
||||
#define SER_FMT_VER_INVALID 255
|
||||
// Highest supported serialization version
|
||||
#define SER_FMT_VER_HIGHEST 17
|
||||
#define SER_FMT_VER_HIGHEST 18
|
||||
// Lowest supported serialization version
|
||||
#define SER_FMT_VER_LOWEST 0
|
||||
|
||||
|
|
186
src/server.cpp
186
src/server.cpp
|
@ -37,6 +37,31 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
|
||||
#define BLOCK_EMERGE_FLAG_FROMDISK (1<<0)
|
||||
|
||||
class MapEditEventIgnorer
|
||||
{
|
||||
public:
|
||||
MapEditEventIgnorer(bool *flag):
|
||||
m_flag(flag)
|
||||
{
|
||||
if(*m_flag == false)
|
||||
*m_flag = true;
|
||||
else
|
||||
m_flag = NULL;
|
||||
}
|
||||
|
||||
~MapEditEventIgnorer()
|
||||
{
|
||||
if(m_flag)
|
||||
{
|
||||
assert(*m_flag);
|
||||
*m_flag = false;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
bool *m_flag;
|
||||
};
|
||||
|
||||
void * ServerThread::Thread()
|
||||
{
|
||||
ThreadStarted();
|
||||
|
@ -150,8 +175,8 @@ void * EmergeThread::Thread()
|
|||
|
||||
ServerMap &map = ((ServerMap&)m_server->m_env.getMap());
|
||||
|
||||
core::map<v3s16, MapBlock*> changed_blocks;
|
||||
core::map<v3s16, MapBlock*> lighting_invalidated_blocks;
|
||||
//core::map<v3s16, MapBlock*> changed_blocks;
|
||||
//core::map<v3s16, MapBlock*> lighting_invalidated_blocks;
|
||||
|
||||
MapBlock *block = NULL;
|
||||
bool got_block = true;
|
||||
|
@ -162,32 +187,6 @@ void * EmergeThread::Thread()
|
|||
if(optional)
|
||||
only_from_disk = true;
|
||||
|
||||
v2s16 chunkpos = map.sector_to_chunk(p2d);
|
||||
|
||||
bool generate_chunk = false;
|
||||
if(only_from_disk == false)
|
||||
{
|
||||
JMutexAutoLock envlock(m_server->m_env_mutex);
|
||||
if(map.chunkNonVolatile(chunkpos) == false)
|
||||
generate_chunk = true;
|
||||
}
|
||||
if(generate_chunk)
|
||||
{
|
||||
ChunkMakeData data;
|
||||
|
||||
{
|
||||
JMutexAutoLock envlock(m_server->m_env_mutex);
|
||||
map.initChunkMake(data, chunkpos);
|
||||
}
|
||||
|
||||
makeChunk(&data);
|
||||
|
||||
{
|
||||
JMutexAutoLock envlock(m_server->m_env_mutex);
|
||||
map.finishChunkMake(data, changed_blocks);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Fetch block from map or generate a single block
|
||||
*/
|
||||
|
@ -196,36 +195,55 @@ void * EmergeThread::Thread()
|
|||
|
||||
// Load sector if it isn't loaded
|
||||
if(map.getSectorNoGenerateNoEx(p2d) == NULL)
|
||||
map.loadSectorFull(p2d);
|
||||
//map.loadSectorFull(p2d);
|
||||
map.loadSectorMeta(p2d);
|
||||
|
||||
block = map.getBlockNoCreateNoEx(p);
|
||||
if(!block || block->isDummy())
|
||||
if(!block || block->isDummy() || !block->isGenerated())
|
||||
{
|
||||
if(only_from_disk)
|
||||
// Get, load or create sector
|
||||
/*ServerMapSector *sector =
|
||||
(ServerMapSector*)map.createSector(p2d);*/
|
||||
|
||||
// Load/generate block
|
||||
|
||||
/*block = map.emergeBlock(p, sector, changed_blocks,
|
||||
lighting_invalidated_blocks);*/
|
||||
|
||||
block = map.loadBlock(p);
|
||||
|
||||
if(block == NULL && only_from_disk == false)
|
||||
block = map.generateBlock(p, modified_blocks);
|
||||
//block = map.generateBlock(p, changed_blocks);
|
||||
/*block = map.generateBlock(p, block, sector, changed_blocks,
|
||||
lighting_invalidated_blocks);*/
|
||||
|
||||
if(block == NULL)
|
||||
{
|
||||
got_block = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get, load or create sector
|
||||
ServerMapSector *sector =
|
||||
(ServerMapSector*)map.createSector(p2d);
|
||||
// Generate block
|
||||
block = map.generateBlock(p, block, sector, changed_blocks,
|
||||
lighting_invalidated_blocks);
|
||||
if(block == NULL)
|
||||
got_block = false;
|
||||
/*
|
||||
Ignore map edit events, they will not need to be
|
||||
sent to anybody because the block hasn't been sent
|
||||
to anybody
|
||||
*/
|
||||
MapEditEventIgnorer ign(&m_server->m_ignore_map_edit_events);
|
||||
|
||||
// Activate objects and stuff
|
||||
m_server->m_env.activateBlock(block, 3600);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if(block->getLightingExpired()){
|
||||
/*if(block->getLightingExpired()){
|
||||
lighting_invalidated_blocks[block->getPos()] = block;
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
// TODO: Some additional checking and lighting updating,
|
||||
// see emergeBlock
|
||||
// see emergeBlock
|
||||
}
|
||||
|
||||
{//envlock
|
||||
|
@ -237,7 +255,8 @@ void * EmergeThread::Thread()
|
|||
Collect a list of blocks that have been modified in
|
||||
addition to the fetched one.
|
||||
*/
|
||||
|
||||
|
||||
#if 0
|
||||
if(lighting_invalidated_blocks.size() > 0)
|
||||
{
|
||||
/*dstream<<"lighting "<<lighting_invalidated_blocks.size()
|
||||
|
@ -258,11 +277,12 @@ void * EmergeThread::Thread()
|
|||
MapBlock *block = i.getNode()->getValue();
|
||||
modified_blocks.insert(block->getPos(), block);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
// If we got no block, there should be no invalidated blocks
|
||||
else
|
||||
{
|
||||
assert(lighting_invalidated_blocks.size() == 0);
|
||||
//assert(lighting_invalidated_blocks.size() == 0);
|
||||
}
|
||||
|
||||
}//envlock
|
||||
|
@ -597,12 +617,16 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
|||
{
|
||||
block_is_invalid = true;
|
||||
}*/
|
||||
|
||||
|
||||
#if 0
|
||||
v2s16 p2d(p.X, p.Z);
|
||||
ServerMap *map = (ServerMap*)(&server->m_env.getMap());
|
||||
v2s16 chunkpos = map->sector_to_chunk(p2d);
|
||||
if(map->chunkNonVolatile(chunkpos) == false)
|
||||
block_is_invalid = true;
|
||||
#endif
|
||||
if(block->isGenerated() == false)
|
||||
block_is_invalid = true;
|
||||
#if 1
|
||||
/*
|
||||
If block is not close, don't send it unless it is near
|
||||
|
@ -649,6 +673,7 @@ void RemoteClient::GetNextBlocks(Server *server, float dtime,
|
|||
//TODO: Get value from somewhere
|
||||
// Allow only one block in emerge queue
|
||||
//if(server->m_emerge_queue.peerItemCount(peer_id) < 1)
|
||||
// Allow two blocks in queue per client
|
||||
if(server->m_emerge_queue.peerItemCount(peer_id) < 2)
|
||||
{
|
||||
//dstream<<"Adding block to emerge queue"<<std::endl;
|
||||
|
@ -1630,19 +1655,28 @@ void Server::AsyncRunStep()
|
|||
Send queued-for-sending map edit events.
|
||||
*/
|
||||
{
|
||||
// Don't send too many at a time
|
||||
u32 count = 0;
|
||||
while(m_unsent_map_edit_queue.size() != 0)
|
||||
{
|
||||
MapEditEvent* event = m_unsent_map_edit_queue.pop_front();
|
||||
|
||||
// Players far away from the change are stored here.
|
||||
// Instead of sending the changes, MapBlocks are set not sent
|
||||
// for them.
|
||||
core::list<u16> far_players;
|
||||
|
||||
if(event->type == MEET_ADDNODE)
|
||||
{
|
||||
dstream<<"Server: MEET_ADDNODE"<<std::endl;
|
||||
sendAddNode(event->p, event->n, event->already_known_by_peer);
|
||||
sendAddNode(event->p, event->n, event->already_known_by_peer,
|
||||
&far_players, 30);
|
||||
}
|
||||
else if(event->type == MEET_REMOVENODE)
|
||||
{
|
||||
dstream<<"Server: MEET_REMOVENODE"<<std::endl;
|
||||
sendRemoveNode(event->p, event->already_known_by_peer);
|
||||
sendRemoveNode(event->p, event->already_known_by_peer,
|
||||
&far_players, 30);
|
||||
}
|
||||
else if(event->type == MEET_BLOCK_NODE_METADATA_CHANGED)
|
||||
{
|
||||
|
@ -1659,8 +1693,35 @@ void Server::AsyncRunStep()
|
|||
dstream<<"WARNING: Server: Unknown MapEditEvent "
|
||||
<<((u32)event->type)<<std::endl;
|
||||
}
|
||||
|
||||
/*
|
||||
Set blocks not sent to far players
|
||||
*/
|
||||
core::map<v3s16, MapBlock*> modified_blocks2;
|
||||
for(core::map<v3s16, bool>::Iterator
|
||||
i = event->modified_blocks.getIterator();
|
||||
i.atEnd()==false; i++)
|
||||
{
|
||||
v3s16 p = i.getNode()->getKey();
|
||||
modified_blocks2.insert(p, m_env.getMap().getBlockNoCreateNoEx(p));
|
||||
}
|
||||
for(core::list<u16>::Iterator
|
||||
i = far_players.begin();
|
||||
i != far_players.end(); i++)
|
||||
{
|
||||
u16 peer_id = *i;
|
||||
RemoteClient *client = getClient(peer_id);
|
||||
if(client==NULL)
|
||||
continue;
|
||||
client->SetBlocksNotSent(modified_blocks2);
|
||||
}
|
||||
|
||||
delete event;
|
||||
|
||||
// Don't send too many at a time
|
||||
count++;
|
||||
if(count >= 2 && m_unsent_map_edit_queue.size() < 50)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1754,7 +1815,7 @@ void Server::AsyncRunStep()
|
|||
m_env.getMap().save(true);
|
||||
|
||||
// Delete unused sectors
|
||||
u32 deleted_count = m_env.getMap().deleteUnusedSectors(
|
||||
u32 deleted_count = m_env.getMap().unloadUnusedData(
|
||||
g_settings.getFloat("server_unload_unused_sectors_timeout"));
|
||||
if(deleted_count > 0)
|
||||
{
|
||||
|
@ -2565,10 +2626,11 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||
Remove the node
|
||||
(this takes some time so it is done after the quick stuff)
|
||||
*/
|
||||
m_ignore_map_edit_events = true;
|
||||
m_env.getMap().removeNodeAndUpdate(p_under, modified_blocks);
|
||||
m_ignore_map_edit_events = false;
|
||||
|
||||
{
|
||||
MapEditEventIgnorer ign(&m_ignore_map_edit_events);
|
||||
|
||||
m_env.getMap().removeNodeAndUpdate(p_under, modified_blocks);
|
||||
}
|
||||
/*
|
||||
Set blocks not sent to far players
|
||||
*/
|
||||
|
@ -2679,10 +2741,11 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||
This takes some time so it is done after the quick stuff
|
||||
*/
|
||||
core::map<v3s16, MapBlock*> modified_blocks;
|
||||
m_ignore_map_edit_events = true;
|
||||
m_env.getMap().addNodeAndUpdate(p_over, n, modified_blocks);
|
||||
m_ignore_map_edit_events = false;
|
||||
|
||||
{
|
||||
MapEditEventIgnorer ign(&m_ignore_map_edit_events);
|
||||
|
||||
m_env.getMap().addNodeAndUpdate(p_over, n, modified_blocks);
|
||||
}
|
||||
/*
|
||||
Set blocks not sent to far players
|
||||
*/
|
||||
|
@ -3889,10 +3952,16 @@ std::wstring Server::getStatusString()
|
|||
v3f findSpawnPos(ServerMap &map)
|
||||
{
|
||||
//return v3f(50,50,50)*BS;
|
||||
|
||||
|
||||
v2s16 nodepos;
|
||||
s16 groundheight = 0;
|
||||
|
||||
#if 0
|
||||
nodepos = v2s16(0,0);
|
||||
groundheight = 20;
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
// Try to find a good place a few times
|
||||
for(s32 i=0; i<1000; i++)
|
||||
{
|
||||
|
@ -3922,6 +3991,7 @@ v3f findSpawnPos(ServerMap &map)
|
|||
//dstream<<"Searched through "<<i<<" places."<<std::endl;
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
|
||||
// If no suitable place was not found, go above water at least.
|
||||
if(groundheight < WATER_LEVEL)
|
||||
|
@ -3929,7 +3999,7 @@ v3f findSpawnPos(ServerMap &map)
|
|||
|
||||
return intToFloat(v3s16(
|
||||
nodepos.X,
|
||||
groundheight + 2,
|
||||
groundheight + 3,
|
||||
nodepos.Y
|
||||
), BS);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
if( UNIX )
|
||||
set(sqlite3_SRCS sqlite3.c)
|
||||
set(sqlite3_platform_LIBS "")
|
||||
else( UNIX )
|
||||
set(sqlite3_SRCS sqlite3.c)
|
||||
set(sqlite3_platform_LIBS "")
|
||||
endif( UNIX )
|
||||
|
||||
add_library(sqlite3 ${sqlite3_SRCS})
|
||||
|
||||
target_link_libraries(
|
||||
sqlite3
|
||||
${sqlite3_platform_LIBS}
|
||||
)
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
15
src/test.cpp
15
src/test.cpp
|
@ -425,16 +425,27 @@ struct TestMapBlock
|
|||
assert(b.getChangedFlag() == false);
|
||||
|
||||
// All nodes should have been set to
|
||||
// .d=CONTENT_AIR and .getLight() = 0
|
||||
// .d=CONTENT_IGNORE and .getLight() = 0
|
||||
for(u16 z=0; z<MAP_BLOCKSIZE; z++)
|
||||
for(u16 y=0; y<MAP_BLOCKSIZE; y++)
|
||||
for(u16 x=0; x<MAP_BLOCKSIZE; x++)
|
||||
{
|
||||
assert(b.getNode(v3s16(x,y,z)).d == CONTENT_AIR);
|
||||
//assert(b.getNode(v3s16(x,y,z)).d == CONTENT_AIR);
|
||||
assert(b.getNode(v3s16(x,y,z)).d == CONTENT_IGNORE);
|
||||
assert(b.getNode(v3s16(x,y,z)).getLight(LIGHTBANK_DAY) == 0);
|
||||
assert(b.getNode(v3s16(x,y,z)).getLight(LIGHTBANK_NIGHT) == 0);
|
||||
}
|
||||
|
||||
{
|
||||
MapNode n(CONTENT_AIR);
|
||||
for(u16 z=0; z<MAP_BLOCKSIZE; z++)
|
||||
for(u16 y=0; y<MAP_BLOCKSIZE; y++)
|
||||
for(u16 x=0; x<MAP_BLOCKSIZE; x++)
|
||||
{
|
||||
b.setNode(v3s16(x,y,z), n);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Parent fetch functions
|
||||
*/
|
||||
|
|
|
@ -515,6 +515,8 @@ void TextureSource::buildMainAtlas()
|
|||
sourcelist.push_back("glass.png");
|
||||
sourcelist.push_back("mud.png^grass_side.png");
|
||||
sourcelist.push_back("cobble.png");
|
||||
sourcelist.push_back("mossycobble.png");
|
||||
sourcelist.push_back("gravel.png");
|
||||
|
||||
sourcelist.push_back("stone.png^mineral_coal.png");
|
||||
sourcelist.push_back("stone.png^mineral_iron.png");
|
||||
|
|
|
@ -384,6 +384,14 @@ public:
|
|||
|
||||
return m_data[m_area.index(p)];
|
||||
}
|
||||
MapNode getNodeNoExNoEmerge(v3s16 p)
|
||||
{
|
||||
if(m_area.contains(p) == false)
|
||||
return MapNode(CONTENT_IGNORE);
|
||||
if(m_flags[m_area.index(p)] & VOXELFLAG_INEXISTENT)
|
||||
return MapNode(CONTENT_IGNORE);
|
||||
return m_data[m_area.index(p)];
|
||||
}
|
||||
MapNode & getNodeRef(v3s16 p)
|
||||
{
|
||||
emerge(p);
|
||||
|
|
Loading…
Reference in New Issue