Merge remote-tracking branch 'origin/upstream'

This commit is contained in:
Nils Dagsson Moskopp 2011-07-30 18:53:54 +02:00
commit 4ef9c7675a
35 changed files with 2817 additions and 2103 deletions

BIN
data/junglegrass.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 672 B

BIN
data/jungletree.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 502 B

BIN
data/jungletree_top.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 507 B

113
po/en/minetest.pot Normal file

@ -0,0 +1,113 @@
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the PACKAGE package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2011-07-24 11:32+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: 8bit\n"
#: src/guiMainMenu.cpp:180
msgid "Name/Password"
msgstr ""
#: src/guiMainMenu.cpp:203
msgid "Address/Port"
msgstr ""
#: src/guiMainMenu.cpp:223
msgid "Leave address blank to start a local server."
msgstr ""
#: src/guiMainMenu.cpp:230
msgid "Fancy trees"
msgstr ""
#: src/guiMainMenu.cpp:236
msgid "Smooth Lighting"
msgstr ""
#: src/guiMainMenu.cpp:244
msgid "Start Game / Connect"
msgstr ""
#: src/guiMainMenu.cpp:253
msgid "Change keys"
msgstr ""
#: src/guiMainMenu.cpp:276
msgid "Creative Mode"
msgstr ""
#: src/guiMainMenu.cpp:282
msgid "Enable Damage"
msgstr ""
#: src/guiMainMenu.cpp:290
msgid "Delete map"
msgstr ""
#: src/guiMessageMenu.cpp:93 src/guiTextInputMenu.cpp:111
msgid "Proceed"
msgstr ""
#: src/guiPasswordChange.cpp:102
msgid "Old Password"
msgstr ""
#: src/guiPasswordChange.cpp:117
msgid "New Password"
msgstr ""
#: src/guiPasswordChange.cpp:131
msgid "Confirm Password"
msgstr ""
#: src/guiPasswordChange.cpp:146
msgid "Change"
msgstr ""
#: src/guiPasswordChange.cpp:155
msgid "Passwords do not match!"
msgstr ""
#: src/guiPauseMenu.cpp:110
msgid "Continue"
msgstr ""
#: src/guiPauseMenu.cpp:117
msgid "Change Password"
msgstr ""
#: src/guiPauseMenu.cpp:124
msgid "Disconnect"
msgstr ""
#: src/guiPauseMenu.cpp:131
msgid "Exit to OS"
msgstr ""
#: src/guiPauseMenu.cpp:138
msgid ""
"Keys:\n"
"- WASD: Walk\n"
"- Mouse left: dig blocks\n"
"- Mouse right: place blocks\n"
"- Mouse wheel: select item\n"
"- 0...9: select item\n"
"- Shift: sneak\n"
"- R: Toggle viewing all loaded chunks\n"
"- I: Inventory menu\n"
"- ESC: This menu\n"
"- T: Chat\n"
msgstr ""

@ -78,7 +78,8 @@ collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d,
{ {
try{ try{
// Object collides into walkable nodes // Object collides into walkable nodes
if(content_walkable(map->getNode(v3s16(x,y,z)).d) == false) MapNode n = map->getNode(v3s16(x,y,z));
if(content_features(n).walkable == false)
continue; continue;
} }
catch(InvalidPositionException &e) catch(InvalidPositionException &e)

@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "inventory.h" #include "inventory.h"
#include "content_mapnode.h" #include "content_mapnode.h"
#include "player.h" #include "player.h"
#include "mapnode.h" // For content_t
/* /*
items: actually *items[9] items: actually *items[9]
@ -446,7 +447,7 @@ void craft_set_creative_inventory(Player *player)
*/ */
// CONTENT_IGNORE-terminated list // CONTENT_IGNORE-terminated list
u8 material_items[] = { content_t material_items[] = {
CONTENT_TORCH, CONTENT_TORCH,
CONTENT_COBBLE, CONTENT_COBBLE,
CONTENT_MUD, CONTENT_MUD,
@ -472,7 +473,7 @@ void craft_set_creative_inventory(Player *player)
CONTENT_IGNORE CONTENT_IGNORE
}; };
u8 *mip = material_items; content_t *mip = material_items;
for(u16 i=0; i<PLAYER_INVENTORY_SIZE; i++) for(u16 i=0; i<PLAYER_INVENTORY_SIZE; i++)
{ {
if(*mip == CONTENT_IGNORE) if(*mip == CONTENT_IGNORE)

@ -23,7 +23,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
//#include "serverobject.h" //#include "serverobject.h"
#include "content_sao.h" #include "content_sao.h"
bool item_material_is_cookable(u8 content) bool item_material_is_cookable(content_t content)
{ {
if(content == CONTENT_TREE) if(content == CONTENT_TREE)
return true; return true;
@ -34,7 +34,7 @@ bool item_material_is_cookable(u8 content)
return false; return false;
} }
InventoryItem* item_material_create_cook_result(u8 content) InventoryItem* item_material_create_cook_result(content_t content)
{ {
if(content == CONTENT_TREE) if(content == CONTENT_TREE)
return new CraftItem("lump_of_coal", 1); return new CraftItem("lump_of_coal", 1);

@ -22,13 +22,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common_irrlicht.h" // For u8, s16 #include "common_irrlicht.h" // For u8, s16
#include <string> #include <string>
#include "mapnode.h" // For content_t
class InventoryItem; class InventoryItem;
class ServerActiveObject; class ServerActiveObject;
class ServerEnvironment; class ServerEnvironment;
bool item_material_is_cookable(u8 content); bool item_material_is_cookable(content_t content);
InventoryItem* item_material_create_cook_result(u8 content); InventoryItem* item_material_create_cook_result(content_t content);
std::string item_craft_get_image_name(const std::string &subname); std::string item_craft_get_image_name(const std::string &subname);
ServerActiveObject* item_craft_create_object(const std::string &subname, ServerActiveObject* item_craft_create_object(const std::string &subname,

@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "content_mapnode.h" #include "content_mapnode.h"
#include "main.h" // For g_settings and g_texturesource #include "main.h" // For g_settings and g_texturesource
#include "mineral.h" #include "mineral.h"
#include "mapblock_mesh.h" // For MapBlock_LightColor()
#ifndef SERVER #ifndef SERVER
// Create a cuboid. // Create a cuboid.
@ -198,6 +199,17 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
AtlasPointer pa_papyrus = g_texturesource->getTexture( AtlasPointer pa_papyrus = g_texturesource->getTexture(
g_texturesource->getTextureId("papyrus.png")); g_texturesource->getTextureId("papyrus.png"));
material_papyrus.setTexture(0, pa_papyrus.atlas); material_papyrus.setTexture(0, pa_papyrus.atlas);
// junglegrass material
video::SMaterial material_junglegrass;
material_junglegrass.setFlag(video::EMF_LIGHTING, false);
material_junglegrass.setFlag(video::EMF_BILINEAR_FILTER, false);
material_junglegrass.setFlag(video::EMF_FOG_ENABLE, true);
material_junglegrass.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
AtlasPointer pa_junglegrass = g_texturesource->getTexture(
g_texturesource->getTextureId("junglegrass.png"));
material_junglegrass.setTexture(0, pa_junglegrass.atlas);
for(s16 z=0; z<MAP_BLOCKSIZE; z++) for(s16 z=0; z<MAP_BLOCKSIZE; z++)
for(s16 y=0; y<MAP_BLOCKSIZE; y++) for(s16 y=0; y<MAP_BLOCKSIZE; y++)
for(s16 x=0; x<MAP_BLOCKSIZE; x++) for(s16 x=0; x<MAP_BLOCKSIZE; x++)
@ -209,7 +221,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
/* /*
Add torches to mesh Add torches to mesh
*/ */
if(n.d == CONTENT_TORCH) if(n.getContent() == CONTENT_TORCH)
{ {
video::SColor c(255,255,255,255); video::SColor c(255,255,255,255);
@ -222,7 +234,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0), video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0),
}; };
v3s16 dir = unpackDir(n.dir); v3s16 dir = unpackDir(n.param2);
for(s32 i=0; i<4; i++) for(s32 i=0; i<4; i++)
{ {
@ -272,10 +284,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
/* /*
Signs on walls Signs on walls
*/ */
else if(n.d == CONTENT_SIGN_WALL) else if(n.getContent() == CONTENT_SIGN_WALL)
{ {
u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio)); u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
video::SColor c(255,l,l,l); video::SColor c = MapBlock_LightColor(255, l);
float d = (float)BS/16; float d = (float)BS/16;
// Wall at X+ of node // Wall at X+ of node
@ -287,7 +299,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
video::S3DVertex(BS/2-d,BS/2,-BS/2, 0,0,0, c, 0,0), video::S3DVertex(BS/2-d,BS/2,-BS/2, 0,0,0, c, 0,0),
}; };
v3s16 dir = unpackDir(n.dir); v3s16 dir = unpackDir(n.param2);
for(s32 i=0; i<4; i++) for(s32 i=0; i<4; i++)
{ {
@ -327,26 +339,26 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
/* /*
Add flowing water to mesh Add flowing water to mesh
*/ */
else if(n.d == CONTENT_WATER) else if(n.getContent() == CONTENT_WATER)
{ {
bool top_is_water = false; bool top_is_water = false;
MapNode ntop = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z)); MapNode ntop = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z));
if(ntop.d == CONTENT_WATER || ntop.d == CONTENT_WATERSOURCE) if(ntop.getContent() == CONTENT_WATER || ntop.getContent() == CONTENT_WATERSOURCE)
top_is_water = true; top_is_water = true;
u8 l = 0; u8 l = 0;
// Use the light of the node on top if possible // Use the light of the node on top if possible
if(content_features(ntop.d).param_type == CPT_LIGHT) if(content_features(ntop).param_type == CPT_LIGHT)
l = decode_light(ntop.getLightBlend(data->m_daynight_ratio)); l = decode_light(ntop.getLightBlend(data->m_daynight_ratio));
// Otherwise use the light of this node (the water) // Otherwise use the light of this node (the water)
else else
l = decode_light(n.getLightBlend(data->m_daynight_ratio)); l = decode_light(n.getLightBlend(data->m_daynight_ratio));
video::SColor c(WATER_ALPHA,l,l,l); video::SColor c = MapBlock_LightColor(WATER_ALPHA, l);
// Neighbor water levels (key = relative position) // Neighbor water levels (key = relative position)
// Includes current node // Includes current node
core::map<v3s16, f32> neighbor_levels; core::map<v3s16, f32> neighbor_levels;
core::map<v3s16, u8> neighbor_contents; core::map<v3s16, content_t> neighbor_contents;
core::map<v3s16, u8> neighbor_flags; core::map<v3s16, u8> neighbor_flags;
const u8 neighborflag_top_is_water = 0x01; const u8 neighborflag_top_is_water = 0x01;
v3s16 neighbor_dirs[9] = { v3s16 neighbor_dirs[9] = {
@ -368,14 +380,14 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
// Check neighbor // Check neighbor
v3s16 p2 = p + neighbor_dirs[i]; v3s16 p2 = p + neighbor_dirs[i];
MapNode n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2); MapNode n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2);
if(n2.d != CONTENT_IGNORE) if(n2.getContent() != CONTENT_IGNORE)
{ {
content = n2.d; content = n2.getContent();
if(n2.d == CONTENT_WATERSOURCE) if(n2.getContent() == CONTENT_WATERSOURCE)
level = (-0.5+node_water_level) * BS; level = (-0.5+node_water_level) * BS;
else if(n2.d == CONTENT_WATER) else if(n2.getContent() == CONTENT_WATER)
level = (-0.5 + ((float)(n2.param2 & LIQUID_LEVEL_MASK) + 0.5) / 8.0 level = (-0.5 + ((float)n2.param2 + 0.5) / 8.0
* node_water_level) * BS; * node_water_level) * BS;
// Check node above neighbor. // Check node above neighbor.
@ -383,7 +395,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
// doesn't exist // doesn't exist
p2.Y += 1; p2.Y += 1;
n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2); n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2);
if(n2.d == CONTENT_WATERSOURCE || n2.d == CONTENT_WATER) if(n2.getContent() == CONTENT_WATERSOURCE || n2.getContent() == CONTENT_WATER)
flags |= neighborflag_top_is_water; flags |= neighborflag_top_is_water;
} }
@ -591,14 +603,14 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
/* /*
Add water sources to mesh if using new style Add water sources to mesh if using new style
*/ */
else if(n.d == CONTENT_WATERSOURCE && new_style_water) else if(n.getContent() == CONTENT_WATERSOURCE && new_style_water)
{ {
//bool top_is_water = false; //bool top_is_water = false;
bool top_is_air = false; bool top_is_air = false;
MapNode n = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z)); MapNode n = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z));
/*if(n.d == CONTENT_WATER || n.d == CONTENT_WATERSOURCE) /*if(n.getContent() == CONTENT_WATER || n.getContent() == CONTENT_WATERSOURCE)
top_is_water = true;*/ top_is_water = true;*/
if(n.d == CONTENT_AIR) if(n.getContent() == CONTENT_AIR)
top_is_air = true; top_is_air = true;
/*if(top_is_water == true) /*if(top_is_water == true)
@ -607,7 +619,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
continue; continue;
u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio)); u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
video::SColor c(WATER_ALPHA,l,l,l); video::SColor c = MapBlock_LightColor(WATER_ALPHA, l);
video::S3DVertex vertices[4] = video::S3DVertex vertices[4] =
{ {
@ -638,11 +650,11 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
/* /*
Add leaves if using new style Add leaves if using new style
*/ */
else if(n.d == CONTENT_LEAVES && new_style_leaves) else if(n.getContent() == CONTENT_LEAVES && new_style_leaves)
{ {
/*u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));*/ /*u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));*/
u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio)));
video::SColor c(255,l,l,l); video::SColor c = MapBlock_LightColor(255, l);
for(u32 j=0; j<6; j++) for(u32 j=0; j<6; j++)
{ {
@ -706,10 +718,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
/* /*
Add glass Add glass
*/ */
else if(n.d == CONTENT_GLASS) else if(n.getContent() == CONTENT_GLASS)
{ {
u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio)));
video::SColor c(255,l,l,l); video::SColor c = MapBlock_LightColor(255, l);
for(u32 j=0; j<6; j++) for(u32 j=0; j<6; j++)
{ {
@ -769,10 +781,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
/* /*
Add fence Add fence
*/ */
else if(n.d == CONTENT_FENCE) else if(n.getContent() == CONTENT_FENCE)
{ {
u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio)));
video::SColor c(255,l,l,l); video::SColor c = MapBlock_LightColor(255, l);
const f32 post_rad=(f32)BS/10; const f32 post_rad=(f32)BS/10;
const f32 bar_rad=(f32)BS/20; const f32 bar_rad=(f32)BS/20;
@ -795,7 +807,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
v3s16 p2 = p; v3s16 p2 = p;
p2.X++; p2.X++;
MapNode n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2); MapNode n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2);
if(n2.d == CONTENT_FENCE) if(n2.getContent() == CONTENT_FENCE)
{ {
pos = intToFloat(p+blockpos_nodes, BS); pos = intToFloat(p+blockpos_nodes, BS);
pos.X += BS/2; pos.X += BS/2;
@ -821,7 +833,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
p2 = p; p2 = p;
p2.Z++; p2.Z++;
n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2); n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2);
if(n2.d == CONTENT_FENCE) if(n2.getContent() == CONTENT_FENCE)
{ {
pos = intToFloat(p+blockpos_nodes, BS); pos = intToFloat(p+blockpos_nodes, BS);
pos.Z += BS/2; pos.Z += BS/2;
@ -848,7 +860,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
/* /*
Add stones with minerals if stone is invisible Add stones with minerals if stone is invisible
*/ */
else if(n.d == CONTENT_STONE && invisible_stone && n.getMineral() != MINERAL_NONE) else if(n.getContent() == CONTENT_STONE && invisible_stone && n.getMineral() != MINERAL_NONE)
{ {
for(u32 j=0; j<6; j++) for(u32 j=0; j<6; j++)
{ {
@ -856,17 +868,18 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
v3s16 dir = g_6dirs[j]; v3s16 dir = g_6dirs[j];
/*u8 l = 0; /*u8 l = 0;
MapNode n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + dir); MapNode n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + dir);
if(content_features(n2.d).param_type == CPT_LIGHT) if(content_features(n2).param_type == CPT_LIGHT)
l = decode_light(n2.getLightBlend(data->m_daynight_ratio)); l = decode_light(n2.getLightBlend(data->m_daynight_ratio));
else else
l = 255;*/ l = 255;*/
u8 l = 255; u8 l = 255;
video::SColor c(255,l,l,l); video::SColor c = MapBlock_LightColor(255, l);
// Get the right texture // Get the right texture
TileSpec ts = n.getTile(dir); TileSpec ts = n.getTile(dir);
AtlasPointer ap = ts.texture; AtlasPointer ap = ts.texture;
material_general.setTexture(0, ap.atlas); material_general.setTexture(0, ap.atlas);
video::S3DVertex vertices[4] = 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, 0,1),
@ -916,10 +929,10 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
} }
} }
#endif #endif
else if(n.d == CONTENT_PAPYRUS) else if(n.getContent() == CONTENT_PAPYRUS)
{ {
u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio)));
video::SColor c(255,l,l,l); video::SColor c = MapBlock_LightColor(255, l);
for(u32 j=0; j<4; j++) for(u32 j=0; j<4; j++)
{ {
@ -966,10 +979,61 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
collector.append(material_papyrus, vertices, 4, indices, 6); collector.append(material_papyrus, vertices, 4, indices, 6);
} }
} }
else if(n.d == CONTENT_RAIL) else if(n.getContent() == CONTENT_JUNGLEGRASS)
{
u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio)));
video::SColor c = MapBlock_LightColor(255, l);
for(u32 j=0; j<4; j++)
{
video::S3DVertex vertices[4] =
{
video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c,
pa_papyrus.x0(), pa_papyrus.y1()),
video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c,
pa_papyrus.x1(), pa_papyrus.y1()),
video::S3DVertex(BS/2,BS/1,0, 0,0,0, c,
pa_papyrus.x1(), pa_papyrus.y0()),
video::S3DVertex(-BS/2,BS/1,0, 0,0,0, c,
pa_papyrus.x0(), pa_papyrus.y0()),
};
if(j == 0)
{
for(u16 i=0; i<4; i++)
vertices[i].Pos.rotateXZBy(45);
}
else if(j == 1)
{
for(u16 i=0; i<4; i++)
vertices[i].Pos.rotateXZBy(-45);
}
else if(j == 2)
{
for(u16 i=0; i<4; i++)
vertices[i].Pos.rotateXZBy(135);
}
else if(j == 3)
{
for(u16 i=0; i<4; i++)
vertices[i].Pos.rotateXZBy(-135);
}
for(u16 i=0; i<4; i++)
{
vertices[i].Pos *= 1.3;
vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
}
u16 indices[] = {0,1,2,2,3,0};
// Add to mesh collector
collector.append(material_junglegrass, vertices, 4, indices, 6);
}
}
else if(n.getContent() == CONTENT_RAIL)
{ {
u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio)); u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
video::SColor c(255,l,l,l); video::SColor c = MapBlock_LightColor(255, l);
bool is_rail_x [] = { false, false }; /* x-1, x+1 */ bool is_rail_x [] = { false, false }; /* x-1, x+1 */
bool is_rail_z [] = { false, false }; /* z-1, z+1 */ bool is_rail_z [] = { false, false }; /* z-1, z+1 */
@ -979,13 +1043,13 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
MapNode n_minus_z = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y,z-1)); MapNode n_minus_z = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y,z-1));
MapNode n_plus_z = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y,z+1)); MapNode n_plus_z = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y,z+1));
if(n_minus_x.d == CONTENT_RAIL) if(n_minus_x.getContent() == CONTENT_RAIL)
is_rail_x[0] = true; is_rail_x[0] = true;
if(n_plus_x.d == CONTENT_RAIL) if(n_plus_x.getContent() == CONTENT_RAIL)
is_rail_x[1] = true; is_rail_x[1] = true;
if(n_minus_z.d == CONTENT_RAIL) if(n_minus_z.getContent() == CONTENT_RAIL)
is_rail_z[0] = true; is_rail_z[0] = true;
if(n_plus_z.d == CONTENT_RAIL) if(n_plus_z.getContent() == CONTENT_RAIL)
is_rail_z[1] = true; is_rail_z[1] = true;
float d = (float)BS/16; float d = (float)BS/16;

