forked from Mirrorlandia_minetest/minetest
minecraft-style water done (but no texture animation or sound)
This commit is contained in:
parent
0fa0e0752a
commit
d44abdab17
@ -97,7 +97,11 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
*/
|
*/
|
||||||
#define MAX_OBJECTDATA_SIZE 450
|
#define MAX_OBJECTDATA_SIZE 450
|
||||||
|
|
||||||
#define WATER_LEVEL (0)
|
/*
|
||||||
|
This is good to be a bit different than 0 so that water level
|
||||||
|
is not between to MapBlocks
|
||||||
|
*/
|
||||||
|
#define WATER_LEVEL 3
|
||||||
|
|
||||||
// Length of cracking animation in count of images
|
// Length of cracking animation in count of images
|
||||||
#define CRACK_ANIMATION_LENGTH 5
|
#define CRACK_ANIMATION_LENGTH 5
|
||||||
|
@ -62,8 +62,8 @@ void set_default_settings()
|
|||||||
g_settings.setDefault("active_object_range", "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", "1");
|
||||||
g_settings.setDefault("max_simultaneous_block_sends_server_total", "4");
|
g_settings.setDefault("max_simultaneous_block_sends_server_total", "4");
|
||||||
g_settings.setDefault("water_moves", "true");
|
//g_settings.setDefault("water_moves", "true");
|
||||||
g_settings.setDefault("disable_water_climb", "true");
|
//g_settings.setDefault("disable_water_climb", "true");
|
||||||
//g_settings.setDefault("endless_water", "true");
|
//g_settings.setDefault("endless_water", "true");
|
||||||
g_settings.setDefault("max_block_send_distance", "6");
|
g_settings.setDefault("max_block_send_distance", "6");
|
||||||
g_settings.setDefault("max_block_generate_distance", "6");
|
g_settings.setDefault("max_block_generate_distance", "6");
|
||||||
|
@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||||||
#define LIGHT_HEADER
|
#define LIGHT_HEADER
|
||||||
|
|
||||||
#include "common_irrlicht.h"
|
#include "common_irrlicht.h"
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Day/night cache:
|
Day/night cache:
|
||||||
@ -78,7 +79,7 @@ inline u8 decode_light(u8 light)
|
|||||||
return light_decode_table[LIGHT_MAX];
|
return light_decode_table[LIGHT_MAX];
|
||||||
|
|
||||||
if(light > LIGHT_MAX)
|
if(light > LIGHT_MAX)
|
||||||
throw;
|
light = LIGHT_MAX;
|
||||||
|
|
||||||
return light_decode_table[light];
|
return light_decode_table[light];
|
||||||
}
|
}
|
||||||
|
11
src/main.cpp
11
src/main.cpp
@ -116,12 +116,16 @@ TODO: Startup and configuration menu
|
|||||||
|
|
||||||
Graphics:
|
Graphics:
|
||||||
|
|
||||||
|
TODO:
|
||||||
|
|
||||||
TODO: Optimize day/night mesh updating somehow
|
TODO: Optimize day/night mesh updating somehow
|
||||||
- create copies of all textures for all lighting values and only
|
- create copies of all textures for all lighting values and only
|
||||||
change texture for material?
|
change texture for material?
|
||||||
- Umm... the collecting of the faces is the slow part
|
- Umm... the collecting of the faces is the slow part
|
||||||
-> what about just changing the color values of the existing
|
-> what about just changing the color values of the existing
|
||||||
meshbuffers? It should go quite fast.
|
meshbuffers? It should go quite fast.
|
||||||
|
- This is not easy; There'd need to be a buffer somewhere
|
||||||
|
that would contain the night and day lighting values.
|
||||||
|
|
||||||
TODO: Draw big amounts of torches better (that is, throw them in the
|
TODO: Draw big amounts of torches better (that is, throw them in the
|
||||||
same meshbuffer (can the meshcollector class be used?))
|
same meshbuffer (can the meshcollector class be used?))
|
||||||
@ -129,9 +133,13 @@ TODO: Draw big amounts of torches better (that is, throw them in the
|
|||||||
TODO: Combine MapBlock's face caches to so big pieces that VBO
|
TODO: Combine MapBlock's face caches to so big pieces that VBO
|
||||||
gets used
|
gets used
|
||||||
- That is >500 vertices
|
- That is >500 vertices
|
||||||
|
- This is not easy; all the MapBlocks close to the player would
|
||||||
|
still need to be drawn separately and combining the blocks
|
||||||
|
would have to happen in a background thread
|
||||||
|
|
||||||
TODO: Make fetching sector's blocks more efficient when rendering
|
TODO: Make fetching sector's blocks more efficient when rendering
|
||||||
sectors that have very large amounts of blocks (on client)
|
sectors that have very large amounts of blocks (on client)
|
||||||
|
- Is this necessary at all?
|
||||||
|
|
||||||
Configuration:
|
Configuration:
|
||||||
|
|
||||||
@ -210,6 +218,9 @@ TODO: Map generator version 2
|
|||||||
- There could be a certain height (to which mountains only reach)
|
- There could be a certain height (to which mountains only reach)
|
||||||
where some minerals are found
|
where some minerals are found
|
||||||
|
|
||||||
|
FIXME: The new pre-sunlight-propagation code messes up with initial
|
||||||
|
water lighting
|
||||||
|
|
||||||
Doing now:
|
Doing now:
|
||||||
======================================================================
|
======================================================================
|
||||||
|
|
||||||
|
391
src/map.cpp
391
src/map.cpp
@ -926,6 +926,37 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
|
|||||||
MapBlock *block = i.getNode()->getValue();
|
MapBlock *block = i.getNode()->getValue();
|
||||||
block->updateDayNightDiff();
|
block->updateDayNightDiff();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add neighboring liquid nodes and the node itself if it is
|
||||||
|
liquid (=water node was added) to transform queue.
|
||||||
|
*/
|
||||||
|
v3s16 dirs[7] = {
|
||||||
|
v3s16(0,0,0), // self
|
||||||
|
v3s16(0,0,1), // back
|
||||||
|
v3s16(0,1,0), // top
|
||||||
|
v3s16(1,0,0), // right
|
||||||
|
v3s16(0,0,-1), // front
|
||||||
|
v3s16(0,-1,0), // bottom
|
||||||
|
v3s16(-1,0,0), // left
|
||||||
|
};
|
||||||
|
for(u16 i=0; i<7; i++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
v3s16 p2 = p + dirs[i];
|
||||||
|
|
||||||
|
MapNode n2 = getNode(p2);
|
||||||
|
if(content_liquid(n2.d))
|
||||||
|
{
|
||||||
|
m_transforming_liquid.push_back(p2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}catch(InvalidPositionException &e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1063,6 +1094,35 @@ void Map::removeNodeAndUpdate(v3s16 p,
|
|||||||
MapBlock *block = i.getNode()->getValue();
|
MapBlock *block = i.getNode()->getValue();
|
||||||
block->updateDayNightDiff();
|
block->updateDayNightDiff();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add neighboring liquid nodes to transform queue.
|
||||||
|
*/
|
||||||
|
v3s16 dirs[6] = {
|
||||||
|
v3s16(0,0,1), // back
|
||||||
|
v3s16(0,1,0), // top
|
||||||
|
v3s16(1,0,0), // right
|
||||||
|
v3s16(0,0,-1), // front
|
||||||
|
v3s16(0,-1,0), // bottom
|
||||||
|
v3s16(-1,0,0), // left
|
||||||
|
};
|
||||||
|
for(u16 i=0; i<6; i++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
v3s16 p2 = p + dirs[i];
|
||||||
|
|
||||||
|
MapNode n2 = getNode(p2);
|
||||||
|
if(content_liquid(n2.d))
|
||||||
|
{
|
||||||
|
m_transforming_liquid.push_back(p2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}catch(InvalidPositionException &e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef SERVER
|
#ifndef SERVER
|
||||||
@ -1303,6 +1363,276 @@ void Map::PrintInfo(std::ostream &out)
|
|||||||
out<<"Map: ";
|
out<<"Map: ";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define WATER_DROP_BOOST 4
|
||||||
|
|
||||||
|
void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
|
||||||
|
{
|
||||||
|
DSTACK(__FUNCTION_NAME);
|
||||||
|
TimeTaker timer("transformLiquids()");
|
||||||
|
|
||||||
|
u32 loopcount = 0;
|
||||||
|
u32 initial_size = m_transforming_liquid.size();
|
||||||
|
while(m_transforming_liquid.size() != 0)
|
||||||
|
{
|
||||||
|
v3s16 p0 = m_transforming_liquid.pop_front();
|
||||||
|
|
||||||
|
MapNode n0 = getNode(p0);
|
||||||
|
|
||||||
|
// Don't deal with non-liquids
|
||||||
|
if(content_liquid(n0.d) == false)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bool is_source = !content_flowing_liquid(n0.d);
|
||||||
|
|
||||||
|
u8 liquid_level = 8;
|
||||||
|
if(is_source == false)
|
||||||
|
liquid_level = n0.param2 & 0x0f;
|
||||||
|
|
||||||
|
// Turn possible source into non-source
|
||||||
|
u8 nonsource_c = make_liquid_flowing(n0.d);
|
||||||
|
|
||||||
|
/*
|
||||||
|
If not source, check that some node flows into this one
|
||||||
|
and what is the level of liquid in this one
|
||||||
|
*/
|
||||||
|
if(is_source == false)
|
||||||
|
{
|
||||||
|
s8 new_liquid_level_max = -1;
|
||||||
|
|
||||||
|
v3s16 dirs_from[5] = {
|
||||||
|
v3s16(0,1,0), // top
|
||||||
|
v3s16(0,0,1), // back
|
||||||
|
v3s16(1,0,0), // right
|
||||||
|
v3s16(0,0,-1), // front
|
||||||
|
v3s16(-1,0,0), // left
|
||||||
|
};
|
||||||
|
for(u16 i=0; i<5; i++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
bool from_top = (i==0);
|
||||||
|
|
||||||
|
v3s16 p2 = p0 + dirs_from[i];
|
||||||
|
MapNode n2 = getNode(p2);
|
||||||
|
|
||||||
|
if(content_liquid(n2.d))
|
||||||
|
{
|
||||||
|
u8 n2_nonsource_c = make_liquid_flowing(n2.d);
|
||||||
|
// Check that the liquids are the same type
|
||||||
|
if(n2_nonsource_c != nonsource_c)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: Not handling: different liquids"
|
||||||
|
" collide"<<std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
bool n2_is_source = !content_flowing_liquid(n2.d);
|
||||||
|
s8 n2_liquid_level = 8;
|
||||||
|
if(n2_is_source == false)
|
||||||
|
n2_liquid_level = n2.param2 & 0x07;
|
||||||
|
|
||||||
|
s8 new_liquid_level = -1;
|
||||||
|
if(from_top)
|
||||||
|
{
|
||||||
|
//new_liquid_level = 7;
|
||||||
|
if(n2_liquid_level >= 7 - WATER_DROP_BOOST)
|
||||||
|
new_liquid_level = 7;
|
||||||
|
else
|
||||||
|
new_liquid_level = n2_liquid_level + WATER_DROP_BOOST;
|
||||||
|
}
|
||||||
|
else if(n2_liquid_level > 0)
|
||||||
|
{
|
||||||
|
new_liquid_level = n2_liquid_level - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(new_liquid_level > new_liquid_level_max)
|
||||||
|
new_liquid_level_max = new_liquid_level;
|
||||||
|
}
|
||||||
|
|
||||||
|
}catch(InvalidPositionException &e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
} //for
|
||||||
|
|
||||||
|
/*
|
||||||
|
If liquid level should be something else, update it and
|
||||||
|
add all the neighboring water nodes to the transform queue.
|
||||||
|
*/
|
||||||
|
if(new_liquid_level_max != liquid_level)
|
||||||
|
{
|
||||||
|
if(new_liquid_level_max == -1)
|
||||||
|
{
|
||||||
|
// Remove water alltoghether
|
||||||
|
n0.d = CONTENT_AIR;
|
||||||
|
n0.param2 = 0;
|
||||||
|
setNode(p0, n0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
n0.param2 = new_liquid_level_max;
|
||||||
|
setNode(p0, n0);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Block has been modified
|
||||||
|
{
|
||||||
|
v3s16 blockpos = getNodeBlockPos(p0);
|
||||||
|
MapBlock *block = getBlockNoCreateNoEx(blockpos);
|
||||||
|
if(block != NULL)
|
||||||
|
modified_blocks.insert(blockpos, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add neighboring non-source liquid nodes to transform queue.
|
||||||
|
*/
|
||||||
|
v3s16 dirs[6] = {
|
||||||
|
v3s16(0,0,1), // back
|
||||||
|
v3s16(0,1,0), // top
|
||||||
|
v3s16(1,0,0), // right
|
||||||
|
v3s16(0,0,-1), // front
|
||||||
|
v3s16(0,-1,0), // bottom
|
||||||
|
v3s16(-1,0,0), // left
|
||||||
|
};
|
||||||
|
for(u16 i=0; i<6; i++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
v3s16 p2 = p0 + dirs[i];
|
||||||
|
|
||||||
|
MapNode n2 = getNode(p2);
|
||||||
|
if(content_flowing_liquid(n2.d))
|
||||||
|
{
|
||||||
|
m_transforming_liquid.push_back(p2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}catch(InvalidPositionException &e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a new one from queue if the node has turned into non-water
|
||||||
|
if(content_liquid(n0.d) == false)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Flow water from this node
|
||||||
|
*/
|
||||||
|
v3s16 dirs_to[5] = {
|
||||||
|
v3s16(0,-1,0), // bottom
|
||||||
|
v3s16(0,0,1), // back
|
||||||
|
v3s16(1,0,0), // right
|
||||||
|
v3s16(0,0,-1), // front
|
||||||
|
v3s16(-1,0,0), // left
|
||||||
|
};
|
||||||
|
for(u16 i=0; i<5; i++)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
bool to_bottom = (i == 0);
|
||||||
|
|
||||||
|
// If liquid is at lowest possible height, it's not going
|
||||||
|
// anywhere except down
|
||||||
|
if(liquid_level == 0 && to_bottom == false)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
u8 liquid_next_level = 0;
|
||||||
|
// If going to bottom
|
||||||
|
if(to_bottom)
|
||||||
|
{
|
||||||
|
//liquid_next_level = 7;
|
||||||
|
if(liquid_level >= 7 - WATER_DROP_BOOST)
|
||||||
|
liquid_next_level = 7;
|
||||||
|
else
|
||||||
|
liquid_next_level = liquid_level + WATER_DROP_BOOST;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
liquid_next_level = liquid_level - 1;
|
||||||
|
|
||||||
|
bool n2_changed = false;
|
||||||
|
bool flowed = false;
|
||||||
|
|
||||||
|
v3s16 p2 = p0 + dirs_to[i];
|
||||||
|
|
||||||
|
MapNode n2 = getNode(p2);
|
||||||
|
|
||||||
|
if(content_liquid(n2.d))
|
||||||
|
{
|
||||||
|
u8 n2_nonsource_c = make_liquid_flowing(n2.d);
|
||||||
|
// Check that the liquids are the same type
|
||||||
|
if(n2_nonsource_c != nonsource_c)
|
||||||
|
{
|
||||||
|
dstream<<"WARNING: Not handling: different liquids"
|
||||||
|
" collide"<<std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
bool n2_is_source = !content_flowing_liquid(n2.d);
|
||||||
|
u8 n2_liquid_level = 8;
|
||||||
|
if(n2_is_source == false)
|
||||||
|
n2_liquid_level = n2.param2 & 0x07;
|
||||||
|
|
||||||
|
if(to_bottom)
|
||||||
|
{
|
||||||
|
flowed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(n2_is_source)
|
||||||
|
{
|
||||||
|
// Just flow into the source, nothing changes.
|
||||||
|
// n2_changed is not set because destination didn't change
|
||||||
|
flowed = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(liquid_next_level > liquid_level)
|
||||||
|
{
|
||||||
|
n2.param2 = liquid_next_level;
|
||||||
|
setNode(p2, n2);
|
||||||
|
|
||||||
|
n2_changed = true;
|
||||||
|
flowed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if(n2.d == CONTENT_AIR)
|
||||||
|
{
|
||||||
|
n2.d = nonsource_c;
|
||||||
|
n2.param2 = liquid_next_level;
|
||||||
|
setNode(p2, n2);
|
||||||
|
|
||||||
|
n2_changed = true;
|
||||||
|
flowed = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(n2_changed)
|
||||||
|
{
|
||||||
|
m_transforming_liquid.push_back(p2);
|
||||||
|
|
||||||
|
v3s16 blockpos = getNodeBlockPos(p2);
|
||||||
|
MapBlock *block = getBlockNoCreateNoEx(blockpos);
|
||||||
|
if(block != NULL)
|
||||||
|
modified_blocks.insert(blockpos, block);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If n2_changed to bottom, don't flow anywhere else
|
||||||
|
if(to_bottom && flowed)
|
||||||
|
break;
|
||||||
|
|
||||||
|
}catch(InvalidPositionException &e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
loopcount++;
|
||||||
|
//if(loopcount >= 100000)
|
||||||
|
if(loopcount >= initial_size * 1)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
dstream<<"Map::transformLiquids(): loopcount="<<loopcount<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
ServerMap
|
ServerMap
|
||||||
*/
|
*/
|
||||||
@ -1327,15 +1657,20 @@ ServerMap::ServerMap(std::string savedir, HMParams hmp, MapParams mp):
|
|||||||
/*
|
/*
|
||||||
NOTE: BEWARE: Too big amount of these will make map generation
|
NOTE: BEWARE: Too big amount of these will make map generation
|
||||||
slow. Especially those that are read by every block emerge.
|
slow. Especially those that are read by every block emerge.
|
||||||
|
|
||||||
|
Fetch times:
|
||||||
|
1000 points: 2-3ms
|
||||||
|
5000 points: 15ms
|
||||||
|
15000 points: 40ms
|
||||||
*/
|
*/
|
||||||
|
|
||||||
for(u32 i=0; i<15000; i++)
|
for(u32 i=0; i<5000; i++)
|
||||||
{
|
{
|
||||||
/*u32 lim = MAP_GENERATION_LIMIT;
|
/*u32 lim = MAP_GENERATION_LIMIT;
|
||||||
if(i < 400)
|
if(i < 400)
|
||||||
lim = 2000;*/
|
lim = 2000;*/
|
||||||
|
|
||||||
u32 lim = 1000 + MAP_GENERATION_LIMIT * i / 15000;
|
u32 lim = 1000 + MAP_GENERATION_LIMIT * i / 5000;
|
||||||
|
|
||||||
v3s16 p(
|
v3s16 p(
|
||||||
-lim + myrand()%(lim*2),
|
-lim + myrand()%(lim*2),
|
||||||
@ -1679,17 +2014,19 @@ MapSector * ServerMap::emergeSector(v2s16 p2d)
|
|||||||
Get local attributes
|
Get local attributes
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//dstream<<"emergeSector(): Reading point attribute lists"<<std::endl;
|
float local_plants_amount = 0.0;
|
||||||
|
{
|
||||||
// Get plant amount from attributes
|
//dstream<<"emergeSector(): Reading point attribute lists"<<std::endl;
|
||||||
PointAttributeList *palist = m_padb.getList("plants_amount");
|
//TimeTaker attrtimer("emergeSector() attribute fetch");
|
||||||
assert(palist);
|
|
||||||
/*float local_plants_amount =
|
// Get plant amount from attributes
|
||||||
palist->getNearAttr(nodepos2d).getFloat();*/
|
PointAttributeList *palist = m_padb.getList("plants_amount");
|
||||||
float local_plants_amount =
|
assert(palist);
|
||||||
palist->getInterpolatedFloat(nodepos2d);
|
/*local_plants_amount =
|
||||||
|
palist->getNearAttr(nodepos2d).getFloat();*/
|
||||||
//dstream<<"emergeSector(): done."<<std::endl;
|
local_plants_amount =
|
||||||
|
palist->getInterpolatedFloat(nodepos2d);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Generate sector heightmap
|
Generate sector heightmap
|
||||||
@ -1988,6 +2325,12 @@ MapBlock * ServerMap::emergeBlock(
|
|||||||
n.d = water_material;
|
n.d = water_material;
|
||||||
n.setLight(LIGHTBANK_DAY,
|
n.setLight(LIGHTBANK_DAY,
|
||||||
diminish_light(LIGHT_SUN, WATER_LEVEL-real_y+1));
|
diminish_light(LIGHT_SUN, WATER_LEVEL-real_y+1));
|
||||||
|
/*
|
||||||
|
Add to transforming liquid queue (in case it'd
|
||||||
|
start flowing)
|
||||||
|
*/
|
||||||
|
v3s16 real_pos = v3s16(x0,y0,z0) + p*MAP_BLOCKSIZE;
|
||||||
|
m_transforming_liquid.push_back(real_pos);
|
||||||
}
|
}
|
||||||
// else air
|
// else air
|
||||||
else
|
else
|
||||||
@ -2692,7 +3035,8 @@ continue_generating:
|
|||||||
core::map<v3s16, bool> light_sources;
|
core::map<v3s16, bool> light_sources;
|
||||||
bool black_air_left = false;
|
bool black_air_left = false;
|
||||||
bool bottom_invalid =
|
bool bottom_invalid =
|
||||||
block->propagateSunlight(light_sources, true, &black_air_left);
|
block->propagateSunlight(light_sources, true,
|
||||||
|
&black_air_left, true);
|
||||||
|
|
||||||
// If sunlight didn't reach everywhere and part of block is
|
// If sunlight didn't reach everywhere and part of block is
|
||||||
// above ground, lighting has to be properly updated
|
// above ground, lighting has to be properly updated
|
||||||
@ -2700,6 +3044,11 @@ continue_generating:
|
|||||||
{
|
{
|
||||||
lighting_invalidated_blocks[block->getPos()] = block;
|
lighting_invalidated_blocks[block->getPos()] = block;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(bottom_invalid)
|
||||||
|
{
|
||||||
|
lighting_invalidated_blocks[block->getPos()] = block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2739,7 +3088,7 @@ continue_generating:
|
|||||||
if(haxmode)
|
if(haxmode)
|
||||||
{
|
{
|
||||||
// Don't calculate lighting at all
|
// Don't calculate lighting at all
|
||||||
lighting_invalidated_blocks.clear();
|
//lighting_invalidated_blocks.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
return block;
|
return block;
|
||||||
@ -3523,11 +3872,12 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||||||
|
|
||||||
// Total distance
|
// Total distance
|
||||||
f32 d = blockpos_relative.getLength();
|
f32 d = blockpos_relative.getLength();
|
||||||
|
|
||||||
/*
|
|
||||||
Draw the faces of the block
|
|
||||||
*/
|
|
||||||
#if 1
|
#if 1
|
||||||
|
/*
|
||||||
|
Update expired mesh
|
||||||
|
*/
|
||||||
|
|
||||||
bool mesh_expired = false;
|
bool mesh_expired = false;
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -3585,6 +3935,9 @@ void ClientMap::renderMap(video::IVideoDriver* driver, s32 pass)
|
|||||||
continue;
|
continue;
|
||||||
}*/
|
}*/
|
||||||
#endif
|
#endif
|
||||||
|
/*
|
||||||
|
Draw the faces of the block
|
||||||
|
*/
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(block->mesh_mutex);
|
JMutexAutoLock lock(block->mesh_mutex);
|
||||||
|
|
||||||
|
@ -236,6 +236,8 @@ public:
|
|||||||
|
|
||||||
// For debug printing
|
// For debug printing
|
||||||
virtual void PrintInfo(std::ostream &out);
|
virtual void PrintInfo(std::ostream &out);
|
||||||
|
|
||||||
|
void transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Variables
|
Variables
|
||||||
|
325
src/mapblock.cpp
325
src/mapblock.cpp
@ -146,6 +146,25 @@ u8 MapBlock::getFaceLight(u32 daynight_ratio, MapNode n, MapNode n2,
|
|||||||
v3s16 face_dir)
|
v3s16 face_dir)
|
||||||
{
|
{
|
||||||
try{
|
try{
|
||||||
|
// DEBUG
|
||||||
|
/*{
|
||||||
|
if(n.d == CONTENT_WATER)
|
||||||
|
{
|
||||||
|
u8 l = n.param2*2;
|
||||||
|
if(l > LIGHT_MAX)
|
||||||
|
l = LIGHT_MAX;
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
if(n2.d == CONTENT_WATER)
|
||||||
|
{
|
||||||
|
u8 l = n2.param2*2;
|
||||||
|
if(l > LIGHT_MAX)
|
||||||
|
l = LIGHT_MAX;
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
u8 light;
|
u8 light;
|
||||||
u8 l1 = n.getLightBlend(daynight_ratio);
|
u8 l1 = n.getLightBlend(daynight_ratio);
|
||||||
u8 l2 = n2.getLightBlend(daynight_ratio);
|
u8 l2 = n2.getLightBlend(daynight_ratio);
|
||||||
@ -645,10 +664,10 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
|||||||
|
|
||||||
mesh_new = new scene::SMesh();
|
mesh_new = new scene::SMesh();
|
||||||
|
|
||||||
|
MeshCollector collector;
|
||||||
|
|
||||||
if(fastfaces_new.size() > 0)
|
if(fastfaces_new.size() > 0)
|
||||||
{
|
{
|
||||||
MeshCollector collector;
|
|
||||||
|
|
||||||
for(u32 i=0; i<fastfaces_new.size(); i++)
|
for(u32 i=0; i<fastfaces_new.size(); i++)
|
||||||
{
|
{
|
||||||
FastFace &f = fastfaces_new[i];
|
FastFace &f = fastfaces_new[i];
|
||||||
@ -685,16 +704,6 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
|||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
collector.fillMesh(mesh_new);
|
|
||||||
|
|
||||||
// Use VBO for mesh (this just would set this for ever buffer)
|
|
||||||
// This will lead to infinite memory usage because or irrlicht.
|
|
||||||
//mesh_new->setHardwareMappingHint(scene::EHM_STATIC);
|
|
||||||
|
|
||||||
/*std::cout<<"MapBlock has "<<fastfaces_new.size()<<" faces "
|
|
||||||
<<"and uses "<<mesh_new->getMeshBufferCount()
|
|
||||||
<<" materials (meshbuffers)"<<std::endl;*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -714,8 +723,6 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
|||||||
|
|
||||||
if(n.d == CONTENT_TORCH)
|
if(n.d == CONTENT_TORCH)
|
||||||
{
|
{
|
||||||
//scene::IMeshBuffer *buf = new scene::SMeshBuffer();
|
|
||||||
scene::SMeshBuffer *buf = new scene::SMeshBuffer();
|
|
||||||
video::SColor c(255,255,255,255);
|
video::SColor c(255,255,255,255);
|
||||||
|
|
||||||
video::S3DVertex vertices[4] =
|
video::S3DVertex vertices[4] =
|
||||||
@ -746,36 +753,266 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
|||||||
vertices[i].Pos += intToFloat(p + getPosRelative());
|
vertices[i].Pos += intToFloat(p + getPosRelative());
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 indices[] = {0,1,2,2,3,0};
|
|
||||||
buf->append(vertices, 4, indices, 6);
|
|
||||||
|
|
||||||
// Set material
|
// Set material
|
||||||
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
|
video::SMaterial material;
|
||||||
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
|
material.setFlag(video::EMF_LIGHTING, false);
|
||||||
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
|
material.setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||||
//buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
buf->getMaterial().MaterialType
|
//material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL;
|
||||||
|
material.MaterialType
|
||||||
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
= video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
|
||||||
if(dir == v3s16(0,-1,0))
|
if(dir == v3s16(0,-1,0))
|
||||||
buf->getMaterial().setTexture(0,
|
material.setTexture(0,
|
||||||
g_irrlicht->getTexture(porting::getDataPath("torch_on_floor.png").c_str()));
|
g_irrlicht->getTexture(porting::getDataPath("torch_on_floor.png").c_str()));
|
||||||
else if(dir == v3s16(0,1,0))
|
else if(dir == v3s16(0,1,0))
|
||||||
buf->getMaterial().setTexture(0,
|
material.setTexture(0,
|
||||||
g_irrlicht->getTexture(porting::getDataPath("torch_on_ceiling.png").c_str()));
|
g_irrlicht->getTexture(porting::getDataPath("torch_on_ceiling.png").c_str()));
|
||||||
// For backwards compatibility
|
// For backwards compatibility
|
||||||
else if(dir == v3s16(0,0,0))
|
else if(dir == v3s16(0,0,0))
|
||||||
buf->getMaterial().setTexture(0,
|
material.setTexture(0,
|
||||||
g_irrlicht->getTexture(porting::getDataPath("torch_on_floor.png").c_str()));
|
g_irrlicht->getTexture(porting::getDataPath("torch_on_floor.png").c_str()));
|
||||||
else
|
else
|
||||||
buf->getMaterial().setTexture(0,
|
material.setTexture(0,
|
||||||
g_irrlicht->getTexture(porting::getDataPath("torch.png").c_str()));
|
g_irrlicht->getTexture(porting::getDataPath("torch.png").c_str()));
|
||||||
|
|
||||||
// Add to mesh
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
mesh_new->addMeshBuffer(buf);
|
// Add to mesh collector
|
||||||
buf->drop();
|
collector.append(material, vertices, 4, indices, 6);
|
||||||
|
}
|
||||||
|
else if(n.d == CONTENT_WATER)
|
||||||
|
{
|
||||||
|
bool top_is_water = false;
|
||||||
|
try{
|
||||||
|
MapNode n = getNodeParent(v3s16(x,y+1,z));
|
||||||
|
if(n.d == CONTENT_WATER || n.d == CONTENT_WATERSOURCE)
|
||||||
|
top_is_water = true;
|
||||||
|
}catch(InvalidPositionException &e){}
|
||||||
|
|
||||||
|
video::SColor c(128,255,255,255);
|
||||||
|
|
||||||
|
// Neighbor water levels (key = relative position)
|
||||||
|
// Includes current node
|
||||||
|
core::map<v3s16, f32> neighbor_levels;
|
||||||
|
core::map<v3s16, u8> neighbor_contents;
|
||||||
|
v3s16 neighbor_dirs[9] = {
|
||||||
|
v3s16(0,0,0),
|
||||||
|
v3s16(0,0,1),
|
||||||
|
v3s16(0,0,-1),
|
||||||
|
v3s16(1,0,0),
|
||||||
|
v3s16(-1,0,0),
|
||||||
|
v3s16(1,0,1),
|
||||||
|
v3s16(-1,0,-1),
|
||||||
|
v3s16(1,0,-1),
|
||||||
|
v3s16(-1,0,1),
|
||||||
|
};
|
||||||
|
for(u32 i=0; i<9; i++)
|
||||||
|
{
|
||||||
|
u8 content = CONTENT_AIR;
|
||||||
|
float level = -0.5 * BS;
|
||||||
|
try{
|
||||||
|
v3s16 p2 = p + neighbor_dirs[i];
|
||||||
|
MapNode n2 = getNodeParent(p2);
|
||||||
|
|
||||||
|
content = n2.d;
|
||||||
|
|
||||||
|
if(n2.d == CONTENT_WATERSOURCE)
|
||||||
|
level = 0.5 * BS;
|
||||||
|
else if(n2.d == CONTENT_WATER)
|
||||||
|
level = (-0.5 + ((float)n2.param2 + 0.5) / 8.0) * BS;
|
||||||
|
}
|
||||||
|
catch(InvalidPositionException &e){}
|
||||||
|
|
||||||
|
neighbor_levels.insert(neighbor_dirs[i], level);
|
||||||
|
neighbor_contents.insert(neighbor_dirs[i], content);
|
||||||
|
}
|
||||||
|
|
||||||
|
//float water_level = (-0.5 + ((float)n.param2 + 0.5) / 8.0) * BS;
|
||||||
|
//float water_level = neighbor_levels[v3s16(0,0,0)];
|
||||||
|
|
||||||
|
// Corner heights (average between four waters)
|
||||||
|
f32 corner_levels[4];
|
||||||
|
|
||||||
|
v3s16 halfdirs[4] = {
|
||||||
|
v3s16(0,0,0),
|
||||||
|
v3s16(1,0,0),
|
||||||
|
v3s16(1,0,1),
|
||||||
|
v3s16(0,0,1),
|
||||||
|
};
|
||||||
|
for(u32 i=0; i<4; i++)
|
||||||
|
{
|
||||||
|
v3s16 cornerdir = halfdirs[i];
|
||||||
|
float cornerlevel = 0;
|
||||||
|
u32 valid_count = 0;
|
||||||
|
for(u32 j=0; j<4; j++)
|
||||||
|
{
|
||||||
|
v3s16 neighbordir = cornerdir - halfdirs[j];
|
||||||
|
u8 content = neighbor_contents[neighbordir];
|
||||||
|
// Special case for source nodes
|
||||||
|
if(content == CONTENT_WATERSOURCE)
|
||||||
|
{
|
||||||
|
cornerlevel = 0.5*BS;
|
||||||
|
valid_count = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if(content == CONTENT_WATER)
|
||||||
|
{
|
||||||
|
cornerlevel += neighbor_levels[neighbordir];
|
||||||
|
valid_count++;
|
||||||
|
}
|
||||||
|
else if(content == CONTENT_AIR)
|
||||||
|
{
|
||||||
|
cornerlevel += -0.5*BS;
|
||||||
|
valid_count++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(valid_count > 0)
|
||||||
|
cornerlevel /= valid_count;
|
||||||
|
corner_levels[i] = cornerlevel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Generate sides
|
||||||
|
*/
|
||||||
|
|
||||||
|
v3s16 side_dirs[4] = {
|
||||||
|
v3s16(1,0,0),
|
||||||
|
v3s16(-1,0,0),
|
||||||
|
v3s16(0,0,1),
|
||||||
|
v3s16(0,0,-1),
|
||||||
|
};
|
||||||
|
s16 side_corners[4][2] = {
|
||||||
|
{1, 2},
|
||||||
|
{3, 0},
|
||||||
|
{2, 3},
|
||||||
|
{0, 1},
|
||||||
|
};
|
||||||
|
for(u32 i=0; i<4; i++)
|
||||||
|
{
|
||||||
|
v3s16 dir = side_dirs[i];
|
||||||
|
|
||||||
|
//float neighbor_level = neighbor_levels[dir];
|
||||||
|
/*if(neighbor_level > -0.5*BS + 0.001)
|
||||||
|
continue;*/
|
||||||
|
/*if(neighbor_level > water_level - 0.1*BS)
|
||||||
|
continue;*/
|
||||||
|
|
||||||
|
u8 neighbor_content = neighbor_contents[dir];
|
||||||
|
|
||||||
|
if(neighbor_content != CONTENT_AIR
|
||||||
|
&& neighbor_content != CONTENT_WATER)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bool neighbor_is_water = (neighbor_content == CONTENT_WATER);
|
||||||
|
|
||||||
|
if(neighbor_is_water == true && top_is_water == false)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
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,0,BS/2, 0,0,0, c, 0,1),
|
||||||
|
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,1),
|
||||||
|
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
|
||||||
|
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),
|
||||||
|
};
|
||||||
|
|
||||||
|
if(top_is_water)
|
||||||
|
{
|
||||||
|
vertices[2].Pos.Y = 0.5*BS;
|
||||||
|
vertices[3].Pos.Y = 0.5*BS;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vertices[2].Pos.Y = corner_levels[side_corners[i][0]];
|
||||||
|
vertices[3].Pos.Y = corner_levels[side_corners[i][1]];
|
||||||
|
}
|
||||||
|
|
||||||
|
if(neighbor_is_water)
|
||||||
|
{
|
||||||
|
vertices[0].Pos.Y = corner_levels[side_corners[i][1]];
|
||||||
|
vertices[1].Pos.Y = corner_levels[side_corners[i][0]];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
vertices[0].Pos.Y = -0.5*BS;
|
||||||
|
vertices[1].Pos.Y = -0.5*BS;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(s32 j=0; j<4; j++)
|
||||||
|
{
|
||||||
|
if(dir == v3s16(0,0,1))
|
||||||
|
vertices[j].Pos.rotateXZBy(0);
|
||||||
|
if(dir == v3s16(0,0,-1))
|
||||||
|
vertices[j].Pos.rotateXZBy(180);
|
||||||
|
if(dir == v3s16(-1,0,0))
|
||||||
|
vertices[j].Pos.rotateXZBy(90);
|
||||||
|
if(dir == v3s16(1,0,-0))
|
||||||
|
vertices[j].Pos.rotateXZBy(-90);
|
||||||
|
|
||||||
|
vertices[j].Pos += intToFloat(p + getPosRelative());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set material
|
||||||
|
video::SMaterial material;
|
||||||
|
material.setFlag(video::EMF_LIGHTING, false);
|
||||||
|
material.setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||||
|
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
|
||||||
|
material.setTexture(0,
|
||||||
|
g_irrlicht->getTexture(porting::getDataPath("water.png").c_str()));
|
||||||
|
|
||||||
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
|
// Add to mesh collector
|
||||||
|
collector.append(material, vertices, 4, indices, 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Generate top side, if appropriate
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(top_is_water == false)
|
||||||
|
{
|
||||||
|
video::S3DVertex vertices[4] =
|
||||||
|
{
|
||||||
|
video::S3DVertex(-BS/2,0,-BS/2, 0,0,0, c, 0,1),
|
||||||
|
video::S3DVertex(BS/2,0,-BS/2, 0,0,0, c, 1,1),
|
||||||
|
video::S3DVertex(BS/2,0,BS/2, 0,0,0, c, 1,0),
|
||||||
|
video::S3DVertex(-BS/2,0,BS/2, 0,0,0, c, 0,0),
|
||||||
|
};
|
||||||
|
|
||||||
|
for(s32 i=0; i<4; i++)
|
||||||
|
{
|
||||||
|
//vertices[i].Pos.Y += water_level;
|
||||||
|
//vertices[i].Pos.Y += neighbor_levels[v3s16(0,0,0)];
|
||||||
|
vertices[i].Pos.Y += corner_levels[i];
|
||||||
|
vertices[i].Pos += intToFloat(p + getPosRelative());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set material
|
||||||
|
video::SMaterial material;
|
||||||
|
material.setFlag(video::EMF_LIGHTING, false);
|
||||||
|
material.setFlag(video::EMF_BACK_FACE_CULLING, false);
|
||||||
|
material.setFlag(video::EMF_BILINEAR_FILTER, false);
|
||||||
|
material.MaterialType = video::EMT_TRANSPARENT_VERTEX_ALPHA;
|
||||||
|
material.setTexture(0,
|
||||||
|
g_irrlicht->getTexture(porting::getDataPath("water.png").c_str()));
|
||||||
|
|
||||||
|
u16 indices[] = {0,1,2,2,3,0};
|
||||||
|
// Add to mesh collector
|
||||||
|
collector.append(material, vertices, 4, indices, 6);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add stuff from collector to mesh
|
||||||
|
*/
|
||||||
|
|
||||||
|
collector.fillMesh(mesh_new);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Do some stuff to the mesh
|
Do some stuff to the mesh
|
||||||
*/
|
*/
|
||||||
@ -792,6 +1029,14 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
|||||||
mesh_new = NULL;
|
mesh_new = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Use VBO for mesh (this just would set this for ever buffer)
|
||||||
|
// This will lead to infinite memory usage because or irrlicht.
|
||||||
|
//mesh_new->setHardwareMappingHint(scene::EHM_STATIC);
|
||||||
|
|
||||||
|
/*std::cout<<"MapBlock has "<<fastfaces_new.size()<<" faces "
|
||||||
|
<<"and uses "<<mesh_new->getMeshBufferCount()
|
||||||
|
<<" materials (meshbuffers)"<<std::endl;*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Replace the mesh
|
Replace the mesh
|
||||||
*/
|
*/
|
||||||
@ -872,7 +1117,8 @@ void MapBlock::updateMesh(u32 daynight_ratio)
|
|||||||
air is left in block.
|
air is left in block.
|
||||||
*/
|
*/
|
||||||
bool MapBlock::propagateSunlight(core::map<v3s16, bool> & light_sources,
|
bool MapBlock::propagateSunlight(core::map<v3s16, bool> & light_sources,
|
||||||
bool remove_light, bool *black_air_left)
|
bool remove_light, bool *black_air_left,
|
||||||
|
bool grow_grass)
|
||||||
{
|
{
|
||||||
// Whether the sunlight at the top of the bottom block is valid
|
// Whether the sunlight at the top of the bottom block is valid
|
||||||
bool block_below_is_valid = true;
|
bool block_below_is_valid = true;
|
||||||
@ -962,10 +1208,23 @@ bool MapBlock::propagateSunlight(core::map<v3s16, bool> & light_sources,
|
|||||||
}
|
}
|
||||||
else if(n.light_propagates() == false)
|
else if(n.light_propagates() == false)
|
||||||
{
|
{
|
||||||
// Turn mud into grass
|
if(grow_grass)
|
||||||
if(n.d == CONTENT_MUD && current_light == LIGHT_SUN)
|
|
||||||
{
|
{
|
||||||
n.d = CONTENT_GRASS;
|
bool upper_is_air = false;
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if(getNodeParent(pos+v3s16(0,1,0)).d == CONTENT_AIR)
|
||||||
|
upper_is_air = true;
|
||||||
|
}
|
||||||
|
catch(InvalidPositionException &e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
// Turn mud into grass
|
||||||
|
if(upper_is_air && n.d == CONTENT_MUD
|
||||||
|
&& current_light == LIGHT_SUN)
|
||||||
|
{
|
||||||
|
n.d = CONTENT_GRASS;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// A solid object is on the way.
|
// A solid object is on the way.
|
||||||
|
@ -315,7 +315,8 @@ public:
|
|||||||
|
|
||||||
// See comments in mapblock.cpp
|
// See comments in mapblock.cpp
|
||||||
bool propagateSunlight(core::map<v3s16, bool> & light_sources,
|
bool propagateSunlight(core::map<v3s16, bool> & light_sources,
|
||||||
bool remove_light=false, bool *black_air_left=NULL);
|
bool remove_light=false, bool *black_air_left=NULL,
|
||||||
|
bool grow_grass=false);
|
||||||
|
|
||||||
// Copies data to VoxelManipulator to getPosRelative()
|
// Copies data to VoxelManipulator to getPosRelative()
|
||||||
void copyTo(VoxelManipulator &dst);
|
void copyTo(VoxelManipulator &dst);
|
||||||
|
@ -35,7 +35,8 @@ u16 g_content_tiles[USEFUL_CONTENT_COUNT][6] =
|
|||||||
{
|
{
|
||||||
{TILE_STONE,TILE_STONE,TILE_STONE,TILE_STONE,TILE_STONE,TILE_STONE},
|
{TILE_STONE,TILE_STONE,TILE_STONE,TILE_STONE,TILE_STONE,TILE_STONE},
|
||||||
{TILE_GRASS,TILE_MUD,TILE_MUD_WITH_GRASS,TILE_MUD_WITH_GRASS,TILE_MUD_WITH_GRASS,TILE_MUD_WITH_GRASS},
|
{TILE_GRASS,TILE_MUD,TILE_MUD_WITH_GRASS,TILE_MUD_WITH_GRASS,TILE_MUD_WITH_GRASS,TILE_MUD_WITH_GRASS},
|
||||||
{TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER},
|
//{TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER},
|
||||||
|
{TILE_NONE,TILE_NONE,TILE_NONE,TILE_NONE,TILE_NONE,TILE_NONE},
|
||||||
{TILE_NONE,TILE_NONE,TILE_NONE,TILE_NONE,TILE_NONE,TILE_NONE},
|
{TILE_NONE,TILE_NONE,TILE_NONE,TILE_NONE,TILE_NONE,TILE_NONE},
|
||||||
{TILE_TREE_TOP,TILE_TREE_TOP,TILE_TREE,TILE_TREE,TILE_TREE,TILE_TREE},
|
{TILE_TREE_TOP,TILE_TREE_TOP,TILE_TREE,TILE_TREE,TILE_TREE,TILE_TREE},
|
||||||
{TILE_LEAVES,TILE_LEAVES,TILE_LEAVES,TILE_LEAVES,TILE_LEAVES,TILE_LEAVES},
|
{TILE_LEAVES,TILE_LEAVES,TILE_LEAVES,TILE_LEAVES,TILE_LEAVES,TILE_LEAVES},
|
||||||
|
@ -108,7 +108,7 @@ inline bool sunlight_propagates_content(u8 m)
|
|||||||
inline u8 content_solidness(u8 m)
|
inline u8 content_solidness(u8 m)
|
||||||
{
|
{
|
||||||
// As of now, every pseudo node like torches are added to this
|
// As of now, every pseudo node like torches are added to this
|
||||||
if(m == CONTENT_AIR || m == CONTENT_TORCH)
|
if(m == CONTENT_AIR || m == CONTENT_TORCH || m == CONTENT_WATER)
|
||||||
return 0;
|
return 0;
|
||||||
if(m == CONTENT_WATER || m == CONTENT_WATERSOURCE)
|
if(m == CONTENT_WATER || m == CONTENT_WATERSOURCE)
|
||||||
return 1;
|
return 1;
|
||||||
@ -121,12 +121,30 @@ inline bool content_walkable(u8 m)
|
|||||||
return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE && m != CONTENT_TORCH);
|
return (m != CONTENT_AIR && m != CONTENT_WATER && m != CONTENT_WATERSOURCE && m != CONTENT_TORCH);
|
||||||
}
|
}
|
||||||
|
|
||||||
// A liquid resists fast movement
|
|
||||||
inline bool content_liquid(u8 m)
|
inline bool content_liquid(u8 m)
|
||||||
{
|
{
|
||||||
return (m == CONTENT_WATER || m == CONTENT_WATERSOURCE);
|
return (m == CONTENT_WATER || m == CONTENT_WATERSOURCE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool content_flowing_liquid(u8 m)
|
||||||
|
{
|
||||||
|
return (m == CONTENT_WATER);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool content_liquid_source(u8 m)
|
||||||
|
{
|
||||||
|
return (m == CONTENT_WATERSOURCE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// CONTENT_WATER || CONTENT_WATERSOURCE -> CONTENT_WATER
|
||||||
|
// CONTENT_LAVA || CONTENT_LAVASOURCE -> CONTENT_LAVA
|
||||||
|
inline u8 make_liquid_flowing(u8 m)
|
||||||
|
{
|
||||||
|
if(m == CONTENT_WATER || m == CONTENT_WATERSOURCE)
|
||||||
|
return CONTENT_WATER;
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
|
||||||
// Pointable contents can be pointed to in the map
|
// Pointable contents can be pointed to in the map
|
||||||
inline bool content_pointable(u8 m)
|
inline bool content_pointable(u8 m)
|
||||||
{
|
{
|
||||||
@ -349,6 +367,8 @@ struct MapNode
|
|||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
|
u8 param2;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Pressure for liquids
|
Pressure for liquids
|
||||||
*/
|
*/
|
||||||
|
@ -971,7 +971,8 @@ Server::Server(
|
|||||||
m_time_of_day_send_timer(0),
|
m_time_of_day_send_timer(0),
|
||||||
m_uptime(0)
|
m_uptime(0)
|
||||||
{
|
{
|
||||||
m_flowwater_timer = 0.0;
|
//m_flowwater_timer = 0.0;
|
||||||
|
m_liquid_transform_timer = 0.0;
|
||||||
m_print_info_timer = 0.0;
|
m_print_info_timer = 0.0;
|
||||||
m_objectdata_timer = 0.0;
|
m_objectdata_timer = 0.0;
|
||||||
m_emergethread_trigger_timer = 0.0;
|
m_emergethread_trigger_timer = 0.0;
|
||||||
@ -1140,9 +1141,54 @@ void Server::AsyncRunStep()
|
|||||||
/*
|
/*
|
||||||
Do background stuff
|
Do background stuff
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Transform liquids
|
||||||
|
*/
|
||||||
|
m_liquid_transform_timer += dtime;
|
||||||
|
if(m_liquid_transform_timer >= 1.00)
|
||||||
{
|
{
|
||||||
//m_env.getMap().
|
m_liquid_transform_timer -= 1.00;
|
||||||
|
|
||||||
|
JMutexAutoLock lock(m_env_mutex);
|
||||||
|
|
||||||
|
core::map<v3s16, MapBlock*> modified_blocks;
|
||||||
|
m_env.getMap().transformLiquids(modified_blocks);
|
||||||
|
#if 0
|
||||||
|
/*
|
||||||
|
Update lighting
|
||||||
|
*/
|
||||||
|
core::map<v3s16, MapBlock*> lighting_modified_blocks;
|
||||||
|
ServerMap &map = ((ServerMap&)m_env.getMap());
|
||||||
|
map.updateLighting(modified_blocks, lighting_modified_blocks);
|
||||||
|
|
||||||
|
// Add blocks modified by lighting to modified_blocks
|
||||||
|
for(core::map<v3s16, MapBlock*>::Iterator
|
||||||
|
i = lighting_modified_blocks.getIterator();
|
||||||
|
i.atEnd() == false; i++)
|
||||||
|
{
|
||||||
|
MapBlock *block = i.getNode()->getValue();
|
||||||
|
modified_blocks.insert(block->getPos(), block);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
Set the modified blocks unsent for all the clients
|
||||||
|
*/
|
||||||
|
|
||||||
|
JMutexAutoLock lock2(m_con_mutex);
|
||||||
|
|
||||||
|
for(core::map<u16, RemoteClient*>::Iterator
|
||||||
|
i = m_clients.getIterator();
|
||||||
|
i.atEnd() == false; i++)
|
||||||
|
{
|
||||||
|
RemoteClient *client = i.getNode()->getValue();
|
||||||
|
|
||||||
|
if(modified_blocks.size() > 0)
|
||||||
|
{
|
||||||
|
// Remove block from sent history
|
||||||
|
client->SetBlocksNotSent(modified_blocks);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -457,7 +457,8 @@ private:
|
|||||||
void handlePeerChange(PeerChange &c);
|
void handlePeerChange(PeerChange &c);
|
||||||
void handlePeerChanges();
|
void handlePeerChanges();
|
||||||
|
|
||||||
float m_flowwater_timer;
|
//float m_flowwater_timer;
|
||||||
|
float m_liquid_transform_timer;
|
||||||
float m_print_info_timer;
|
float m_print_info_timer;
|
||||||
float m_objectdata_timer;
|
float m_objectdata_timer;
|
||||||
float m_emergethread_trigger_timer;
|
float m_emergethread_trigger_timer;
|
||||||
|
@ -1608,7 +1608,7 @@ public:
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void pop_front()
|
Value pop_front()
|
||||||
{
|
{
|
||||||
typename core::list<Value>::Iterator i = m_list.begin();
|
typename core::list<Value>::Iterator i = m_list.begin();
|
||||||
Value value = *i;
|
Value value = *i;
|
||||||
@ -1617,6 +1617,12 @@ public:
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 size()
|
||||||
|
{
|
||||||
|
assert(m_list.size() == m_map.size());
|
||||||
|
return m_list.size();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
core::map<Value, u8> m_map;
|
core::map<Value, u8> m_map;
|
||||||
core::list<Value> m_list;
|
core::list<Value> m_list;
|
||||||
|
Loading…
Reference in New Issue
Block a user