#include "inventory.h"
#include "content_mapnode.h"
#include "player.h"
+#include "mapnode.h" // For content_t
/*
items: actually *items[9]
}
}
+ // Rail
+ {
+ ItemSpec specs[9];
+ specs[0] = ItemSpec(ITEM_CRAFT, "steel_ingot");
+ specs[1] = ItemSpec(ITEM_CRAFT, "Stick");
+ specs[2] = ItemSpec(ITEM_CRAFT, "steel_ingot");
+ specs[3] = ItemSpec(ITEM_CRAFT, "steel_ingot");
+ specs[4] = ItemSpec(ITEM_CRAFT, "Stick");
+ specs[5] = ItemSpec(ITEM_CRAFT, "steel_ingot");
+ specs[6] = ItemSpec(ITEM_CRAFT, "steel_ingot");
+ specs[7] = ItemSpec(ITEM_CRAFT, "Stick");
+ specs[8] = ItemSpec(ITEM_CRAFT, "steel_ingot");
+ if(checkItemCombination(items, specs))
+ {
+ return new MaterialItem(CONTENT_RAIL, 15);
+ }
+ }
+
// Chest
{
ItemSpec specs[9];
}
}
+ // Sandstone
+ {
+ ItemSpec specs[9];
+ specs[3] = ItemSpec(ITEM_MATERIAL, CONTENT_SAND);
+ specs[4] = ItemSpec(ITEM_MATERIAL, CONTENT_SAND);
+ specs[6] = ItemSpec(ITEM_MATERIAL, CONTENT_SAND);
+ specs[7] = ItemSpec(ITEM_MATERIAL, CONTENT_SAND);
+ if(checkItemCombination(items, specs))
+ {
+ return new MaterialItem(CONTENT_SANDSTONE, 1);
+ }
+ }
+
+ // Clay
+ {
+ ItemSpec specs[9];
+ specs[3] = ItemSpec(ITEM_CRAFT, "lump_of_clay");
+ specs[4] = ItemSpec(ITEM_CRAFT, "lump_of_clay");
+ specs[6] = ItemSpec(ITEM_CRAFT, "lump_of_clay");
+ specs[7] = ItemSpec(ITEM_CRAFT, "lump_of_clay");
+ if(checkItemCombination(items, specs))
+ {
+ return new MaterialItem(CONTENT_CLAY, 1);
+ }
+ }
+
+ // Brick
+ {
+ ItemSpec specs[9];
+ specs[3] = ItemSpec(ITEM_CRAFT, "clay_brick");
+ specs[4] = ItemSpec(ITEM_CRAFT, "clay_brick");
+ specs[6] = ItemSpec(ITEM_CRAFT, "clay_brick");
+ specs[7] = ItemSpec(ITEM_CRAFT, "clay_brick");
+ if(checkItemCombination(items, specs))
+ {
+ return new MaterialItem(CONTENT_BRICK, 1);
+ }
+ }
+
+ // Paper
+ {
+ ItemSpec specs[9];
+ specs[3] = ItemSpec(ITEM_MATERIAL, CONTENT_PAPYRUS);
+ specs[4] = ItemSpec(ITEM_MATERIAL, CONTENT_PAPYRUS);
+ specs[5] = ItemSpec(ITEM_MATERIAL, CONTENT_PAPYRUS);
+ if(checkItemCombination(items, specs))
+ {
+ return new CraftItem("paper", 1);
+ }
+ }
+
+ // Book
+ {
+ ItemSpec specs[9];
+ specs[1] = ItemSpec(ITEM_CRAFT, "paper");
+ specs[4] = ItemSpec(ITEM_CRAFT, "paper");
+ specs[7] = ItemSpec(ITEM_CRAFT, "paper");
+ if(checkItemCombination(items, specs))
+ {
+ return new CraftItem("book", 1);
+ }
+ }
+
+ // Book shelf
+ {
+ ItemSpec specs[9];
+ specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+ specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+ specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+ specs[3] = ItemSpec(ITEM_CRAFT, "book");
+ specs[4] = ItemSpec(ITEM_CRAFT, "book");
+ specs[5] = ItemSpec(ITEM_CRAFT, "book");
+ specs[6] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+ specs[7] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+ specs[8] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD);
+ if(checkItemCombination(items, specs))
+ {
+ return new MaterialItem(CONTENT_BOOKSHELF, 1);
+ }
+ }
+
return NULL;
}
*/
// CONTENT_IGNORE-terminated list
- u8 material_items[] = {
+ content_t material_items[] = {
CONTENT_TORCH,
CONTENT_COBBLE,
CONTENT_MUD,
CONTENT_STONE,
CONTENT_SAND,
+ CONTENT_SANDSTONE,
+ CONTENT_CLAY,
+ CONTENT_BRICK,
CONTENT_TREE,
CONTENT_LEAVES,
+ CONTENT_CACTUS,
+ CONTENT_PAPYRUS,
+ CONTENT_BOOKSHELF,
CONTENT_GLASS,
CONTENT_FENCE,
+ CONTENT_RAIL,
CONTENT_MESE,
CONTENT_WATERSOURCE,
CONTENT_CLOUD,
CONTENT_IGNORE
};
- u8 *mip = material_items;
+ content_t *mip = material_items;
for(u16 i=0; i<PLAYER_INVENTORY_SIZE; i++)
{
if(*mip == CONTENT_IGNORE)
//#include "serverobject.h"
#include "content_sao.h"
-bool item_material_is_cookable(u8 content)
+bool item_material_is_cookable(content_t content)
{
if(content == CONTENT_TREE)
return true;
return false;
}
-InventoryItem* item_material_create_cook_result(u8 content)
+InventoryItem* item_material_create_cook_result(content_t content)
{
if(content == CONTENT_TREE)
return new CraftItem("lump_of_coal", 1);
{
if(subname == "Stick")
return "stick.png";
+ else if(subname == "paper")
+ return "paper.png";
+ else if(subname == "book")
+ return "book.png";
else if(subname == "lump_of_coal")
return "lump_of_coal.png";
else if(subname == "lump_of_iron")
return "lump_of_iron.png";
+ else if(subname == "lump_of_clay")
+ return "lump_of_clay.png";
else if(subname == "steel_ingot")
return "steel_ingot.png";
+ else if(subname == "clay_brick")
+ return "clay_brick.png";
else if(subname == "rat")
return "rat.png";
+ else if(subname == "firefly")
+ return "firefly.png";
else
return "cloud.png"; // just something
}
ServerActiveObject *obj = new RatSAO(env, id, pos);
return obj;
}
+ else if(subname == "firefly")
+ {
+ ServerActiveObject *obj = new FireflySAO(env, id, pos);
+ return obj;
+ }
return NULL;
}
s16 item_craft_get_drop_count(const std::string &subname)
{
- if(subname == "rat")
+ if(subname == "rat" || subname == "firefly")
return 1;
return -1;
bool item_craft_is_cookable(const std::string &subname)
{
- if(subname == "lump_of_iron")
+ if(subname == "lump_of_iron" || subname == "lump_of_clay")
return true;
return false;
{
if(subname == "lump_of_iron")
return new CraftItem("steel_ingot", 1);
+ else if(subname == "lump_of_clay")
+ return new CraftItem("clay_brick", 1);
return NULL;
}
material_general.setFlag(video::EMF_FOG_ENABLE, true);
material_general.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+
+ // Papyrus material
+ video::SMaterial material_papyrus;
+ material_papyrus.setFlag(video::EMF_LIGHTING, false);
+ material_papyrus.setFlag(video::EMF_BILINEAR_FILTER, false);
+ material_papyrus.setFlag(video::EMF_FOG_ENABLE, true);
+ material_papyrus.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+ AtlasPointer pa_papyrus = g_texturesource->getTexture(
+ g_texturesource->getTextureId("papyrus.png"));
+ material_papyrus.setTexture(0, pa_papyrus.atlas);
for(s16 z=0; z<MAP_BLOCKSIZE; z++)
for(s16 y=0; y<MAP_BLOCKSIZE; y++)
for(s16 x=0; x<MAP_BLOCKSIZE; x++)
/*
Add torches to mesh
*/
- if(n.d == CONTENT_TORCH)
+ if(n.getContent() == CONTENT_TORCH)
{
video::SColor c(255,255,255,255);
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++)
{
/*
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));
video::SColor c(255,l,l,l);
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++)
{
/*
Add flowing water to mesh
*/
- else if(n.d == CONTENT_WATER)
+ else if(n.getContent() == CONTENT_WATER)
{
bool top_is_water = false;
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;
u8 l = 0;
// 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));
// Otherwise use the light of this node (the water)
else
// Neighbor water levels (key = relative position)
// Includes current node
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;
const u8 neighborflag_top_is_water = 0x01;
v3s16 neighbor_dirs[9] = {
// Check neighbor
v3s16 p2 = p + neighbor_dirs[i];
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;
- else if(n2.d == CONTENT_WATER)
- level = (-0.5 + ((float)(n2.param2 & LIQUID_LEVEL_MASK) + 0.5) / 8.0
+ else if(n2.getContent() == CONTENT_WATER)
+ level = (-0.5 + ((float)n2.param2 + 0.5) / 8.0
* node_water_level) * BS;
// Check node above neighbor.
// doesn't exist
p2.Y += 1;
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;
}
/*
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_air = false;
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;*/
- if(n.d == CONTENT_AIR)
+ if(n.getContent() == CONTENT_AIR)
top_is_air = true;
/*if(top_is_water == true)
/*
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(undiminish_light(n.getLightBlend(data->m_daynight_ratio)));
/*
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)));
video::SColor c(255,l,l,l);
/*
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)));
video::SColor c(255,l,l,l);
v3s16 p2 = p;
p2.X++;
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.X += BS/2;
p2 = p;
p2.Z++;
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.Z += BS/2;
/*
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++)
{
v3s16 dir = g_6dirs[j];
/*u8 l = 0;
MapNode n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + dir);
- if(content_features(n2.d).param_type == CPT_LIGHT)
+ if(content_features(n2).param_type == CPT_LIGHT)
l = decode_light(n2.getLightBlend(data->m_daynight_ratio));
else
l = 255;*/
TileSpec ts = n.getTile(dir);
AtlasPointer ap = ts.texture;
material_general.setTexture(0, ap.atlas);
+
video::S3DVertex vertices[4] =
- {
+ {
/*video::S3DVertex(-BS/2,-BS/2,BS/2, 0,0,0, c, 0,1),
video::S3DVertex(BS/2,-BS/2,BS/2, 0,0,0, c, 1,1),
video::S3DVertex(BS/2,BS/2,BS/2, 0,0,0, c, 1,0),
vertices[i].Pos.rotateXZBy(90);
}
else if(j == 4)
- else if(n.d == CONTENT_PAPYRUS)
+
+ for(u16 i=0; i<4; i++)
+ {
+ vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
+ }
+
+ u16 indices[] = {0,1,2,2,3,0};
+ // Add to mesh collector
+ collector.append(material_general, vertices, 4, indices, 6);
+ }
+ }
+ #endif
++ else if(n.getContent() == CONTENT_PAPYRUS)
+ {
+ u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio)));
+ video::SColor c(255,l,l,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/2,0, 0,0,0, c,
+ pa_papyrus.x1(), pa_papyrus.y0()),
+ video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c,
+ pa_papyrus.x0(), pa_papyrus.y0()),
+ };
+
+ if(j == 0)
{
for(u16 i=0; i<4; i++)
- vertices[i].Pos.rotateYZBy(-90);
+ vertices[i].Pos.rotateXZBy(45);
}
- else if(j == 5)
+ else if(j == 1)
{
for(u16 i=0; i<4; i++)
- vertices[i].Pos.rotateYZBy(90);
+ 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++)
u16 indices[] = {0,1,2,2,3,0};
// Add to mesh collector
- collector.append(material_general, vertices, 4, indices, 6);
+ collector.append(material_papyrus, vertices, 4, indices, 6);
}
}
- #endif
- else if(n.d == CONTENT_RAIL)
++ else if(n.getContent() == CONTENT_RAIL)
+ {
+ u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));
+ video::SColor c(255,l,l,l);
+
+ bool is_rail_x [] = { false, false }; /* x-1, x+1 */
+ bool is_rail_z [] = { false, false }; /* z-1, z+1 */
+
+ MapNode n_minus_x = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x-1,y,z));
+ MapNode n_plus_x = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x+1,y,z));
+ 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));
+
- if(n_minus_x.d == CONTENT_RAIL)
++ if(n_minus_x.getContent() == CONTENT_RAIL)
+ is_rail_x[0] = true;
- if(n_plus_x.d == CONTENT_RAIL)
++ if(n_plus_x.getContent() == CONTENT_RAIL)
+ is_rail_x[1] = true;
- if(n_minus_z.d == CONTENT_RAIL)
++ if(n_minus_z.getContent() == CONTENT_RAIL)
+ is_rail_z[0] = true;
- if(n_plus_z.d == CONTENT_RAIL)
++ if(n_plus_z.getContent() == CONTENT_RAIL)
+ is_rail_z[1] = true;
+
+ float d = (float)BS/16;
+ video::S3DVertex vertices[4] =
+ {
+ video::S3DVertex(-BS/2,-BS/2+d,-BS/2, 0,0,0, c,
+ 0, 1),
+ video::S3DVertex(BS/2,-BS/2+d,-BS/2, 0,0,0, c,
+ 1, 1),
+ video::S3DVertex(BS/2,-BS/2+d,BS/2, 0,0,0, c,
+ 1, 0),
+ video::S3DVertex(-BS/2,-BS/2+d,BS/2, 0,0,0, c,
+ 0, 0),
+ };
+
+ video::SMaterial material_rail;
+ material_rail.setFlag(video::EMF_LIGHTING, false);
+ material_rail.setFlag(video::EMF_BACK_FACE_CULLING, false);
+ material_rail.setFlag(video::EMF_BILINEAR_FILTER, false);
+ material_rail.setFlag(video::EMF_FOG_ENABLE, true);
+ material_rail.MaterialType
+ = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
+
+ int adjacencies = is_rail_x[0] + is_rail_x[1] + is_rail_z[0] + is_rail_z[1];
+
+ // Assign textures
+ if(adjacencies < 2)
+ material_rail.setTexture(0, g_texturesource->getTextureRaw("rail.png"));
+ else if(adjacencies == 2)
+ {
+ if((is_rail_x[0] && is_rail_x[1]) || (is_rail_z[0] && is_rail_z[1]))
+ material_rail.setTexture(0, g_texturesource->getTextureRaw("rail.png"));
+ else
+ material_rail.setTexture(0, g_texturesource->getTextureRaw("rail_curved.png"));
+ }
+ else if(adjacencies == 3)
+ material_rail.setTexture(0, g_texturesource->getTextureRaw("rail_t_junction.png"));
+ else if(adjacencies == 4)
+ material_rail.setTexture(0, g_texturesource->getTextureRaw("rail_crossing.png"));
+ // Rotate textures
+ int angle = 0;
+
+ if(adjacencies == 1)
+ {
+ if(is_rail_x[0] || is_rail_x[1])
+ angle = 90;
+ }
+ else if(adjacencies == 2)
+ {
+ if(is_rail_x[0] && is_rail_x[1])
+ angle = 90;
+ else if(is_rail_x[0] && is_rail_z[0])
+ angle = 270;
+ else if(is_rail_x[0] && is_rail_z[1])
+ angle = 180;
+ else if(is_rail_x[1] && is_rail_z[1])
+ angle = 90;
+ }
+ else if(adjacencies == 3)
+ {
+ if(!is_rail_x[0])
+ angle=0;
+ if(!is_rail_x[1])
+ angle=180;
+ if(!is_rail_z[0])
+ angle=90;
+ if(!is_rail_z[1])
+ angle=270;
+ }
+
+ if(angle != 0) {
+ for(u16 i=0; i<4; i++)
+ vertices[i].Pos.rotateXZBy(angle);
+ }
+
+ for(s32 i=0; i<4; i++)
+ {
+ vertices[i].Pos += intToFloat(p + blockpos_nodes, BS);
+ }
+
+ u16 indices[] = {0,1,2,2,3,0};
+ collector.append(material_rail, vertices, 4, indices, 6);
+ }
}
}
#endif
void setDirtLikeDiggingProperties(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()
{
// Read some settings
bool new_style_leaves = g_settings.getBool("new_style_leaves");
bool invisible_stone = g_settings.getBool("invisible_stone");
- u8 i;
+ content_t i;
ContentFeatures *f = NULL;
i = CONTENT_STONE;
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
setDirtLikeDiggingProperties(f->digging_properties, 1.75);
+ i = CONTENT_SANDSTONE;
+ f = &content_features(i);
+ f->setAllTextures("sandstone.png");
+ f->setInventoryTextureCube("sandstone.png", "sandstone.png", "sandstone.png");
+ f->param_type = CPT_MINERAL;
+ f->is_ground_content = true;
+ f->dug_item = std::string("MaterialItem ")+itos(CONTENT_SAND)+" 1";
+ setDirtLikeDiggingProperties(f->digging_properties, 1.0);
+
+ i = CONTENT_CLAY;
+ f = &content_features(i);
+ f->setAllTextures("clay.png");
+ f->setInventoryTextureCube("clay.png", "clay.png", "clay.png");
+ f->param_type = CPT_MINERAL;
+ f->is_ground_content = true;
+ f->dug_item = std::string("CraftItem lump_of_clay 4");
+ setDirtLikeDiggingProperties(f->digging_properties, 1.0);
+
+ i = CONTENT_BRICK;
+ f = &content_features(i);
+ f->setAllTextures("brick.png");
+ f->setInventoryTextureCube("brick.png", "brick.png", "brick.png");
+ f->param_type = CPT_MINERAL;
+ f->is_ground_content = true;
+ f->dug_item = std::string("CraftItem clay_brick 4");
+ setStoneLikeDiggingProperties(f->digging_properties, 1.0);
+
i = CONTENT_TREE;
f = &content_features(i);
f->setAllTextures("tree.png");
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
setWoodLikeDiggingProperties(f->digging_properties, 0.15);
+ i = CONTENT_CACTUS;
+ f = &content_features(i);
+ f->setAllTextures("cactus_side.png");
+ f->setTexture(0, "cactus_top.png");
+ f->setTexture(1, "cactus_top.png");
+ f->setInventoryTextureCube("cactus_top.png", "cactus_side.png", "cactus_side.png");
+ f->param_type = CPT_MINERAL;
+ f->is_ground_content = true;
+ f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
+ setWoodLikeDiggingProperties(f->digging_properties, 0.75);
+
+ i = CONTENT_PAPYRUS;
+ f = &content_features(i);
+ f->setInventoryTexture("papyrus.png");
+ f->light_propagates = true;
+ f->param_type = CPT_LIGHT;
+ f->is_ground_content = true;
+ 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.25);
+
+ i = CONTENT_BOOKSHELF;
+ f = &content_features(i);
+ f->setAllTextures("bookshelf.png");
+ f->setTexture(0, "wood.png");
+ f->setTexture(1, "wood.png");
+ // FIXME: setInventoryTextureCube() only cares for the first texture
+ f->setInventoryTextureCube("bookshelf.png", "bookshelf.png", "bookshelf.png");
+ //f->setInventoryTextureCube("wood.png", "bookshelf.png", "bookshelf.png");
+ f->param_type = CPT_MINERAL;
+ f->is_ground_content = true;
+ setWoodLikeDiggingProperties(f->digging_properties, 0.75);
+
i = CONTENT_GLASS;
f = &content_features(i);
f->light_propagates = true;
f->setInventoryTexture("item_fence.png");
setWoodLikeDiggingProperties(f->digging_properties, 0.75);
+ i = CONTENT_RAIL;
+ f = &content_features(i);
+ f->setInventoryTexture("rail.png");
+ f->light_propagates = true;
+ f->param_type = CPT_LIGHT;
+ f->is_ground_content = true;
+ f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
+ f->solidness = 0; // drawn separately, makes no faces
+ f->air_equivalent = true; // grass grows underneath
+ f->walkable = false;
+ setDirtLikeDiggingProperties(f->digging_properties, 0.75);
+
// Deprecated
i = CONTENT_COALSTONE;
f = &content_features(i);
f->buildable_to = true;
f->liquid_type = LIQUID_FLOWING;
f->liquid_alternative_flowing = CONTENT_WATER;
+ f->liquid_alternative_source = CONTENT_WATERSOURCE;
i = CONTENT_WATERSOURCE;
f = &content_features(i);
f->liquid_type = LIQUID_SOURCE;
f->dug_item = std::string("MaterialItem ")+itos(i)+" 1";
f->liquid_alternative_flowing = CONTENT_WATER;
+ f->liquid_alternative_source = CONTENT_WATERSOURCE;
i = CONTENT_TORCH;
f = &content_features(i);
#ifndef CONTENT_MAPNODE_HEADER
#define CONTENT_MAPNODE_HEADER
+#include "mapnode.h"
+
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
+ Ranges:
*/
- // Use these sparingly, only when the extra space in param2 is needed.
+
+// 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_GRASS 1
#define CONTENT_WATER 2
#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
-// 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_CHEST 15
#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_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
- // 0x800...0xfff: param2 higher 4 bytes are not usable
++// 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
++
+
#endif
{
v3s16 p(x0,y0,z0);
MapNode n = block->getNodeNoEx(p);
- if(n.d == CONTENT_IGNORE)
+ if(n.getContent() == CONTENT_IGNORE)
continue;
- if(content_features(n.d).liquid_type != LIQUID_NONE)
+ if(content_features(n).liquid_type != LIQUID_NONE)
continue;
- if(content_features(n.d).walkable)
+ if(content_features(n).walkable)
{
last_node_walkable = true;
continue;
if(last_node_walkable)
{
// 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 1
// Test something:
// Convert all mud under proper day lighting to grass
- if(n.d == CONTENT_MUD)
+ if(n.getContent() == CONTENT_MUD)
{
if(dtime_s > 300)
{
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.d = CONTENT_GRASS;
+ n.setContent(CONTENT_GRASS);
m_map->addNodeWithEvent(p, n);
}
}
v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0), BS);
try{
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);
}
}
Test something:
Convert mud under proper lighting to grass
*/
- if(n.d == CONTENT_MUD)
+ if(n.getContent() == CONTENT_MUD)
{
if(myrand()%20 == 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.getLightBlend(getDayNightRatio()) >= 13)
{
- n.d = CONTENT_GRASS;
+ n.setContent(CONTENT_GRASS);
m_map->addNodeWithEvent(p, n);
}
}
/*
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)
{
MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0));
- if(n_top.d != CONTENT_AIR
- && n_top.d != CONTENT_IGNORE)
+ if(n_top.getContent() != CONTENT_AIR
+ && n_top.getContent() != CONTENT_IGNORE)
{
- n.d = CONTENT_MUD;
+ n.setContent(CONTENT_MUD);
m_map->addNodeWithEvent(p, n);
}
}
//TestSAO *obj = new TestSAO(this, 0, pos);
//ServerActiveObject *obj = new ItemSAO(this, 0, pos, "CraftItem Stick 1");
//ServerActiveObject *obj = new RatSAO(this, 0, pos);
- ServerActiveObject *obj = new Oerkki1SAO(this, 0, pos);
+ //ServerActiveObject *obj = new Oerkki1SAO(this, 0, pos);
+ ServerActiveObject *obj = new FireflySAO(this, 0, pos);
addActiveObject(obj);
}
#endif
v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0), BS);
try{
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);
// Update mesh on client
if(m_map->mapType() == MAPTYPE_CLIENT)
v3f pos_f = camera_pos;
v3s16 p_nodes = floatToInt(pos_f, BS);
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();
core::rect<s32> rect(0,0, ss.X, ss.Y);
try
{
n = client->getNode(v3s16(x,y,z));
- if(content_pointable(n.d) == false)
+ if(content_pointable(n.getContent()) == false)
continue;
}
catch(InvalidPositionException &e)
/*
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);
dir_f *= BS/2 - BS/6 - BS/20;
v3f cpf = npf + dir_f;
}
}
}
- 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);
dir_f *= BS/2 - BS/6 - BS/20;
v3f cpf = npf + dir_f;
}
}
}
- 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);
+ dir_f *= BS/2 - BS/6 - BS/20;
+ v3f cpf = npf + dir_f;
+ f32 distance = (cpf - camera_position).getLength();
+
+ float d = (float)BS/16;
+ v3f vertices[4] =
+ {
+ v3f(BS/2, -BS/2+d, -BS/2),
+ v3f(-BS/2, -BS/2, BS/2),
+ };
+
+ for(s32 i=0; i<2; i++)
+ {
+ vertices[i] += npf;
+ }
+
+ core::aabbox3d<f32> box;
+
+ box = core::aabbox3d<f32>(vertices[0]);
+ box.addInternalPoint(vertices[1]);
+
+ if(distance < mindistance)
+ {
+ if(box.intersectsWithLine(shootline))
+ {
+ nodefound = true;
+ nodepos = np;
+ neighbourpos = np;
+ mindistance = distance;
+ nodehilightbox = box;
+ }
+ }
+ }
/*
Regular blocks
*/
}
// Get digging properties for material and tool
- u8 material = n.d;
+ content_t material = n.getContent();
DiggingProperties prop =
getDiggingProperties(material, toolname);
*/
if(farmesh)
{
- farmesh_range = draw_control.wanted_range * 10;
- if(draw_control.range_all && farmesh_range < 500)
- farmesh_range = 500;
- if(farmesh_range > 1000)
- farmesh_range = 1000;
-
farmesh->step(dtime);
farmesh->update(v2f(player_position.X, player_position.Z),
- 0.05+brightness*0.95, farmesh_range);
+ 0.05+brightness*0.95);
}
// Store brightness value
endscenetime_avg = endscenetime_avg * 0.95 + (float)endscenetime*0.05;
char temptext[300];
- snprintf(temptext, 300, "Minetest-c55 %s ("
+ snprintf(temptext, 300, "Minetest-delta %s ("
"R: range_all=%i"
")"
" drawtime=%.0f, beginscenetime=%.0f"
+ This was left to be done by the old system and it sends only the\r
nearest ones.\r
\r
+Vim conversion regexpes for moving to extended content type storage:\r
+%s/\(\.\|->\)d \([!=]=\)/\1getContent() \2/g\r
+%s/content_features(\([^.]*\)\.d)/content_features(\1)/g\r
+%s/\(\.\|->\)d = \([^;]*\);/\1setContent(\2);/g\r
+%s/\(getNodeNoExNoEmerge([^)]*)\)\.d/\1.getContent()/g\r
+%s/\(getNodeNoExNoEmerge(.*)\)\.d/\1.getContent()/g\r
+%s/\.d;/.getContent();/g\r
+%s/\(content_liquid\|content_flowing_liquid\|make_liquid_flowing\|content_pointable\)(\([^.]*\).d)/\1(\2.getContent())/g\r
+Other things to note:\r
+- node.d = node.param0 (only in raw serialization; use getContent() otherwise)\r
+- node.param = node.param1\r
+- node.dir = node.param2\r
+- content_walkable(node.d) etc should be changed to\r
+ content_features(node).walkable etc\r
+- Also check for lines that store the result of getContent to a 8-bit\r
+ variable and fix them (result of getContent() must be stored in\r
+ content_t, which is 16-bit)\r
+\r
Old, wild and random suggestions that probably won't be done:\r
-------------------------------------------------------------\r
\r
\r
TODO: Merge bahamada's audio stuff (clean patch available)\r
\r
-TODO: Merge key configuration menu (no clean patch available)\r
+TODO: Move content_features to mapnode_content_features.{h,cpp} or so\r
\r
+ TODO: Add some kind of content range validation to mapnode serialization\r
+ \r
+ TODO: Make sure menu text position is fixed\r
+ \r
+ TODO: Fix sector over limits error\r
+ \r
Making it more portable:\r
------------------------\r
\r
#include "keycode.h"\r
#include "tile.h"\r
\r
+ #include "gettext.h"\r
+ \r
// This makes textures\r
ITextureSource *g_texturesource = NULL;\r
\r
\r
// Create user data directory\r
fs::CreateDir(porting::path_userdata);\r
+ \r
+ setlocale(LC_MESSAGES, "");
+ bindtextdomain("minetest", (porting::path_userdata+"/locale").c_str());\r
+ textdomain("minetest");\r
\r
// Initialize debug streams\r
#ifdef RUN_IN_PLACE\r
\r
// Set device in game parameters\r
device = device;\r
+ \r
+ // Set the window caption\r
+ device->setWindowCaption(L"Minetest [Main Menu]");\r
\r
// Create time getter\r
g_timegetter = new IrrlichtTimeGetter(device);\r
else
{
/*// 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);
modified_blocks.insert(blockpos, block);
}*/
/*
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{
MapNode bottomnode = getNode(bottompos);
- if(bottomnode.d == CONTENT_GRASS
- || bottomnode.d == CONTENT_GRASS_FOOTSTEPS)
+ if(bottomnode.getContent() == CONTENT_GRASS
+ || bottomnode.getContent() == CONTENT_GRASS_FOOTSTEPS)
{
- bottomnode.d = CONTENT_MUD;
+ bottomnode.setContent(CONTENT_MUD);
setNode(bottompos, bottomnode);
}
}
If the new node is mud and it is under sunlight, change it
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
If node lets sunlight through and is under sunlight, it has
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);
}
Add intial metadata
*/
- NodeMetadata *meta_proto = content_features(n.d).initial_metadata;
+ NodeMetadata *meta_proto = content_features(n).initial_metadata;
if(meta_proto)
{
NodeMetadata *meta = meta_proto->clone();
TODO: This could be optimized by mass-unlighting instead
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;
for(;; y--){
v3s16 p2 = p + dirs[i];
MapNode n2 = getNode(p2);
- if(content_liquid(n2.d) || n2.d == CONTENT_AIR)
+ if(content_liquid(n2.getContent()))
{
m_transforming_liquid.push_back(p2);
}
v3s16 toppos = p + v3s16(0,1,0);
// 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,
*/
MapNode n;
- n.d = replace_material;
+ n.setContent(replace_material);
setNode(p, n);
for(s32 i=0; i<2; i++)
}
/*
- Add neighboring liquid nodes to transform queue.
+ Add neighboring liquid nodes and this node to transform queue.
+ (it's vital for the node itself to get updated last.)
*/
- v3s16 dirs[6] = {
+ v3s16 dirs[7] = {
v3s16(0,0,1), // back
v3s16(0,1,0), // top
v3s16(1,0,0), // right
v3s16(0,0,-1), // front
v3s16(0,-1,0), // bottom
v3s16(-1,0,0), // left
+ v3s16(0,0,0), // self
};
- for(u16 i=0; i<6; i++)
+ for(u16 i=0; i<7; i++)
{
try
{
v3s16 p2 = p + dirs[i];
MapNode n2 = getNode(p2);
- if(content_liquid(n2.d) || n2.d == CONTENT_AIR)
+ if(content_liquid(n2.getContent()))
{
m_transforming_liquid.push_back(p2);
}
MapNode n0 = getNodeNoEx(p0);
// Don't deal with non-liquids
- if(content_liquid(n0.d) == false)
+ if(content_liquid(n0.getContent()) == false)
continue;
- bool is_source = !content_flowing_liquid(n0.d);
+ bool is_source = !content_flowing_liquid(n0.getContent());
u8 liquid_level = 8;
if(is_source == false)
liquid_level = n0.param2 & 0x0f;
// Turn possible source into non-source
- u8 nonsource_c = make_liquid_flowing(n0.d);
+ u8 nonsource_c = make_liquid_flowing(n0.getContent());
/*
If not source, check that some node flows into this one
v3s16 p2 = p0 + dirs_from[i];
MapNode n2 = getNodeNoEx(p2);
- if(content_liquid(n2.d))
+ if(content_liquid(n2.getContent()))
{
- u8 n2_nonsource_c = make_liquid_flowing(n2.d);
+ u8 n2_nonsource_c = make_liquid_flowing(n2.getContent());
// Check that the liquids are the same type
if(n2_nonsource_c != nonsource_c)
{
" collide"<<std::endl;
continue;
}
- bool n2_is_source = !content_flowing_liquid(n2.d);
+ bool n2_is_source = !content_flowing_liquid(n2.getContent());
s8 n2_liquid_level = 8;
if(n2_is_source == false)
n2_liquid_level = n2.param2 & 0x07;
if(new_liquid_level_max == -1)
{
// Remove water alltoghether
- n0.d = CONTENT_AIR;
+ n0.setContent(CONTENT_AIR);
n0.param2 = 0;
setNode(p0, n0);
}
v3s16 p2 = p0 + dirs[i];
MapNode n2 = getNodeNoEx(p2);
- if(content_flowing_liquid(n2.d))
+ if(content_flowing_liquid(n2.getContent()))
{
m_transforming_liquid.push_back(p2);
}
}
// Get a new one from queue if the node has turned into non-water
- if(content_liquid(n0.d) == false)
+ if(content_liquid(n0.getContent()) == false)
continue;
/*
MapNode n2 = getNodeNoEx(p2);
//dstream<<"[1] n2.param="<<(int)n2.param<<std::endl;
- if(content_liquid(n2.d))
+ if(content_liquid(n2.getContent()))
{
- u8 n2_nonsource_c = make_liquid_flowing(n2.d);
+ u8 n2_nonsource_c = make_liquid_flowing(n2.getContent());
// Check that the liquids are the same type
if(n2_nonsource_c != nonsource_c)
{
" collide"<<std::endl;
continue;
}
- bool n2_is_source = !content_flowing_liquid(n2.d);
+ bool n2_is_source = !content_flowing_liquid(n2.getContent());
u8 n2_liquid_level = 8;
if(n2_is_source == false)
n2_liquid_level = n2.param2 & 0x07;
}
}
}
- else if(n2.d == CONTENT_AIR)
+ else if(n2.getContent() == CONTENT_AIR)
{
- n2.d = nonsource_c;
+ n2.setContent(nonsource_c);
n2.param2 = liquid_next_level;
setNode(p2, n2);
{
v3s16 p(x0,y0,z0);
MapNode n = block->getNode(p);
- if(n.d == CONTENT_IGNORE)
+ if(n.getContent() == CONTENT_IGNORE)
{
dstream<<"CONTENT_IGNORE at "
<<"("<<p.X<<","<<p.Y<<","<<p.Z<<")"
{
MapNode n;
if(y0%2==0)
- n.d = CONTENT_AIR;
+ n.setContent(CONTENT_AIR);
else
- n.d = CONTENT_STONE;
+ n.setContent(CONTENT_STONE);
block->setNode(v3s16(x0,y0,z0), n);
}
}
for(; p.Y>min; p.Y--)
{
MapNode n = getNodeNoEx(p);
- if(n.d != CONTENT_IGNORE)
+ if(n.getContent() != CONTENT_IGNORE)
break;
}
if(p.Y == min)
goto 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;
// Search existing walkable and return it
for(; p.Y>min; p.Y--)
{
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;
}
{
MapNode &n = vmanip.m_data[i];
if(content_walkable(n.d)
- && n.d != CONTENT_TREE
- && n.d != CONTENT_LEAVES)
+ && n.getContent() != CONTENT_TREE
+ && n.getContent() != CONTENT_LEAVES)
break;
vmanip.m_area.add_y(em, i, -1);
MapNode treenode(CONTENT_TREE);
MapNode leavesnode(CONTENT_LEAVES);
- s16 trunk_h = myrand_range(3, 6);
+ s16 trunk_h = myrand_range(4, 5);
v3s16 p1 = p0;
for(s16 ii=0; ii<trunk_h; ii++)
{
// p1 is now the last piece of the trunk
p1.Y -= 1;
- VoxelArea leaves_a(v3s16(-2,-2,-2), v3s16(2,2,2));
+ VoxelArea leaves_a(v3s16(-2,-1,-2), v3s16(2,2,2));
//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++)
if(vmanip.m_area.contains(p) == false)
continue;
u32 vi = vmanip.m_area.index(p);
- if(vmanip.m_data[vi].d != CONTENT_AIR
- && vmanip.m_data[vi].d != CONTENT_IGNORE)
+ if(vmanip.m_data[vi].getContent() != CONTENT_AIR
+ && vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
continue;
u32 i = leaves_a.index(x,y,z);
if(leaves_d[i] == 1)
}
}
+ void make_papyrus(VoxelManipulator &vmanip, v3s16 p0)
+ {
+ MapNode papyrusnode(CONTENT_PAPYRUS);
+
+ s16 trunk_h = myrand_range(2, 3);
+ 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)] = papyrusnode;
+ p1.Y++;
+ }
+ }
+
+ void make_cactus(VoxelManipulator &vmanip, v3s16 p0)
+ {
+ MapNode cactusnode(CONTENT_CACTUS);
+
+ s16 trunk_h = 3;
+ 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)] = cactusnode;
+ p1.Y++;
+ }
+ }
+
#if 0
static void make_randomstone(VoxelManipulator &vmanip, v3s16 p0)
{
if(vmanip.m_area.contains(p) == false)
continue;
u32 vi = vmanip.m_area.index(p);
- if(vmanip.m_data[vi].d != CONTENT_AIR
- && vmanip.m_data[vi].d != CONTENT_IGNORE)
+ if(vmanip.m_data[vi].getContent() != CONTENT_AIR
+ && vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
continue;
u32 i = stone_a.index(x,y,z);
if(stone_d[i] == 1)
if(vmanip.m_area.contains(p) == false)
continue;
u32 vi = vmanip.m_area.index(p);
- /*if(vmanip.m_data[vi].d != CONTENT_AIR
- && vmanip.m_data[vi].d != CONTENT_IGNORE)
+ /*if(vmanip.m_data[vi].getContent() != CONTENT_AIR
+ && vmanip.m_data[vi].getContent() != CONTENT_IGNORE)
continue;*/
u32 i = stone_a.index(x,y,z);
if(stone_d[i] == 1)
p.Y += make_stairs;
/*// If already empty
- if(vmanip.getNodeNoExNoEmerge(p).d
+ if(vmanip.getNodeNoExNoEmerge(p).getContent()
== CONTENT_AIR
- && vmanip.getNodeNoExNoEmerge(p+v3s16(0,1,0)).d
+ && vmanip.getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent()
== CONTENT_AIR)
{
}*/
randomizeDir();
continue;
}
- if(vmanip.getNodeNoExNoEmerge(p).d
+ if(vmanip.getNodeNoExNoEmerge(p).getContent()
== CONTENT_COBBLE
- && vmanip.getNodeNoExNoEmerge(p1).d
+ && vmanip.getNodeNoExNoEmerge(p1).getContent()
== CONTENT_COBBLE)
{
// Found wall, this is a good place!
Determine where to move next
*/
// 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
- && vmanip.getNodeNoExNoEmerge(p+v3s16(0,1,0)).d
+ && vmanip.getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent()
== CONTENT_AIR
- && vmanip.getNodeNoExNoEmerge(p+v3s16(0,2,0)).d
+ && vmanip.getNodeNoExNoEmerge(p+v3s16(0,2,0)).getContent()
== CONTENT_AIR)
p += v3s16(0,1,0);
// 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
- && vmanip.getNodeNoExNoEmerge(p+v3s16(0,0,0)).d
+ && vmanip.getNodeNoExNoEmerge(p+v3s16(0,0,0)).getContent()
== CONTENT_AIR
- && vmanip.getNodeNoExNoEmerge(p+v3s16(0,-1,0)).d
+ && vmanip.getNodeNoExNoEmerge(p+v3s16(0,-1,0)).getContent()
== CONTENT_AIR)
p += v3s16(0,-1,0);
// Check if walking is now possible
- if(vmanip.getNodeNoExNoEmerge(p).d
+ if(vmanip.getNodeNoExNoEmerge(p).getContent()
!= CONTENT_AIR
- || vmanip.getNodeNoExNoEmerge(p+v3s16(0,1,0)).d
+ || vmanip.getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent()
!= CONTENT_AIR)
{
// Cannot continue walking here
fits = false;
break;
}
- if(vmanip.m_data[vi].d == CONTENT_IGNORE)
+ if(vmanip.m_data[vi].getContent() == CONTENT_IGNORE)
{
fits = false;
break;
NoiseParams get_ground_noise1_params(u64 seed)
{
- return NoiseParams(NOISE_PERLIN, seed+983240, 5,
- 0.60, 100.0, 30.0);
+ return NoiseParams(NOISE_PERLIN, seed+983240, 4,
+ 0.55, 80.0, 40.0);
}
NoiseParams get_ground_crumbleness_params(u64 seed)
double f = 0.55 + noise2d_perlin(
0.5+(float)p.X/250, 0.5+(float)p.Z/250,
- seed+920381, 3, 0.5);
+ seed+920381, 3, 0.45);
if(f < 0.01)
f = 0.01;
else if(f >= 1.0)
{
v3s16 p(x0,y0,z0);
MapNode n = block->getNodeNoEx(p);
- if(n.d == CONTENT_IGNORE)
+ if(n.getContent() == CONTENT_IGNORE)
continue;
- if(content_features(n.d).liquid_type != LIQUID_NONE)
+ if(content_features(n).liquid_type != LIQUID_NONE)
continue;
- if(content_features(n.d).walkable)
+ if(content_features(n).walkable)
{
last_node_walkable = true;
continue;
if(last_node_walkable)
{
// 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)
{
data->seed, v2s16(blockpos.X, blockpos.Z), 1);
// Maximum amount of ground above the bottom of the central block
s16 maximum_ground_depth = maximum_groundlevel - node_min.Y;
-
+
+ #if 0
/*
Special case for high air or water: Just fill with air and water.
*/
for(s16 y=node_min.Y; y<=node_max.Y; y++)
{
// 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)
vmanip.m_data[i] = MapNode(CONTENT_WATERSOURCE);
// We're done
return;
}
+ #endif
/*
If block is deep underground, this is set to true and ground
for(s16 y=node_min.Y; y<=node_max.Y; y++)
{
// 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.
// This avoids caves inside water.
{
v3s16 p = v3s16(x,y,z) + g_27dirs[i];
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)
vmanip.m_data[vi] = MapNode(CONTENT_MESE);
}
{
}*/
- if(new_content.d != CONTENT_IGNORE)
+ if(new_content.getContent() != CONTENT_IGNORE)
{
for(u16 i=0; i<27; i++)
{
v3s16 p = v3s16(x,y,z) + g_27dirs[i];
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)
vmanip.m_data[vi] = new_content;
{
v3s16 p = v3s16(x,y,z) + g_27dirs[i];
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)
vmanip.m_data[vi] = MapNode(CONTENT_STONE, MINERAL_COAL);
}
{
v3s16 p = v3s16(x,y,z) + g_27dirs[i];
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)
vmanip.m_data[vi] = MapNode(CONTENT_STONE, MINERAL_IRON);
}
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--)
{
- 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)
{
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--)
{
- if(vmanip.m_data[i].d == CONTENT_AIR)
+ if(vmanip.m_data[i].getContent() == CONTENT_AIR)
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;
data->vmanip->m_area.add_y(em, i, -1);
}
double d = noise3d_perlin((float)x/2.5,
(float)y/2.5,(float)z/2.5,
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)
{
- vmanip.m_data[i].d = CONTENT_MOSSYCOBBLE;
+ vmanip.m_data[i].setContent(CONTENT_MOSSYCOBBLE);
}
}
/*else if(vmanip.m_flags[i] & VMANIP_FLAG_DUNGEON_INSIDE)
{
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);
}
{
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);
data->transforming_liquid.push_back(p);
// This can be done because water_found can only
// turn to true and end up here after going through
// 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);
data->transforming_liquid.push_back(p);
u32 current_depth = 0;
bool air_detected = false;
bool water_detected = false;
+ bool have_clay = false;
+
// Use fast index incrementing
s16 start_y = node_max.Y+2;
v3s16 em = vmanip.m_area.getExtent();
u32 i = vmanip.m_area.index(v3s16(p2d.X, start_y, p2d.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;
- if(vmanip.m_data[i].d == CONTENT_AIR)
+ if(vmanip.m_data[i].getContent() == CONTENT_AIR)
air_detected = true;
- if((vmanip.m_data[i].d == CONTENT_STONE
- || vmanip.m_data[i].d == CONTENT_GRASS
- || vmanip.m_data[i].d == CONTENT_MUD
- || vmanip.m_data[i].d == CONTENT_SAND
- || vmanip.m_data[i].d == CONTENT_GRAVEL
+ if((vmanip.m_data[i].getContent() == CONTENT_STONE
+ || vmanip.m_data[i].getContent() == CONTENT_GRASS
+ || vmanip.m_data[i].getContent() == CONTENT_MUD
+ || vmanip.m_data[i].getContent() == CONTENT_SAND
+ || vmanip.m_data[i].getContent() == CONTENT_GRAVEL
) && (air_detected || water_detected))
{
if(current_depth == 0 && y <= WATER_LEVEL+2
{
if(have_sand)
{
- vmanip.m_data[i] = MapNode(CONTENT_SAND);
+ // Determine whether to have clay in the sand here
+ double claynoise = noise2d_perlin(
+ 0.5+(float)p2d.X/500, 0.5+(float)p2d.Y/500,
+ data->seed+4321, 6, 0.95) + 0.5;
+
+ have_clay = (y <= WATER_LEVEL) && (y >= WATER_LEVEL-2) && (
+ ((claynoise > 0) && (claynoise < 0.04) && (current_depth == 0)) ||
+ ((claynoise > 0) && (claynoise < 0.12) && (current_depth == 1))
+ );
+ if (have_clay)
+ vmanip.m_data[i] = MapNode(CONTENT_CLAY);
+ else
+ vmanip.m_data[i] = MapNode(CONTENT_SAND);
}
#if 1
else if(current_depth==0 && !water_detected
}
else
{
- if(vmanip.m_data[i].d == CONTENT_MUD
- || vmanip.m_data[i].d == CONTENT_GRASS)
+ if(vmanip.m_data[i].getContent() == CONTENT_MUD
+ || vmanip.m_data[i].getContent() == CONTENT_GRASS)
vmanip.m_data[i] = MapNode(CONTENT_STONE);
}
{
u32 i = data->vmanip->m_area.index(p);
MapNode *n = &data->vmanip->m_data[i];
- if(n->getContent() != CONTENT_AIR && n->getContent() != CONTENT_IGNORE)
- 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;
break;
// If not found, handle next one
if(found == false)
continue;
- /*
- Trees grow only on mud and grass
- */
+
{
u32 i = data->vmanip->m_area.index(p);
MapNode *n = &data->vmanip->m_data[i];
- if(n->getContent() != CONTENT_MUD && n->getContent() != CONTENT_GRASS)
- continue;
+
- 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;
+
+ // 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++;
+ make_papyrus(vmanip, p);
+ }
+ // 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++;
+ make_tree(vmanip, p);
+ }
+ // 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++;
+ make_cactus(vmanip, p);
+ }
}
- // Tree will be placed one higher
- p.Y++;
- // Make a tree
- make_tree(vmanip, p);
}
#if 0
/*{
u32 i = data->vmanip->m_area.index(v3s16(p));
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;
}*/
// Will be placed one higher
/*{
u32 i = data->vmanip->m_area.index(v3s16(p));
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;
}*/
// Will be placed one lower
/*
Naming scheme:
- 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
-*/
-/*
- Ranges:
+ Content ranges:
0x000...0x07f: param2 is fully usable
0x800...0xfff: param2 lower 4 bytes are free
*/
typedef u16 content_t;
+#define MAX_CONTENT 0xfff
/*
Initializes all kind of stuff in here.
struct ContentFeatures
{
- // If non-NULL, content is translated to this when deserialized
- //MapNode *translate_to;
-
- // Type of MapNode::param
+ // Type of MapNode::param1
ContentParamType param_type;
/*
NodeMetadata *initial_metadata;
// If the content is liquid, this is the flowing version of the liquid.
- // If content is flowing liquid, this is the same content.
- u8 liquid_alternative_flowing;
+ // If content is liquid, this is the same content.
+ content_t liquid_alternative_flowing;
+ // 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
u8 light_source;
void reset()
{
- //translate_to = NULL;
param_type = CPT_NONE;
inventory_texture = NULL;
is_ground_content = false;
/*
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.
in param.
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;
}
NOTE: It doesn't seem to go through torches regardlessly of this
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;
}
2: Opaque
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;
}
// Objects collide with walkable contents
// 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;
}
// 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;
}
// 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;
}
// 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;
}
// CONTENT_WATER || CONTENT_WATERSOURCE -> CONTENT_WATER
// CONTENT_LAVA || CONTENT_LAVASOURCE -> CONTENT_LAVA
// 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;
assert(c != CONTENT_IGNORE);
}
// Pointable contents can be pointed to in the map
// 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;
}
// 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;
}
// 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;
}
1: Face uses m1'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)
return 0;
LIGHTBANK_NIGHT
};
-/*
- Masks for MapNode.param2 of flowing liquids
- */
-#define LIQUID_LEVEL_MASK 0x07
-#define LIQUID_FLOW_DOWN_MASK 0x08
-
/*
This is the stuff what the whole world consists of.
*/
-
struct MapNode
{
/*
union
{
u8 param0;
- u8 d;
+ //u8 d;
};
/*
union
{
u8 param1;
- s8 param;
+ //s8 param;
};
/*
The second parameter. Initialized to 0.
E.g. direction for torches and flowing water.
+ If param0 >= 0x80, bits 0xf0 of this is extended content type data
*/
union
{
u8 param2;
- u8 dir;
+ //u8 dir;
};
MapNode(const MapNode & 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;
- param = a_param;
+ //param0 = a_param0;
+ param1 = a_param1;
param2 = a_param2;
+ // Set after other params because this needs to override part of param2
+ setContent(content);
}
bool operator==(const MapNode &other)
{
- return (d == other.d
- && param == other.param
+ return (param0 == other.param0
+ && param1 == other.param1
&& param2 == other.param2);
}
// To be used everywhere
content_t getContent()
{
- return d;
+ if(param0 < 0x80)
+ return param0;
+ else
+ return (param0<<4) + (param2>>4);
}
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;
+ }
}
/*
*/
bool light_propagates()
{
- return light_propagates_content(d);
+ return light_propagates_content(getContent());
}
bool sunlight_propagates()
{
- return sunlight_propagates_content(d);
+ return sunlight_propagates_content(getContent());
}
u8 solidness()
{
- return content_solidness(d);
+ return content_solidness(getContent());
}
u8 light_source()
{
- return content_features(d).light_source;
+ return content_features(*this).light_source;
}
u8 getLightBanksWithSource()
// Select the brightest of [light source, propagated light]
u8 lightday = 0;
u8 lightnight = 0;
- if(content_features(d).param_type == CPT_LIGHT)
+ if(content_features(*this).param_type == CPT_LIGHT)
{
- lightday = param & 0x0f;
- lightnight = (param>>4)&0x0f;
+ lightday = param1 & 0x0f;
+ lightnight = (param1>>4)&0x0f;
}
if(light_source() > lightday)
lightday = light_source();
{
// Select the brightest of [light source, propagated light]
u8 light = 0;
- if(content_features(d).param_type == CPT_LIGHT)
+ if(content_features(*this).param_type == CPT_LIGHT)
{
if(bank == LIGHTBANK_DAY)
- light = param & 0x0f;
+ light = param1 & 0x0f;
else if(bank == LIGHTBANK_NIGHT)
- light = (param>>4)&0x0f;
+ light = (param1>>4)&0x0f;
else
assert(0);
}
void setLight(enum LightBank bank, u8 a_light)
{
// 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;
if(bank == LIGHTBANK_DAY)
{
- param &= 0xf0;
- param |= a_light & 0x0f;
+ param1 &= 0xf0;
+ param1 |= a_light & 0x0f;
}
else if(bank == LIGHTBANK_NIGHT)
{
- param &= 0x0f;
- param |= (a_light & 0x0f)<<4;
+ param1 &= 0x0f;
+ param1 |= (a_light & 0x0f)<<4;
}
else
assert(0);