@ -31,6 +31,65 @@ void setStoneLikeDiggingProperties(DiggingPropertiesList &list, float toughness)
void setDirtLikeDiggingProperties(DiggingPropertiesList &list, float toughness); void setDirtLikeDiggingProperties(DiggingPropertiesList &list, float toughness);
void setWoodLikeDiggingProperties(DiggingPropertiesList &list, float toughness); void setWoodLikeDiggingProperties(DiggingPropertiesList &list, float toughness);
content_t trans_table_19[][2] = {
{CONTENT_GRASS, 1},
{CONTENT_TREE, 4},
{CONTENT_LEAVES, 5},
{CONTENT_GRASS_FOOTSTEPS, 6},
{CONTENT_MESE, 7},
{CONTENT_MUD, 8},
{CONTENT_CLOUD, 10},
{CONTENT_COALSTONE, 11},
{CONTENT_WOOD, 12},
{CONTENT_SAND, 13},
{CONTENT_COBBLE, 18},
{CONTENT_STEEL, 19},
{CONTENT_GLASS, 20},
{CONTENT_MOSSYCOBBLE, 22},
{CONTENT_GRAVEL, 23},
{CONTENT_SANDSTONE, 24},
{CONTENT_CACTUS, 25},
{CONTENT_BRICK, 26},
{CONTENT_CLAY, 27},
{CONTENT_PAPYRUS, 28},
{CONTENT_BOOKSHELF, 29},
};
MapNode mapnode_translate_from_internal(MapNode n_from, u8 version)
{
MapNode result = n_from;
if(version <= 19)
{
content_t c_from = n_from.getContent();
for(u32 i=0; i<sizeof(trans_table_19)/sizeof(trans_table_19[0]); i++)
{
if(trans_table_19[i][0] == c_from)
{
result.setContent(trans_table_19[i][1]);
break;
}
}
}
return result;
}
MapNode mapnode_translate_to_internal(MapNode n_from, u8 version)
{
MapNode result = n_from;
if(version <= 19)
{
content_t c_from = n_from.getContent();
for(u32 i=0; i<sizeof(trans_table_19)/sizeof(trans_table_19[0]); i++)
{
if(trans_table_19[i][1] == c_from)
{
result.setContent(trans_table_19[i][0]);
break;
}
}
}
return result;
}
void content_mapnode_init() void content_mapnode_init()
{ {
// Read some settings // Read some settings
@ -38,7 +97,7 @@ void content_mapnode_init()
bool new_style_leaves = g_settings.getBool("new_style_leaves"); bool new_style_leaves = g_settings.getBool("new_style_leaves");
bool invisible_stone = g_settings.getBool("invisible_stone"); bool invisible_stone = g_settings.getBool("invisible_stone");
u8 i; content_t i;
ContentFeatures *f = NULL; ContentFeatures *f = NULL;
i = CONTENT_STONE; i = CONTENT_STONE;
@ -136,12 +195,34 @@ void content_mapnode_init()
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
setWoodLikeDiggingProperties(f->digging_properties, 1.0); setWoodLikeDiggingProperties(f->digging_properties, 1.0);
i = CONTENT_JUNGLETREE;
f = &content_features(i);
f->setAllTextures("jungletree.png");
f->setTexture(0, "jungletree_top.png");
f->setTexture(1, "jungletree_top.png");
f->param_type = CPT_MINERAL;
//f->is_ground_content = true;
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
setWoodLikeDiggingProperties(f->digging_properties, 1.0);
i = CONTENT_JUNGLEGRASS;
f = &content_features(i);
f->setInventoryTexture("junglegrass.png");
f->light_propagates = true;
f->param_type = CPT_LIGHT;
//f->is_ground_content = true;
f->air_equivalent = false; // grass grows underneath
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
f->solidness = 0; // drawn separately, makes no faces
f->walkable = false;
setWoodLikeDiggingProperties(f->digging_properties, 0.10);
i = CONTENT_LEAVES; i = CONTENT_LEAVES;
f = &content_features(i); f = &content_features(i);
f->light_propagates = true; f->light_propagates = true;
//f->param_type = CPT_MINERAL; //f->param_type = CPT_MINERAL;
f->param_type = CPT_LIGHT; f->param_type = CPT_LIGHT;
f->is_ground_content = true; //f->is_ground_content = true;
if(new_style_leaves) if(new_style_leaves)
{ {
f->solidness = 0; // drawn separately, makes no faces f->solidness = 0; // drawn separately, makes no faces
@ -191,6 +272,7 @@ void content_mapnode_init()
i = CONTENT_GLASS; i = CONTENT_GLASS;
f = &content_features(i); f = &content_features(i);
f->light_propagates = true; f->light_propagates = true;
f->sunlight_propagates = true;
f->param_type = CPT_LIGHT; f->param_type = CPT_LIGHT;
f->is_ground_content = true; f->is_ground_content = true;
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";

@ -20,43 +20,57 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#ifndef CONTENT_MAPNODE_HEADER #ifndef CONTENT_MAPNODE_HEADER
#define CONTENT_MAPNODE_HEADER #define CONTENT_MAPNODE_HEADER
#include "mapnode.h"
void content_mapnode_init(); void content_mapnode_init();
MapNode mapnode_translate_from_internal(MapNode n_from, u8 version);
MapNode mapnode_translate_to_internal(MapNode n_from, u8 version);
/* /*
Node content type IDs Node content type IDs
Ranges:
*/ */
// 0x000...0x07f (0...127): param2 is fully usable
// 126 and 127 are reserved.
// Use these sparingly, only when the extra space in param2 might be needed.
#define CONTENT_STONE 0 #define CONTENT_STONE 0
#define CONTENT_GRASS 1
#define CONTENT_WATER 2 #define CONTENT_WATER 2
#define CONTENT_TORCH 3 #define CONTENT_TORCH 3
#define CONTENT_TREE 4
#define CONTENT_LEAVES 5
#define CONTENT_GRASS_FOOTSTEPS 6
#define CONTENT_MESE 7
#define CONTENT_MUD 8
#define CONTENT_WATERSOURCE 9 #define CONTENT_WATERSOURCE 9
// Pretty much useless, clouds won't be drawn this way
#define CONTENT_CLOUD 10
#define CONTENT_COALSTONE 11
#define CONTENT_WOOD 12
#define CONTENT_SAND 13
#define CONTENT_SIGN_WALL 14 #define CONTENT_SIGN_WALL 14
#define CONTENT_CHEST 15 #define CONTENT_CHEST 15
#define CONTENT_FURNACE 16 #define CONTENT_FURNACE 16
//#define CONTENT_WORKBENCH 17
#define CONTENT_COBBLE 18
#define CONTENT_STEEL 19
#define CONTENT_GLASS 20
#define CONTENT_FENCE 21 #define CONTENT_FENCE 21
#define CONTENT_MOSSYCOBBLE 22
#define CONTENT_GRAVEL 23
#define CONTENT_SANDSTONE 24
#define CONTENT_CACTUS 25
#define CONTENT_BRICK 26
#define CONTENT_CLAY 27
#define CONTENT_PAPYRUS 28
#define CONTENT_BOOKSHELF 29
#define CONTENT_RAIL 30 #define CONTENT_RAIL 30
// 0x800...0xfff (2048...4095): higher 4 bytes of param2 are not usable
#define CONTENT_GRASS 0x800 //1
#define CONTENT_TREE 0x801 //4
#define CONTENT_LEAVES 0x802 //5
#define CONTENT_GRASS_FOOTSTEPS 0x803 //6
#define CONTENT_MESE 0x804 //7
#define CONTENT_MUD 0x805 //8
// Pretty much useless, clouds won't be drawn this way
#define CONTENT_CLOUD 0x806 //10
#define CONTENT_COALSTONE 0x807 //11
#define CONTENT_WOOD 0x808 //12
#define CONTENT_SAND 0x809 //13
#define CONTENT_COBBLE 0x80a //18
#define CONTENT_STEEL 0x80b //19
#define CONTENT_GLASS 0x80c //20
#define CONTENT_MOSSYCOBBLE 0x80d //22
#define CONTENT_GRAVEL 0x80e //23
#define CONTENT_SANDSTONE 0x80f //24
#define CONTENT_CACTUS 0x810 //25
#define CONTENT_BRICK 0x811 //26
#define CONTENT_CLAY 0x812 //27
#define CONTENT_PAPYRUS 0x813 //28
#define CONTENT_BOOKSHELF 0x814 //29
#define CONTENT_JUNGLETREE 0x815
#define CONTENT_JUNGLEGRASS 0x816
#endif #endif

@ -51,7 +51,7 @@ void set_default_settings()
g_settings.setDefault("wanted_fps", "30"); g_settings.setDefault("wanted_fps", "30");
g_settings.setDefault("fps_max", "60"); g_settings.setDefault("fps_max", "60");
g_settings.setDefault("viewing_range_nodes_max", "300"); g_settings.setDefault("viewing_range_nodes_max", "300");
g_settings.setDefault("viewing_range_nodes_min", "25"); g_settings.setDefault("viewing_range_nodes_min", "15");
g_settings.setDefault("screenW", "800"); g_settings.setDefault("screenW", "800");
g_settings.setDefault("screenH", "600"); g_settings.setDefault("screenH", "600");
g_settings.setDefault("address", ""); g_settings.setDefault("address", "");

@ -543,11 +543,11 @@ void spawnRandomObjects(MapBlock *block)
{ {
v3s16 p(x0,y0,z0); v3s16 p(x0,y0,z0);
MapNode n = block->getNodeNoEx(p); MapNode n = block->getNodeNoEx(p);
if(n.d == CONTENT_IGNORE) if(n.getContent() == CONTENT_IGNORE)
continue; continue;
if(content_features(n.d).liquid_type != LIQUID_NONE) if(content_features(n).liquid_type != LIQUID_NONE)
continue; continue;
if(content_features(n.d).walkable) if(content_features(n).walkable)
{ {
last_node_walkable = true; last_node_walkable = true;
continue; continue;
@ -555,7 +555,7 @@ void spawnRandomObjects(MapBlock *block)
if(last_node_walkable) if(last_node_walkable)
{ {
// If block contains light information // If block contains light information
if(content_features(n.d).param_type == CPT_LIGHT) if(content_features(n).param_type == CPT_LIGHT)
{ {
if(n.getLight(LIGHTBANK_DAY) <= 5) if(n.getLight(LIGHTBANK_DAY) <= 5)
{ {
@ -624,15 +624,15 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
#if 1 #if 1
// Test something: // Test something:
// Convert all mud under proper day lighting to grass // Convert all mud under proper day lighting to grass
if(n.d == CONTENT_MUD) if(n.getContent() == CONTENT_MUD)
{ {
if(dtime_s > 300) if(dtime_s > 300)
{ {
MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0)); MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0));
if(content_features(n_top.d).air_equivalent && if(content_features(n_top).air_equivalent &&
n_top.getLight(LIGHTBANK_DAY) >= 13) n_top.getLight(LIGHTBANK_DAY) >= 13)
{ {
n.d = CONTENT_GRASS; n.setContent(CONTENT_GRASS);
m_map->addNodeWithEvent(p, n); m_map->addNodeWithEvent(p, n);
} }
} }
@ -686,9 +686,9 @@ void ServerEnvironment::step(float dtime)
v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0), BS); v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0), BS);
try{ try{
MapNode n = m_map->getNode(bottompos); MapNode n = m_map->getNode(bottompos);
if(n.d == CONTENT_GRASS) if(n.getContent() == CONTENT_GRASS)
{ {
n.d = CONTENT_GRASS_FOOTSTEPS; n.setContent(CONTENT_GRASS_FOOTSTEPS);
m_map->setNode(bottompos, n); m_map->setNode(bottompos, n);
} }
} }
@ -859,15 +859,15 @@ void ServerEnvironment::step(float dtime)
Test something: Test something:
Convert mud under proper lighting to grass Convert mud under proper lighting to grass
*/ */
if(n.d == CONTENT_MUD) if(n.getContent() == CONTENT_MUD)
{ {
if(myrand()%20 == 0) if(myrand()%20 == 0)
{ {
MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0)); MapNode n_top = m_map->getNodeNoEx(p+v3s16(0,1,0));
if(content_features(n_top.d).air_equivalent && if(content_features(n_top).air_equivalent &&
n_top.getLightBlend(getDayNightRatio()) >= 13) n_top.getLightBlend(getDayNightRatio()) >= 13)
{ {
n.d = CONTENT_GRASS; n.setContent(CONTENT_GRASS);
m_map->addNodeWithEvent(p, n); m_map->addNodeWithEvent(p, n);
} }
} }
@ -875,15 +875,14 @@ void ServerEnvironment::step(float dtime)
/* /*
Convert grass into mud if under something else than air Convert grass into mud if under something else than air
*/ */
else if(n.d == CONTENT_GRASS) else if(n.getContent() == CONTENT_GRASS)
{ {
//if(myrand()%20 == 0) //if(myrand()%20 == 0)
{ {
MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0)); MapNode n_top = m_map->getNodeNoEx(p+v3s16(0,1,0));
if(n_top.d != CONTENT_AIR if(content_features(n_top).air_equivalent == false)
&& n_top.d != CONTENT_IGNORE)
{ {
n.d = CONTENT_MUD; n.setContent(CONTENT_MUD);
m_map->addNodeWithEvent(p, n); m_map->addNodeWithEvent(p, n);
} }
} }
@ -1633,9 +1632,9 @@ void ClientEnvironment::step(float dtime)
v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0), BS); v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0), BS);
try{ try{
MapNode n = m_map->getNode(bottompos); MapNode n = m_map->getNode(bottompos);
if(n.d == CONTENT_GRASS) if(n.getContent() == CONTENT_GRASS)
{ {
n.d = CONTENT_GRASS_FOOTSTEPS; n.setContent(CONTENT_GRASS_FOOTSTEPS);
m_map->setNode(bottompos, n); m_map->setNode(bottompos, n);
// Update mesh on client // Update mesh on client
if(m_map->mapType() == MAPTYPE_CLIENT) if(m_map->mapType() == MAPTYPE_CLIENT)
@ -1874,7 +1873,7 @@ void ClientEnvironment::drawPostFx(video::IVideoDriver* driver, v3f camera_pos)
v3f pos_f = camera_pos; v3f pos_f = camera_pos;
v3s16 p_nodes = floatToInt(pos_f, BS); v3s16 p_nodes = floatToInt(pos_f, BS);
MapNode n = m_map->getNodeNoEx(p_nodes); MapNode n = m_map->getNodeNoEx(p_nodes);
if(n.d == CONTENT_WATER || n.d == CONTENT_WATERSOURCE) if(n.getContent() == CONTENT_WATER || n.getContent() == CONTENT_WATERSOURCE)
{ {
v2u32 ss = driver->getScreenSize(); v2u32 ss = driver->getScreenSize();
core::rect<s32> rect(0,0, ss.X, ss.Y); core::rect<s32> rect(0,0, ss.X, ss.Y);

@ -417,7 +417,7 @@ void getPointedNode(Client *client, v3f player_position,
try try
{ {
n = client->getNode(v3s16(x,y,z)); n = client->getNode(v3s16(x,y,z));
if(content_pointable(n.d) == false) if(content_pointable(n.getContent()) == false)
continue; continue;
} }
catch(InvalidPositionException &e) catch(InvalidPositionException &e)
@ -442,9 +442,9 @@ void getPointedNode(Client *client, v3f player_position,
/* /*
Meta-objects Meta-objects
*/ */
if(n.d == CONTENT_TORCH) if(n.getContent() == CONTENT_TORCH)
{ {
v3s16 dir = unpackDir(n.dir); v3s16 dir = unpackDir(n.param2);
v3f dir_f = v3f(dir.X, dir.Y, dir.Z); v3f dir_f = v3f(dir.X, dir.Y, dir.Z);
dir_f *= BS/2 - BS/6 - BS/20; dir_f *= BS/2 - BS/6 - BS/20;
v3f cpf = npf + dir_f; v3f cpf = npf + dir_f;
@ -489,9 +489,9 @@ void getPointedNode(Client *client, v3f player_position,
} }
} }
} }
else if(n.d == CONTENT_SIGN_WALL) else if(n.getContent() == CONTENT_SIGN_WALL)
{ {
v3s16 dir = unpackDir(n.dir); v3s16 dir = unpackDir(n.param2);
v3f dir_f = v3f(dir.X, dir.Y, dir.Z); v3f dir_f = v3f(dir.X, dir.Y, dir.Z);
dir_f *= BS/2 - BS/6 - BS/20; dir_f *= BS/2 - BS/6 - BS/20;
v3f cpf = npf + dir_f; v3f cpf = npf + dir_f;
@ -538,9 +538,9 @@ void getPointedNode(Client *client, v3f player_position,
} }
} }
} }
else if(n.d == CONTENT_RAIL) else if(n.getContent() == CONTENT_RAIL)
{ {
v3s16 dir = unpackDir(n.dir); v3s16 dir = unpackDir(n.param0);
v3f dir_f = v3f(dir.X, dir.Y, dir.Z); v3f dir_f = v3f(dir.X, dir.Y, dir.Z);
dir_f *= BS/2 - BS/6 - BS/20; dir_f *= BS/2 - BS/6 - BS/20;
v3f cpf = npf + dir_f; v3f cpf = npf + dir_f;
@ -1038,9 +1038,9 @@ void the_game(
//bool screensize_changed = screensize != last_screensize; //bool screensize_changed = screensize != last_screensize;
// Resize hotbar // Resize hotbar
if(screensize.Y <= 600) if(screensize.Y <= 800)
hotbar_imagesize = 32; hotbar_imagesize = 32;
else if(screensize.Y <= 1024) else if(screensize.Y <= 1280)
hotbar_imagesize = 48; hotbar_imagesize = 48;
else else
hotbar_imagesize = 64; hotbar_imagesize = 64;
@ -1759,7 +1759,7 @@ void the_game(
} }
// Get digging properties for material and tool // Get digging properties for material and tool
u8 material = n.d; content_t material = n.getContent();
DiggingProperties prop = DiggingProperties prop =
getDiggingProperties(material, toolname); getDiggingProperties(material, toolname);

@ -61,7 +61,7 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is)
is>>material; is>>material;
u16 count; u16 count;
is>>count; is>>count;
if(material > 255) if(material > MAX_CONTENT)
throw SerializationError("Too large material number"); throw SerializationError("Too large material number");
return new MaterialItem(material, count); return new MaterialItem(material, count);
} }

@ -30,8 +30,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "common_irrlicht.h" #include "common_irrlicht.h"
#include "debug.h" #include "debug.h"
#include "mapblockobject.h" #include "mapblockobject.h"
// For g_materials #include "main.h" // For g_materials
#include "main.h" #include "mapnode.h" // For content_t
#define QUANTITY_ITEM_MAX_COUNT 99 #define QUANTITY_ITEM_MAX_COUNT 99
@ -113,7 +113,7 @@ protected:
class MaterialItem : public InventoryItem class MaterialItem : public InventoryItem
{ {
public: public:
MaterialItem(u8 content, u16 count): MaterialItem(content_t content, u16 count):
InventoryItem(count) InventoryItem(count)
{ {
m_content = content; m_content = content;
@ -175,12 +175,12 @@ public:
/* /*
Special methods Special methods
*/ */
u8 getMaterial() content_t getMaterial()
{ {
return m_content; return m_content;
} }
private: private:
u8 m_content; content_t m_content;
}; };
//TODO: Remove //TODO: Remove

@ -54,6 +54,30 @@ A list of "active blocks" in which stuff happens. (+=done)
+ This was left to be done by the old system and it sends only the + This was left to be done by the old system and it sends only the
nearest ones. nearest ones.
Vim conversion regexpes for moving to extended content type storage:
%s/\(\.\|->\)d \([!=]=\)/\1getContent() \2/g
%s/content_features(\([^.]*\)\.d)/content_features(\1)/g
%s/\(\.\|->\)d = \([^;]*\);/\1setContent(\2);/g
%s/\(getNodeNoExNoEmerge([^)]*)\)\.d/\1.getContent()/g
%s/\(getNodeNoExNoEmerge(.*)\)\.d/\1.getContent()/g
%s/\.d;/.getContent();/g
%s/\(content_liquid\|content_flowing_liquid\|make_liquid_flowing\|content_pointable\)(\([^.]*\).d)/\1(\2.getContent())/g
Other things to note:
- node.d = node.param0 (only in raw serialization; use getContent() otherwise)
- node.param = node.param1
- node.dir = node.param2
- content_walkable(node.d) etc should be changed to
content_features(node).walkable etc
- Also check for lines that store the result of getContent to a 8-bit
variable and fix them (result of getContent() must be stored in
content_t, which is 16-bit)
NOTE: Seeds in 1260:6c77e7dbfd29:
5721858502589302589:
Spawns you on a small sand island with a surface dungeon
2983455799928051958:
Enormous jungle + a surface dungeon at ~(250,0,0)
Old, wild and random suggestions that probably won't be done: Old, wild and random suggestions that probably won't be done:
------------------------------------------------------------- -------------------------------------------------------------
@ -312,7 +336,7 @@ Map:
TODO: Mineral and ground material properties TODO: Mineral and ground material properties
- This way mineral ground toughness can be calculated with just - This way mineral ground toughness can be calculated with just
some formula, as well as tool strengths some formula, as well as tool strengths. Sounds too.
- There are TODOs in appropriate files: material.h, content_mapnode.h - There are TODOs in appropriate files: material.h, content_mapnode.h
TODO: Flowing water to actually contain flow direction information TODO: Flowing water to actually contain flow direction information
@ -320,6 +344,9 @@ TODO: Flowing water to actually contain flow direction information
TODO: Consider smoothening cave floors after generating them TODO: Consider smoothening cave floors after generating them
TODO: Fix make_tree, make_* to use seed-position-consistent pseudorandom
- delta also
Misc. stuff: Misc. stuff:
------------ ------------
TODO: Make sure server handles removing grass when a block is placed (etc) TODO: Make sure server handles removing grass when a block is placed (etc)
@ -332,12 +359,13 @@ TODO: Think about using same bits for material for fences and doors, for
TODO: Move mineral to param2, increment map serialization version, add TODO: Move mineral to param2, increment map serialization version, add
conversion conversion
TODO: Restart irrlicht completely when coming back to main menu from game. SUGG: Restart irrlicht completely when coming back to main menu from game.
- This gets rid of everything that is stored in irrlicht's caches. - This gets rid of everything that is stored in irrlicht's caches.
- This might be needed for texture pack selection in menu
TODO: Merge bahamada's audio stuff (clean patch available) TODO: Merge bahamada's audio stuff (clean patch available)
TODO: Merge key configuration menu (no clean patch available) TODO: Move content_features to mapnode_content_features.{h,cpp} or so
Making it more portable: Making it more portable:
------------------------ ------------------------
@ -1060,6 +1088,7 @@ int main(int argc, char *argv[])
std::locale::global(std::locale("C")); std::locale::global(std::locale("C"));
// This enables printing all characters in bitmap font // This enables printing all characters in bitmap font
setlocale(LC_CTYPE, "en_US"); setlocale(LC_CTYPE, "en_US");
/* /*
Parse command line Parse command line
*/ */
@ -1153,7 +1182,7 @@ int main(int argc, char *argv[])
BEGIN_DEBUG_EXCEPTION_HANDLER BEGIN_DEBUG_EXCEPTION_HANDLER
// Print startup message // Print startup message
dstream<<DTIME<<PROJECT_NAME << dstream<<DTIME<<PROJECT_NAME
" with SER_FMT_VER_HIGHEST="<<(int)SER_FMT_VER_HIGHEST " with SER_FMT_VER_HIGHEST="<<(int)SER_FMT_VER_HIGHEST
<<", "<<BUILD_INFO <<", "<<BUILD_INFO
<<std::endl; <<std::endl;
@ -1650,3 +1679,4 @@ int main(int argc, char *argv[])
} }
//END //END

@ -630,9 +630,9 @@ s16 Map::propagateSunlight(v3s16 start,
else else
{ {
/*// Turn mud into grass /*// Turn mud into grass
if(n.d == CONTENT_MUD) if(n.getContent() == CONTENT_MUD)
{ {
n.d = CONTENT_GRASS; n.setContent(CONTENT_GRASS);
block->setNode(relpos, n); block->setNode(relpos, n);
modified_blocks.insert(blockpos, block); modified_blocks.insert(blockpos, block);
}*/ }*/
@ -920,15 +920,15 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
/* /*
If the new node is solid and there is grass below, change it to mud If the new node is solid and there is grass below, change it to mud
*/ */
if(content_features(n.d).walkable == true) if(content_features(n).walkable == true)
{ {
try{ try{
MapNode bottomnode = getNode(bottompos); MapNode bottomnode = getNode(bottompos);
if(bottomnode.d == CONTENT_GRASS if(bottomnode.getContent() == CONTENT_GRASS
|| bottomnode.d == CONTENT_GRASS_FOOTSTEPS) || bottomnode.getContent() == CONTENT_GRASS_FOOTSTEPS)
{ {
bottomnode.d = CONTENT_MUD; bottomnode.setContent(CONTENT_MUD);
setNode(bottompos, bottomnode); setNode(bottompos, bottomnode);
} }
} }
@ -943,9 +943,9 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
If the new node is mud and it is under sunlight, change it If the new node is mud and it is under sunlight, change it
to grass to grass
*/ */
if(n.d == CONTENT_MUD && node_under_sunlight) if(n.getContent() == CONTENT_MUD && node_under_sunlight)
{ {
n.d = CONTENT_GRASS; n.setContent(CONTENT_GRASS);
} }
#endif #endif
@ -986,7 +986,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
If node lets sunlight through and is under sunlight, it has If node lets sunlight through and is under sunlight, it has
sunlight too. sunlight too.
*/ */
if(node_under_sunlight && content_features(n.d).sunlight_propagates) if(node_under_sunlight && content_features(n).sunlight_propagates)
{ {
n.setLight(LIGHTBANK_DAY, LIGHT_SUN); n.setLight(LIGHTBANK_DAY, LIGHT_SUN);
} }
@ -1001,7 +1001,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
Add intial metadata Add intial metadata
*/ */
NodeMetadata *meta_proto = content_features(n.d).initial_metadata; NodeMetadata *meta_proto = content_features(n).initial_metadata;
if(meta_proto) if(meta_proto)
{ {
NodeMetadata *meta = meta_proto->clone(); NodeMetadata *meta = meta_proto->clone();
@ -1015,7 +1015,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
TODO: This could be optimized by mass-unlighting instead TODO: This could be optimized by mass-unlighting instead
of looping of looping
*/ */
if(node_under_sunlight && !content_features(n.d).sunlight_propagates) if(node_under_sunlight && !content_features(n).sunlight_propagates)
{ {
s16 y = p.Y - 1; s16 y = p.Y - 1;
for(;; y--){ for(;; y--){
@ -1086,7 +1086,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
v3s16 p2 = p + dirs[i]; v3s16 p2 = p + dirs[i];
MapNode n2 = getNode(p2); MapNode n2 = getNode(p2);
if(content_liquid(n2.d) || n2.d == CONTENT_AIR) if(content_liquid(n2.getContent()))
{ {
m_transforming_liquid.push_back(p2); m_transforming_liquid.push_back(p2);
} }
@ -1111,7 +1111,7 @@ void Map::removeNodeAndUpdate(v3s16 p,
v3s16 toppos = p + v3s16(0,1,0); v3s16 toppos = p + v3s16(0,1,0);
// Node will be replaced with this // Node will be replaced with this
u8 replace_material = CONTENT_AIR; content_t replace_material = CONTENT_AIR;
/* /*
If there is a node at top and it doesn't have sunlight, If there is a node at top and it doesn't have sunlight,
@ -1158,7 +1158,7 @@ void Map::removeNodeAndUpdate(v3s16 p,
*/ */
MapNode n; MapNode n;
n.d = replace_material; n.setContent(replace_material);
setNode(p, n); setNode(p, n);
for(s32 i=0; i<2; i++) for(s32 i=0; i<2; i++)
@ -1260,7 +1260,7 @@ void Map::removeNodeAndUpdate(v3s16 p,
v3s16 p2 = p + dirs[i]; v3s16 p2 = p + dirs[i];
MapNode n2 = getNode(p2); MapNode n2 = getNode(p2);
if(content_liquid(n2.d) || n2.d == CONTENT_AIR) if(content_liquid(n2.getContent()))
{ {
m_transforming_liquid.push_back(p2); m_transforming_liquid.push_back(p2);
} }
@ -1576,20 +1576,20 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
*/ */
s8 liquid_level = -1; s8 liquid_level = -1;
u8 liquid_kind = CONTENT_IGNORE; u8 liquid_kind = CONTENT_IGNORE;
LiquidType liquid_type = content_features(n0.d).liquid_type; LiquidType liquid_type = content_features(n0.getContent()).liquid_type;
switch (liquid_type) { switch (liquid_type) {
case LIQUID_SOURCE: case LIQUID_SOURCE:
liquid_level = 8; liquid_level = 8;
liquid_kind = content_features(n0.d).liquid_alternative_flowing; liquid_kind = content_features(n0.getContent()).liquid_alternative_flowing;
break; break;
case LIQUID_FLOWING: case LIQUID_FLOWING:
liquid_level = (n0.param2 & LIQUID_LEVEL_MASK); liquid_level = (n0.param2 & LIQUID_LEVEL_MASK);
liquid_kind = n0.d; liquid_kind = n0.getContent();
break; break;
case LIQUID_NONE: case LIQUID_NONE:
// if this is an air node, it *could* be transformed into a liquid. otherwise, // if this is an air node, it *could* be transformed into a liquid. otherwise,
// continue with the next node. // continue with the next node.
if (n0.d != CONTENT_AIR) if (n0.getContent() != CONTENT_AIR)
continue; continue;
liquid_kind = CONTENT_AIR; liquid_kind = CONTENT_AIR;
break; break;
@ -1627,9 +1627,9 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
} }
v3s16 npos = p0 + dirs[i]; v3s16 npos = p0 + dirs[i];
NodeNeighbor nb = {getNodeNoEx(npos), nt, npos}; NodeNeighbor nb = {getNodeNoEx(npos), nt, npos};
switch (content_features(nb.n.d).liquid_type) { switch (content_features(nb.n.getContent()).liquid_type) {
case LIQUID_NONE: case LIQUID_NONE:
if (nb.n.d == CONTENT_AIR) { if (nb.n.getContent() == CONTENT_AIR) {
airs[num_airs++] = nb; airs[num_airs++] = nb;
// if the current node happens to be a flowing node, it will start to flow down here. // if the current node happens to be a flowing node, it will start to flow down here.
if (nb.t == NEIGHBOR_LOWER) if (nb.t == NEIGHBOR_LOWER)
@ -1641,8 +1641,8 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
case LIQUID_SOURCE: case LIQUID_SOURCE:
// if this node is not (yet) of a liquid type, choose the first liquid type we encounter // if this node is not (yet) of a liquid type, choose the first liquid type we encounter
if (liquid_kind == CONTENT_AIR) if (liquid_kind == CONTENT_AIR)
liquid_kind = content_features(nb.n.d).liquid_alternative_flowing; liquid_kind = content_features(nb.n.getContent()).liquid_alternative_flowing;
if (content_features(nb.n.d).liquid_alternative_flowing !=liquid_kind) { if (content_features(nb.n.getContent()).liquid_alternative_flowing !=liquid_kind) {
neutrals[num_neutrals++] = nb; neutrals[num_neutrals++] = nb;
} else { } else {
sources[num_sources++] = nb; sources[num_sources++] = nb;
@ -1651,8 +1651,8 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
case LIQUID_FLOWING: case LIQUID_FLOWING:
// if this node is not (yet) of a liquid type, choose the first liquid type we encounter // if this node is not (yet) of a liquid type, choose the first liquid type we encounter
if (liquid_kind == CONTENT_AIR) if (liquid_kind == CONTENT_AIR)
liquid_kind = content_features(nb.n.d).liquid_alternative_flowing; liquid_kind = content_features(nb.n.getContent()).liquid_alternative_flowing;
if (content_features(nb.n.d).liquid_alternative_flowing != liquid_kind) { if (content_features(nb.n.getContent()).liquid_alternative_flowing != liquid_kind) {
neutrals[num_neutrals++] = nb; neutrals[num_neutrals++] = nb;
} else { } else {
flows[num_flows++] = nb; flows[num_flows++] = nb;
@ -1722,7 +1722,7 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
/* /*
check if anything has changed. if not, just continue with the next node. check if anything has changed. if not, just continue with the next node.
*/ */
if (new_node_content == n0.d && (content_features(n0.d).liquid_type != LIQUID_FLOWING || if (new_node_content == n0.getContent() && (content_features(n0.getContent()).liquid_type != LIQUID_FLOWING ||
((n0.param2 & LIQUID_LEVEL_MASK) == (u8)new_node_level && ((n0.param2 & LIQUID_LEVEL_MASK) == (u8)new_node_level &&
((n0.param2 & LIQUID_FLOW_DOWN_MASK) == LIQUID_FLOW_DOWN_MASK) ((n0.param2 & LIQUID_FLOW_DOWN_MASK) == LIQUID_FLOW_DOWN_MASK)
== flowing_down))) == flowing_down)))
@ -1733,8 +1733,8 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
update the current node update the current node
*/ */
bool flow_down_enabled = (flowing_down && ((n0.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK)); bool flow_down_enabled = (flowing_down && ((n0.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK));
n0.d = new_node_content; n0.setContent(new_node_content);
if (content_features(n0.d).liquid_type == LIQUID_FLOWING) { if (content_features(n0.getContent()).liquid_type == LIQUID_FLOWING) {
// set level to last 3 bits, flowing down bit to 4th bit // set level to last 3 bits, flowing down bit to 4th bit
n0.param2 = (flowing_down ? LIQUID_FLOW_DOWN_MASK : 0x00) | (new_node_level & LIQUID_LEVEL_MASK); n0.param2 = (flowing_down ? LIQUID_FLOW_DOWN_MASK : 0x00) | (new_node_level & LIQUID_LEVEL_MASK);
} else { } else {
@ -1749,7 +1749,7 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
/* /*
enqueue neighbors for update if neccessary enqueue neighbors for update if neccessary
*/ */
switch (content_features(n0.d).liquid_type) { switch (content_features(n0.getContent()).liquid_type) {
case LIQUID_SOURCE: case LIQUID_SOURCE:
// make sure source flows into all neighboring nodes // make sure source flows into all neighboring nodes
for (u16 i = 0; i < num_flows; i++) for (u16 i = 0; i < num_flows; i++)
@ -2003,8 +2003,10 @@ ServerMap::~ServerMap()
void ServerMap::initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos) void ServerMap::initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos)
{ {
/*dstream<<"initBlockMake(): ("<<blockpos.X<<","<<blockpos.Y<<"," bool enable_mapgen_debug_info = g_settings.getBool("enable_mapgen_debug_info");
<<blockpos.Z<<")"<<std::endl;*/ if(enable_mapgen_debug_info)
dstream<<"initBlockMake(): ("<<blockpos.X<<","<<blockpos.Y<<","
<<blockpos.Z<<")"<<std::endl;
// Do nothing if not inside limits (+-1 because of neighbors) // Do nothing if not inside limits (+-1 because of neighbors)
if(blockpos_over_limit(blockpos - v3s16(1,1,1)) || if(blockpos_over_limit(blockpos - v3s16(1,1,1)) ||
@ -2034,25 +2036,28 @@ void ServerMap::initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos)
for(s16 y=-1; y<=1; y++) for(s16 y=-1; y<=1; y++)
{ {
//MapBlock *block = createBlock(blockpos); v3s16 p(blockpos.X+x, blockpos.Y+y, blockpos.Z+z);
//MapBlock *block = createBlock(p);
// 1) get from memory, 2) load from disk // 1) get from memory, 2) load from disk
MapBlock *block = emergeBlock(blockpos, false); MapBlock *block = emergeBlock(p, false);
// 3) create a blank one // 3) create a blank one
if(block == NULL) if(block == NULL)
block = createBlock(blockpos); {
block = createBlock(p);
/*
Block gets sunlight if this is true.
Refer to the map generator heuristics.
*/
bool ug = mapgen::block_is_underground(data->seed, p);
block->setIsUnderground(ug);
}
// Lighting will not be valid after make_chunk is called // Lighting will not be valid after make_chunk is called
block->setLightingExpired(true); block->setLightingExpired(true);
// Lighting will be calculated // Lighting will be calculated
//block->setLightingExpired(false); //block->setLightingExpired(false);
/*
Block gets sunlight if this is true.
This should be set to true when the top side of a block
is completely exposed to the sky.
*/
block->setIsUnderground(false);
} }
} }
} }
@ -2128,10 +2133,14 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
assert(block); assert(block);
/* /*
Set is_underground flag for lighting with sunlight Set is_underground flag for lighting with sunlight.
*/
Refer to map generator heuristics.
NOTE: This is done in initChunkMake
*/
//block->setIsUnderground(mapgen::block_is_underground(data->seed, blockpos));
block->setIsUnderground(mapgen::block_is_underground(data->seed, blockpos));
/* /*
Add sunlight to central block. Add sunlight to central block.
@ -2162,6 +2171,13 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
#if 1 #if 1
// Center block // Center block
lighting_update_blocks.insert(block->getPos(), block); lighting_update_blocks.insert(block->getPos(), block);
/*{
s16 x = 0;
s16 z = 0;
v3s16 p = block->getPos()+v3s16(x,1,z);
lighting_update_blocks[p] = getBlockNoCreateNoEx(p);
}*/
#endif #endif
#if 0 #if 0
// All modified blocks // All modified blocks
@ -2178,9 +2194,29 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
lighting_update_blocks.insert(i.getNode()->getKey(), lighting_update_blocks.insert(i.getNode()->getKey(),
i.getNode()->getValue()); i.getNode()->getValue());
} }
/*// Also force-add all the upmost blocks for proper sunlight
for(s16 x=-1; x<=1; x++)
for(s16 z=-1; z<=1; z++)
{
v3s16 p = block->getPos()+v3s16(x,1,z);
lighting_update_blocks[p] = getBlockNoCreateNoEx(p);
}*/
#endif #endif
updateLighting(lighting_update_blocks, changed_blocks); updateLighting(lighting_update_blocks, changed_blocks);
/*
Set lighting to non-expired state in all of them.
This is cheating, but it is not fast enough if all of them
would actually be updated.
*/
for(s16 x=-1; x<=1; x++)
for(s16 y=-1; y<=1; y++)
for(s16 z=-1; z<=1; z++)
{
v3s16 p = block->getPos()+v3s16(x,y,z);
getBlockNoCreateNoEx(p)->setLightingExpired(false);
}
if(enable_mapgen_debug_info == false) if(enable_mapgen_debug_info == false)
t.stop(true); // Hide output t.stop(true); // Hide output
} }
@ -2221,6 +2257,25 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data,
/*dstream<<"finishBlockMake() done for ("<<blockpos.X<<","<<blockpos.Y<<"," /*dstream<<"finishBlockMake() done for ("<<blockpos.X<<","<<blockpos.Y<<","
<<blockpos.Z<<")"<<std::endl;*/ <<blockpos.Z<<")"<<std::endl;*/
#if 0
if(enable_mapgen_debug_info)
{
/*
Analyze resulting blocks
*/
for(s16 x=-1; x<=1; x++)
for(s16 y=-1; y<=1; y++)
for(s16 z=-1; z<=1; z++)
{
v3s16 p = block->getPos()+v3s16(x,y,z);
MapBlock *block = getBlockNoCreateNoEx(p);
char spos[20];
snprintf(spos, 20, "(%2d,%2d,%2d)", x, y, z);
dstream<<"Generated "<<spos<<": "
<<analyze_block(block)<<std::endl;
}
}
#endif
return block; return block;
} }
@ -2355,7 +2410,7 @@ MapBlock * ServerMap::generateBlock(
{ {
v3s16 p(x0,y0,z0); v3s16 p(x0,y0,z0);
MapNode n = block->getNode(p); MapNode n = block->getNode(p);
if(n.d == CONTENT_IGNORE) if(n.getContent() == CONTENT_IGNORE)
{ {
dstream<<"CONTENT_IGNORE at " dstream<<"CONTENT_IGNORE at "
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")" <<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
@ -2384,9 +2439,9 @@ MapBlock * ServerMap::generateBlock(
{ {
MapNode n; MapNode n;
if(y0%2==0) if(y0%2==0)
n.d = CONTENT_AIR; n.setContent(CONTENT_AIR);
else else
n.d = CONTENT_STONE; n.setContent(CONTENT_STONE);
block->setNode(v3s16(x0,y0,z0), n); block->setNode(v3s16(x0,y0,z0), n);
} }
} }
@ -2470,7 +2525,7 @@ MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate)
{ {
MapBlock *block = getBlockNoCreateNoEx(p); MapBlock *block = getBlockNoCreateNoEx(p);
if(block) if(block && block->isDummy() == false)
return block; return block;
} }
@ -2667,19 +2722,19 @@ s16 ServerMap::findGroundLevel(v2s16 p2d)
for(; p.Y>min; p.Y--) for(; p.Y>min; p.Y--)
{ {
MapNode n = getNodeNoEx(p); MapNode n = getNodeNoEx(p);
if(n.d != CONTENT_IGNORE) if(n.getContent() != CONTENT_IGNORE)
break; break;
} }
if(p.Y == min) if(p.Y == min)
goto plan_b; goto plan_b;
// If this node is not air, go to plan b // If this node is not air, go to plan b
if(getNodeNoEx(p).d != CONTENT_AIR) if(getNodeNoEx(p).getContent() != CONTENT_AIR)
goto plan_b; goto plan_b;
// Search existing walkable and return it // Search existing walkable and return it
for(; p.Y>min; p.Y--) for(; p.Y>min; p.Y--)
{ {
MapNode n = getNodeNoEx(p); MapNode n = getNodeNoEx(p);
if(content_walkable(n.d) && n.d != CONTENT_IGNORE) if(content_walkable(n.d) && n.getContent() != CONTENT_IGNORE)
return p.Y; return p.Y;
} }
@ -4072,10 +4127,16 @@ void ManualMapVoxelManipulator::blitBackAll(
i = m_loaded_blocks.getIterator(); i = m_loaded_blocks.getIterator();
i.atEnd() == false; i++) i.atEnd() == false; i++)
{ {
v3s16 p = i.getNode()->getKey();
bool existed = i.getNode()->getValue(); bool existed = i.getNode()->getValue();
if(existed == false) if(existed == false)
{
// The Great Bug was found using this
/*dstream<<"ManualMapVoxelManipulator::blitBackAll: "
<<"Inexistent ("<<p.X<<","<<p.Y<<","<<p.Z<<")"
<<std::endl;*/
continue; continue;
v3s16 p = i.getNode()->getKey(); }
MapBlock *block = m_map->getBlockNoCreateNoEx(p); MapBlock *block = m_map->getBlockNoCreateNoEx(p);
if(block == NULL) if(block == NULL)
{ {

@ -242,7 +242,12 @@ bool MapBlock::propagateSunlight(core::map<v3s16, bool> & light_sources,
// Check if node above block has sunlight // Check if node above block has sunlight
try{ try{
MapNode n = getNodeParent(v3s16(x, MAP_BLOCKSIZE, z)); MapNode n = getNodeParent(v3s16(x, MAP_BLOCKSIZE, z));
if(n.d == CONTENT_IGNORE || n.getLight(LIGHTBANK_DAY) != LIGHT_SUN) if(n.getContent() == CONTENT_IGNORE)
{
// Trust heuristics
no_sunlight = is_underground;
}
else if(n.getLight(LIGHTBANK_DAY) != LIGHT_SUN)
{ {
no_sunlight = true; no_sunlight = true;
} }
@ -260,8 +265,8 @@ bool MapBlock::propagateSunlight(core::map<v3s16, bool> & light_sources,
else else
{ {
MapNode n = getNode(v3s16(x, MAP_BLOCKSIZE-1, z)); MapNode n = getNode(v3s16(x, MAP_BLOCKSIZE-1, z));
//if(n.d == CONTENT_WATER || n.d == CONTENT_WATERSOURCE) //if(n.getContent() == CONTENT_WATER || n.getContent() == CONTENT_WATERSOURCE)
if(content_features(n.d).sunlight_propagates == false) if(content_features(n).sunlight_propagates == false)
{ {
no_sunlight = true; no_sunlight = true;
} }
@ -322,14 +327,14 @@ bool MapBlock::propagateSunlight(core::map<v3s16, bool> & light_sources,
bool upper_is_air = false; bool upper_is_air = false;
try try
{ {
if(getNodeParent(pos+v3s16(0,1,0)).d == CONTENT_AIR) if(getNodeParent(pos+v3s16(0,1,0)).getContent() == CONTENT_AIR)
upper_is_air = true; upper_is_air = true;
} }
catch(InvalidPositionException &e) catch(InvalidPositionException &e)
{ {
} }
// Turn mud into grass // Turn mud into grass
if(upper_is_air && n.d == CONTENT_MUD if(upper_is_air && n.getContent() == CONTENT_MUD
&& current_light == LIGHT_SUN) && current_light == LIGHT_SUN)
{ {
n.d = CONTENT_GRASS; n.d = CONTENT_GRASS;
@ -473,7 +478,7 @@ void MapBlock::updateDayNightDiff()
for(u32 i=0; i<MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; i++) for(u32 i=0; i<MAP_BLOCKSIZE*MAP_BLOCKSIZE*MAP_BLOCKSIZE; i++)
{ {
MapNode &n = data[i]; MapNode &n = data[i];
if(n.d != CONTENT_AIR) if(n.getContent() != CONTENT_AIR)
{ {
only_air = false; only_air = false;
break; break;
@ -496,8 +501,8 @@ s16 MapBlock::getGroundLevel(v2s16 p2d)
s16 y = MAP_BLOCKSIZE-1; s16 y = MAP_BLOCKSIZE-1;
for(; y>=0; y--) for(; y>=0; y--)
{ {
//if(is_ground_content(getNodeRef(p2d.X, y, p2d.Y).d)) MapNode n = getNodeRef(p2d.X, y, p2d.Y);
if(content_features(getNodeRef(p2d.X, y, p2d.Y).d).walkable) if(content_features(n).walkable)
{ {
if(y == MAP_BLOCKSIZE-1) if(y == MAP_BLOCKSIZE-1)
return -2; return -2;
@ -560,7 +565,7 @@ void MapBlock::serialize(std::ostream &os, u8 version)
SharedBuffer<u8> materialdata(nodecount); SharedBuffer<u8> materialdata(nodecount);
for(u32 i=0; i<nodecount; i++) for(u32 i=0; i<nodecount; i++)
{ {
materialdata[i] = data[i].d; materialdata[i] = data[i].param0;
} }
compress(materialdata, os, version); compress(materialdata, os, version);
@ -568,7 +573,7 @@ void MapBlock::serialize(std::ostream &os, u8 version)
SharedBuffer<u8> lightdata(nodecount); SharedBuffer<u8> lightdata(nodecount);
for(u32 i=0; i<nodecount; i++) for(u32 i=0; i<nodecount; i++)
{ {
lightdata[i] = data[i].param; lightdata[i] = data[i].param1;
} }
compress(lightdata, os, version); compress(lightdata, os, version);
@ -715,7 +720,7 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
("MapBlock::deSerialize: invalid format"); ("MapBlock::deSerialize: invalid format");
for(u32 i=0; i<s.size(); i++) for(u32 i=0; i<s.size(); i++)
{ {
data[i].d = s[i]; data[i].param0 = s[i];
} }
} }
{ {
@ -728,7 +733,7 @@ void MapBlock::deSerialize(std::istream &is, u8 version)
("MapBlock::deSerialize: invalid format"); ("MapBlock::deSerialize: invalid format");
for(u32 i=0; i<s.size(); i++) for(u32 i=0; i<s.size(); i++)
{ {
data[i].param = s[i]; data[i].param1 = s[i];
} }
} }
@ -862,5 +867,130 @@ void MapBlock::deSerializeDiskExtra(std::istream &is, u8 version)
} }
} }
/*
Get a quick string to describe what a block actually contains
*/
std::string analyze_block(MapBlock *block)
{
if(block == NULL)
{
return "NULL";
}
std::ostringstream desc;
v3s16 p = block->getPos();
char spos[20];
snprintf(spos, 20, "(%2d,%2d,%2d), ", p.X, p.Y, p.Z);
desc<<spos;
switch(block->getModified())
{
case MOD_STATE_CLEAN:
desc<<"CLEAN, ";
break;
case MOD_STATE_WRITE_AT_UNLOAD:
desc<<"WRITE_AT_UNLOAD, ";
break;
case MOD_STATE_WRITE_NEEDED:
desc<<"WRITE_NEEDED, ";
break;
default:
desc<<"unknown getModified()="+itos(block->getModified())+", ";
}
if(block->isGenerated())
desc<<"is_gen [X], ";
else
desc<<"is_gen [ ], ";
if(block->getIsUnderground())
desc<<"is_ug [X], ";
else
desc<<"is_ug [ ], ";
#ifndef SERVER
if(block->getMeshExpired())
desc<<"mesh_exp [X], ";
else
desc<<"mesh_exp [ ], ";
#endif
if(block->getLightingExpired())
desc<<"lighting_exp [X], ";
else
desc<<"lighting_exp [ ], ";
if(block->isDummy())
{
desc<<"Dummy, ";
}
else
{
// We'll just define the numbers here, don't want to include
// content_mapnode.h
const content_t content_water = 2;
const content_t content_watersource = 9;
const content_t content_tree = 0x801;
const content_t content_leaves = 0x802;
const content_t content_jungletree = 0x815;
bool full_ignore = true;
bool some_ignore = false;
bool full_air = true;
bool some_air = false;
bool trees = false;
bool water = false;
for(s16 z0=0; z0<MAP_BLOCKSIZE; z0++)
for(s16 y0=0; y0<MAP_BLOCKSIZE; y0++)
for(s16 x0=0; x0<MAP_BLOCKSIZE; x0++)
{
v3s16 p(x0,y0,z0);
MapNode n = block->getNode(p);
content_t c = n.getContent();
if(c == CONTENT_IGNORE)
some_ignore = true;
else
full_ignore = false;
if(c == CONTENT_AIR)
some_air = true;
else
full_air = false;
if(c == content_tree || c == content_jungletree
|| c == content_leaves)
trees = true;
if(c == content_water
|| c == content_watersource)
water = true;
}
desc<<"content {";
std::ostringstream ss;
if(full_ignore)
ss<<"IGNORE (full), ";
else if(some_ignore)
ss<<"IGNORE, ";
if(full_air)
ss<<"AIR (full), ";
else if(some_air)
ss<<"AIR, ";
if(trees)
ss<<"trees, ";
if(water)
ss<<"water, ";
if(ss.str().size()>=2)
desc<<ss.str().substr(0, ss.str().size()-2);
desc<<"}, ";
}
return desc.str().substr(0, desc.str().size()-2);
}
//END //END

@ -743,5 +743,10 @@ inline s16 getNodeBlockY(s16 y)
return getContainerPos(y, MAP_BLOCKSIZE); return getContainerPos(y, MAP_BLOCKSIZE);
} }
/*
Get a quick string to describe what a block actually contains
*/
std::string analyze_block(MapBlock *block);
#endif #endif

@ -140,9 +140,24 @@ void getNodeVertexDirs(v3s16 dir, v3s16 *vertex_dirs)
} }
} }
inline video::SColor lightColor(u8 alpha, u8 light) video::SColor MapBlock_LightColor(u8 alpha, u8 light)
{ {
#if 0
return video::SColor(alpha,light,light,light); return video::SColor(alpha,light,light,light);
#endif
//return video::SColor(alpha,light,light,MYMAX(0, (s16)light-25)+25);
/*return video::SColor(alpha,light,light,MYMAX(0,
pow((float)light/255.0, 0.8)*255.0));*/
#if 1
// Emphase blue a bit in darker places
float lim = 80;
float power = 0.8;
if(light > lim)
return video::SColor(alpha,light,light,light);
else
return video::SColor(alpha,light,light,MYMAX(0,
pow((float)light/lim, power)*lim));
#endif
} }
struct FastFace struct FastFace
@ -198,7 +213,7 @@ void makeFastFace(TileSpec tile, u8 li0, u8 li1, u8 li2, u8 li3, v3f p,
float w = tile.texture.size.X; float w = tile.texture.size.X;
float h = tile.texture.size.Y; float h = tile.texture.size.Y;
/*video::SColor c = lightColor(alpha, li); /*video::SColor c = MapBlock_LightColor(alpha, li);
face.vertices[0] = video::S3DVertex(vertex_pos[0], v3f(0,1,0), c, face.vertices[0] = video::S3DVertex(vertex_pos[0], v3f(0,1,0), c,
core::vector2d<f32>(x0+w*abs_scale, y0+h)); core::vector2d<f32>(x0+w*abs_scale, y0+h));
@ -210,16 +225,16 @@ void makeFastFace(TileSpec tile, u8 li0, u8 li1, u8 li2, u8 li3, v3f p,
core::vector2d<f32>(x0+w*abs_scale, y0));*/ core::vector2d<f32>(x0+w*abs_scale, y0));*/
face.vertices[0] = video::S3DVertex(vertex_pos[0], v3f(0,1,0), face.vertices[0] = video::S3DVertex(vertex_pos[0], v3f(0,1,0),
lightColor(alpha, li0), MapBlock_LightColor(alpha, li0),
core::vector2d<f32>(x0+w*abs_scale, y0+h)); core::vector2d<f32>(x0+w*abs_scale, y0+h));
face.vertices[1] = video::S3DVertex(vertex_pos[1], v3f(0,1,0), face.vertices[1] = video::S3DVertex(vertex_pos[1], v3f(0,1,0),
lightColor(alpha, li1), MapBlock_LightColor(alpha, li1),
core::vector2d<f32>(x0, y0+h)); core::vector2d<f32>(x0, y0+h));
face.vertices[2] = video::S3DVertex(vertex_pos[2], v3f(0,1,0), face.vertices[2] = video::S3DVertex(vertex_pos[2], v3f(0,1,0),
lightColor(alpha, li2), MapBlock_LightColor(alpha, li2),
core::vector2d<f32>(x0, y0)); core::vector2d<f32>(x0, y0));
face.vertices[3] = video::S3DVertex(vertex_pos[3], v3f(0,1,0), face.vertices[3] = video::S3DVertex(vertex_pos[3], v3f(0,1,0),
lightColor(alpha, li3), MapBlock_LightColor(alpha, li3),
core::vector2d<f32>(x0+w*abs_scale, y0)); core::vector2d<f32>(x0+w*abs_scale, y0));
face.tile = tile; face.tile = tile;
@ -285,7 +300,7 @@ TileSpec getNodeTile(MapNode mn, v3s16 p, v3s16 face_dir,
return spec; return spec;
} }
u8 getNodeContent(v3s16 p, MapNode mn, NodeModMap &temp_mods) content_t getNodeContent(v3s16 p, MapNode mn, NodeModMap &temp_mods)
{ {
/* /*
Check temporary modifications on this node Check temporary modifications on this node
@ -320,7 +335,7 @@ u8 getNodeContent(v3s16 p, MapNode mn, NodeModMap &temp_mods)
} }
} }
return mn.d; return mn.getContent();
} }
v3s16 dirs8[8] = { v3s16 dirs8[8] = {
@ -343,16 +358,16 @@ u8 getSmoothLight(v3s16 p, VoxelManipulator &vmanip, u32 daynight_ratio)
for(u32 i=0; i<8; i++) for(u32 i=0; i<8; i++)
{ {
MapNode n = vmanip.getNodeNoEx(p - dirs8[i]); MapNode n = vmanip.getNodeNoEx(p - dirs8[i]);
if(content_features(n.d).param_type == CPT_LIGHT if(content_features(n).param_type == CPT_LIGHT
// Fast-style leaves look better this way // Fast-style leaves look better this way
&& content_features(n.d).solidness != 2) && content_features(n).solidness != 2)
{ {
light += decode_light(n.getLightBlend(daynight_ratio)); light += decode_light(n.getLightBlend(daynight_ratio));
light_count++; light_count++;
} }
else else
{ {
if(n.d != CONTENT_IGNORE) if(n.getContent() != CONTENT_IGNORE)
ambient_occlusion++; ambient_occlusion++;
} }
} }
@ -408,8 +423,8 @@ void getTileInfo(
TileSpec tile1 = getNodeTile(n1, p + face_dir, -face_dir, temp_mods); TileSpec tile1 = getNodeTile(n1, p + face_dir, -face_dir, temp_mods);
// This is hackish // This is hackish
u8 content0 = getNodeContent(p, n0, temp_mods); content_t content0 = getNodeContent(p, n0, temp_mods);
u8 content1 = getNodeContent(p + face_dir, n1, temp_mods); content_t content1 = getNodeContent(p + face_dir, n1, temp_mods);
u8 mf = face_contents(content0, content1); u8 mf = face_contents(content0, content1);
if(mf == 0) if(mf == 0)

@ -121,6 +121,9 @@ private:
core::array<PreMeshBuffer> m_prebuffers; core::array<PreMeshBuffer> m_prebuffers;
}; };
// Helper functions
video::SColor MapBlock_LightColor(u8 alpha, u8 light);
class MapBlock; class MapBlock;
struct MeshMakeData struct MeshMakeData
@ -137,6 +140,7 @@ struct MeshMakeData
void fill(u32 daynight_ratio, MapBlock *block); void fill(u32 daynight_ratio, MapBlock *block);
}; };
// This is the highest-level function in here
scene::SMesh* makeMapBlockMesh(MeshMakeData *data); scene::SMesh* makeMapBlockMesh(MeshMakeData *data);
#endif #endif

@ -161,8 +161,8 @@ void MovingObject::move(float dtime, v3f acceleration)
for(s16 x = oldpos_i.X - 1; x <= oldpos_i.X + 1; x++) for(s16 x = oldpos_i.X - 1; x <= oldpos_i.X + 1; x++)
{ {
try{ try{
if(content_walkable(m_block->getNodeParent(v3s16(x,y,z)).d) MapNode n = m_block->getNodeParent(v3s16(x,y,z));
== false) if(content_features(n).walkable == false)
continue; continue;
} }
catch(InvalidPositionException &e) catch(InvalidPositionException &e)

@ -67,8 +67,8 @@ static s16 find_ground_level_clever(VoxelManipulator &vmanip, v2s16 p2d)
{ {
MapNode &n = vmanip.m_data[i]; MapNode &n = vmanip.m_data[i];
if(content_walkable(n.d) if(content_walkable(n.d)
&& n.d != CONTENT_TREE && n.getContent() != CONTENT_TREE
&& n.d != CONTENT_LEAVES) && n.getContent() != CONTENT_LEAVES)
break; break;
vmanip.m_area.add_y(em, i, -1); vmanip.m_area.add_y(em, i, -1);
@ -143,8 +143,94 @@ static void make_tree(VoxelManipulator &vmanip, v3s16 p0)
if(vmanip.m_area.contains(p) == false) if(vmanip.m_area.contains(p) == false)
continue; continue;
u32 vi = vmanip.m_area.index(p); u32 vi = vmanip.m_area.index(p);
if(vmanip.m_data[vi].d != CONTENT_AIR if(vmanip.m_data[vi].getContent() != CONTENT_AIR
&& vmanip.m_data[vi].d != CONTENT_IGNORE) && vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
continue;
u32 i = leaves_a.index(x,y,z);
if(leaves_d[i] == 1)
vmanip.m_data[vi] = leavesnode;
}
}
static void make_jungletree(VoxelManipulator &vmanip, v3s16 p0)
{
MapNode treenode(CONTENT_JUNGLETREE);
MapNode leavesnode(CONTENT_LEAVES);
for(s16 x=-1; x<=1; x++)
for(s16 z=-1; z<=1; z++)
{
if(myrand_range(0, 2) == 0)
continue;
v3s16 p1 = p0 + v3s16(x,0,z);
v3s16 p2 = p0 + v3s16(x,-1,z);
if(vmanip.m_area.contains(p2)
&& vmanip.m_data[vmanip.m_area.index(p2)] == CONTENT_AIR)
vmanip.m_data[vmanip.m_area.index(p2)] = treenode;
else if(vmanip.m_area.contains(p1))
vmanip.m_data[vmanip.m_area.index(p1)] = treenode;
}
s16 trunk_h = myrand_range(8, 12);
v3s16 p1 = p0;
for(s16 ii=0; ii<trunk_h; ii++)
{
if(vmanip.m_area.contains(p1))
vmanip.m_data[vmanip.m_area.index(p1)] = treenode;
p1.Y++;
}
// p1 is now the last piece of the trunk
p1.Y -= 1;
VoxelArea leaves_a(v3s16(-3,-2,-3), v3s16(3,2,3));
//SharedPtr<u8> leaves_d(new u8[leaves_a.getVolume()]);
Buffer<u8> leaves_d(leaves_a.getVolume());
for(s32 i=0; i<leaves_a.getVolume(); i++)
leaves_d[i] = 0;
// Force leaves at near the end of the trunk
{
s16 d = 1;
for(s16 z=-d; z<=d; z++)
for(s16 y=-d; y<=d; y++)
for(s16 x=-d; x<=d; x++)
{
leaves_d[leaves_a.index(v3s16(x,y,z))] = 1;
}
}
// Add leaves randomly
for(u32 iii=0; iii<30; iii++)
{
s16 d = 1;
v3s16 p(
myrand_range(leaves_a.MinEdge.X, leaves_a.MaxEdge.X-d),
myrand_range(leaves_a.MinEdge.Y, leaves_a.MaxEdge.Y-d),
myrand_range(leaves_a.MinEdge.Z, leaves_a.MaxEdge.Z-d)
);
for(s16 z=0; z<=d; z++)
for(s16 y=0; y<=d; y++)
for(s16 x=0; x<=d; x++)
{
leaves_d[leaves_a.index(p+v3s16(x,y,z))] = 1;
}
}
// Blit leaves to vmanip
for(s16 z=leaves_a.MinEdge.Z; z<=leaves_a.MaxEdge.Z; z++)
for(s16 y=leaves_a.MinEdge.Y; y<=leaves_a.MaxEdge.Y; y++)
for(s16 x=leaves_a.MinEdge.X; x<=leaves_a.MaxEdge.X; x++)
{
v3s16 p(x,y,z);
p += p1;
if(vmanip.m_area.contains(p) == false)
continue;
u32 vi = vmanip.m_area.index(p);
if(vmanip.m_data[vi].getContent() != CONTENT_AIR
&& vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
continue; continue;
u32 i = leaves_a.index(x,y,z); u32 i = leaves_a.index(x,y,z);
if(leaves_d[i] == 1) if(leaves_d[i] == 1)
@ -251,8 +337,8 @@ static void make_randomstone(VoxelManipulator &vmanip, v3s16 p0)
if(vmanip.m_area.contains(p) == false) if(vmanip.m_area.contains(p) == false)
continue; continue;
u32 vi = vmanip.m_area.index(p); u32 vi = vmanip.m_area.index(p);
if(vmanip.m_data[vi].d != CONTENT_AIR if(vmanip.m_data[vi].getContent() != CONTENT_AIR
&& vmanip.m_data[vi].d != CONTENT_IGNORE) && vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
continue; continue;
u32 i = stone_a.index(x,y,z); u32 i = stone_a.index(x,y,z);
if(stone_d[i] == 1) if(stone_d[i] == 1)
@ -335,8 +421,8 @@ static void make_largestone(VoxelManipulator &vmanip, v3s16 p0)
if(vmanip.m_area.contains(p) == false) if(vmanip.m_area.contains(p) == false)
continue; continue;
u32 vi = vmanip.m_area.index(p); u32 vi = vmanip.m_area.index(p);
/*if(vmanip.m_data[vi].d != CONTENT_AIR /*if(vmanip.m_data[vi].getContent() != CONTENT_AIR
&& vmanip.m_data[vi].d != CONTENT_IGNORE) && vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
continue;*/ continue;*/
u32 i = stone_a.index(x,y,z); u32 i = stone_a.index(x,y,z);
if(stone_d[i] == 1) if(stone_d[i] == 1)
@ -544,9 +630,9 @@ static void make_corridor(VoxelManipulator &vmanip, v3s16 doorplace,
p.Y += make_stairs; p.Y += make_stairs;
/*// If already empty /*// If already empty
if(vmanip.getNodeNoExNoEmerge(p).d if(vmanip.getNodeNoExNoEmerge(p).getContent()
== CONTENT_AIR == CONTENT_AIR
&& vmanip.getNodeNoExNoEmerge(p+v3s16(0,1,0)).d && vmanip.getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent()
== CONTENT_AIR) == CONTENT_AIR)
{ {
}*/ }*/
@ -642,9 +728,9 @@ public:
randomizeDir(); randomizeDir();
continue; continue;
} }
if(vmanip.getNodeNoExNoEmerge(p).d if(vmanip.getNodeNoExNoEmerge(p).getContent()
== CONTENT_COBBLE == CONTENT_COBBLE
&& vmanip.getNodeNoExNoEmerge(p1).d && vmanip.getNodeNoExNoEmerge(p1).getContent()
== CONTENT_COBBLE) == CONTENT_COBBLE)
{ {
// Found wall, this is a good place! // Found wall, this is a good place!
@ -658,25 +744,25 @@ public:
Determine where to move next Determine where to move next
*/ */
// Jump one up if the actual space is there // Jump one up if the actual space is there
if(vmanip.getNodeNoExNoEmerge(p+v3s16(0,0,0)).d if(vmanip.getNodeNoExNoEmerge(p+v3s16(0,0,0)).getContent()
== CONTENT_COBBLE == CONTENT_COBBLE
&& vmanip.getNodeNoExNoEmerge(p+v3s16(0,1,0)).d && vmanip.getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent()
== CONTENT_AIR == CONTENT_AIR
&& vmanip.getNodeNoExNoEmerge(p+v3s16(0,2,0)).d && vmanip.getNodeNoExNoEmerge(p+v3s16(0,2,0)).getContent()
== CONTENT_AIR) == CONTENT_AIR)
p += v3s16(0,1,0); p += v3s16(0,1,0);
// Jump one down if the actual space is there // Jump one down if the actual space is there
if(vmanip.getNodeNoExNoEmerge(p+v3s16(0,1,0)).d if(vmanip.getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent()
== CONTENT_COBBLE == CONTENT_COBBLE
&& vmanip.getNodeNoExNoEmerge(p+v3s16(0,0,0)).d && vmanip.getNodeNoExNoEmerge(p+v3s16(0,0,0)).getContent()
== CONTENT_AIR == CONTENT_AIR
&& vmanip.getNodeNoExNoEmerge(p+v3s16(0,-1,0)).d && vmanip.getNodeNoExNoEmerge(p+v3s16(0,-1,0)).getContent()
== CONTENT_AIR) == CONTENT_AIR)
p += v3s16(0,-1,0); p += v3s16(0,-1,0);
// Check if walking is now possible // Check if walking is now possible
if(vmanip.getNodeNoExNoEmerge(p).d if(vmanip.getNodeNoExNoEmerge(p).getContent()
!= CONTENT_AIR != CONTENT_AIR
|| vmanip.getNodeNoExNoEmerge(p+v3s16(0,1,0)).d || vmanip.getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent()
!= CONTENT_AIR) != CONTENT_AIR)
{ {
// Cannot continue walking here // Cannot continue walking here
@ -798,7 +884,7 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random)
fits = false; fits = false;
break; break;
} }
if(vmanip.m_data[vi].d == CONTENT_IGNORE) if(vmanip.m_data[vi].getContent() == CONTENT_IGNORE)
{ {
fits = false; fits = false;
break; break;
@ -1004,13 +1090,26 @@ double tree_amount_2d(u64 seed, v2s16 p)
double noise = noise2d_perlin( double noise = noise2d_perlin(
0.5+(float)p.X/125, 0.5+(float)p.Y/125, 0.5+(float)p.X/125, 0.5+(float)p.Y/125,
seed+2, 4, 0.66); seed+2, 4, 0.66);
double zeroval = -0.35; double zeroval = -0.39;
if(noise < zeroval) if(noise < zeroval)
return 0; return 0;
else else
return 0.04 * (noise-zeroval) / (1.0-zeroval); return 0.04 * (noise-zeroval) / (1.0-zeroval);
} }
double surface_humidity_2d(u64 seed, v2s16 p)
{
double noise = noise2d_perlin(
0.5+(float)p.X/500, 0.5+(float)p.Y/500,
seed+72384, 4, 0.66);
noise = (noise + 1.0)/2.0;
if(noise < 0.0)
noise = 0.0;
if(noise > 1.0)
noise = 1.0;
return noise;
}
#if 0 #if 0
double randomstone_amount_2d(u64 seed, v2s16 p) double randomstone_amount_2d(u64 seed, v2s16 p)
{ {
@ -1273,11 +1372,11 @@ void add_random_objects(MapBlock *block)
{ {
v3s16 p(x0,y0,z0); v3s16 p(x0,y0,z0);
MapNode n = block->getNodeNoEx(p); MapNode n = block->getNodeNoEx(p);
if(n.d == CONTENT_IGNORE) if(n.getContent() == CONTENT_IGNORE)
continue; continue;
if(content_features(n.d).liquid_type != LIQUID_NONE) if(content_features(n).liquid_type != LIQUID_NONE)
continue; continue;
if(content_features(n.d).walkable) if(content_features(n).walkable)
{ {
last_node_walkable = true; last_node_walkable = true;
continue; continue;
@ -1285,7 +1384,7 @@ void add_random_objects(MapBlock *block)
if(last_node_walkable) if(last_node_walkable)
{ {
// If block contains light information // If block contains light information
if(content_features(n.d).param_type == CPT_LIGHT) if(content_features(n).param_type == CPT_LIGHT)
{ {
if(n.getLight(LIGHTBANK_DAY) <= 3) if(n.getLight(LIGHTBANK_DAY) <= 3)
{ {
@ -1392,7 +1491,7 @@ void make_block(BlockMakeData *data)
for(s16 y=node_min.Y; y<=node_max.Y; y++) for(s16 y=node_min.Y; y<=node_max.Y; y++)
{ {
// Only modify places that have no content // Only modify places that have no content
if(vmanip.m_data[i].d == CONTENT_IGNORE) if(vmanip.m_data[i].getContent() == CONTENT_IGNORE)
{ {
if(y <= WATER_LEVEL) if(y <= WATER_LEVEL)
vmanip.m_data[i] = MapNode(CONTENT_WATERSOURCE); vmanip.m_data[i] = MapNode(CONTENT_WATERSOURCE);
@ -1498,7 +1597,7 @@ void make_block(BlockMakeData *data)
for(s16 y=node_min.Y; y<=node_max.Y; y++) for(s16 y=node_min.Y; y<=node_max.Y; y++)
{ {
// Only modify places that have no content // Only modify places that have no content
if(vmanip.m_data[i].d == CONTENT_IGNORE) if(vmanip.m_data[i].getContent() == CONTENT_IGNORE)
{ {
// First priority: make air and water. // First priority: make air and water.
// This avoids caves inside water. // This avoids caves inside water.
@ -1543,7 +1642,7 @@ void make_block(BlockMakeData *data)
{ {
v3s16 p = v3s16(x,y,z) + g_27dirs[i]; v3s16 p = v3s16(x,y,z) + g_27dirs[i];
u32 vi = vmanip.m_area.index(p); u32 vi = vmanip.m_area.index(p);
if(vmanip.m_data[vi].d == CONTENT_STONE) if(vmanip.m_data[vi].getContent() == CONTENT_STONE)
if(mineralrandom.next()%8 == 0) if(mineralrandom.next()%8 == 0)
vmanip.m_data[vi] = MapNode(CONTENT_MESE); vmanip.m_data[vi] = MapNode(CONTENT_MESE);
} }
@ -1584,13 +1683,13 @@ void make_block(BlockMakeData *data)
{ {
}*/ }*/
if(new_content.d != CONTENT_IGNORE) if(new_content.getContent() != CONTENT_IGNORE)
{ {
for(u16 i=0; i<27; i++) for(u16 i=0; i<27; i++)
{ {
v3s16 p = v3s16(x,y,z) + g_27dirs[i]; v3s16 p = v3s16(x,y,z) + g_27dirs[i];
u32 vi = vmanip.m_area.index(p); u32 vi = vmanip.m_area.index(p);
if(vmanip.m_data[vi].d == base_content) if(vmanip.m_data[vi].getContent() == base_content)
{ {
if(mineralrandom.next()%sparseness == 0) if(mineralrandom.next()%sparseness == 0)
vmanip.m_data[vi] = new_content; vmanip.m_data[vi] = new_content;
@ -1621,7 +1720,7 @@ void make_block(BlockMakeData *data)
{ {
v3s16 p = v3s16(x,y,z) + g_27dirs[i]; v3s16 p = v3s16(x,y,z) + g_27dirs[i];
u32 vi = vmanip.m_area.index(p); u32 vi = vmanip.m_area.index(p);
if(vmanip.m_data[vi].d == CONTENT_STONE) if(vmanip.m_data[vi].getContent() == CONTENT_STONE)
if(mineralrandom.next()%8 == 0) if(mineralrandom.next()%8 == 0)
vmanip.m_data[vi] = MapNode(CONTENT_STONE, MINERAL_COAL); vmanip.m_data[vi] = MapNode(CONTENT_STONE, MINERAL_COAL);
} }
@ -1647,7 +1746,7 @@ void make_block(BlockMakeData *data)
{ {
v3s16 p = v3s16(x,y,z) + g_27dirs[i]; v3s16 p = v3s16(x,y,z) + g_27dirs[i];
u32 vi = vmanip.m_area.index(p); u32 vi = vmanip.m_area.index(p);
if(vmanip.m_data[vi].d == CONTENT_STONE) if(vmanip.m_data[vi].getContent() == CONTENT_STONE)
if(mineralrandom.next()%8 == 0) if(mineralrandom.next()%8 == 0)
vmanip.m_data[vi] = MapNode(CONTENT_STONE, MINERAL_IRON); vmanip.m_data[vi] = MapNode(CONTENT_STONE, MINERAL_IRON);
} }
@ -1670,7 +1769,7 @@ void make_block(BlockMakeData *data)
u32 i = vmanip.m_area.index(v3s16(p2d.X, node_max.Y, p2d.Y)); u32 i = vmanip.m_area.index(v3s16(p2d.X, node_max.Y, p2d.Y));
for(s16 y=node_max.Y; y>=node_min.Y; y--) for(s16 y=node_max.Y; y>=node_min.Y; y--)
{ {
if(vmanip.m_data[i].d == CONTENT_STONE) if(vmanip.m_data[i].getContent() == CONTENT_STONE)
{ {
if(noisebuf_ground_crumbleness.get(x,y,z) > 1.3) if(noisebuf_ground_crumbleness.get(x,y,z) > 1.3)
{ {
@ -1722,9 +1821,9 @@ void make_block(BlockMakeData *data)
u32 i = vmanip.m_area.index(v3s16(p2d.X, full_node_max.Y, p2d.Y)); u32 i = vmanip.m_area.index(v3s16(p2d.X, full_node_max.Y, p2d.Y));
for(s16 y=full_node_max.Y; y>=full_node_min.Y; y--) for(s16 y=full_node_max.Y; y>=full_node_min.Y; y--)
{ {
if(vmanip.m_data[i].d == CONTENT_AIR) if(vmanip.m_data[i].getContent() == CONTENT_AIR)
vmanip.m_flags[i] |= VMANIP_FLAG_DUNGEON_PRESERVE; vmanip.m_flags[i] |= VMANIP_FLAG_DUNGEON_PRESERVE;
else if(vmanip.m_data[i].d == CONTENT_WATERSOURCE) else if(vmanip.m_data[i].getContent() == CONTENT_WATERSOURCE)
vmanip.m_flags[i] |= VMANIP_FLAG_DUNGEON_PRESERVE; vmanip.m_flags[i] |= VMANIP_FLAG_DUNGEON_PRESERVE;
data->vmanip->m_area.add_y(em, i, -1); data->vmanip->m_area.add_y(em, i, -1);
} }
@ -1755,17 +1854,17 @@ void make_block(BlockMakeData *data)
double d = noise3d_perlin((float)x/2.5, double d = noise3d_perlin((float)x/2.5,
(float)y/2.5,(float)z/2.5, (float)y/2.5,(float)z/2.5,
blockseed, 2, 1.4); blockseed, 2, 1.4);
if(vmanip.m_data[i].d == CONTENT_COBBLE) if(vmanip.m_data[i].getContent() == CONTENT_COBBLE)
{ {
if(d < wetness/3.0) if(d < wetness/3.0)
{ {
vmanip.m_data[i].d = CONTENT_MOSSYCOBBLE; vmanip.m_data[i].setContent(CONTENT_MOSSYCOBBLE);
} }
} }
/*else if(vmanip.m_flags[i] & VMANIP_FLAG_DUNGEON_INSIDE) /*else if(vmanip.m_flags[i] & VMANIP_FLAG_DUNGEON_INSIDE)
{ {
if(wetness > 1.2) if(wetness > 1.2)
vmanip.m_data[i].d = CONTENT_MUD; vmanip.m_data[i].setContent(CONTENT_MUD);
}*/ }*/
data->vmanip->m_area.add_y(em, i, -1); data->vmanip->m_area.add_y(em, i, -1);
} }
@ -1791,7 +1890,7 @@ void make_block(BlockMakeData *data)
{ {
if(water_found == false) if(water_found == false)
{ {
if(vmanip.m_data[i].d == CONTENT_WATERSOURCE) if(vmanip.m_data[i].getContent() == CONTENT_WATERSOURCE)
{ {
v3s16 p = v3s16(p2d.X, y, p2d.Y); v3s16 p = v3s16(p2d.X, y, p2d.Y);
data->transforming_liquid.push_back(p); data->transforming_liquid.push_back(p);
@ -1803,7 +1902,7 @@ void make_block(BlockMakeData *data)
// This can be done because water_found can only // This can be done because water_found can only
// turn to true and end up here after going through // turn to true and end up here after going through
// a single block. // a single block.
if(vmanip.m_data[i+1].d != CONTENT_WATERSOURCE) if(vmanip.m_data[i+1].getContent() != CONTENT_WATERSOURCE)
{ {
v3s16 p = v3s16(p2d.X, y+1, p2d.Y); v3s16 p = v3s16(p2d.X, y+1, p2d.Y);
data->transforming_liquid.push_back(p); data->transforming_liquid.push_back(p);
@ -1846,16 +1945,16 @@ void make_block(BlockMakeData *data)
u32 i = vmanip.m_area.index(v3s16(p2d.X, start_y, p2d.Y)); u32 i = vmanip.m_area.index(v3s16(p2d.X, start_y, p2d.Y));
for(s16 y=start_y; y>=node_min.Y-3; y--) for(s16 y=start_y; y>=node_min.Y-3; y--)
{ {
if(vmanip.m_data[i].d == CONTENT_WATERSOURCE) if(vmanip.m_data[i].getContent() == CONTENT_WATERSOURCE)
water_detected = true; water_detected = true;
if(vmanip.m_data[i].d == CONTENT_AIR) if(vmanip.m_data[i].getContent() == CONTENT_AIR)
air_detected = true; air_detected = true;
if((vmanip.m_data[i].d == CONTENT_STONE if((vmanip.m_data[i].getContent() == CONTENT_STONE
|| vmanip.m_data[i].d == CONTENT_GRASS || vmanip.m_data[i].getContent() == CONTENT_GRASS
|| vmanip.m_data[i].d == CONTENT_MUD || vmanip.m_data[i].getContent() == CONTENT_MUD
|| vmanip.m_data[i].d == CONTENT_SAND || vmanip.m_data[i].getContent() == CONTENT_SAND
|| vmanip.m_data[i].d == CONTENT_GRAVEL || vmanip.m_data[i].getContent() == CONTENT_GRAVEL
) && (air_detected || water_detected)) ) && (air_detected || water_detected))
{ {
if(current_depth == 0 && y <= WATER_LEVEL+2 if(current_depth == 0 && y <= WATER_LEVEL+2
@ -1890,8 +1989,8 @@ void make_block(BlockMakeData *data)
} }
else else
{ {
if(vmanip.m_data[i].d == CONTENT_MUD if(vmanip.m_data[i].getContent() == CONTENT_MUD
|| vmanip.m_data[i].d == CONTENT_GRASS) || vmanip.m_data[i].getContent() == CONTENT_GRASS)
vmanip.m_data[i] = MapNode(CONTENT_STONE); vmanip.m_data[i] = MapNode(CONTENT_STONE);
} }
@ -1909,11 +2008,19 @@ void make_block(BlockMakeData *data)
} }
/* /*
Add trees Calculate some stuff
*/ */
float surface_humidity = surface_humidity_2d(data->seed, p2d_center);
bool is_jungle = surface_humidity > 0.75;
// Amount of trees // Amount of trees
u32 tree_count = block_area_nodes * tree_amount_2d(data->seed, p2d_center); u32 tree_count = block_area_nodes * tree_amount_2d(data->seed, p2d_center);
if(is_jungle)
tree_count *= 5;
/*
Add trees
*/
PseudoRandom treerandom(blockseed); PseudoRandom treerandom(blockseed);
// Put trees in random places on part of division // Put trees in random places on part of division
for(u32 i=0; i<tree_count; i++) for(u32 i=0; i<tree_count; i++)
@ -1938,7 +2045,7 @@ void make_block(BlockMakeData *data)
{ {
u32 i = data->vmanip->m_area.index(p); u32 i = data->vmanip->m_area.index(p);
MapNode *n = &data->vmanip->m_data[i]; MapNode *n = &data->vmanip->m_data[i];
if(n->d != CONTENT_AIR && n->d != CONTENT_WATERSOURCE && n->d != CONTENT_IGNORE) if(n->getContent() != CONTENT_AIR && n->getContent() != CONTENT_WATERSOURCE && n->getContent() != CONTENT_IGNORE)
{ {
found = true; found = true;
break; break;
@ -1952,23 +2059,27 @@ void make_block(BlockMakeData *data)
u32 i = data->vmanip->m_area.index(p); u32 i = data->vmanip->m_area.index(p);
MapNode *n = &data->vmanip->m_data[i]; MapNode *n = &data->vmanip->m_data[i];
if(n->d != CONTENT_MUD && n->d != CONTENT_GRASS && n->d != CONTENT_SAND) if(n->getContent() != CONTENT_MUD && n->getContent() != CONTENT_GRASS && n->getContent() != CONTENT_SAND)
continue; continue;
// Papyrus grows only on mud and in water // Papyrus grows only on mud and in water
if(n->d == CONTENT_MUD && y <= WATER_LEVEL) if(n->getContent() == CONTENT_MUD && y <= WATER_LEVEL)
{ {
p.Y++; p.Y++;
make_papyrus(vmanip, p); make_papyrus(vmanip, p);
} }
// Trees grow only on mud and grass, on land // Trees grow only on mud and grass, on land
else if((n->d == CONTENT_MUD || n->d == CONTENT_GRASS) && y > WATER_LEVEL + 2) else if((n->getContent() == CONTENT_MUD || n->getContent() == CONTENT_GRASS) && y > WATER_LEVEL + 2)
{ {
p.Y++; p.Y++;
//if(surface_humidity_2d(data->seed, v2s16(x, y)) < 0.5)
if(is_jungle == false)
make_tree(vmanip, p); make_tree(vmanip, p);
else
make_jungletree(vmanip, p);
} }
// Cactii grow only on sand, on land // Cactii grow only on sand, on land
else if(n->d == CONTENT_SAND && y > WATER_LEVEL + 2) else if(n->getContent() == CONTENT_SAND && y > WATER_LEVEL + 2)
{ {
p.Y++; p.Y++;
make_cactus(vmanip, p); make_cactus(vmanip, p);
@ -1976,6 +2087,54 @@ void make_block(BlockMakeData *data)
} }
} }
/*
Add jungle grass
*/
if(is_jungle)
{
PseudoRandom grassrandom(blockseed);
for(u32 i=0; i<surface_humidity*5*tree_count; i++)
{
s16 x = grassrandom.range(node_min.X, node_max.X);
s16 z = grassrandom.range(node_min.Z, node_max.Z);
s16 y = find_ground_level_from_noise(data->seed, v2s16(x,z), 4);
if(y < WATER_LEVEL)
continue;
if(y < node_min.Y || y > node_max.Y)
continue;
/*
Find exact ground level
*/
v3s16 p(x,y+6,z);
bool found = false;
for(; p.Y >= y-6; p.Y--)
{
u32 i = data->vmanip->m_area.index(p);
MapNode *n = &data->vmanip->m_data[i];
if(content_features(*n).is_ground_content
|| n->getContent() == CONTENT_JUNGLETREE)
{
found = true;
break;
}
}
// If not found, handle next one
if(found == false)
continue;
p.Y++;
if(vmanip.m_area.contains(p) == false)
continue;
if(vmanip.m_data[vmanip.m_area.index(p)].getContent() != CONTENT_AIR)
continue;
/*p.Y--;
if(vmanip.m_area.contains(p))
vmanip.m_data[vmanip.m_area.index(p)] = CONTENT_MUD;
p.Y++;*/
if(vmanip.m_area.contains(p))
vmanip.m_data[vmanip.m_area.index(p)] = CONTENT_JUNGLEGRASS;
}
}
#if 0 #if 0
/* /*
Add some kind of random stones Add some kind of random stones
@ -2000,7 +2159,7 @@ void make_block(BlockMakeData *data)
/*{ /*{
u32 i = data->vmanip->m_area.index(v3s16(p)); u32 i = data->vmanip->m_area.index(v3s16(p));
MapNode *n = &data->vmanip->m_data[i]; MapNode *n = &data->vmanip->m_data[i];
if(n->d != CONTENT_MUD && n->d != CONTENT_GRASS) if(n->getContent() != CONTENT_MUD && n->getContent() != CONTENT_GRASS)
continue; continue;
}*/ }*/
// Will be placed one higher // Will be placed one higher
@ -2035,7 +2194,7 @@ void make_block(BlockMakeData *data)
/*{ /*{
u32 i = data->vmanip->m_area.index(v3s16(p)); u32 i = data->vmanip->m_area.index(v3s16(p));
MapNode *n = &data->vmanip->m_data[i]; MapNode *n = &data->vmanip->m_data[i];
if(n->d != CONTENT_MUD && n->d != CONTENT_GRASS) if(n->getContent() != CONTENT_MUD && n->getContent() != CONTENT_GRASS)
continue; continue;
}*/ }*/
// Will be placed one lower // Will be placed one lower

@ -30,8 +30,6 @@ with this program; if not, write to the Free Software Foundation, Inc.,
ContentFeatures::~ContentFeatures() ContentFeatures::~ContentFeatures()
{ {
/*if(translate_to)
delete translate_to;*/
if(initial_metadata) if(initial_metadata)
delete initial_metadata; delete initial_metadata;
} }
@ -83,12 +81,16 @@ void ContentFeatures::setInventoryTextureCube(std::string top,
inventory_texture = g_texturesource->getTextureRaw(imgname_full); inventory_texture = g_texturesource->getTextureRaw(imgname_full);
} }
struct ContentFeatures g_content_features[256]; struct ContentFeatures g_content_features[MAX_CONTENT+1];
ContentFeatures & content_features(u8 i) ContentFeatures & content_features(content_t i)
{ {
return g_content_features[i]; return g_content_features[i];
} }
ContentFeatures & content_features(MapNode &n)
{
return content_features(n.getContent());
}
/* /*
See mapnode.h for description. See mapnode.h for description.
@ -128,7 +130,7 @@ void init_mapnode()
initial_material_type = MATERIAL_ALPHA_SIMPLE; initial_material_type = MATERIAL_ALPHA_SIMPLE;
else else
initial_material_type = MATERIAL_ALPHA_NONE;*/ initial_material_type = MATERIAL_ALPHA_NONE;*/
for(u16 i=0; i<256; i++) for(u16 i=0; i<MAX_CONTENT+1; i++)
{ {
ContentFeatures *f = &g_content_features[i]; ContentFeatures *f = &g_content_features[i];
// Re-initialize // Re-initialize
@ -142,7 +144,7 @@ void init_mapnode()
Initially set every block to be shown as an unknown block. Initially set every block to be shown as an unknown block.
Don't touch CONTENT_IGNORE or CONTENT_AIR. Don't touch CONTENT_IGNORE or CONTENT_AIR.
*/ */
for(u16 i=0; i<256; i++) for(u16 i=0; i<MAX_CONTENT+1; i++)
{ {
if(i == CONTENT_IGNORE || i == CONTENT_AIR) if(i == CONTENT_IGNORE || i == CONTENT_AIR)
continue; continue;
@ -183,7 +185,7 @@ v3s16 facedir_rotate(u8 facedir, v3s16 dir)
TileSpec MapNode::getTile(v3s16 dir) TileSpec MapNode::getTile(v3s16 dir)
{ {
if(content_features(d).param_type == CPT_FACEDIR_SIMPLE) if(content_features(*this).param_type == CPT_FACEDIR_SIMPLE)
dir = facedir_rotate(param1, dir); dir = facedir_rotate(param1, dir);
TileSpec spec; TileSpec spec;
@ -207,16 +209,16 @@ TileSpec MapNode::getTile(v3s16 dir)
if(dir_i == -1) if(dir_i == -1)
// Non-directional // Non-directional
spec = content_features(d).tiles[0]; spec = content_features(*this).tiles[0];
else else
spec = content_features(d).tiles[dir_i]; spec = content_features(*this).tiles[dir_i];
/* /*
If it contains some mineral, change texture id If it contains some mineral, change texture id
*/ */
if(content_features(d).param_type == CPT_MINERAL && g_texturesource) if(content_features(*this).param_type == CPT_MINERAL && g_texturesource)
{ {
u8 mineral = param & 0x1f; u8 mineral = getMineral();
std::string mineral_texture_name = mineral_block_texture(mineral); std::string mineral_texture_name = mineral_block_texture(mineral);
if(mineral_texture_name != "") if(mineral_texture_name != "")
{ {
@ -235,9 +237,9 @@ TileSpec MapNode::getTile(v3s16 dir)
u8 MapNode::getMineral() u8 MapNode::getMineral()
{ {
if(content_features(d).param_type == CPT_MINERAL) if(content_features(*this).param_type == CPT_MINERAL)
{ {
return param & 0x1f; return param1 & 0x0f;
} }
return MINERAL_NONE; return MINERAL_NONE;
@ -260,33 +262,36 @@ void MapNode::serialize(u8 *dest, u8 version)
if(!ser_ver_supported(version)) if(!ser_ver_supported(version))
throw VersionMismatchException("ERROR: MapNode format not supported"); throw VersionMismatchException("ERROR: MapNode format not supported");
u8 actual_d = d; // Translate to wanted version
MapNode n_foreign = mapnode_translate_from_internal(*this, version);
// Convert from new version to old u8 actual_param0 = n_foreign.param0;
// Convert special values from new version to old
if(version <= 18) if(version <= 18)
{ {
// In these versions, CONTENT_IGNORE and CONTENT_AIR // In these versions, CONTENT_IGNORE and CONTENT_AIR
// are 255 and 254 // are 255 and 254
if(actual_d == CONTENT_IGNORE) if(actual_param0 == CONTENT_IGNORE)
actual_d = 255; actual_param0 = 255;
else if(actual_d == CONTENT_AIR) else if(actual_param0 == CONTENT_AIR)
actual_d = 254; actual_param0 = 254;
} }
if(version == 0) if(version == 0)
{ {
dest[0] = actual_d; dest[0] = actual_param0;
} }
else if(version <= 9) else if(version <= 9)
{ {
dest[0] = actual_d; dest[0] = actual_param0;
dest[1] = param; dest[1] = n_foreign.param1;
} }
else else
{ {
dest[0] = actual_d; dest[0] = actual_param0;
dest[1] = param; dest[1] = n_foreign.param1;
dest[2] = param2; dest[2] = n_foreign.param2;
} }
} }
void MapNode::deSerialize(u8 *source, u8 version) void MapNode::deSerialize(u8 *source, u8 version)
@ -296,47 +301,50 @@ void MapNode::deSerialize(u8 *source, u8 version)
if(version == 0) if(version == 0)
{ {
d = source[0]; param0 = source[0];
} }
else if(version == 1) else if(version == 1)
{ {
d = source[0]; param0 = source[0];
// This version doesn't support saved lighting // This version doesn't support saved lighting
if(light_propagates() || light_source() > 0) if(light_propagates() || light_source() > 0)
param = 0; param1 = 0;
else else
param = source[1]; param1 = source[1];
} }
else if(version <= 9) else if(version <= 9)
{ {
d = source[0]; param0 = source[0];
param = source[1]; param1 = source[1];
} }
else else
{ {
d = source[0]; param0 = source[0];
param = source[1]; param1 = source[1];
param2 = source[2]; param2 = source[2];
} }
// Convert from old version to new // Convert special values from old version to new
if(version <= 18) if(version <= 18)
{ {
// In these versions, CONTENT_IGNORE and CONTENT_AIR // In these versions, CONTENT_IGNORE and CONTENT_AIR
// are 255 and 254 // are 255 and 254
if(d == 255) if(param0 == 255)
d = CONTENT_IGNORE; param0 = CONTENT_IGNORE;
else if(d == 254) else if(param0 == 254)
d = CONTENT_AIR; param0 = CONTENT_AIR;
} }
// version 19 is fucked up with sometimes the old values and sometimes not // version 19 is fucked up with sometimes the old values and sometimes not
if(version == 19) if(version == 19)
{ {
if(d == 255) if(param0 == 255)
d = CONTENT_IGNORE; param0 = CONTENT_IGNORE;
else if(d == 254) else if(param0 == 254)
d = CONTENT_AIR; param0 = CONTENT_AIR;
} }
// Translate to our known version
*this = mapnode_translate_to_internal(*this, version);
} }
/* /*

@ -32,16 +32,15 @@ with this program; if not, write to the Free Software Foundation, Inc.,
/* /*
Naming scheme: Naming scheme:
- Material = irrlicht's Material class - Material = irrlicht's Material class
- Content = (u8) content of a node - Content = (content_t) content of a node
- Tile = TileSpec at some side of a node of some content type - Tile = TileSpec at some side of a node of some content type
*/
/* Content ranges:
Ranges:
0x000...0x07f: param2 is fully usable 0x000...0x07f: param2 is fully usable
0x800...0xfff: param2 lower 4 bytes are free 0x800...0xfff: param2 lower 4 bytes are free
*/ */
typedef u16 content_t; typedef u16 content_t;
#define MAX_CONTENT 0xfff
/* /*
Initializes all kind of stuff in here. Initializes all kind of stuff in here.
@ -102,10 +101,7 @@ class NodeMetadata;
struct ContentFeatures struct ContentFeatures
{ {
// If non-NULL, content is translated to this when deserialized // Type of MapNode::param1
//MapNode *translate_to;
// Type of MapNode::param
ContentParamType param_type; ContentParamType param_type;
/* /*
@ -120,6 +116,7 @@ struct ContentFeatures
video::ITexture *inventory_texture; video::ITexture *inventory_texture;
// True for all ground-like things like stone and mud, false for eg. trees
bool is_ground_content; bool is_ground_content;
bool light_propagates; bool light_propagates;
bool sunlight_propagates; bool sunlight_propagates;
@ -150,10 +147,10 @@ struct ContentFeatures
NodeMetadata *initial_metadata; NodeMetadata *initial_metadata;
// If the content is liquid, this is the flowing version of the liquid. // If the content is liquid, this is the flowing version of the liquid.
// If content is flowing liquid, this is the same content. // If content is liquid, this is the same content.
u8 liquid_alternative_flowing; content_t liquid_alternative_flowing;
// If the content is liquid, this is the source version of the liquid. // If the content is liquid, this is the source version of the liquid.
u8 liquid_alternative_source; content_t liquid_alternative_source;
// Amount of light the node emits // Amount of light the node emits
u8 light_source; u8 light_source;
@ -165,7 +162,6 @@ struct ContentFeatures
void reset() void reset()
{ {
//translate_to = NULL;
param_type = CPT_NONE; param_type = CPT_NONE;
inventory_texture = NULL; inventory_texture = NULL;
is_ground_content = false; is_ground_content = false;
@ -230,8 +226,8 @@ struct ContentFeatures
/* /*
Call this to access the ContentFeature list Call this to access the ContentFeature list
*/ */
ContentFeatures & content_features(u8 i); ContentFeatures & content_features(content_t i);
ContentFeatures & content_features(MapNode &n);
/* /*
Here is a bunch of DEPRECATED functions. Here is a bunch of DEPRECATED functions.
@ -242,7 +238,7 @@ ContentFeatures & content_features(u8 i);
in param. in param.
NOTE: Don't use, use "content_features(m).whatever" instead NOTE: Don't use, use "content_features(m).whatever" instead
*/ */
inline bool light_propagates_content(u8 m) inline bool light_propagates_content(content_t m)
{ {
return content_features(m).light_propagates; return content_features(m).light_propagates;
} }
@ -251,7 +247,7 @@ inline bool light_propagates_content(u8 m)
NOTE: It doesn't seem to go through torches regardlessly of this NOTE: It doesn't seem to go through torches regardlessly of this
NOTE: Don't use, use "content_features(m).whatever" instead NOTE: Don't use, use "content_features(m).whatever" instead
*/ */
inline bool sunlight_propagates_content(u8 m) inline bool sunlight_propagates_content(content_t m)
{ {
return content_features(m).sunlight_propagates; return content_features(m).sunlight_propagates;
} }
@ -263,35 +259,35 @@ inline bool sunlight_propagates_content(u8 m)
2: Opaque 2: Opaque
NOTE: Don't use, use "content_features(m).whatever" instead NOTE: Don't use, use "content_features(m).whatever" instead
*/ */
inline u8 content_solidness(u8 m) inline u8 content_solidness(content_t m)
{ {
return content_features(m).solidness; return content_features(m).solidness;
} }
// Objects collide with walkable contents // Objects collide with walkable contents
// NOTE: Don't use, use "content_features(m).whatever" instead // NOTE: Don't use, use "content_features(m).whatever" instead
inline bool content_walkable(u8 m) inline bool content_walkable(content_t m)
{ {
return content_features(m).walkable; return content_features(m).walkable;
} }
// NOTE: Don't use, use "content_features(m).whatever" instead // NOTE: Don't use, use "content_features(m).whatever" instead
inline bool content_liquid(u8 m) inline bool content_liquid(content_t m)
{ {
return content_features(m).liquid_type != LIQUID_NONE; return content_features(m).liquid_type != LIQUID_NONE;
} }
// NOTE: Don't use, use "content_features(m).whatever" instead // NOTE: Don't use, use "content_features(m).whatever" instead
inline bool content_flowing_liquid(u8 m) inline bool content_flowing_liquid(content_t m)
{ {
return content_features(m).liquid_type == LIQUID_FLOWING; return content_features(m).liquid_type == LIQUID_FLOWING;
} }
// NOTE: Don't use, use "content_features(m).whatever" instead // NOTE: Don't use, use "content_features(m).whatever" instead
inline bool content_liquid_source(u8 m) inline bool content_liquid_source(content_t m)
{ {
return content_features(m).liquid_type == LIQUID_SOURCE; return content_features(m).liquid_type == LIQUID_SOURCE;
} }
// CONTENT_WATER || CONTENT_WATERSOURCE -> CONTENT_WATER // CONTENT_WATER || CONTENT_WATERSOURCE -> CONTENT_WATER
// CONTENT_LAVA || CONTENT_LAVASOURCE -> CONTENT_LAVA // CONTENT_LAVA || CONTENT_LAVASOURCE -> CONTENT_LAVA
// NOTE: Don't use, use "content_features(m).whatever" instead // NOTE: Don't use, use "content_features(m).whatever" instead
inline u8 make_liquid_flowing(u8 m) inline content_t make_liquid_flowing(content_t m)
{ {
u8 c = content_features(m).liquid_alternative_flowing; u8 c = content_features(m).liquid_alternative_flowing;
assert(c != CONTENT_IGNORE); assert(c != CONTENT_IGNORE);
@ -299,17 +295,17 @@ inline u8 make_liquid_flowing(u8 m)
} }
// Pointable contents can be pointed to in the map // Pointable contents can be pointed to in the map
// NOTE: Don't use, use "content_features(m).whatever" instead // NOTE: Don't use, use "content_features(m).whatever" instead
inline bool content_pointable(u8 m) inline bool content_pointable(content_t m)
{ {
return content_features(m).pointable; return content_features(m).pointable;
} }
// NOTE: Don't use, use "content_features(m).whatever" instead // NOTE: Don't use, use "content_features(m).whatever" instead
inline bool content_diggable(u8 m) inline bool content_diggable(content_t m)
{ {
return content_features(m).diggable; return content_features(m).diggable;
} }
// NOTE: Don't use, use "content_features(m).whatever" instead // NOTE: Don't use, use "content_features(m).whatever" instead
inline bool content_buildable_to(u8 m) inline bool content_buildable_to(content_t m)
{ {
return content_features(m).buildable_to; return content_features(m).buildable_to;
} }
@ -321,7 +317,7 @@ inline bool content_buildable_to(u8 m)
1: Face uses m1's content 1: Face uses m1's content
2: Face uses m2's content 2: Face uses m2's content
*/ */
inline u8 face_contents(u8 m1, u8 m2) inline u8 face_contents(content_t m1, content_t m2)
{ {
if(m1 == CONTENT_IGNORE || m2 == CONTENT_IGNORE) if(m1 == CONTENT_IGNORE || m2 == CONTENT_IGNORE)
return 0; return 0;
@ -425,7 +421,7 @@ struct MapNode
union union
{ {
u8 param0; u8 param0;
u8 d; //u8 d;
}; };
/* /*
@ -440,17 +436,18 @@ struct MapNode
union union
{ {
u8 param1; u8 param1;
s8 param; //s8 param;
}; };
/* /*
The second parameter. Initialized to 0. The second parameter. Initialized to 0.
E.g. direction for torches and flowing water. E.g. direction for torches and flowing water.
If param0 >= 0x80, bits 0xf0 of this is extended content type data
*/ */
union union
{ {
u8 param2; u8 param2;
u8 dir; //u8 dir;
}; };
MapNode(const MapNode & n) MapNode(const MapNode & n)
@ -458,28 +455,44 @@ struct MapNode
*this = n; *this = n;
} }
MapNode(u8 data=CONTENT_AIR, u8 a_param=0, u8 a_param2=0) MapNode(content_t content=CONTENT_AIR, u8 a_param1=0, u8 a_param2=0)
{ {
d = data; //param0 = a_param0;
param = a_param; param1 = a_param1;
param2 = a_param2; param2 = a_param2;
// Set after other params because this needs to override part of param2
setContent(content);
} }
bool operator==(const MapNode &other) bool operator==(const MapNode &other)
{ {
return (d == other.d return (param0 == other.param0
&& param == other.param && param1 == other.param1
&& param2 == other.param2); && param2 == other.param2);
} }
// To be used everywhere // To be used everywhere
content_t getContent() content_t getContent()
{ {
return d; if(param0 < 0x80)
return param0;
else
return (param0<<4) + (param2>>4);
} }
void setContent(content_t c) void setContent(content_t c)
{ {
d = c; if(c < 0x80)
{
if(param0 >= 0x80)
param2 &= ~(0xf0);
param0 = c;
}
else
{
param0 = c>>4;
param2 &= ~(0xf0);
param2 |= (c&0x0f)<<4;
}
} }
/* /*
@ -487,19 +500,19 @@ struct MapNode
*/ */
bool light_propagates() bool light_propagates()
{ {
return light_propagates_content(d); return light_propagates_content(getContent());
} }
bool sunlight_propagates() bool sunlight_propagates()
{ {
return sunlight_propagates_content(d); return sunlight_propagates_content(getContent());
} }
u8 solidness() u8 solidness()
{ {
return content_solidness(d); return content_solidness(getContent());
} }
u8 light_source() u8 light_source()
{ {
return content_features(d).light_source; return content_features(*this).light_source;
} }
u8 getLightBanksWithSource() u8 getLightBanksWithSource()
@ -507,10 +520,10 @@ struct MapNode
// Select the brightest of [light source, propagated light] // Select the brightest of [light source, propagated light]
u8 lightday = 0; u8 lightday = 0;
u8 lightnight = 0; u8 lightnight = 0;
if(content_features(d).param_type == CPT_LIGHT) if(content_features(*this).param_type == CPT_LIGHT)
{ {
lightday = param & 0x0f; lightday = param1 & 0x0f;
lightnight = (param>>4)&0x0f; lightnight = (param1>>4)&0x0f;
} }
if(light_source() > lightday) if(light_source() > lightday)
lightday = light_source(); lightday = light_source();
@ -523,12 +536,12 @@ struct MapNode
{ {
// Select the brightest of [light source, propagated light] // Select the brightest of [light source, propagated light]
u8 light = 0; u8 light = 0;
if(content_features(d).param_type == CPT_LIGHT) if(content_features(*this).param_type == CPT_LIGHT)
{ {
if(bank == LIGHTBANK_DAY) if(bank == LIGHTBANK_DAY)
light = param & 0x0f; light = param1 & 0x0f;
else if(bank == LIGHTBANK_NIGHT) else if(bank == LIGHTBANK_NIGHT)
light = (param>>4)&0x0f; light = (param1>>4)&0x0f;
else else
assert(0); assert(0);
} }
@ -566,17 +579,17 @@ struct MapNode
void setLight(enum LightBank bank, u8 a_light) void setLight(enum LightBank bank, u8 a_light)
{ {
// If node doesn't contain light data, ignore this // If node doesn't contain light data, ignore this
if(content_features(d).param_type != CPT_LIGHT) if(content_features(*this).param_type != CPT_LIGHT)
return; return;
if(bank == LIGHTBANK_DAY) if(bank == LIGHTBANK_DAY)
{ {
param &= 0xf0; param1 &= 0xf0;
param |= a_light & 0x0f; param1 |= a_light & 0x0f;
} }
else if(bank == LIGHTBANK_NIGHT) else if(bank == LIGHTBANK_NIGHT)
{ {
param &= 0x0f; param1 &= 0x0f;
param |= (a_light & 0x0f)<<4; param1 |= (a_light & 0x0f)<<4;
} }
else else
assert(0); assert(0);

@ -3,12 +3,12 @@
// NOTE: DEPRECATED // NOTE: DEPRECATED
DiggingPropertiesList * getDiggingPropertiesList(u8 content) DiggingPropertiesList * getDiggingPropertiesList(u16 content)
{ {
return &content_features(content).digging_properties; return &content_features(content).digging_properties;
} }
DiggingProperties getDiggingProperties(u8 content, const std::string &tool) DiggingProperties getDiggingProperties(u16 content, const std::string &tool)
{ {
DiggingPropertiesList *mprop = getDiggingPropertiesList(content); DiggingPropertiesList *mprop = getDiggingPropertiesList(content);
if(mprop == NULL) if(mprop == NULL)

@ -97,7 +97,7 @@ private:
}; };
// For getting the default properties, set tool="" // For getting the default properties, set tool=""
DiggingProperties getDiggingProperties(u8 material, const std::string &tool); DiggingProperties getDiggingProperties(u16 material, const std::string &tool);
#endif #endif

@ -342,13 +342,13 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
if(in_water) if(in_water)
{ {
v3s16 pp = floatToInt(position + v3f(0,BS*0.1,0), BS); v3s16 pp = floatToInt(position + v3f(0,BS*0.1,0), BS);
in_water = content_liquid(map.getNode(pp).d); in_water = content_liquid(map.getNode(pp).getContent());
} }
// If not in water, the threshold of going in is at lower y // If not in water, the threshold of going in is at lower y
else else
{ {
v3s16 pp = floatToInt(position + v3f(0,BS*0.5,0), BS); v3s16 pp = floatToInt(position + v3f(0,BS*0.5,0), BS);
in_water = content_liquid(map.getNode(pp).d); in_water = content_liquid(map.getNode(pp).getContent());
} }
} }
catch(InvalidPositionException &e) catch(InvalidPositionException &e)
@ -361,7 +361,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
*/ */
try{ try{
v3s16 pp = floatToInt(position + v3f(0,0,0), BS); v3s16 pp = floatToInt(position + v3f(0,0,0), BS);
in_water_stable = content_liquid(map.getNode(pp).d); in_water_stable = content_liquid(map.getNode(pp).getContent());
} }
catch(InvalidPositionException &e) catch(InvalidPositionException &e)
{ {
@ -470,7 +470,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
{ {
try{ try{
// Player collides into walkable nodes // Player collides into walkable nodes
if(content_walkable(map.getNode(v3s16(x,y,z)).d) == false) if(content_walkable(map.getNode(v3s16(x,y,z)).getContent()) == false)
continue; continue;
} }
catch(InvalidPositionException &e) catch(InvalidPositionException &e)
@ -633,10 +633,10 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d,
try{ try{
// The node to be sneaked on has to be walkable // The node to be sneaked on has to be walkable
if(content_walkable(map.getNode(p).d) == false) if(content_walkable(map.getNode(p).getContent()) == false)
continue; continue;
// And the node above it has to be nonwalkable // And the node above it has to be nonwalkable
if(content_walkable(map.getNode(p+v3s16(0,1,0)).d) == true) if(content_walkable(map.getNode(p+v3s16(0,1,0)).getContent()) == true)
continue; continue;
} }
catch(InvalidPositionException &e) catch(InvalidPositionException &e)

@ -55,11 +55,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
17: MapBlocks contain timestamp 17: MapBlocks contain timestamp
18: new generator (not really necessary, but it's there) 18: new generator (not really necessary, but it's there)
19: new content type handling 19: new content type handling
20: many existing content types translated to extended ones
*/ */
// This represents an uninitialized or invalid format // This represents an uninitialized or invalid format
#define SER_FMT_VER_INVALID 255 #define SER_FMT_VER_INVALID 255
// Highest supported serialization version // Highest supported serialization version
#define SER_FMT_VER_HIGHEST 19 #define SER_FMT_VER_HIGHEST 20
// Lowest supported serialization version // Lowest supported serialization version
#define SER_FMT_VER_LOWEST 0 #define SER_FMT_VER_LOWEST 0

@ -105,10 +105,10 @@ void * EmergeThread::Thread()
DSTACK(__FUNCTION_NAME); DSTACK(__FUNCTION_NAME);
//bool debug=false;
BEGIN_DEBUG_EXCEPTION_HANDLER BEGIN_DEBUG_EXCEPTION_HANDLER
bool enable_mapgen_debug_info = g_settings.getBool("enable_mapgen_debug_info");
/* /*
Get block info from queue, emerge them and send them Get block info from queue, emerge them and send them
to clients. to clients.
@ -155,7 +155,7 @@ void * EmergeThread::Thread()
Also decrement the emerge queue count in clients. Also decrement the emerge queue count in clients.
*/ */
bool optional = true; bool only_from_disk = true;
{ {
core::map<u16, u8>::Iterator i; core::map<u16, u8>::Iterator i;
@ -166,14 +166,15 @@ void * EmergeThread::Thread()
// Check flags // Check flags
u8 flags = i.getNode()->getValue(); u8 flags = i.getNode()->getValue();
if((flags & BLOCK_EMERGE_FLAG_FROMDISK) == false) if((flags & BLOCK_EMERGE_FLAG_FROMDISK) == false)
optional = false; only_from_disk = false;
} }
} }
/*dstream<<"EmergeThread: p=" if(enable_mapgen_debug_info)
dstream<<"EmergeThread: p="
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<") " <<"("<<p.X<<","<<p.Y<<","<<p.Z<<") "
<<"optional="<<optional<<std::endl;*/ <<"only_from_disk="<<only_from_disk<<std::endl;
ServerMap &map = ((ServerMap&)m_server->m_env.getMap()); ServerMap &map = ((ServerMap&)m_server->m_env.getMap());
@ -184,11 +185,6 @@ void * EmergeThread::Thread()
bool got_block = true; bool got_block = true;
core::map<v3s16, MapBlock*> modified_blocks; core::map<v3s16, MapBlock*> modified_blocks;
bool only_from_disk = false;
if(optional)
only_from_disk = true;
/* /*
Fetch block from map or generate a single block Fetch block from map or generate a single block
*/ */
@ -203,6 +199,9 @@ void * EmergeThread::Thread()
block = map.getBlockNoCreateNoEx(p); block = map.getBlockNoCreateNoEx(p);
if(!block || block->isDummy() || !block->isGenerated()) if(!block || block->isDummy() || !block->isGenerated())
{ {
if(enable_mapgen_debug_info)
dstream<<"EmergeThread: not in memory, loading"<<std::endl;
// Get, load or create sector // Get, load or create sector
/*ServerMapSector *sector = /*ServerMapSector *sector =
(ServerMapSector*)map.createSector(p2d);*/ (ServerMapSector*)map.createSector(p2d);*/
@ -214,11 +213,19 @@ void * EmergeThread::Thread()
block = map.loadBlock(p); block = map.loadBlock(p);
if(block == NULL && only_from_disk == false) if(only_from_disk == false)
{
if(block == NULL || block->isGenerated() == false)
{
if(enable_mapgen_debug_info)
dstream<<"EmergeThread: generating"<<std::endl;
block = map.generateBlock(p, modified_blocks); block = map.generateBlock(p, modified_blocks);
//block = map.generateBlock(p, changed_blocks); }
/*block = map.generateBlock(p, block, sector, changed_blocks, }
lighting_invalidated_blocks);*/
if(enable_mapgen_debug_info)
dstream<<"EmergeThread: ended up with: "
<<analyze_block(block)<<std::endl;
if(block == NULL) if(block == NULL)
{ {
@ -2494,7 +2501,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
// Mandatory parameter; actually used for nothing // Mandatory parameter; actually used for nothing
core::map<v3s16, MapBlock*> modified_blocks; core::map<v3s16, MapBlock*> modified_blocks;
u8 material = CONTENT_IGNORE; content_t material = CONTENT_IGNORE;
u8 mineral = MINERAL_NONE; u8 mineral = MINERAL_NONE;
bool cannot_remove_node = false; bool cannot_remove_node = false;
@ -2505,7 +2512,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
// Get mineral // Get mineral
mineral = n.getMineral(); mineral = n.getMineral();
// Get material at position // Get material at position
material = n.d; material = n.getContent();
// If not yet cancelled // If not yet cancelled
if(cannot_remove_node == false) if(cannot_remove_node == false)
{ {
@ -2705,7 +2712,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
<<" because privileges are "<<getPlayerPrivs(player) <<" because privileges are "<<getPlayerPrivs(player)
<<std::endl; <<std::endl;
if(content_buildable_to(n2.d) == false if(content_features(n2).buildable_to == false
|| no_enough_privs) || no_enough_privs)
{ {
// Client probably has wrong data. // Client probably has wrong data.
@ -2736,14 +2743,14 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
// Create node data // Create node data
MaterialItem *mitem = (MaterialItem*)item; MaterialItem *mitem = (MaterialItem*)item;
MapNode n; MapNode n;
n.d = mitem->getMaterial(); n.setContent(mitem->getMaterial());
// Calculate direction for wall mounted stuff // Calculate direction for wall mounted stuff
if(content_features(n.d).wall_mounted) if(content_features(n).wall_mounted)
n.dir = packDir(p_under - p_over); n.param2 = packDir(p_under - p_over);
// Calculate the direction for furnaces and chests and stuff // Calculate the direction for furnaces and chests and stuff
if(content_features(n.d).param_type == CPT_FACEDIR_SIMPLE) if(content_features(n).param_type == CPT_FACEDIR_SIMPLE)
{ {
v3f playerpos = player->getPosition(); v3f playerpos = player->getPosition();
v3f blockpos = intToFloat(p_over, BS) - playerpos; v3f blockpos = intToFloat(p_over, BS) - playerpos;

@ -219,14 +219,14 @@ struct TestMapNode
MapNode n; MapNode n;
// Default values // Default values
assert(n.d == CONTENT_AIR); assert(n.getContent() == CONTENT_AIR);
assert(n.getLight(LIGHTBANK_DAY) == 0); assert(n.getLight(LIGHTBANK_DAY) == 0);
assert(n.getLight(LIGHTBANK_NIGHT) == 0); assert(n.getLight(LIGHTBANK_NIGHT) == 0);
// Transparency // Transparency
n.d = CONTENT_AIR; n.setContent(CONTENT_AIR);
assert(n.light_propagates() == true); assert(n.light_propagates() == true);
n.d = CONTENT_STONE; n.setContent(CONTENT_STONE);
assert(n.light_propagates() == false); assert(n.light_propagates() == false);
} }
}; };
@ -284,7 +284,7 @@ struct TestVoxelManipulator
v.print(dstream); v.print(dstream);
assert(v.getNode(v3s16(-1,0,-1)).d == 2); assert(v.getNode(v3s16(-1,0,-1)).getContent() == 2);
dstream<<"*** Reading from inexistent (0,0,-1) ***"<<std::endl; dstream<<"*** Reading from inexistent (0,0,-1) ***"<<std::endl;
@ -298,7 +298,7 @@ struct TestVoxelManipulator
v.print(dstream); v.print(dstream);
assert(v.getNode(v3s16(-1,0,-1)).d == 2); assert(v.getNode(v3s16(-1,0,-1)).getContent() == 2);
EXCEPTION_CHECK(InvalidPositionException, v.getNode(v3s16(0,1,1))); EXCEPTION_CHECK(InvalidPositionException, v.getNode(v3s16(0,1,1)));
#if 0 #if 0
@ -331,11 +331,11 @@ struct TestVoxelManipulator
MapNode n; MapNode n;
//n.pressure = size.Y - y; //n.pressure = size.Y - y;
if(*p == '#') if(*p == '#')
n.d = CONTENT_STONE; n.setContent(CONTENT_STONE);
else if(*p == '.') else if(*p == '.')
n.d = CONTENT_WATER; n.setContent(CONTENT_WATER);
else if(*p == ' ') else if(*p == ' ')
n.d = CONTENT_AIR; n.setContent(CONTENT_AIR);
else else
assert(0); assert(0);
v.setNode(v3s16(x,y,z), n); v.setNode(v3s16(x,y,z), n);
@ -469,8 +469,8 @@ struct TestMapBlock
for(u16 y=0; y<MAP_BLOCKSIZE; y++) for(u16 y=0; y<MAP_BLOCKSIZE; y++)
for(u16 x=0; x<MAP_BLOCKSIZE; x++) 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)).getContent() == CONTENT_AIR);
assert(b.getNode(v3s16(x,y,z)).d == CONTENT_IGNORE); assert(b.getNode(v3s16(x,y,z)).getContent() == CONTENT_IGNORE);
assert(b.getNode(v3s16(x,y,z)).getLight(LIGHTBANK_DAY) == 0); assert(b.getNode(v3s16(x,y,z)).getLight(LIGHTBANK_DAY) == 0);
assert(b.getNode(v3s16(x,y,z)).getLight(LIGHTBANK_NIGHT) == 0); assert(b.getNode(v3s16(x,y,z)).getLight(LIGHTBANK_NIGHT) == 0);
} }
@ -489,7 +489,7 @@ struct TestMapBlock
Parent fetch functions Parent fetch functions
*/ */
parent.position_valid = false; parent.position_valid = false;
parent.node.d = 5; parent.node.setContent(5);
MapNode n; MapNode n;
@ -497,7 +497,7 @@ struct TestMapBlock
assert(b.isValidPositionParent(v3s16(0,0,0)) == true); assert(b.isValidPositionParent(v3s16(0,0,0)) == true);
assert(b.isValidPositionParent(v3s16(MAP_BLOCKSIZE-1,MAP_BLOCKSIZE-1,MAP_BLOCKSIZE-1)) == true); assert(b.isValidPositionParent(v3s16(MAP_BLOCKSIZE-1,MAP_BLOCKSIZE-1,MAP_BLOCKSIZE-1)) == true);
n = b.getNodeParent(v3s16(0,MAP_BLOCKSIZE-1,0)); n = b.getNodeParent(v3s16(0,MAP_BLOCKSIZE-1,0));
assert(n.d == CONTENT_AIR); assert(n.getContent() == CONTENT_AIR);
// ...but outside the block they should be invalid // ...but outside the block they should be invalid
assert(b.isValidPositionParent(v3s16(-121,2341,0)) == false); assert(b.isValidPositionParent(v3s16(-121,2341,0)) == false);
@ -523,15 +523,15 @@ struct TestMapBlock
assert(b.isValidPositionParent(v3s16(-1,0,0)) == true); assert(b.isValidPositionParent(v3s16(-1,0,0)) == true);
assert(b.isValidPositionParent(v3s16(MAP_BLOCKSIZE-1,MAP_BLOCKSIZE-1,MAP_BLOCKSIZE)) == true); assert(b.isValidPositionParent(v3s16(MAP_BLOCKSIZE-1,MAP_BLOCKSIZE-1,MAP_BLOCKSIZE)) == true);
n = b.getNodeParent(v3s16(0,0,MAP_BLOCKSIZE)); n = b.getNodeParent(v3s16(0,0,MAP_BLOCKSIZE));
assert(n.d == 5); assert(n.getContent() == 5);
/* /*
Set a node Set a node
*/ */
v3s16 p(1,2,0); v3s16 p(1,2,0);
n.d = 4; n.setContent(4);
b.setNode(p, n); b.setNode(p, n);
assert(b.getNode(p).d == 4); assert(b.getNode(p).getContent() == 4);
//TODO: Update to new system //TODO: Update to new system
/*assert(b.getNodeTile(p) == 4); /*assert(b.getNodeTile(p) == 4);
assert(b.getNodeTile(v3s16(-1,-1,0)) == 5);*/ assert(b.getNodeTile(v3s16(-1,-1,0)) == 5);*/
@ -556,7 +556,7 @@ struct TestMapBlock
*/ */
parent.position_valid = true; parent.position_valid = true;
b.setIsUnderground(false); b.setIsUnderground(false);
parent.node.d = CONTENT_AIR; parent.node.setContent(CONTENT_AIR);
parent.node.setLight(LIGHTBANK_DAY, LIGHT_SUN); parent.node.setLight(LIGHTBANK_DAY, LIGHT_SUN);
parent.node.setLight(LIGHTBANK_NIGHT, 0); parent.node.setLight(LIGHTBANK_NIGHT, 0);
core::map<v3s16, bool> light_sources; core::map<v3s16, bool> light_sources;
@ -611,7 +611,7 @@ struct TestMapBlock
for(u16 y=0; y<MAP_BLOCKSIZE; y++){ for(u16 y=0; y<MAP_BLOCKSIZE; y++){
for(u16 x=0; x<MAP_BLOCKSIZE; x++){ for(u16 x=0; x<MAP_BLOCKSIZE; x++){
MapNode n; MapNode n;
n.d = CONTENT_AIR; n.setContent(CONTENT_AIR);
n.setLight(LIGHTBANK_DAY, 0); n.setLight(LIGHTBANK_DAY, 0);
b.setNode(v3s16(x,y,z), n); b.setNode(v3s16(x,y,z), n);
} }

@ -179,7 +179,7 @@ void TextureSource::processQueue()
dstream<<"INFO: TextureSource::processQueue(): " dstream<<"INFO: TextureSource::processQueue(): "
<<"got texture request with " <<"got texture request with "
<<"name="<<request.key <<"name=\""<<request.key<<"\""
<<std::endl; <<std::endl;
GetResult<std::string, u32, u8, u8> GetResult<std::string, u32, u8, u8>
@ -194,7 +194,7 @@ void TextureSource::processQueue()
u32 TextureSource::getTextureId(const std::string &name) u32 TextureSource::getTextureId(const std::string &name)
{ {
//dstream<<"INFO: getTextureId(): name="<<name<<std::endl; //dstream<<"INFO: getTextureId(): \""<<name<<"\""<<std::endl;
{ {
/* /*
@ -218,7 +218,7 @@ u32 TextureSource::getTextureId(const std::string &name)
} }
else else
{ {
dstream<<"INFO: getTextureId(): Queued: name="<<name<<std::endl; dstream<<"INFO: getTextureId(): Queued: name=\""<<name<<"\""<<std::endl;
// We're gonna ask the result to be put into here // We're gonna ask the result to be put into here
ResultQueue<std::string, u32, u8, u8> result_queue; ResultQueue<std::string, u32, u8, u8> result_queue;
@ -226,8 +226,8 @@ u32 TextureSource::getTextureId(const std::string &name)
// Throw a request in // Throw a request in
m_get_texture_queue.add(name, 0, 0, &result_queue); m_get_texture_queue.add(name, 0, 0, &result_queue);
dstream<<"INFO: Waiting for texture from main thread, name=" dstream<<"INFO: Waiting for texture from main thread, name=\""
<<name<<std::endl; <<name<<"\""<<std::endl;
try try
{ {
@ -276,7 +276,7 @@ video::IImage* generate_image_from_scratch(std::string name,
*/ */
u32 TextureSource::getTextureIdDirect(const std::string &name) u32 TextureSource::getTextureIdDirect(const std::string &name)
{ {
dstream<<"INFO: getTextureIdDirect(): name="<<name<<std::endl; //dstream<<"INFO: getTextureIdDirect(): name=\""<<name<<"\""<<std::endl;
// Empty name means texture 0 // Empty name means texture 0
if(name == "") if(name == "")
@ -305,14 +305,14 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
n = m_name_to_id.find(name); n = m_name_to_id.find(name);
if(n != NULL) if(n != NULL)
{ {
dstream<<"INFO: getTextureIdDirect(): name="<<name dstream<<"INFO: getTextureIdDirect(): \""<<name
<<" found in cache"<<std::endl; <<"\" found in cache"<<std::endl;
return n->getValue(); return n->getValue();
} }
} }
dstream<<"INFO: getTextureIdDirect(): name="<<name dstream<<"INFO: getTextureIdDirect(): \""<<name
<<" NOT found in cache. Creating it."<<std::endl; <<"\" NOT found in cache. Creating it."<<std::endl;
/* /*
Get the base image Get the base image
@ -346,12 +346,13 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
{ {
// Construct base name // Construct base name
base_image_name = name.substr(0, last_separator_position); base_image_name = name.substr(0, last_separator_position);
dstream<<"INFO: getTextureIdDirect(): Calling itself recursively" /*dstream<<"INFO: getTextureIdDirect(): Calling itself recursively"
" to get base image, name="<<base_image_name<<std::endl; " to get base image of \""<<name<<"\" = \""
<<base_image_name<<"\""<<std::endl;*/
base_image_id = getTextureIdDirect(base_image_name); base_image_id = getTextureIdDirect(base_image_name);
} }
dstream<<"base_image_id="<<base_image_id<<std::endl; //dstream<<"base_image_id="<<base_image_id<<std::endl;
video::IVideoDriver* driver = m_device->getVideoDriver(); video::IVideoDriver* driver = m_device->getVideoDriver();
assert(driver); assert(driver);
@ -393,9 +394,9 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
core::rect<s32>(pos_from, dim) // from core::rect<s32>(pos_from, dim) // from
); );
dstream<<"INFO: getTextureIdDirect(): Loaded \"" /*dstream<<"INFO: getTextureIdDirect(): Loaded \""
<<base_image_name<<"\" from image cache" <<base_image_name<<"\" from image cache"
<<std::endl; <<std::endl;*/
} }
} }
@ -405,7 +406,7 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
*/ */
std::string last_part_of_name = name.substr(last_separator_position+1); std::string last_part_of_name = name.substr(last_separator_position+1);
dstream<<"last_part_of_name="<<last_part_of_name<<std::endl; //dstream<<"last_part_of_name=\""<<last_part_of_name<<"\""<<std::endl;
// Generate image according to part of name // Generate image according to part of name
if(generate_image(last_part_of_name, baseimg, m_device) == false) if(generate_image(last_part_of_name, baseimg, m_device) == false)
@ -447,8 +448,8 @@ u32 TextureSource::getTextureIdDirect(const std::string &name)
m_atlaspointer_cache.push_back(nap); m_atlaspointer_cache.push_back(nap);
m_name_to_id.insert(name, id); m_name_to_id.insert(name, id);
dstream<<"INFO: getTextureIdDirect(): name="<<name /*dstream<<"INFO: getTextureIdDirect(): "
<<": succesfully returning id="<<id<<std::endl; <<"Returning id="<<id<<" for name \""<<name<<"\""<<std::endl;*/
return id; return id;
} }
@ -517,13 +518,11 @@ void TextureSource::buildMainAtlas()
sourcelist.push_back("cobble.png"); sourcelist.push_back("cobble.png");
sourcelist.push_back("mossycobble.png"); sourcelist.push_back("mossycobble.png");
sourcelist.push_back("gravel.png"); sourcelist.push_back("gravel.png");
sourcelist.push_back("cactus.png");
sourcelist.push_back("jungletree.png");
sourcelist.push_back("stone.png^mineral_coal.png"); sourcelist.push_back("stone.png^mineral_coal.png");
sourcelist.push_back("stone.png^mineral_iron.png"); sourcelist.push_back("stone.png^mineral_iron.png");
sourcelist.push_back("mud.png^mineral_coal.png");
sourcelist.push_back("mud.png^mineral_iron.png");
sourcelist.push_back("sand.png^mineral_coal.png");
sourcelist.push_back("sand.png^mineral_iron.png");
// Padding to disallow texture bleeding // Padding to disallow texture bleeding
s32 padding = 16; s32 padding = 16;
@ -580,6 +579,9 @@ void TextureSource::buildMainAtlas()
break; break;
} }
dstream<<"INFO: TextureSource::buildMainAtlas(): Adding \""<<name
<<"\" to texture atlas"<<std::endl;
// Tile it a few times in the X direction // Tile it a few times in the X direction
u16 xwise_tiling = 16; u16 xwise_tiling = 16;
for(u32 j=0; j<xwise_tiling; j++) for(u32 j=0; j<xwise_tiling; j++)
@ -670,8 +672,8 @@ void TextureSource::buildMainAtlas()
video::IImage* generate_image_from_scratch(std::string name, video::IImage* generate_image_from_scratch(std::string name,
IrrlichtDevice *device) IrrlichtDevice *device)
{ {
dstream<<"INFO: generate_image_from_scratch(): " /*dstream<<"INFO: generate_image_from_scratch(): "
"name="<<name<<std::endl; "\""<<name<<"\""<<std::endl;*/
video::IVideoDriver* driver = device->getVideoDriver(); video::IVideoDriver* driver = device->getVideoDriver();
assert(driver); assert(driver);
@ -708,8 +710,9 @@ video::IImage* generate_image_from_scratch(std::string name,
{ {
// Construct base name // Construct base name
base_image_name = name.substr(0, last_separator_position); base_image_name = name.substr(0, last_separator_position);
dstream<<"INFO: generate_image_from_scratch(): Calling itself recursively" /*dstream<<"INFO: generate_image_from_scratch(): Calling itself recursively"
" to get base image, name="<<base_image_name<<std::endl; " to get base image of \""<<name<<"\" = \""
<<base_image_name<<"\""<<std::endl;*/
baseimg = generate_image_from_scratch(base_image_name, device); baseimg = generate_image_from_scratch(base_image_name, device);
} }
@ -719,7 +722,7 @@ video::IImage* generate_image_from_scratch(std::string name,
*/ */
std::string last_part_of_name = name.substr(last_separator_position+1); std::string last_part_of_name = name.substr(last_separator_position+1);
dstream<<"last_part_of_name="<<last_part_of_name<<std::endl; //dstream<<"last_part_of_name=\""<<last_part_of_name<<"\""<<std::endl;
// Generate image according to part of name // Generate image according to part of name
if(generate_image(last_part_of_name, baseimg, device) == false) if(generate_image(last_part_of_name, baseimg, device) == false)
@ -744,21 +747,21 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
{ {
// A normal texture; load it from a file // A normal texture; load it from a file
std::string path = getTexturePath(part_of_name.c_str()); std::string path = getTexturePath(part_of_name.c_str());
dstream<<"INFO: getTextureIdDirect(): Loading path \""<<path /*dstream<<"INFO: generate_image(): Loading path \""<<path
<<"\""<<std::endl; <<"\""<<std::endl;*/
video::IImage *image = driver->createImageFromFile(path.c_str()); video::IImage *image = driver->createImageFromFile(path.c_str());
if(image == NULL) if(image == NULL)
{ {
dstream<<"WARNING: Could not load image \""<<part_of_name dstream<<"WARNING: generate_image(): Could not load image \""
<<"\" from path \""<<path<<"\"" <<part_of_name<<"\" from path \""<<path<<"\""
<<" while building texture"<<std::endl; <<" while building texture"<<std::endl;
//return false; //return false;
dstream<<"WARNING: Creating a dummy"<<" image for \"" dstream<<"WARNING: generate_image(): Creating a dummy"
<<part_of_name<<"\""<<std::endl; <<" image for \""<<part_of_name<<"\""<<std::endl;
// Just create a dummy image // Just create a dummy image
//core::dimension2d<u32> dim(2,2); //core::dimension2d<u32> dim(2,2);
@ -782,7 +785,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
// If base image is NULL, load as base. // If base image is NULL, load as base.
if(baseimg == NULL) if(baseimg == NULL)
{ {
dstream<<"INFO: Setting "<<part_of_name<<" as base"<<std::endl; //dstream<<"INFO: Setting "<<part_of_name<<" as base"<<std::endl;
/* /*
Copy it this way to get an alpha channel. Copy it this way to get an alpha channel.
Otherwise images with alpha cannot be blitted on Otherwise images with alpha cannot be blitted on
@ -796,7 +799,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
// Else blit on base. // Else blit on base.
else else
{ {
dstream<<"INFO: Blitting "<<part_of_name<<" on base"<<std::endl; //dstream<<"INFO: Blitting "<<part_of_name<<" on base"<<std::endl;
// Size of the copied area // Size of the copied area
core::dimension2d<u32> dim = image->getDimension(); core::dimension2d<u32> dim = image->getDimension();
//core::dimension2d<u32> dim(16,16); //core::dimension2d<u32> dim(16,16);
@ -817,7 +820,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
{ {
// A special texture modification // A special texture modification
dstream<<"INFO: getTextureIdDirect(): generating special " dstream<<"INFO: generate_image(): generating special "
<<"modification \""<<part_of_name<<"\"" <<"modification \""<<part_of_name<<"\""
<<std::endl; <<std::endl;
@ -840,9 +843,9 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
{ {
if(baseimg == NULL) if(baseimg == NULL)
{ {
dstream<<"WARNING: getTextureIdDirect(): baseimg==NULL " dstream<<"WARNING: generate_image(): baseimg==NULL "
<<"for part_of_name="<<part_of_name <<"for part_of_name=\""<<part_of_name
<<", cancelling."<<std::endl; <<"\", cancelling."<<std::endl;
return false; return false;
} }
@ -977,9 +980,9 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
{ {
if(baseimg == NULL) if(baseimg == NULL)
{ {
dstream<<"WARNING: getTextureIdDirect(): baseimg==NULL " dstream<<"WARNING: generate_image(): baseimg==NULL "
<<"for part_of_name="<<part_of_name <<"for part_of_name=\""<<part_of_name
<<", cancelling."<<std::endl; <<"\", cancelling."<<std::endl;
return false; return false;
} }
@ -997,9 +1000,9 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
{ {
if(baseimg != NULL) if(baseimg != NULL)
{ {
dstream<<"WARNING: getTextureIdDirect(): baseimg!=NULL " dstream<<"WARNING: generate_image(): baseimg!=NULL "
<<"for part_of_name="<<part_of_name <<"for part_of_name=\""<<part_of_name
<<", cancelling."<<std::endl; <<"\", cancelling."<<std::endl;
return false; return false;
} }
@ -1007,14 +1010,14 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
std::string path = getTexturePath(filename.c_str()); std::string path = getTexturePath(filename.c_str());
dstream<<"INFO: getTextureIdDirect(): Loading path \""<<path dstream<<"INFO: generate_image(): Loading path \""<<path
<<"\""<<std::endl; <<"\""<<std::endl;
video::IImage *image = driver->createImageFromFile(path.c_str()); video::IImage *image = driver->createImageFromFile(path.c_str());
if(image == NULL) if(image == NULL)
{ {
dstream<<"WARNING: getTextureIdDirect(): Loading path \"" dstream<<"WARNING: generate_image(): Loading path \""
<<path<<"\" failed"<<std::endl; <<path<<"\" failed"<<std::endl;
} }
else else
@ -1048,9 +1051,9 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
{ {
if(baseimg != NULL) if(baseimg != NULL)
{ {
dstream<<"WARNING: getTextureIdDirect(): baseimg!=NULL " dstream<<"WARNING: generate_image(): baseimg!=NULL "
<<"for part_of_name="<<part_of_name <<"for part_of_name=\""<<part_of_name
<<", cancelling."<<std::endl; <<"\", cancelling."<<std::endl;
return false; return false;
} }
@ -1066,7 +1069,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
if(driver->queryFeature(video::EVDF_RENDER_TO_TARGET) == false) if(driver->queryFeature(video::EVDF_RENDER_TO_TARGET) == false)
{ {
dstream<<"WARNING: getTextureIdDirect(): EVDF_RENDER_TO_TARGET" dstream<<"WARNING: generate_image(): EVDF_RENDER_TO_TARGET"
" not supported. Creating fallback image"<<std::endl; " not supported. Creating fallback image"<<std::endl;
baseimg = generate_image_from_scratch( baseimg = generate_image_from_scratch(
imagename_top, device); imagename_top, device);
@ -1075,7 +1078,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
u32 w0 = 64; u32 w0 = 64;
u32 h0 = 64; u32 h0 = 64;
dstream<<"INFO: inventorycube w="<<w0<<" h="<<h0<<std::endl; //dstream<<"INFO: inventorycube w="<<w0<<" h="<<h0<<std::endl;
core::dimension2d<u32> dim(w0,h0); core::dimension2d<u32> dim(w0,h0);
// Generate images for the faces of the cube // Generate images for the faces of the cube
@ -1177,7 +1180,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg,
} }
else else
{ {
dstream<<"WARNING: getTextureIdDirect(): Invalid " dstream<<"WARNING: generate_image(): Invalid "
" modification: \""<<part_of_name<<"\""<<std::endl; " modification: \""<<part_of_name<<"\""<<std::endl;
} }
} }

@ -93,7 +93,7 @@ void VoxelManipulator::print(std::ostream &o, VoxelPrintMode mode)
else else
{ {
c = 'X'; c = 'X';
u8 m = m_data[m_area.index(x,y,z)].d; content_t m = m_data[m_area.index(x,y,z)].getContent();
u8 pr = m_data[m_area.index(x,y,z)].param2; u8 pr = m_data[m_area.index(x,y,z)].param2;
if(mode == VOXELPRINT_MATERIAL) if(mode == VOXELPRINT_MATERIAL)
{ {

@ -170,6 +170,9 @@ stuff = {}
starttime = time.time() starttime = time.time()
def data_is_air(d):
return (d == 254 or d == 126)
# Go through all sectors. # Go through all sectors.
for n in range(len(xlist)): for n in range(len(xlist)):
#if n > 500: #if n > 500:
@ -283,7 +286,7 @@ for n in range(len(xlist)):
for (x, z) in reversed(pixellist): for (x, z) in reversed(pixellist):
for y in reversed(range(16)): for y in reversed(range(16)):
datapos = x + y * 16 + z * 256 datapos = x + y * 16 + z * 256
if(ord(mapdata[datapos]) != 254 and ord(mapdata[datapos]) in colors): if(not data_is_air(ord(mapdata[datapos])) and ord(mapdata[datapos]) in colors):
if(ord(mapdata[datapos]) == 2 or ord(mapdata[datapos]) == 9): if(ord(mapdata[datapos]) == 2 or ord(mapdata[datapos]) == 9):
water[(x, z)] += 1 water[(x, z)] += 1
# Add dummy stuff for drawing sea without seabed # Add dummy stuff for drawing sea without seabed
@ -293,7 +296,7 @@ for n in range(len(xlist)):
# Memorize information on the type and height of the block and for drawing the picture. # Memorize information on the type and height of the block and for drawing the picture.
stuff[(chunkxpos + x, chunkzpos + z)] = (chunkypos + y, ord(mapdata[datapos]), water[(x, z)]) stuff[(chunkxpos + x, chunkzpos + z)] = (chunkypos + y, ord(mapdata[datapos]), water[(x, z)])
break break
elif(ord(mapdata[datapos]) != 254 and ord(mapdata[datapos]) not in colors): elif(not data_is_air(ord(mapdata[datapos])) and ord(mapdata[datapos]) not in colors):
print "strange block: " + xhex + "/" + zhex + "/" + yhex + " x: " + str(x) + " y: " + str(y) + " z: " + str(z) + " palikka: " + str(ord(mapdata[datapos])) print "strange block: " + xhex + "/" + zhex + "/" + yhex + " x: " + str(x) + " y: " + str(y) + " z: " + str(z) + " palikka: " + str(ord(mapdata[datapos]))
# After finding all the pixels in the sector, we can move on to the next sector without having to continue the Y axis. # After finding all the pixels in the sector, we can move on to the next sector without having to continue the Y axis.
@ -324,7 +327,7 @@ for n in range(len(xlist)):
for (x, z) in reversed(pixellist): for (x, z) in reversed(pixellist):
for y in reversed(range(16)): for y in reversed(range(16)):
datapos = x + y * 16 + z * 256 datapos = x + y * 16 + z * 256
if(ord(mapdata[datapos]) != 254 and ord(mapdata[datapos]) in colors): if(not data_is_air(ord(mapdata[datapos])) and ord(mapdata[datapos]) in colors):
if(ord(mapdata[datapos]) == 2 or ord(mapdata[datapos]) == 9): if(ord(mapdata[datapos]) == 2 or ord(mapdata[datapos]) == 9):
water[(x, z)] += 1 water[(x, z)] += 1
# Add dummy stuff for drawing sea without seabed # Add dummy stuff for drawing sea without seabed
@ -334,7 +337,7 @@ for n in range(len(xlist)):
# Memorize information on the type and height of the block and for drawing the picture. # Memorize information on the type and height of the block and for drawing the picture.
stuff[(chunkxpos + x, chunkzpos + z)] = (chunkypos + y, ord(mapdata[datapos]), water[(x, z)]) stuff[(chunkxpos + x, chunkzpos + z)] = (chunkypos + y, ord(mapdata[datapos]), water[(x, z)])
break break
elif(ord(mapdata[datapos]) != 254 and ord(mapdata[datapos]) not in colors): elif(not data_is_air(ord(mapdata[datapos])) and ord(mapdata[datapos]) not in colors):
print "outo palikka: " + xhex + "/" + zhex + "/" + yhex + " x: " + str(x) + " y: " + str(y) + " z: " + str(z) + " palikka: " + str(ord(mapdata[datapos])) print "outo palikka: " + xhex + "/" + zhex + "/" + yhex + " x: " + str(x) + " y: " + str(y) + " z: " + str(z) + " palikka: " + str(ord(mapdata[datapos]))
# After finding all the pixels in the sector, we can move on to the next sector without having to continue the Y axis. # After finding all the pixels in the sector, we can move on to the next sector without having to continue the Y axis.