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/content_craft.cpp106
-rw-r--r--src/content_inventory.cpp12
-rw-r--r--src/content_mapblock.cpp167
-rw-r--r--src/content_mapnode.cpp75
-rw-r--r--src/content_mapnode.h7
-rw-r--r--src/defaultsettings.cpp2
-rw-r--r--src/environment.cpp78
-rw-r--r--src/farmesh.cpp14
-rw-r--r--src/farmesh.h3
-rw-r--r--src/game.cpp45
-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/keycode.cpp45
-rw-r--r--src/keycode.h3
-rw-r--r--src/map.cpp46
-rw-r--r--src/mapgen.cpp86
-rw-r--r--src/mapnode.h4
21 files changed, 1441 insertions, 81 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/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..4c28fe3c6 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++)
@@ -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/environment.cpp b/src/environment.cpp
index d55aa38d1..0dab54213 100644
--- a/src/environment.cpp
+++ b/src/environment.cpp
@@ -594,7 +594,7 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
block->setTimestamp(m_game_time);
//dstream<<"Block is "<<dtime_s<<" seconds old."<<std::endl;
-
+
// Activate stored objects
activateObjects(block);
@@ -612,7 +612,7 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime)
// TODO: Do something
// TODO: Implement usage of ActiveBlockModifier
-
+
// Here's a quick demonstration
v3s16 p0;
for(p0.X=0; p0.X<MAP_BLOCKSIZE; p0.X++)
@@ -748,8 +748,8 @@ void ServerEnvironment::step(float dtime)
MapBlock *block = m_map->getBlockNoCreateNoEx(p);
if(block==NULL)
continue;
-
// Set current time as timestamp (and let it set ChangedFlag)
+
block->setTimestamp(m_game_time);
}
@@ -770,7 +770,75 @@ void ServerEnvironment::step(float dtime)
if(block==NULL)
continue;
- activateBlock(block);
+ // Get time difference
+ u32 dtime_s = 0;
+ u32 stamp = block->getTimestamp();
+ if(m_game_time > stamp && stamp != BLOCK_TIMESTAMP_UNDEFINED)
+ dtime_s = m_game_time - block->getTimestamp();
+
+ // Set current time as timestamp (and let it set ChangedFlag)
+ block->setTimestamp(m_game_time);
+
+ //dstream<<"Block is "<<dtime_s<<" seconds old."<<std::endl;
+
+ // Activate stored objects
+ activateObjects(block);
+
+ // Run node metadata
+ bool changed = block->m_node_metadata.step((float)dtime_s);
+ if(changed)
+ {
+ MapEditEvent event;
+ event.type = MEET_BLOCK_NODE_METADATA_CHANGED;
+ event.p = p;
+ m_map->dispatchEvent(&event);
+
+ block->setChangedFlag();
+ }
+
+ // TODO: Do something
+ // TODO: Implement usage of ActiveBlockModifier
+
+ // Here's a quick demonstration
+ v3s16 p0;
+ for(p0.X=0; p0.X<MAP_BLOCKSIZE; p0.X++)
+ for(p0.Y=0; p0.Y<MAP_BLOCKSIZE; p0.Y++)
+ for(p0.Z=0; p0.Z<MAP_BLOCKSIZE; p0.Z++)
+ {
+ v3s16 p = p0 + block->getPosRelative();
+ MapNode n = block->getNodeNoEx(p0);
+ // Test something:
+ // Convert all mud under proper day lighting to grass
+ if(n.d == CONTENT_MUD)
+ {
+ if(dtime_s > 300)
+ {
+ MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0));
+ if(content_features(n_top.d).air_equivalent &&
+ n_top.getLight(LIGHTBANK_DAY) >= 13)
+ {
+ n.d = CONTENT_GRASS;
+ m_map->addNodeWithEvent(p, n);
+ }
+ }
+ }
+ /*
+ Convert grass into mud if under something else than air
+ */
+ else if(n.d == CONTENT_GRASS)
+ {
+ //if(myrand()%20 == 0)
+ {
+ MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0));
+ if(n_top.d != CONTENT_AIR
+ && n_top.d != CONTENT_IGNORE)
+ {
+ n.d = CONTENT_MUD;
+ m_map->addNodeWithEvent(p, n);
+ }
+ }
+ }
+ }
}
}
@@ -886,8 +954,8 @@ void ServerEnvironment::step(float dtime)
n.d = CONTENT_MUD;
m_map->addNodeWithEvent(p, n);
}
+ }
}
- }
}
}
}
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..d77b45da5 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
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/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 dc66b4d55..10e1302b1 100644
--- a/src/map.cpp
+++ b/src/map.cpp
@@ -1241,16 +1241,24 @@ void Map::removeNodeAndUpdate(v3s16 p,
/*
Add neighboring liquid nodes to transform queue.
+
+ Also add horizontal neighbors of node on top of removed node
+ because they could be affected of the water on top flowing
+ down instead of into them.
*/
- v3s16 dirs[6] = {
+ v3s16 dirs[10] = {
v3s16(0,0,1), // back
v3s16(0,1,0), // top
+ v3s16(1,1,0), // topright
+ v3s16(-1,1,0), // topleft
+ v3s16(0,1,1), // topback
+ v3s16(0,1,-1), // topfront
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++)
+ for(u16 i=0; i<10; i++)
{
try
{
@@ -1571,6 +1579,9 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
// Turn possible source into non-source
u8 nonsource_c = make_liquid_flowing(n0.d);
+ // Counts surrounding liquid source blocks
+ u8 surrounding_sources = 0;
+
/*
If not source, check that some node flows into this one
and what is the level of liquid in this one
@@ -1605,7 +1616,9 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
}
bool n2_is_source = !content_flowing_liquid(n2.d);
s8 n2_liquid_level = 8;
- if(n2_is_source == false)
+ if(n2_is_source)
+ surrounding_sources++;
+ else
n2_liquid_level = n2.param2 & 0x07;
s8 new_liquid_level = -1;
@@ -1619,7 +1632,20 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
}
else if(n2_liquid_level > 0)
{
- new_liquid_level = n2_liquid_level - 1;
+ // If the neighbor node isn't a source and flows downwards,
+ // it doesn't flow into this node
+ if (n2_is_source)
+ {
+ new_liquid_level = n2_liquid_level - 1;
+ }
+ else
+ {
+ // Node below n2
+ MapNode n3 = getNodeNoEx(p2 + v3s16(0,-1,0));
+ // NOTE: collision of different liquids not yet handled here.
+ if (content_features(n3.d).liquid_type != LIQUID_FLOWING)
+ new_liquid_level = n2_liquid_level - 1;
+ }
}
if(new_liquid_level > new_liquid_level_max)
@@ -1631,9 +1657,14 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
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 != liquid_level || (!is_source && surrounding_sources >= 2))
{
- if(new_liquid_level_max == -1)
+ if (surrounding_sources >= 2)
+ {
+ n0.d = content_features(n0.d).liquid_alternative_source;
+ setNode(p0,n0);
+ }
+ else if(new_liquid_level_max == -1)
{
// Remove water alltoghether
n0.d = CONTENT_AIR;
@@ -1643,6 +1674,7 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
else
{
n0.param2 = new_liquid_level_max;
+ liquid_level = new_liquid_level_max;
setNode(p0, n0);
}
@@ -1750,7 +1782,7 @@ void Map::transformLiquids(core::map<v3s16, MapBlock*> & modified_blocks)
}
else
{
- if(liquid_next_level > liquid_level)
+ if(liquid_next_level > n2_liquid_level)
{
n2.param2 = liquid_next_level;
setNode(p2, n2);
diff --git a/src/mapgen.cpp b/src/mapgen.cpp
index 4a2a39aec..d7b6e56c4 100644
--- a/src/mapgen.cpp
+++ b/src/mapgen.cpp
@@ -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,15 @@ void make_block(BlockMakeData *data)
u32 current_depth = 0;
bool air_detected = false;
bool water_detected = false;
+ bool have_clay = false;
+
+ // 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);
+
+ have_clay = have_sand && (claynoise > 1.25);
+
// Use fast index incrementing
s16 start_y = node_max.Y+2;
v3s16 em = vmanip.m_area.getExtent();
@@ -1834,7 +1873,10 @@ void make_block(BlockMakeData *data)
{
if(have_sand)
{
- vmanip.m_data[i] = MapNode(CONTENT_SAND);
+ 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 +1936,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 +1945,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..8bbd4eb79 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;