aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt1
-rw-r--r--src/client.cpp6
-rw-r--r--src/clouds.cpp92
-rw-r--r--src/content_craft.cpp106
-rw-r--r--src/content_inventory.cpp12
-rw-r--r--src/content_mapblock.cpp169
-rw-r--r--src/content_mapnode.cpp75
-rw-r--r--src/content_mapnode.h7
-rw-r--r--src/defaultsettings.cpp2
-rw-r--r--src/farmesh.cpp14
-rw-r--r--src/farmesh.h3
-rw-r--r--src/game.cpp47
-rw-r--r--src/guiKeyChangeMenu.cpp598
-rw-r--r--src/guiKeyChangeMenu.h133
-rw-r--r--src/guiMainMenu.cpp71
-rw-r--r--src/guiMainMenu.h20
-rw-r--r--src/guiPauseMenu.cpp4
-rw-r--r--src/keycode.cpp45
-rw-r--r--src/keycode.h3
-rw-r--r--src/map.cpp435
-rw-r--r--src/mapgen.cpp92
-rw-r--r--src/mapnode.h11
22 files changed, 1636 insertions, 310 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 847269456..dfe5b5753 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -110,6 +110,7 @@ set(minetest_SRCS
clouds.cpp
clientobject.cpp
guiMainMenu.cpp
+ guiKeyChangeMenu.cpp
guiMessageMenu.cpp
guiTextInputMenu.cpp
guiInventoryMenu.cpp
diff --git a/src/client.cpp b/src/client.cpp
index 585fce11c..4f0baa573 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -5,7 +5,7 @@ Copyright (C) 2010 celeron55, Perttu Ahola <celeron55@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
-MeshUpdateQueue::(at your option) any later version.
+(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -328,7 +328,8 @@ void Client::step(float dtime)
core::list<v3s16> deleted_blocks;
- g_settings.getFloat("client_unload_unused_data_timeout");
+ float delete_unused_sectors_timeout =
+ g_settings.getFloat("client_delete_unused_sectors_timeout");
// Delete sector blocks
/*u32 num = m_env.getMap().unloadUnusedData
@@ -931,7 +932,6 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
*/
//m_env.getClientMap().updateMeshes(block->getPos(), getDayNightRatio());
-
/*
Add it to mesh update queue and set it to be acknowledged after update.
*/
diff --git a/src/clouds.cpp b/src/clouds.cpp
index 122beedac..d754cc15e 100644
--- a/src/clouds.cpp
+++ b/src/clouds.cpp
@@ -84,7 +84,7 @@ void Clouds::render()
*/
const s16 cloud_radius_i = 12;
- const float cloud_size = BS*50;
+ const float cloud_size = BS*48;
const v2f cloud_speed(-BS*2, 0);
// Position of cloud noise origin in world coordinates
@@ -123,24 +123,88 @@ void Clouds::render()
(float)p_in_noise_i.X*cloud_size/BS/200,
(float)p_in_noise_i.Y*cloud_size/BS/200,
m_seed, 3, 0.4);
- if(noise < 0.8)
+ if(noise < 0.95)
continue;
-
- v2f p1 = p0 + v2f(1,1)*cloud_size;
- //video::SColor c(128,255,255,255);
float b = m_brightness;
- video::SColor c(128,b*230,b*230,b*255);
- video::S3DVertex vertices[4] =
+ video::SColor c_top(128,b*240,b*240,b*255);
+ video::SColor c_side_1(128,b*230,b*230,b*255);
+ video::SColor c_side_2(128,b*220,b*220,b*245);
+ video::SColor c_bottom(128,b*205,b*205,b*230);
+
+ video::S3DVertex v[4] =
{
- video::S3DVertex(p0.X,m_cloud_y,p0.Y, 0,0,0, c, 0,1),
- video::S3DVertex(p0.X,m_cloud_y,p1.Y, 0,0,0, c, 1,1),
- video::S3DVertex(p1.X,m_cloud_y,p1.Y, 0,0,0, c, 1,0),
- video::S3DVertex(p1.X,m_cloud_y,p0.Y, 0,0,0, c, 0,0),
+ video::S3DVertex(0,0,0, 0,0,0, c_top, 0, 1),
+ video::S3DVertex(0,0,0, 0,0,0, c_top, 1, 1),
+ video::S3DVertex(0,0,0, 0,0,0, c_top, 1, 0),
+ video::S3DVertex(0,0,0, 0,0,0, c_top, 0, 0)
};
- u16 indices[] = {0,1,2,2,3,0};
- driver->drawVertexPrimitiveList(vertices, 4, indices, 2,
- video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT);
+
+ f32 rx = cloud_size;
+ f32 ry = 8*BS;
+ f32 rz = cloud_size;
+
+ for(int i=0;i<6;i++)
+ {
+ switch(i)
+ {
+ case 0: // top
+ v[0].Pos.X=-rx; v[0].Pos.Y= ry; v[0].Pos.Z=-rz;
+ v[1].Pos.X=-rx; v[1].Pos.Y= ry; v[1].Pos.Z= rz;
+ v[2].Pos.X= rx; v[2].Pos.Y= ry; v[2].Pos.Z= rz;
+ v[3].Pos.X= rx; v[3].Pos.Y= ry, v[3].Pos.Z=-rz;
+ break;
+ case 1: // back
+ for(int j=0;j<4;j++)
+ v[j].Color=c_side_1;
+ v[0].Pos.X=-rx; v[0].Pos.Y= ry; v[0].Pos.Z=-rz;
+ v[1].Pos.X= rx; v[1].Pos.Y= ry; v[1].Pos.Z=-rz;
+ v[2].Pos.X= rx; v[2].Pos.Y=-ry; v[2].Pos.Z=-rz;
+ v[3].Pos.X=-rx; v[3].Pos.Y=-ry, v[3].Pos.Z=-rz;
+ break;
+ case 2: //right
+ for(int j=0;j<4;j++)
+ v[j].Color=c_side_2;
+ v[0].Pos.X= rx; v[0].Pos.Y= ry; v[0].Pos.Z=-rz;
+ v[1].Pos.X= rx; v[1].Pos.Y= ry; v[1].Pos.Z= rz;
+ v[2].Pos.X= rx; v[2].Pos.Y=-ry; v[2].Pos.Z= rz;
+ v[3].Pos.X= rx; v[3].Pos.Y=-ry, v[3].Pos.Z=-rz;
+ break;
+ case 3: // front
+ for(int j=0;j<4;j++)
+ v[j].Color=c_side_1;
+ v[0].Pos.X= rx; v[0].Pos.Y= ry; v[0].Pos.Z= rz;
+ v[1].Pos.X=-rx; v[1].Pos.Y= ry; v[1].Pos.Z= rz;
+ v[2].Pos.X=-rx; v[2].Pos.Y=-ry; v[2].Pos.Z= rz;
+ v[3].Pos.X= rx; v[3].Pos.Y=-ry, v[3].Pos.Z= rz;
+ break;
+ case 4: // left
+ for(int j=0;j<4;j++)
+ v[j].Color=c_side_2;
+ v[0].Pos.X=-rx; v[0].Pos.Y= ry; v[0].Pos.Z= rz;
+ v[1].Pos.X=-rx; v[1].Pos.Y= ry; v[1].Pos.Z=-rz;
+ v[2].Pos.X=-rx; v[2].Pos.Y=-ry; v[2].Pos.Z=-rz;
+ v[3].Pos.X=-rx; v[3].Pos.Y=-ry, v[3].Pos.Z= rz;
+ break;
+ case 5: // bottom
+ for(int j=0;j<4;j++)
+ v[j].Color=c_bottom;
+ v[0].Pos.X= rx; v[0].Pos.Y=-ry; v[0].Pos.Z= rz;
+ v[1].Pos.X=-rx; v[1].Pos.Y=-ry; v[1].Pos.Z= rz;
+ v[2].Pos.X=-rx; v[2].Pos.Y=-ry; v[2].Pos.Z=-rz;
+ v[3].Pos.X= rx; v[3].Pos.Y=-ry, v[3].Pos.Z=-rz;
+ break;
+ }
+
+ v3f pos = v3f(p0.X,m_cloud_y,p0.Y);
+
+ for(u16 i=0; i<4; i++)
+ v[i].Pos += pos;
+ u16 indices[] = {0,1,2,2,3,0};
+ driver->drawVertexPrimitiveList(v, 4, indices, 2,
+ video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT);
+ }
+
}
}
diff --git a/src/content_craft.cpp b/src/content_craft.cpp
index 32d2e6d48..069e68300 100644
--- a/src/content_craft.cpp
+++ b/src/content_craft.cpp
@@ -261,6 +261,24 @@ InventoryItem *craft_get_result(InventoryItem **items)
}
}
+ // 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];
@@ -313,6 +331,87 @@ InventoryItem *craft_get_result(InventoryItem **items)
}
}
+ // 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;
}
@@ -353,10 +452,17 @@ void craft_set_creative_inventory(Player *player)
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,
diff --git a/src/content_inventory.cpp b/src/content_inventory.cpp
index ac48a6195..7d995cb5f 100644
--- a/src/content_inventory.cpp
+++ b/src/content_inventory.cpp
@@ -49,12 +49,20 @@ std::string item_craft_get_image_name(const std::string &subname)
{
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
@@ -83,7 +91,7 @@ s16 item_craft_get_drop_count(const std::string &subname)
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;
@@ -93,6 +101,8 @@ InventoryItem* item_craft_create_cook_result(const std::string &subname)
{
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;
}
diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp
index bdc9baa2a..d8bf71dc0 100644
--- a/src/content_mapblock.cpp
+++ b/src/content_mapblock.cpp
@@ -188,6 +188,16 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
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++)
@@ -365,7 +375,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
if(n2.d == CONTENT_WATERSOURCE)
level = (-0.5+node_water_level) * BS;
else if(n2.d == CONTENT_WATER)
- level = (-0.5 + ((float)n2.param2 + 0.5) / 8.0
+ level = (-0.5 + ((float)(n2.param2 & LIQUID_LEVEL_MASK) + 0.5) / 8.0
* node_water_level) * BS;
// Check node above neighbor.
@@ -857,9 +867,8 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
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),
@@ -895,14 +904,56 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
vertices[i].Pos.rotateXZBy(90);
}
else if(j == 4)
+
+ 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.d == 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++)
@@ -912,11 +963,113 @@ void mapblock_mesh_generate_special(MeshMakeData *data,
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)
+ {
+ 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)
+ is_rail_x[0] = true;
+ if(n_plus_x.d == CONTENT_RAIL)
+ is_rail_x[1] = true;
+ if(n_minus_z.d == CONTENT_RAIL)
+ is_rail_z[0] = true;
+ if(n_plus_z.d == 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
diff --git a/src/content_mapnode.cpp b/src/content_mapnode.cpp
index d82ccc5c9..79e10fd61 100644
--- a/src/content_mapnode.cpp
+++ b/src/content_mapnode.cpp
@@ -99,6 +99,33 @@ void content_mapnode_init()
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");
@@ -127,6 +154,40 @@ void content_mapnode_init()
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;
@@ -148,6 +209,18 @@ void content_mapnode_init()
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);
@@ -202,6 +275,7 @@ void content_mapnode_init()
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);
@@ -233,6 +307,7 @@ void content_mapnode_init()
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);
diff --git a/src/content_mapnode.h b/src/content_mapnode.h
index e314807f9..e53624c21 100644
--- a/src/content_mapnode.h
+++ b/src/content_mapnode.h
@@ -50,6 +50,13 @@ void content_mapnode_init();
#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
#endif
diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp
index cda9eb79a..cbc78ad3f 100644
--- a/src/defaultsettings.cpp
+++ b/src/defaultsettings.cpp
@@ -70,6 +70,8 @@ void set_default_settings()
g_settings.setDefault("fast_move", "false");
g_settings.setDefault("invert_mouse", "false");
g_settings.setDefault("enable_farmesh", "false");
+ g_settings.setDefault("farmesh_trees", "true");
+ g_settings.setDefault("farmesh_distance", "40");
g_settings.setDefault("enable_clouds", "true");
g_settings.setDefault("invisible_stone", "false");
g_settings.setDefault("screenshot_path", ".");
diff --git a/src/farmesh.cpp b/src/farmesh.cpp
index 8f91e3a1a..2cd922434 100644
--- a/src/farmesh.cpp
+++ b/src/farmesh.cpp
@@ -70,6 +70,7 @@ FarMesh::FarMesh(
m_box = core::aabbox3d<f32>(-BS*1000000,-BS*31000,-BS*1000000,
BS*1000000,BS*31000,BS*1000000);
+ trees = g_settings.getBool("farmesh_trees");
}
FarMesh::~FarMesh()
@@ -313,12 +314,11 @@ void FarMesh::render()
}
else
{
- /*// Trees if there are over 0.01 trees per MapNode
- if(tree_amount_avg > 0.01)
+ // Trees if there are over 0.01 trees per MapNode
+ if(trees && tree_amount_avg > 0.01)
c = video::SColor(255,50,128,50);
else
- c = video::SColor(255,107,134,51);*/
- c = video::SColor(255,107,134,51);
+ c = video::SColor(255,107,134,51);
ground_is_mud = true;
}
}
@@ -351,7 +351,7 @@ void FarMesh::render()
video::EVT_STANDARD, scene::EPT_TRIANGLES, video::EIT_16BIT);
// Add some trees if appropriate
- if(tree_amount_avg >= 0.0065 && steepness < 1.4
+ if(trees && tree_amount_avg >= 0.0065 && steepness < 1.4
&& ground_is_mud == true)
{
driver->setMaterial(m_materials[1]);
@@ -404,11 +404,11 @@ void FarMesh::step(float dtime)
m_time += dtime;
}
-void FarMesh::update(v2f camera_p, float brightness, s16 render_range)
+void FarMesh::update(v2f camera_p, float brightness)
{
m_camera_pos = camera_p;
m_brightness = brightness;
- m_render_range = render_range;
+ m_render_range = g_settings.getS16("farmesh_distance")*10;
}
diff --git a/src/farmesh.h b/src/farmesh.h
index 0a30a8aef..577224e15 100644
--- a/src/farmesh.h
+++ b/src/farmesh.h
@@ -67,7 +67,7 @@ public:
void step(float dtime);
- void update(v2f camera_p, float brightness, s16 render_range);
+ void update(v2f camera_p, float brightness);
private:
video::SMaterial m_materials[FARMESH_MATERIAL_COUNT];
@@ -79,6 +79,7 @@ private:
float m_time;
Client *m_client;
s16 m_render_range;
+ bool trees;
};
#endif
diff --git a/src/game.cpp b/src/game.cpp
index faadd0fe7..0f858e879 100644
--- a/src/game.cpp
+++ b/src/game.cpp
@@ -538,6 +538,43 @@ void getPointedNode(Client *client, v3f player_position,
}
}
}
+ else if(n.d == CONTENT_RAIL)
+ {
+ v3s16 dir = unpackDir(n.dir);
+ 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
*/
@@ -1915,15 +1952,9 @@ void the_game(
*/
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
@@ -1990,7 +2021,7 @@ void the_game(
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"
diff --git a/src/guiKeyChangeMenu.cpp b/src/guiKeyChangeMenu.cpp
new file mode 100644
index 000000000..3e594aeca
--- /dev/null
+++ b/src/guiKeyChangeMenu.cpp
@@ -0,0 +1,598 @@
+/*
+ Minetest-delta
+ Copyright (C) 2010-11 celeron55, Perttu Ahola <celeron55@gmail.com>
+ Copyright (C) 2011 Ciaran Gultnieks <ciaran@ciarang.com>
+ Copyright (C) 2011 teddydestodes <derkomtur@schattengang.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "guiKeyChangeMenu.h"
+#include "debug.h"
+#include "serialization.h"
+#include "keycode.h"
+#include "main.h"
+#include <string>
+
+GUIKeyChangeMenu::GUIKeyChangeMenu(gui::IGUIEnvironment* env,
+ gui::IGUIElement* parent, s32 id, IMenuManager *menumgr) :
+ GUIModalMenu(env, parent, id, menumgr)
+{
+ activeKey = -1;
+ init_keys();
+}
+
+GUIKeyChangeMenu::~GUIKeyChangeMenu()
+{
+ removeChildren();
+}
+
+void GUIKeyChangeMenu::removeChildren()
+{
+ const core::list<gui::IGUIElement*> &children = getChildren();
+ core::list<gui::IGUIElement*> children_copy;
+ for (core::list<gui::IGUIElement*>::ConstIterator i = children.begin(); i
+ != children.end(); i++)
+ {
+ children_copy.push_back(*i);
+ }
+ for (core::list<gui::IGUIElement*>::Iterator i = children_copy.begin(); i
+ != children_copy.end(); i++)
+ {
+ (*i)->remove();
+ }
+}
+
+void GUIKeyChangeMenu::regenerateGui(v2u32 screensize)
+{
+ /*
+ Remove stuff
+ */
+ removeChildren();
+
+ /*
+ Calculate new sizes and positions
+ */
+
+ v2s32 size(620, 430);
+
+ core::rect < s32 > rect(screensize.X / 2 - size.X / 2,
+ screensize.Y / 2 - size.Y / 2, screensize.X / 2 + size.X / 2,
+ screensize.Y / 2 + size.Y / 2);
+
+ DesiredRect = rect;
+ recalculateAbsolutePosition(false);
+
+ v2s32 topleft(0, 0);
+
+ {
+ core::rect < s32 > rect(0, 0, 125, 20);
+ rect += topleft + v2s32(25, 3);
+ const wchar_t *text = L"KEYBINDINGS";
+ //gui::IGUIStaticText *t =
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+ v2s32 offset(25, 40);
+ // buttons
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Forward";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->forward = Environment->addButton(rect, this,
+ GUI_ID_KEY_FORWARD_BUTTON,
+ narrow_to_wide(KeyNames[key_forward]).c_str());
+ }
+
+ offset += v2s32(0, 25);
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Backward";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->backward = Environment->addButton(rect, this,
+ GUI_ID_KEY_BACKWARD_BUTTON,
+ narrow_to_wide(KeyNames[key_backward]).c_str());
+ }
+ offset += v2s32(0, 25);
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Left";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->left = Environment->addButton(rect, this, GUI_ID_KEY_LEFT_BUTTON,
+ narrow_to_wide(KeyNames[key_left]).c_str());
+ }
+ offset += v2s32(0, 25);
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Right";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->right = Environment->addButton(rect, this,
+ GUI_ID_KEY_RIGHT_BUTTON,
+ narrow_to_wide(KeyNames[key_right]).c_str());
+ }
+ offset += v2s32(0, 25);
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Use";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->use = Environment->addButton(rect, this, GUI_ID_KEY_USE_BUTTON,
+ narrow_to_wide(KeyNames[key_use]).c_str());
+ }
+ offset += v2s32(0, 25);
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Sneak";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->sneak = Environment->addButton(rect, this,
+ GUI_ID_KEY_SNEAK_BUTTON,
+ narrow_to_wide(KeyNames[key_sneak]).c_str());
+ }
+ offset += v2s32(0, 25);
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Jump";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->jump = Environment->addButton(rect, this, GUI_ID_KEY_JUMP_BUTTON,
+ narrow_to_wide(KeyNames[key_jump]).c_str());
+ }
+
+ offset += v2s32(0, 25);
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Inventory";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->inventory = Environment->addButton(rect, this,
+ GUI_ID_KEY_INVENTORY_BUTTON,
+ narrow_to_wide(KeyNames[key_inventory]).c_str());
+ }
+ offset += v2s32(0, 25);
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Chat";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->chat = Environment->addButton(rect, this, GUI_ID_KEY_CHAT_BUTTON,
+ narrow_to_wide(KeyNames[key_chat]).c_str());
+ }
+
+ //next col
+ offset = v2s32(250, 40);
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Toggle fly";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->fly = Environment->addButton(rect, this, GUI_ID_KEY_FLY_BUTTON,
+ narrow_to_wide(KeyNames[key_fly]).c_str());
+ }
+ offset += v2s32(0, 25);
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Toggle fast";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->fast = Environment->addButton(rect, this, GUI_ID_KEY_FAST_BUTTON,
+ narrow_to_wide(KeyNames[key_fast]).c_str());
+ }
+ offset += v2s32(0, 25);
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Range select";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->range = Environment->addButton(rect, this,
+ GUI_ID_KEY_RANGE_BUTTON,
+ narrow_to_wide(KeyNames[key_range]).c_str());
+ }
+
+ offset += v2s32(0, 25);
+ {
+ core::rect < s32 > rect(0, 0, 100, 20);
+ rect += topleft + v2s32(offset.X, offset.Y);
+ const wchar_t *text = L"Print stacks";
+ Environment->addStaticText(text, rect, false, true, this, -1);
+ //t->setTextAlignment(gui::EGUIA_CENTER, gui::EGUIA_UPPERLEFT);
+ }
+
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(offset.X + 105, offset.Y - 5);
+ this->dump = Environment->addButton(rect, this, GUI_ID_KEY_DUMP_BUTTON,
+ narrow_to_wide(KeyNames[key_dump]).c_str());
+ }
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(size.X - 100 - 20, size.Y - 40);
+ Environment->addButton(rect, this, GUI_ID_BACK_BUTTON, L"Save");
+ }
+ {
+ core::rect < s32 > rect(0, 0, 100, 30);
+ rect += topleft + v2s32(size.X - 100 - 20 - 100 - 20, size.Y - 40);
+ Environment->addButton(rect, this, GUI_ID_ABORT_BUTTON, L"Cancel");
+ }
+}
+
+void GUIKeyChangeMenu::drawMenu()
+{
+ gui::IGUISkin* skin = Environment->getSkin();
+ if (!skin)
+ return;
+ video::IVideoDriver* driver = Environment->getVideoDriver();
+
+ video::SColor bgcolor(140, 0, 0, 0);
+
+ {
+ core::rect < s32 > rect(0, 0, 620, 620);
+ rect += AbsoluteRect.UpperLeftCorner;
+ driver->draw2DRectangle(bgcolor, rect, &AbsoluteClippingRect);
+ }
+
+ gui::IGUIElement::draw();
+}
+
+bool GUIKeyChangeMenu::acceptInput()
+{
+ g_settings.set("keymap_forward", keycode_to_keyname(key_forward));
+ g_settings.set("keymap_backward", keycode_to_keyname(key_backward));
+ g_settings.set("keymap_left", keycode_to_keyname(key_left));
+ g_settings.set("keymap_right", keycode_to_keyname(key_right));
+ g_settings.set("keymap_jump", keycode_to_keyname(key_jump));
+ g_settings.set("keymap_sneak", keycode_to_keyname(key_sneak));
+ g_settings.set("keymap_inventory", keycode_to_keyname(key_inventory));
+ g_settings.set("keymap_chat", keycode_to_keyname(key_chat));
+ g_settings.set("keymap_rangeselect", keycode_to_keyname(key_range));
+ g_settings.set("keymap_freemove", keycode_to_keyname(key_fly));
+ g_settings.set("keymap_fastmove", keycode_to_keyname(key_fast));
+ g_settings.set("keymap_special1", keycode_to_keyname(key_use));
+ g_settings.set("keymap_print_debug_stacks", keycode_to_keyname(key_dump));
+ //clearKeyCache(); Y U NO SCOPE?!
+ return true;
+}
+void GUIKeyChangeMenu::init_keys()
+{
+ key_forward = getKeySetting("keymap_forward");
+ key_backward = getKeySetting("keymap_backward");
+ key_left = getKeySetting("keymap_left");
+ key_right = getKeySetting("keymap_right");
+ key_jump = getKeySetting("keymap_jump");
+ key_sneak = getKeySetting("keymap_sneak");
+ key_inventory = getKeySetting("keymap_inventory");
+ key_chat = getKeySetting("keymap_chat");
+ key_range = getKeySetting("keymap_rangeselect");
+ key_fly = getKeySetting("keymap_freemove");
+ key_fast = getKeySetting("keymap_fastmove");
+ key_use = getKeySetting("keymap_special1");
+ key_dump = getKeySetting("keymap_print_debug_stacks");
+}
+
+bool GUIKeyChangeMenu::resetMenu()
+{
+ if (activeKey >= 0)
+ {
+ switch (activeKey)
+ {
+ case GUI_ID_KEY_FORWARD_BUTTON:
+ this->forward->setText(
+ narrow_to_wide(KeyNames[key_forward]).c_str());
+ break;
+ case GUI_ID_KEY_BACKWARD_BUTTON:
+ this->backward->setText(
+ narrow_to_wide(KeyNames[key_backward]).c_str());
+ break;
+ case GUI_ID_KEY_LEFT_BUTTON:
+ this->left->setText(narrow_to_wide(KeyNames[key_left]).c_str());
+ break;
+ case GUI_ID_KEY_RIGHT_BUTTON:
+ this->right->setText(narrow_to_wide(KeyNames[key_right]).c_str());
+ break;
+ case GUI_ID_KEY_JUMP_BUTTON:
+ this->jump->setText(narrow_to_wide(KeyNames[key_jump]).c_str());
+ break;
+ case GUI_ID_KEY_SNEAK_BUTTON:
+ this->sneak->setText(narrow_to_wide(KeyNames[key_sneak]).c_str());
+ break;
+ case GUI_ID_KEY_INVENTORY_BUTTON:
+ this->inventory->setText(
+ narrow_to_wide(KeyNames[key_inventory]).c_str());
+ break;
+ case GUI_ID_KEY_CHAT_BUTTON:
+ this->chat->setText(narrow_to_wide(KeyNames[key_chat]).c_str());
+ break;
+ case GUI_ID_KEY_RANGE_BUTTON:
+ this->range->setText(narrow_to_wide(KeyNames[key_range]).c_str());
+ break;
+ case GUI_ID_KEY_FLY_BUTTON:
+ this->fly->setText(narrow_to_wide(KeyNames[key_fly]).c_str());
+ break;
+ case GUI_ID_KEY_FAST_BUTTON:
+ this->fast->setText(narrow_to_wide(KeyNames[key_fast]).c_str());
+ break;
+ case GUI_ID_KEY_USE_BUTTON:
+ this->use->setText(narrow_to_wide(KeyNames[key_use]).c_str());
+ break;
+ case GUI_ID_KEY_DUMP_BUTTON:
+ this->dump->setText(narrow_to_wide(KeyNames[key_dump]).c_str());
+ break;
+ }
+ activeKey = -1;
+ return false;
+ }
+ return true;
+}
+bool GUIKeyChangeMenu::OnEvent(const SEvent& event)
+{
+ if (event.EventType == EET_KEY_INPUT_EVENT && activeKey >= 0
+ && event.KeyInput.PressedDown)
+ {
+ if (activeKey == GUI_ID_KEY_FORWARD_BUTTON)
+ {
+ this->forward->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_forward = event.KeyInput.Key;
+ }
+ else if (activeKey == GUI_ID_KEY_BACKWARD_BUTTON)
+ {
+ this->backward->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_backward = event.KeyInput.Key;
+ }
+ else if (activeKey == GUI_ID_KEY_LEFT_BUTTON)
+ {
+ this->left->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_left = event.KeyInput.Key;
+ }
+ else if (activeKey == GUI_ID_KEY_RIGHT_BUTTON)
+ {
+ this->right->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_right = event.KeyInput.Key;
+ }
+ else if (activeKey == GUI_ID_KEY_JUMP_BUTTON)
+ {
+ this->jump->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_jump = event.KeyInput.Key;
+ }
+ else if (activeKey == GUI_ID_KEY_SNEAK_BUTTON)
+ {
+ this->sneak->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_sneak = event.KeyInput.Key;
+ }
+ else if (activeKey == GUI_ID_KEY_INVENTORY_BUTTON)
+ {
+ this->inventory->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_inventory = event.KeyInput.Key;
+ }
+ else if (activeKey == GUI_ID_KEY_CHAT_BUTTON)
+ {
+ this->chat->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_chat = event.KeyInput.Key;
+ }
+ else if (activeKey == GUI_ID_KEY_RANGE_BUTTON)
+ {
+ this->range->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_range = event.KeyInput.Key;
+ }
+ else if (activeKey == GUI_ID_KEY_FLY_BUTTON)
+ {
+ this->fly->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_fly = event.KeyInput.Key;
+ }
+ else if (activeKey == GUI_ID_KEY_FAST_BUTTON)
+ {
+ this->fast->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_fast = event.KeyInput.Key;
+ }
+ else if (activeKey == GUI_ID_KEY_USE_BUTTON)
+ {
+ this->use->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_use = event.KeyInput.Key;
+ }
+ else if (activeKey == GUI_ID_KEY_DUMP_BUTTON)
+ {
+ this->dump->setText(
+ narrow_to_wide(KeyNames[event.KeyInput.Key]).c_str());
+ this->key_dump = event.KeyInput.Key;
+ }
+
+ activeKey = -1;
+ return true;
+ }
+ if (event.EventType == EET_GUI_EVENT)
+ {
+ if (event.GUIEvent.EventType == gui::EGET_ELEMENT_FOCUS_LOST
+ && isVisible())
+ {
+ if (!canTakeFocus(event.GUIEvent.Element))
+ {
+ dstream << "GUIMainMenu: Not allowing focus change."
+ << std::endl;
+ // Returning true disables focus change
+ return true;
+ }
+ }
+ if (event.GUIEvent.EventType == gui::EGET_BUTTON_CLICKED)
+ {
+ switch (event.GUIEvent.Caller->getID())
+ {
+ case GUI_ID_BACK_BUTTON: //back
+ acceptInput();
+ quitMenu();
+ return true;
+ case GUI_ID_ABORT_BUTTON: //abort
+ quitMenu();
+ return true;
+ case GUI_ID_KEY_FORWARD_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->forward->setText(L"press Key");
+ break;
+ case GUI_ID_KEY_BACKWARD_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->backward->setText(L"press Key");
+ break;
+ case GUI_ID_KEY_LEFT_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->left->setText(L"press Key");
+ break;
+ case GUI_ID_KEY_RIGHT_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->right->setText(L"press Key");
+ break;
+ case GUI_ID_KEY_USE_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->use->setText(L"press Key");
+ break;
+ case GUI_ID_KEY_FLY_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->fly->setText(L"press Key");
+ break;
+ case GUI_ID_KEY_FAST_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->fast->setText(L"press Key");
+ break;
+ case GUI_ID_KEY_JUMP_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->jump->setText(L"press Key");
+ break;
+ case GUI_ID_KEY_CHAT_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->chat->setText(L"press Key");
+ break;
+ case GUI_ID_KEY_SNEAK_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->sneak->setText(L"press Key");
+ break;
+ case GUI_ID_KEY_INVENTORY_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->inventory->setText(L"press Key");
+ break;
+ case GUI_ID_KEY_DUMP_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->dump->setText(L"press Key");
+ break;
+ case GUI_ID_KEY_RANGE_BUTTON:
+ resetMenu();
+ activeKey = event.GUIEvent.Caller->getID();
+ this->range->setText(L"press Key");
+ break;
+ }
+ //Buttons
+
+ }
+ }
+ return Parent ? Parent->OnEvent(event) : false;
+}
+
diff --git a/src/guiKeyChangeMenu.h b/src/guiKeyChangeMenu.h
new file mode 100644
index 000000000..389ce7aee
--- /dev/null
+++ b/src/guiKeyChangeMenu.h
@@ -0,0 +1,133 @@
+/*
+ Minetest-delta
+ Copyright (C) 2010-11 celeron55, Perttu Ahola <celeron55@gmail.com>
+ Copyright (C) 2011 Ciaran Gultnieks <ciaran@ciarang.com>
+ Copyright (C) 2011 teddydestodes <derkomtur@schattengang.net>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef GUIKEYCHANGEMENU_HEADER
+#define GUIKEYCHANGEMENU_HEADER
+
+#include "common_irrlicht.h"
+#include "utility.h"
+#include "modalMenu.h"
+#include "client.h"
+#include <string>
+
+static const char *KeyNames[] =
+ { "-", "Left Button", "Right Button", "Cancel", "Middle Button", "X Button 1",
+ "X Button 2", "-", "Back", "Tab", "-", "-", "Clear", "Return", "-",
+ "-", "Shift", "Control", "Menu", "Pause", "Capital", "Kana", "-",
+ "Junja", "Final", "Kanji", "-", "Escape", "Convert", "Nonconvert",
+ "Accept", "Mode Change", "Space", "Priot", "Next", "End", "Home",
+ "Left", "Up", "Right", "Down", "Select", "Print", "Execute",
+ "Snapshot", "Insert", "Delete", "Help", "0", "1", "2", "3", "4", "5",
+ "6", "7", "8", "9", "-", "-", "-", "-", "-", "-", "-", "A", "B", "C",
+ "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N", "O", "P", "Q",
+ "R", "S", "T", "U", "V", "W", "X", "Y", "Z", "Left Windows",
+ "Right Windows", "Apps", "-", "Sleep", "Numpad 0", "Numpad 1",
+ "Numpad 2", "Numpad 3", "Numpad 4", "Numpad 5", "Numpad 6", "Numpad 7",
+ "Numpad 8", "Numpad 9", "Numpad *", "Numpad +", "Numpad /", "Numpad -",
+ "Numpad .", "Numpad /", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8",
+ "F9", "F10", "F11", "F12", "F13", "F14", "F15", "F16", "F17", "F18",
+ "F19", "F20", "F21", "F22", "F23", "F24", "-", "-", "-", "-", "-", "-",
+ "-", "-", "Num Lock", "Scroll Lock", "-", "-", "-", "-", "-", "-", "-",
+ "-", "-", "-", "-", "-", "-", "-", "Left Shift", "Right Shight",
+ "Left Control", "Right Control", "Left Menu", "Right Menu", "-", "-",
+ "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
+ "-", "-", "-", "-", "-", "Plus", "Comma", "Minus", "Period", "-", "-",
+ "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
+ "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
+ "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
+ "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "Attn", "CrSel",
+ "ExSel", "Erase OEF", "Play", "Zoom", "PA1", "OEM Clear", "-" };
+ enum
+ {
+ GUI_ID_BACK_BUTTON = 101, GUI_ID_ABORT_BUTTON, GUI_ID_SCROLL_BAR,
+ //buttons
+ GUI_ID_KEY_FORWARD_BUTTON,
+ GUI_ID_KEY_BACKWARD_BUTTON,
+ GUI_ID_KEY_LEFT_BUTTON,
+ GUI_ID_KEY_RIGHT_BUTTON,
+ GUI_ID_KEY_USE_BUTTON,
+ GUI_ID_KEY_FLY_BUTTON,
+ GUI_ID_KEY_FAST_BUTTON,
+ GUI_ID_KEY_JUMP_BUTTON,
+ GUI_ID_KEY_CHAT_BUTTON,
+ GUI_ID_KEY_SNEAK_BUTTON,
+ GUI_ID_KEY_INVENTORY_BUTTON,
+ GUI_ID_KEY_DUMP_BUTTON,
+ GUI_ID_KEY_RANGE_BUTTON
+ };
+
+class GUIKeyChangeMenu: public GUIModalMenu
+{
+public:
+ GUIKeyChangeMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent,
+ s32 id, IMenuManager *menumgr);
+ ~GUIKeyChangeMenu();
+
+ void removeChildren();
+ /*
+ Remove and re-add (or reposition) stuff
+ */
+ void regenerateGui(v2u32 screensize);
+
+ void drawMenu();
+
+ bool acceptInput();
+
+ bool OnEvent(const SEvent& event);
+
+private:
+
+ void init_keys();
+
+ bool resetMenu();
+
+ gui::IGUIButton *forward;
+ gui::IGUIButton *backward;
+ gui::IGUIButton *left;
+ gui::IGUIButton *right;
+ gui::IGUIButton *use;
+ gui::IGUIButton *sneak;
+ gui::IGUIButton *jump;
+ gui::IGUIButton *inventory;
+ gui::IGUIButton *fly;
+ gui::IGUIButton *fast;
+ gui::IGUIButton *range;
+ gui::IGUIButton *dump;
+ gui::IGUIButton *chat;
+
+ u32 activeKey;
+ u32 key_forward;
+ u32 key_backward;
+ u32 key_left;
+ u32 key_right;
+ u32 key_use;
+ u32 key_sneak;
+ u32 key_jump;
+ u32 key_inventory;
+ u32 key_fly;
+ u32 key_fast;
+ u32 key_range;
+ u32 key_chat;
+ u32 key_dump;
+};
+
+#endif
+
diff --git a/src/guiMainMenu.cpp b/src/guiMainMenu.cpp
index ef0a013f1..cea32860b 100644
--- a/src/guiMainMenu.cpp
+++ b/src/guiMainMenu.cpp
@@ -18,10 +18,13 @@ with this program; if not, write to the Free Software Foundation, Inc.,
*/
#include "guiMainMenu.h"
+#include "guiKeyChangeMenu.h"
#include "debug.h"
#include "serialization.h"
#include <string>
+
+
GUIMainMenu::GUIMainMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id,
IMenuManager *menumgr,
@@ -34,6 +37,10 @@ GUIMainMenu::GUIMainMenu(gui::IGUIEnvironment* env,
m_gamecallback(gamecallback)
{
assert(m_data);
+ this->env = env;
+ this->parent = parent;
+ this->id = id;
+ this->menumgr = menumgr;
}
GUIMainMenu::~GUIMainMenu()
@@ -70,35 +77,35 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
// Client options
{
- gui::IGUIElement *e = getElementFromId(258);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_NAME_INPUT);
if(e != NULL)
text_name = e->getText();
else
text_name = m_data->name;
}
{
- gui::IGUIElement *e = getElementFromId(256);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_ADDRESS_INPUT);
if(e != NULL)
text_address = e->getText();
else
text_address = m_data->address;
}
{
- gui::IGUIElement *e = getElementFromId(257);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_PORT_INPUT);
if(e != NULL)
text_port = e->getText();
else
text_port = m_data->port;
}
{
- gui::IGUIElement *e = getElementFromId(263);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_FANCYTREE_CB);
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
fancy_trees = ((gui::IGUICheckBox*)e)->isChecked();
else
fancy_trees = m_data->fancy_trees;
}
{
- gui::IGUIElement *e = getElementFromId(262);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_SMOOTH_LIGHTING_CB);
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
smooth_lighting = ((gui::IGUICheckBox*)e)->isChecked();
else
@@ -107,14 +114,14 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
// Server options
{
- gui::IGUIElement *e = getElementFromId(259);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_CREATIVE_CB);
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
creative_mode = ((gui::IGUICheckBox*)e)->isChecked();
else
creative_mode = m_data->creative_mode;
}
{
- gui::IGUIElement *e = getElementFromId(261);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_DAMAGE_CB);
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
enable_damage = ((gui::IGUICheckBox*)e)->isChecked();
else
@@ -175,7 +182,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
core::rect<s32> rect(0, 0, 230, 30);
rect += topleft_client + v2s32(160, 50);
gui::IGUIElement *e =
- Environment->addEditBox(text_name.c_str(), rect, true, this, 258);
+ Environment->addEditBox(text_name.c_str(), rect, true, this, GUI_ID_NAME_INPUT);
if(text_name == L"")
Environment->setFocus(e);
}
@@ -198,7 +205,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
core::rect<s32> rect(0, 0, 230, 30);
rect += topleft_client + v2s32(160, 100);
gui::IGUIElement *e =
- Environment->addEditBox(text_address.c_str(), rect, true, this, 256);
+ Environment->addEditBox(text_address.c_str(), rect, true, this, GUI_ID_ADDRESS_INPUT);
if(text_name != L"")
Environment->setFocus(e);
}
@@ -206,7 +213,7 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
core::rect<s32> rect(0, 0, 120, 30);
//rect += topleft_client + v2s32(160+250+20, 125);
rect += topleft_client + v2s32(size_client.X-60-100, 100);
- Environment->addEditBox(text_port.c_str(), rect, true, this, 257);
+ Environment->addEditBox(text_port.c_str(), rect, true, this, GUI_ID_PORT_INPUT);
}
{
core::rect<s32> rect(0, 0, 400, 20);
@@ -217,13 +224,13 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
{
core::rect<s32> rect(0, 0, 250, 30);
rect += topleft_client + v2s32(35, 150);
- Environment->addCheckBox(fancy_trees, rect, this, 263,
+ Environment->addCheckBox(fancy_trees, rect, this, GUI_ID_FANCYTREE_CB,
L"Fancy trees");
}
{
core::rect<s32> rect(0, 0, 250, 30);
rect += topleft_client + v2s32(35, 150+30);
- Environment->addCheckBox(smooth_lighting, rect, this, 262,
+ Environment->addCheckBox(smooth_lighting, rect, this, GUI_ID_SMOOTH_LIGHTING_CB,
L"Smooth Lighting");
}
// Start game button
@@ -231,9 +238,16 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
core::rect<s32> rect(0, 0, 180, 30);
//rect += topleft_client + v2s32(size_client.X/2-180/2, 225-30/2);
rect += topleft_client + v2s32(size_client.X-180-40, 150+25);
- Environment->addButton(rect, this, 257, L"Start Game / Connect");
+ Environment->addButton(rect, this, GUI_ID_JOIN_GAME_BUTTON, L"Start Game / Connect");
}
+ // Key change button
+ {
+ core::rect<s32> rect(0, 0, 100, 30);
+ //rect += topleft_client + v2s32(size_client.X/2-180/2, 225-30/2);
+ rect += topleft_client + v2s32(size_client.X-180-40-100-20, 150+25);
+ Environment->addButton(rect, this, GUI_ID_CHANGE_KEYS_BUTTON, L"Change keys");
+ }
/*
Server section
*/
@@ -254,19 +268,19 @@ void GUIMainMenu::regenerateGui(v2u32 screensize)
{
core::rect<s32> rect(0, 0, 250, 30);
rect += topleft_server + v2s32(35, 30);
- Environment->addCheckBox(creative_mode, rect, this, 259, L"Creative Mode");
+ Environment->addCheckBox(creative_mode, rect, this, GUI_ID_CREATIVE_CB, L"Creative Mode");
}
{
core::rect<s32> rect(0, 0, 250, 30);
rect += topleft_server + v2s32(35, 60);
- Environment->addCheckBox(enable_damage, rect, this, 261, L"Enable Damage");
+ Environment->addCheckBox(enable_damage, rect, this, GUI_ID_DAMAGE_CB, L"Enable Damage");
}
// Map delete button
{
core::rect<s32> rect(0, 0, 130, 30);
//rect += topleft_server + v2s32(size_server.X-40-130, 100+25);
rect += topleft_server + v2s32(40, 100+25);
- Environment->addButton(rect, this, 260, L"Delete world");
+ Environment->addButton(rect, this, GUI_ID_DELETE_MAP_BUTTON, L"Delete map");
}
}
@@ -300,7 +314,7 @@ void GUIMainMenu::drawMenu()
void GUIMainMenu::acceptInput()
{
{
- gui::IGUIElement *e = getElementFromId(258);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_NAME_INPUT);
if(e != NULL)
m_data->name = e->getText();
}
@@ -310,32 +324,32 @@ void GUIMainMenu::acceptInput()
m_data->password = e->getText();
}
{
- gui::IGUIElement *e = getElementFromId(256);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_ADDRESS_INPUT);
if(e != NULL)
m_data->address = e->getText();
}
{
- gui::IGUIElement *e = getElementFromId(257);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_PORT_INPUT);
if(e != NULL)
m_data->port = e->getText();
}
{
- gui::IGUIElement *e = getElementFromId(259);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_CREATIVE_CB);
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
m_data->creative_mode = ((gui::IGUICheckBox*)e)->isChecked();
}
{
- gui::IGUIElement *e = getElementFromId(261);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_DAMAGE_CB);
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
m_data->enable_damage = ((gui::IGUICheckBox*)e)->isChecked();
}
{
- gui::IGUIElement *e = getElementFromId(262);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_SMOOTH_LIGHTING_CB);
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
m_data->smooth_lighting = ((gui::IGUICheckBox*)e)->isChecked();
}
{
- gui::IGUIElement *e = getElementFromId(263);
+ gui::IGUIElement *e = getElementFromId(GUI_ID_FANCYTREE_CB);
if(e != NULL && e->getType() == gui::EGUIET_CHECK_BOX)
m_data->fancy_trees = ((gui::IGUICheckBox*)e)->isChecked();
}
@@ -377,11 +391,16 @@ bool GUIMainMenu::OnEvent(const SEvent& event)
{
switch(event.GUIEvent.Caller->getID())
{
- case 257: // Start game
+ case GUI_ID_JOIN_GAME_BUTTON: // Start game
acceptInput();
quitMenu();
return true;
- case 260: // Delete map
+ case GUI_ID_CHANGE_KEYS_BUTTON: {
+ GUIKeyChangeMenu *kmenu = new GUIKeyChangeMenu(env, parent, -1,menumgr);
+ kmenu->drop();
+ return true;
+ }
+ case GUI_ID_DELETE_MAP_BUTTON: // Delete map
// Don't accept input data, just set deletion request
m_data->delete_map = true;
m_accepted = true;
@@ -393,7 +412,7 @@ bool GUIMainMenu::OnEvent(const SEvent& event)
{
switch(event.GUIEvent.Caller->getID())
{
- case 256: case 257: case 258: case 264:
+ case GUI_ID_ADDRESS_INPUT: case GUI_ID_PORT_INPUT: case GUI_ID_NAME_INPUT: case 264:
acceptInput();
quitMenu();
return true;
diff --git a/src/guiMainMenu.h b/src/guiMainMenu.h
index edd519024..87561f797 100644
--- a/src/guiMainMenu.h
+++ b/src/guiMainMenu.h
@@ -27,6 +27,21 @@ with this program; if not, write to the Free Software Foundation, Inc.,
// For IGameCallback
#include "guiPauseMenu.h"
+enum
+{
+ GUI_ID_QUIT_BUTTON = 101,
+ GUI_ID_NAME_INPUT,
+ GUI_ID_ADDRESS_INPUT,
+ GUI_ID_PORT_INPUT,
+ GUI_ID_FANCYTREE_CB,
+ GUI_ID_SMOOTH_LIGHTING_CB,
+ GUI_ID_DAMAGE_CB,
+ GUI_ID_CREATIVE_CB,
+ GUI_ID_JOIN_GAME_BUTTON,
+ GUI_ID_CHANGE_KEYS_BUTTON,
+ GUI_ID_DELETE_MAP_BUTTON
+};
+
struct MainMenuData
{
MainMenuData():
@@ -87,6 +102,11 @@ private:
MainMenuData *m_data;
bool m_accepted;
IGameCallback *m_gamecallback;
+
+ gui::IGUIEnvironment* env;
+ gui::IGUIElement* parent;
+ s32 id;
+ IMenuManager *menumgr;
};
#endif
diff --git a/src/guiPauseMenu.cpp b/src/guiPauseMenu.cpp
index d32d1a10b..1a885a6ea 100644
--- a/src/guiPauseMenu.cpp
+++ b/src/guiPauseMenu.cpp
@@ -166,8 +166,8 @@ void GUIPauseMenu::regenerateGui(v2u32 screensize)
);*/
std::ostringstream os;
- os<<"Minetest-c55\n";
- os<<"by Perttu Ahola\n";
+ os<<"Minetest-delta\n";
+ os<<"by Perttu Ahola and contributors\n";
os<<"celeron55@gmail.com\n";
os<<BUILD_INFO<<"\n";
os<<"ud_path = "<<wrap_rows(porting::path_userdata, 20)<<"\n";
diff --git a/src/keycode.cpp b/src/keycode.cpp
index ad3c0b401..f014914d0 100644
--- a/src/keycode.cpp
+++ b/src/keycode.cpp
@@ -171,6 +171,46 @@ irr::EKEY_CODE keyname_to_keycode(const char *name)
return irr::KEY_KEY_CODES_COUNT;
}
+static const char *KeyNames[] =
+{ "-", "KEY_LBUTTON", "KEY_RBUTTON", "Cancel", "Middle Button", "X Button 1",
+ "X Button 2", "-", "Back", "Tab", "-", "-", "Clear", "Return", "-",
+ "-", "KEY_SHIFT", "Control", "Menu", "Pause", "Capital", "Kana", "-",
+ "Junja", "Final", "Kanji", "-", "Escape", "Convert", "Nonconvert",
+ "Accept", "Mode Change", "KEY_SPACE", "Priot", "Next", "KEY_END",
+ "KEY_HOME", "Left", "Up", "Right", "Down", "Select", "KEY_PRINT",
+ "Execute", "Snapshot", "Insert", "Delete", "Help", "KEY_KEY_0",
+ "KEY_KEY_1", "KEY_KEY_2", "KEY_KEY_3", "KEY_KEY_4", "KEY_KEY_5",
+ "KEY_KEY_6", "KEY_KEY_7", "KEY_KEY_8", "KEY_KEY_9", "-", "-", "-", "-",
+ "-", "-", "-", "KEY_KEY_A", "KEY_KEY_B", "KEY_KEY_C", "KEY_KEY_D",
+ "KEY_KEY_E", "KEY_KEY_F", "KEY_KEY_G", "KEY_KEY_H", "KEY_KEY_I",
+ "KEY_KEY_J", "KEY_KEY_K", "KEY_KEY_L", "KEY_KEY_M", "KEY_KEY_N",
+ "KEY_KEY_O", "KEY_KEY_P", "KEY_KEY_Q", "KEY_KEY_R", "KEY_KEY_S",
+ "KEY_KEY_T", "KEY_KEY_U", "KEY_KEY_V", "KEY_KEY_W", "KEY_KEY_X",
+ "KEY_KEY_Y", "KEY_KEY_Z", "Left Windows", "Right Windows", "Apps", "-",
+ "Sleep", "KEY_NUMPAD0", "KEY_NUMPAD1", "KEY_NUMPAD2", "KEY_NUMPAD3",
+ "KEY_NUMPAD4", "KEY_NUMPAD5", "KEY_NUMPAD6", "KEY_NUMPAD7",
+ "KEY_NUMPAD8", "KEY_NUMPAD9", "Numpad *", "Numpad +", "Numpad /",
+ "Numpad -", "Numpad .", "Numpad /", "KEY_F1", "KEY_F2", "KEY_F3",
+ "KEY_F4", "KEY_F5", "KEY_F6", "KEY_F7", "KEY_F8", "KEY_F9", "KEY_F10",
+ "KEY_F11", "KEY_F12", "KEY_F13", "KEY_F14", "KEY_F15", "KEY_F16",
+ "KEY_F17", "KEY_F18", "KEY_F19", "KEY_F20", "KEY_F21", "KEY_F22",
+ "KEY_F23", "KEY_F24", "-", "-", "-", "-", "-", "-", "-", "-",
+ "Num Lock", "Scroll Lock", "-", "-", "-", "-", "-", "-", "-", "-", "-",
+ "-", "-", "-", "-", "-", "KEY_LSHIFT", "KEY_RSHIFT", "Left Control",
+ "Right Control", "Left Menu", "Right Menu", "-", "-", "-", "-", "-",
+ "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
+ "-", "-", "Plus", "Comma", "Minus", "Period", "-", "-", "-", "-", "-",
+ "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
+ "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
+ "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-", "-",
+ "-", "-", "-", "-", "-", "-", "-", "-", "Attn", "CrSel", "ExSel",
+ "Erase OEF", "Play", "Zoom", "PA1", "OEM Clear", "-" };
+
+std::string keycode_to_keyname(s32 keycode)
+{
+ return KeyNames[keycode];
+}
+
/*
Key config
*/
@@ -189,4 +229,7 @@ irr::EKEY_CODE getKeySetting(const char *settingname)
return c;
}
-
+void clearKeyCache()
+{
+ g_key_setting_cache.clear();
+}
diff --git a/src/keycode.h b/src/keycode.h
index f19fe3442..9c62004d8 100644
--- a/src/keycode.h
+++ b/src/keycode.h
@@ -21,11 +21,14 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define KEYCODE_HEADER
#include "common_irrlicht.h"
+#include <string>
irr::EKEY_CODE keyname_to_keycode(const char *name);
// Key configuration getter
irr::EKEY_CODE getKeySetting(const char *settingname);
+std::string keycode_to_keyname(s32 keycode);
+void clearCache();
#endif
diff --git a/src/map.cpp b/src/map.cpp
index 9ff0fa6d3..e47b1b212 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -1086,7 +1086,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n,
v3s16 p2 = p + dirs[i];
MapNode n2 = getNode(p2);
- if(content_liquid(n2.d))
+ if(content_liquid(n2.d) || n2.d == CONTENT_AIR)
{
m_transforming_liquid.push_back(p2);
}
@@ -1240,17 +1240,19 @@ void Map::removeNodeAndUpdate(v3s16 p,
}
/*
- 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
{
@@ -1258,7 +1260,7 @@ void Map::removeNodeAndUpdate(v3s16 p,
v3s16 p2 = p + dirs[i];
MapNode n2 = getNode(p2);
- if(content_liquid(n2.d))
+ if(content_liquid(n2.d) || n2.d == CONTENT_AIR)
{
m_transforming_liquid.push_back(p2);
}
@@ -1538,6 +1540,17 @@ void Map::PrintInfo(std::ostream &out)
#define WATER_DROP_BOOST 4
+enum NeighborType {
+ NEIGHBOR_UPPER,
+ NEIGHBOR_SAME_LEVEL,
+ NEIGHBOR_LOWER
+};
+struct NodeNeighbor {
+ MapNode n;
+ NeighborType t;
+ v3s16 p;
+};
+
void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
{
DSTACK(__FUNCTION_NAME);
@@ -1557,240 +1570,220 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
v3s16 p0 = m_transforming_liquid.pop_front();
MapNode n0 = getNodeNoEx(p0);
-
- // Don't deal with non-liquids
- if(content_liquid(n0.d) == false)
- continue;
-
- bool is_source = !content_flowing_liquid(n0.d);
-
- u8 liquid_level = 8;
- if(is_source == false)
- liquid_level = n0.param2 & 0x0f;
-
- // Turn possible source into non-source
- u8 nonsource_c = make_liquid_flowing(n0.d);
-
+
/*
- If not source, check that some node flows into this one
- and what is the level of liquid in this one
- */
- if(is_source == false)
- {
- s8 new_liquid_level_max = -1;
-
- v3s16 dirs_from[5] = {
- v3s16(0,1,0), // top
- v3s16(0,0,1), // back
- v3s16(1,0,0), // right
- v3s16(0,0,-1), // front
- v3s16(-1,0,0), // left
- };
- for(u16 i=0; i<5; i++)
- {
- bool from_top = (i==0);
-
- v3s16 p2 = p0 + dirs_from[i];
- MapNode n2 = getNodeNoEx(p2);
-
- if(content_liquid(n2.d))
- {
- u8 n2_nonsource_c = make_liquid_flowing(n2.d);
- // Check that the liquids are the same type
- if(n2_nonsource_c != nonsource_c)
- {
- dstream<<"WARNING: Not handling: different liquids"
- " collide"<<std::endl;
- continue;
+ Collect information about current node
+ */
+ s8 liquid_level = -1;
+ u8 liquid_kind = CONTENT_IGNORE;
+ LiquidType liquid_type = content_features(n0.d).liquid_type;
+ switch (liquid_type) {
+ case LIQUID_SOURCE:
+ liquid_level = 8;
+ liquid_kind = content_features(n0.d).liquid_alternative_flowing;
+ break;
+ case LIQUID_FLOWING:
+ liquid_level = (n0.param2 & LIQUID_LEVEL_MASK);
+ liquid_kind = n0.d;
+ break;
+ case LIQUID_NONE:
+ // if this is an air node, it *could* be transformed into a liquid. otherwise,
+ // continue with the next node.
+ if (n0.d != CONTENT_AIR)
+ continue;
+ liquid_kind = CONTENT_AIR;
+ break;
+ }
+
+ /*
+ Collect information about the environment
+ */
+ v3s16 dirs[6] = {
+ v3s16( 0, 1, 0), // top
+ v3s16( 0,-1, 0), // bottom
+ v3s16( 1, 0, 0), // right
+ v3s16(-1, 0, 0), // left
+ v3s16( 0, 0, 1), // back
+ v3s16( 0, 0,-1), // front
+ };
+ NodeNeighbor sources[6]; // surrounding sources
+ int num_sources = 0;
+ NodeNeighbor flows[6]; // surrounding flowing liquid nodes
+ int num_flows = 0;
+ NodeNeighbor airs[6]; // surrounding air
+ int num_airs = 0;
+ NodeNeighbor neutrals[6]; // nodes that are solid or another kind of liquid
+ int num_neutrals = 0;
+ bool flowing_down = false;
+ for (u16 i = 0; i < 6; i++) {
+ NeighborType nt = NEIGHBOR_SAME_LEVEL;
+ switch (i) {
+ case 0:
+ nt = NEIGHBOR_UPPER;
+ break;
+ case 1:
+ nt = NEIGHBOR_LOWER;
+ break;
+ }
+ v3s16 npos = p0 + dirs[i];
+ NodeNeighbor nb = {getNodeNoEx(npos), nt, npos};
+ switch (content_features(nb.n.d).liquid_type) {
+ case LIQUID_NONE:
+ if (nb.n.d == CONTENT_AIR) {
+ airs[num_airs++] = nb;
+ // if the current node happens to be a flowing node, it will start to flow down here.
+ if (nb.t == NEIGHBOR_LOWER)
+ flowing_down = true;
+ } else {
+ neutrals[num_neutrals++] = nb;
}
- bool n2_is_source = !content_flowing_liquid(n2.d);
- s8 n2_liquid_level = 8;
- if(n2_is_source == false)
- n2_liquid_level = n2.param2 & 0x07;
-
- s8 new_liquid_level = -1;
- if(from_top)
- {
- //new_liquid_level = 7;
- if(n2_liquid_level >= 7 - WATER_DROP_BOOST)
- new_liquid_level = 7;
- else
- new_liquid_level = n2_liquid_level + WATER_DROP_BOOST;
+ break;
+ case LIQUID_SOURCE:
+ // if this node is not (yet) of a liquid type, choose the first liquid type we encounter
+ if (liquid_kind == CONTENT_AIR)
+ liquid_kind = content_features(nb.n.d).liquid_alternative_flowing;
+ if (content_features(nb.n.d).liquid_alternative_flowing !=liquid_kind) {
+ neutrals[num_neutrals++] = nb;
+ } else {
+ sources[num_sources++] = nb;
}
- else if(n2_liquid_level > 0)
- {
- new_liquid_level = n2_liquid_level - 1;
+ break;
+ case LIQUID_FLOWING:
+ // if this node is not (yet) of a liquid type, choose the first liquid type we encounter
+ if (liquid_kind == CONTENT_AIR)
+ liquid_kind = content_features(nb.n.d).liquid_alternative_flowing;
+ if (content_features(nb.n.d).liquid_alternative_flowing != liquid_kind) {
+ neutrals[num_neutrals++] = nb;
+ } else {
+ flows[num_flows++] = nb;
+ if (nb.t == NEIGHBOR_LOWER)
+ flowing_down = true;
}
-
- if(new_liquid_level > new_liquid_level_max)
- new_liquid_level_max = new_liquid_level;
- }
- } //for
-
- /*
- If liquid level should be something else, update it and
- add all the neighboring water nodes to the transform queue.
- */
- if(new_liquid_level_max != liquid_level)
- {
- if(new_liquid_level_max == -1)
- {
- // Remove water alltoghether
- n0.d = CONTENT_AIR;
- n0.param2 = 0;
- setNode(p0, n0);
- }
- else
- {
- n0.param2 = new_liquid_level_max;
- setNode(p0, n0);
- }
-
- // Block has been modified
- {
- v3s16 blockpos = getNodeBlockPos(p0);
- MapBlock *block = getBlockNoCreateNoEx(blockpos);
- if(block != NULL)
- modified_blocks.insert(blockpos, block);
+ break;
+ }
+ }
+
+ /*
+ decide on the type (and possibly level) of the current node
+ */
+ u8 new_node_content;
+ s8 new_node_level = -1;
+ if (num_sources >= 2 || liquid_type == LIQUID_SOURCE) {
+ // liquid_kind will be set to either the flowing alternative of the node (if it's a liquid)
+ // or the flowing alternative of the first of the surrounding sources (if it's air), so
+ // it's perfectly safe to use liquid_kind here to determine the new node content.
+ new_node_content = content_features(liquid_kind).liquid_alternative_source;
+ } else if (num_sources == 1 && sources[0].t != NEIGHBOR_LOWER) {
+ // liquid_kind is set properly, see above
+ new_node_content = liquid_kind;
+ new_node_level = 7;
+ } else {
+ // no surrounding sources, so get the maximum level that can flow into this node
+ for (u16 i = 0; i < num_flows; i++) {
+ u8 nb_liquid_level = (flows[i].n.param2 & LIQUID_LEVEL_MASK);
+ switch (flows[i].t) {
+ case NEIGHBOR_UPPER:
+ if (nb_liquid_level + WATER_DROP_BOOST > new_node_level) {
+ new_node_level = 7;
+ if (nb_liquid_level + WATER_DROP_BOOST < 7)
+ new_node_level = nb_liquid_level + WATER_DROP_BOOST;
+ }
+ break;
+ case NEIGHBOR_LOWER:
+ break;
+ case NEIGHBOR_SAME_LEVEL:
+ if ((flows[i].n.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK &&
+ nb_liquid_level > 0 && nb_liquid_level - 1 > new_node_level) {
+ new_node_level = nb_liquid_level - 1;
+ }
+ break;
}
-
- /*
- Add neighboring non-source liquid nodes to transform queue.
- */
- v3s16 dirs[6] = {
- v3s16(0,0,1), // back
- v3s16(0,1,0), // top
- v3s16(1,0,0), // right
- v3s16(0,0,-1), // front
- v3s16(0,-1,0), // bottom
- v3s16(-1,0,0), // left
- };
- for(u16 i=0; i<6; i++)
- {
- v3s16 p2 = p0 + dirs[i];
-
- MapNode n2 = getNodeNoEx(p2);
- if(content_flowing_liquid(n2.d))
- {
- m_transforming_liquid.push_back(p2);
+ }
+ // don't flow as far in open terrain - if there isn't at least one adjacent solid block,
+ // substract another unit from the resulting water level.
+ if (!flowing_down && new_node_level >= 1) {
+ bool at_wall = false;
+ for (u16 i = 0; i < num_neutrals; i++) {
+ if (neutrals[i].t == NEIGHBOR_SAME_LEVEL) {
+ at_wall = true;
+ break;
}
}
+ if (!at_wall)
+ new_node_level -= 1;
}
+
+ if (new_node_level >= 0)
+ new_node_content = liquid_kind;
+ else
+ new_node_content = CONTENT_AIR;
}
-
- // Get a new one from queue if the node has turned into non-water
- if(content_liquid(n0.d) == false)
+
+ /*
+ 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 ||
+ ((n0.param2 & LIQUID_LEVEL_MASK) == (u8)new_node_level &&
+ ((n0.param2 & LIQUID_FLOW_DOWN_MASK) == LIQUID_FLOW_DOWN_MASK)
+ == flowing_down)))
continue;
-
+
+
/*
- Flow water from this node
- */
- v3s16 dirs_to[5] = {
- v3s16(0,-1,0), // bottom
- v3s16(0,0,1), // back
- v3s16(1,0,0), // right
- v3s16(0,0,-1), // front
- v3s16(-1,0,0), // left
- };
- for(u16 i=0; i<5; i++)
- {
- bool to_bottom = (i == 0);
-
- // If liquid is at lowest possible height, it's not going
- // anywhere except down
- if(liquid_level == 0 && to_bottom == false)
- continue;
-
- u8 liquid_next_level = 0;
- // If going to bottom
- if(to_bottom)
- {
- //liquid_next_level = 7;
- if(liquid_level >= 7 - WATER_DROP_BOOST)
- liquid_next_level = 7;
- else
- liquid_next_level = liquid_level + WATER_DROP_BOOST;
- }
- else
- liquid_next_level = liquid_level - 1;
-
- bool n2_changed = false;
- bool flowed = false;
-
- v3s16 p2 = p0 + dirs_to[i];
-
- MapNode n2 = getNodeNoEx(p2);
- //dstream<<"[1] n2.param="<<(int)n2.param<<std::endl;
-
- if(content_liquid(n2.d))
- {
- u8 n2_nonsource_c = make_liquid_flowing(n2.d);
- // Check that the liquids are the same type
- if(n2_nonsource_c != nonsource_c)
- {
- dstream<<"WARNING: Not handling: different liquids"
- " collide"<<std::endl;
- continue;
- }
- bool n2_is_source = !content_flowing_liquid(n2.d);
- u8 n2_liquid_level = 8;
- if(n2_is_source == false)
- n2_liquid_level = n2.param2 & 0x07;
-
- if(to_bottom)
- {
- flowed = true;
- }
-
- if(n2_is_source)
- {
- // Just flow into the source, nothing changes.
- // n2_changed is not set because destination didn't change
- flowed = true;
+ update the current node
+ */
+ bool flow_down_enabled = (flowing_down && ((n0.param2 & LIQUID_FLOW_DOWN_MASK) != LIQUID_FLOW_DOWN_MASK));
+ n0.d = new_node_content;
+ if (content_features(n0.d).liquid_type == LIQUID_FLOWING) {
+ // 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);
+ } else {
+ n0.param2 = 0;
+ }
+ setNode(p0, n0);
+ v3s16 blockpos = getNodeBlockPos(p0);
+ MapBlock *block = getBlockNoCreateNoEx(blockpos);
+ if(block != NULL)
+ modified_blocks.insert(blockpos, block);
+
+ /*
+ enqueue neighbors for update if neccessary
+ */
+ switch (content_features(n0.d).liquid_type) {
+ case LIQUID_SOURCE:
+ // make sure source flows into all neighboring nodes
+ for (u16 i = 0; i < num_flows; i++)
+ if (flows[i].t != NEIGHBOR_UPPER)
+ m_transforming_liquid.push_back(flows[i].p);
+ for (u16 i = 0; i < num_airs; i++)
+ if (airs[i].t != NEIGHBOR_UPPER)
+ m_transforming_liquid.push_back(airs[i].p);
+ break;
+ case LIQUID_NONE:
+ // this flow has turned to air; neighboring flows might need to do the same
+ for (u16 i = 0; i < num_flows; i++)
+ m_transforming_liquid.push_back(flows[i].p);
+ break;
+ case LIQUID_FLOWING:
+ for (u16 i = 0; i < num_flows; i++) {
+ u8 flow_level = (flows[i].n.param2 & LIQUID_LEVEL_MASK);
+ // liquid_level is still the ORIGINAL level of this node.
+ if (flows[i].t != NEIGHBOR_UPPER && ((flow_level < liquid_level || flow_level < new_node_level) ||
+ flow_down_enabled))
+ m_transforming_liquid.push_back(flows[i].p);
}
- else
- {
- if(liquid_next_level > liquid_level)
- {
- n2.param2 = liquid_next_level;
- setNode(p2, n2);
-
- n2_changed = true;
- flowed = true;
- }
+ for (u16 i = 0; i < num_airs; i++) {
+ if (airs[i].t != NEIGHBOR_UPPER && (airs[i].t == NEIGHBOR_LOWER || new_node_level > 0))
+ m_transforming_liquid.push_back(airs[i].p);
}
- }
- else if(n2.d == CONTENT_AIR)
- {
- n2.d = nonsource_c;
- n2.param2 = liquid_next_level;
- setNode(p2, n2);
-
- n2_changed = true;
- flowed = true;
- }
-
- //dstream<<"[2] n2.param="<<(int)n2.param<<std::endl;
-
- if(n2_changed)
- {
- m_transforming_liquid.push_back(p2);
-
- v3s16 blockpos = getNodeBlockPos(p2);
- MapBlock *block = getBlockNoCreateNoEx(blockpos);
- if(block != NULL)
- modified_blocks.insert(blockpos, block);
- }
-
- // If n2_changed to bottom, don't flow anywhere else
- if(to_bottom && flowed && !is_source)
break;
}
-
+
loopcount++;
//if(loopcount >= 100000)
- if(loopcount >= initial_size * 1)
+ if(loopcount >= initial_size * 10) {
break;
+ }
}
//dstream<<"Map::transformLiquids(): loopcount="<<loopcount<<std::endl;
}
diff --git a/src/mapgen.cpp b/src/mapgen.cpp
index 4a2a39aec..dfea862a5 100644
--- a/src/mapgen.cpp
+++ b/src/mapgen.cpp
@@ -85,7 +85,7 @@ static void make_tree(VoxelManipulator &vmanip, v3s16 p0)
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++)
{
@@ -97,7 +97,7 @@ static void make_tree(VoxelManipulator &vmanip, v3s16 p0)
// 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++)
@@ -152,6 +152,34 @@ static void make_tree(VoxelManipulator &vmanip, v3s16 p0)
}
}
+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)
{
@@ -909,8 +937,8 @@ NoiseParams get_cave_noise2_params(u64 seed)
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)
@@ -945,7 +973,7 @@ bool val_is_ground(double ground_noise1_val, v3s16 p, 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)
@@ -1345,7 +1373,8 @@ void make_block(BlockMakeData *data)
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.
*/
@@ -1379,6 +1408,7 @@ void make_block(BlockMakeData *data)
// We're done
return;
}
+ #endif
/*
If block is deep underground, this is set to true and ground
@@ -1808,6 +1838,8 @@ void make_block(BlockMakeData *data)
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();
@@ -1834,7 +1866,19 @@ void make_block(BlockMakeData *data)
{
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
@@ -1894,7 +1938,7 @@ void make_block(BlockMakeData *data)
{
u32 i = data->vmanip->m_area.index(p);
MapNode *n = &data->vmanip->m_data[i];
- if(n->d != CONTENT_AIR && n->d != CONTENT_IGNORE)
+ if(n->d != CONTENT_AIR && n->d != CONTENT_WATERSOURCE && n->d != CONTENT_IGNORE)
{
found = true;
break;
@@ -1903,19 +1947,33 @@ void make_block(BlockMakeData *data)
// 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->d != CONTENT_MUD && n->d != CONTENT_GRASS)
- continue;
+
+ if(n->d != CONTENT_MUD && n->d != CONTENT_GRASS && n->d != CONTENT_SAND)
+ continue;
+
+ // Papyrus grows only on mud and in water
+ if(n->d == 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)
+ {
+ p.Y++;
+ make_tree(vmanip, p);
+ }
+ // Cactii grow only on sand, on land
+ else if(n->d == 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
diff --git a/src/mapnode.h b/src/mapnode.h
index 36d48fb9e..33128049a 100644
--- a/src/mapnode.h
+++ b/src/mapnode.h
@@ -150,8 +150,10 @@ struct ContentFeatures
NodeMetadata *initial_metadata;
// If the content is liquid, this is the flowing version of the liquid.
- // If content is liquid, this is the same content.
+ // If content is flowing liquid, this is the same content.
u8 liquid_alternative_flowing;
+ // If the content is liquid, this is the source version of the liquid.
+ u8 liquid_alternative_source;
// Amount of light the node emits
u8 light_source;
@@ -403,9 +405,16 @@ enum LightBank
};
/*
+ 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
{
/*