From 52ad5944c080e858c49267c49703ec79b18e120f Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Thu, 21 Jul 2011 17:00:08 +0300 Subject: [PATCH 01/25] Attempt to fix the big bug. Now server either stops sending map or mapgen starts generating CONTENT_IGNORE. --- src/map.cpp | 72 +++++++++++++++++++++++++++++++++++++----------- src/mapblock.cpp | 7 ++++- 2 files changed, 62 insertions(+), 17 deletions(-) diff --git a/src/map.cpp b/src/map.cpp index 9ff0fa6d3..8bce36f25 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -2033,25 +2033,28 @@ void ServerMap::initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos) for(s16 y=-1; y<=1; y++) { - //MapBlock *block = createBlock(blockpos); + v3s16 p(blockpos.X+x, blockpos.Y+y, blockpos.Z+z); + //MapBlock *block = createBlock(p); // 1) get from memory, 2) load from disk - MapBlock *block = emergeBlock(blockpos, false); + MapBlock *block = emergeBlock(p, false); // 3) create a blank one if(block == NULL) - block = createBlock(blockpos); + { + block = createBlock(p); + + /* + Block gets sunlight if this is true. + + Refer to the map generator heuristics. + */ + bool ug = mapgen::block_is_underground(data->seed, p); + block->setIsUnderground(ug); + } // Lighting will not be valid after make_chunk is called block->setLightingExpired(true); // Lighting will be calculated //block->setLightingExpired(false); - - /* - Block gets sunlight if this is true. - - This should be set to true when the top side of a block - is completely exposed to the sky. - */ - block->setIsUnderground(false); } } } @@ -2126,10 +2129,14 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data, assert(block); /* - Set is_underground flag for lighting with sunlight - */ + Set is_underground flag for lighting with sunlight. + + Refer to map generator heuristics. + + NOTE: This is done in initChunkMake + */ + //block->setIsUnderground(mapgen::block_is_underground(data->seed, blockpos)); - block->setIsUnderground(mapgen::block_is_underground(data->seed, blockpos)); /* Add sunlight to central block. @@ -2160,6 +2167,13 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data, #if 1 // Center block lighting_update_blocks.insert(block->getPos(), block); + + /*{ + s16 x = 0; + s16 z = 0; + v3s16 p = block->getPos()+v3s16(x,1,z); + lighting_update_blocks[p] = getBlockNoCreateNoEx(p); + }*/ #endif #if 0 // All modified blocks @@ -2176,8 +2190,28 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data, lighting_update_blocks.insert(i.getNode()->getKey(), i.getNode()->getValue()); } + /*// Also force-add all the upmost blocks for proper sunlight + for(s16 x=-1; x<=1; x++) + for(s16 z=-1; z<=1; z++) + { + v3s16 p = block->getPos()+v3s16(x,1,z); + lighting_update_blocks[p] = getBlockNoCreateNoEx(p); + }*/ #endif updateLighting(lighting_update_blocks, changed_blocks); + + /* + Set lighting to non-expired state in all of them. + This is cheating, but it is not fast enough if all of them + would actually be updated. + */ + for(s16 x=-1; x<=1; x++) + for(s16 y=-1; y<=1; y++) + for(s16 z=-1; z<=1; z++) + { + v3s16 p = block->getPos()+v3s16(x,y,z); + getBlockNoCreateNoEx(p)->setLightingExpired(false); + } if(enable_mapgen_debug_info == false) t.stop(true); // Hide output @@ -2463,7 +2497,7 @@ MapBlock * ServerMap::emergeBlock(v3s16 p, bool allow_generate) { MapBlock *block = getBlockNoCreateNoEx(p); - if(block) + if(block && block->isDummy() == false) return block; } @@ -4065,10 +4099,16 @@ void ManualMapVoxelManipulator::blitBackAll( i = m_loaded_blocks.getIterator(); i.atEnd() == false; i++) { + v3s16 p = i.getNode()->getKey(); bool existed = i.getNode()->getValue(); if(existed == false) + { + // The Great Bug was found using this + /*dstream<<"ManualMapVoxelManipulator::blitBackAll: " + <<"Inexistent ("<getKey(); + } MapBlock *block = m_map->getBlockNoCreateNoEx(p); if(block == NULL) { diff --git a/src/mapblock.cpp b/src/mapblock.cpp index 647a17756..cdbd54525 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -242,7 +242,12 @@ bool MapBlock::propagateSunlight(core::map & light_sources, // Check if node above block has sunlight try{ MapNode n = getNodeParent(v3s16(x, MAP_BLOCKSIZE, z)); - if(n.d == CONTENT_IGNORE || n.getLight(LIGHTBANK_DAY) != LIGHT_SUN) + if(n.d == CONTENT_IGNORE) + { + // Trust heuristics + no_sunlight = is_underground; + } + else if(n.getLight(LIGHTBANK_DAY) != LIGHT_SUN) { no_sunlight = true; } From 2b3bc337087a7df15bbc7a745ee36e718e6d3950 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Thu, 21 Jul 2011 23:28:30 +0300 Subject: [PATCH 02/25] added some TODOs to main.cpp --- src/main.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main.cpp b/src/main.cpp index 3edf79bd2..505f82fc7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -339,6 +339,12 @@ TODO: Merge bahamada's audio stuff (clean patch available) TODO: Merge key configuration menu (no clean patch available) +TODO: Add some kind of content range validation to mapnode serialization + +TODO: Make sure menu text position is fixed + +TODO: Fix sector over limits error + Making it more portable: ------------------------ From 58f612eca17e9f2bc8d296df0aba627d4e2e18e3 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Fri, 22 Jul 2011 22:35:20 +0300 Subject: [PATCH 03/25] Changing key settings now doesn't require a game restart --- src/guiKeyChangeMenu.cpp | 2 +- src/keycode.cpp | 1 + src/keycode.h | 6 ++++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/guiKeyChangeMenu.cpp b/src/guiKeyChangeMenu.cpp index 3e594aeca..4a11cf93c 100644 --- a/src/guiKeyChangeMenu.cpp +++ b/src/guiKeyChangeMenu.cpp @@ -338,7 +338,7 @@ bool GUIKeyChangeMenu::acceptInput() 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?! + clearKeyCache(); return true; } void GUIKeyChangeMenu::init_keys() diff --git a/src/keycode.cpp b/src/keycode.cpp index f014914d0..d6472d2ea 100644 --- a/src/keycode.cpp +++ b/src/keycode.cpp @@ -233,3 +233,4 @@ void clearKeyCache() { g_key_setting_cache.clear(); } + diff --git a/src/keycode.h b/src/keycode.h index 9c62004d8..300682b12 100644 --- a/src/keycode.h +++ b/src/keycode.h @@ -24,11 +24,13 @@ with this program; if not, write to the Free Software Foundation, Inc., #include irr::EKEY_CODE keyname_to_keycode(const char *name); +std::string keycode_to_keyname(s32 keycode); // Key configuration getter irr::EKEY_CODE getKeySetting(const char *settingname); -std::string keycode_to_keyname(s32 keycode); -void clearCache(); + +// Clear fast lookup cache +void clearKeyCache(); #endif From 7da02e05a6b97eb70fd17abdfdb38d8f99fabad9 Mon Sep 17 00:00:00 2001 From: Nils Dagsson Moskopp Date: Fri, 22 Jul 2011 21:56:00 +0200 Subject: [PATCH 04/25] * README updated --- README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README b/README index e03bdae25..82fcdd331 100644 --- a/README +++ b/README @@ -1,7 +1,7 @@ Minetest Δ (“Minetest Delta”) is a fork of Minetest-c55 , incorporating experimental features that are not (yet) included in Minetest-c55. New features: -* Submenu for key assignment (changes apply after restart) +* Submenu for key assignment * configurable far mesh tree display (boolean) * configurable far mesh rendering distance * volumetric clouds (using fake shading) From 8993d9dd8321aad1243f4fb7fc55259c3747224f Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sat, 23 Jul 2011 02:04:24 +0300 Subject: [PATCH 05/25] Jungle biome/whatever thing --- data/junglegrass.png | Bin 0 -> 672 bytes data/jungletree.png | Bin 0 -> 502 bytes data/jungletree_top.png | Bin 0 -> 507 bytes src/content_mapblock.cpp | 62 +++++++++++++++ src/content_mapnode.cpp | 24 +++++- src/content_mapnode.h | 2 + src/mapgen.cpp | 168 ++++++++++++++++++++++++++++++++++++++- src/mapnode.h | 3 +- 8 files changed, 253 insertions(+), 6 deletions(-) create mode 100644 data/junglegrass.png create mode 100644 data/jungletree.png create mode 100644 data/jungletree_top.png diff --git a/data/junglegrass.png b/data/junglegrass.png new file mode 100644 index 0000000000000000000000000000000000000000..eea87c07c55ea290e364c45f0dbad538c19468c7 GIT binary patch literal 672 zcmV;R0$=@!P)e()ri+n`6JN%O zFJHyPi7zRRd!n0&mwOwQ60#pWi8&7S=l{oJn30syMK!7CKS<|c+d4FIyV z{AUsM9WHGdF74+A>TJWHIPv9AiE-jfV^|0PPRA=8*W}Js-hj|Op;F;lbAwS#7bEUE zU5t8Y)ErH%I<|Cvw{-^q*sjhZh`e4i;wVmhDO4xfqxH#i-ysCRcU3&8Oj08o+P7{7i`d*rrthj3|2b=fo`Y)B|= z=5}=!)SYboxo1UK#w;xnL>_|3!}@bCthpiU-MuH>EO_s6!U&4ZO|*4~@2`T{CZY&3 zsWM%RWR*8eI#;8vV@pR6d3;y|-*HWxj#spGhq0yeU1(Wa@-5W6yJ+hUSz11kcgQXv zl7q-&zBH=z{Z$}b+H!2^y#)H!ySoS?4~}axiE-jfEnM2taZLb^8yH(U#+HsMZ+fzl zD(cwGa=5gm3X`OyqQr-~16f)=ZehDR3u3;lJ2b^rhYm`OxIR5*=&ld(&~Kp4e;h7Mgy>0$zQ z5R%CvLPaPPlnyQ`LcyiDS@bUuih^swt)n2gl`euH>Y!k8C={eZ5uFlnu#mWv(xsaY z`du%L`lj!4-@W&~m%FL`^73ag5eML?cFTg3qFO0p*(Nua9R|Y@g1d)jx^AD&{Q*0B zCsZp%4B0%Y-2%{c`&hO~quwH$NmIxwPGaWFk&Bla9EFS+=Q^eJ?=Pz21jv%4X8P*1$Lefc4$8 z(B|t~U)4`9@2d8_fYNq;Oi-;9@x6fmu(r7v$t0PG6Pr|@B$AnLE<3h($07*qoM6N<$f?HDLB>(^b literal 0 HcmV?d00001 diff --git a/data/jungletree_top.png b/data/jungletree_top.png new file mode 100644 index 0000000000000000000000000000000000000000..2a9b51373d939d19e3486f735761bf57c88614a9 GIT binary patch literal 507 zcmVb^rhYok>JNR5*=wld(%eQ5431@8wWIge|(% z;+q1KaLCDcK@ACo|H6}&rXWEQf*>%0f~J;7ZqXPBuc1IO2wEJZDSFM-Bw|6E4RWsc zJ?)$BJ?Gr>efPWP8lLO)%jX`|ONYB!i^Ge11Su;@rIaV0h@nI3JlDa@?Nq5=I{b(7 z=`Ek{UuysP{zbRa-E zs01)lRkMg;}Q4Bm{YLVb`Bb zJkVhR9Pe!em>-%i0qNm`dQJ_}U9F`iQopS literal 0 HcmV?d00001 diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp index d8bf71dc0..730907222 100644 --- a/src/content_mapblock.cpp +++ b/src/content_mapblock.cpp @@ -198,6 +198,17 @@ void mapblock_mesh_generate_special(MeshMakeData *data, AtlasPointer pa_papyrus = g_texturesource->getTexture( g_texturesource->getTextureId("papyrus.png")); material_papyrus.setTexture(0, pa_papyrus.atlas); + + // junglegrass material + video::SMaterial material_junglegrass; + material_junglegrass.setFlag(video::EMF_LIGHTING, false); + material_junglegrass.setFlag(video::EMF_BILINEAR_FILTER, false); + material_junglegrass.setFlag(video::EMF_FOG_ENABLE, true); + material_junglegrass.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; + AtlasPointer pa_junglegrass = g_texturesource->getTexture( + g_texturesource->getTextureId("junglegrass.png")); + material_junglegrass.setTexture(0, pa_junglegrass.atlas); + for(s16 z=0; zm_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/1,0, 0,0,0, c, + pa_papyrus.x1(), pa_papyrus.y0()), + video::S3DVertex(-BS/2,BS/1,0, 0,0,0, c, + pa_papyrus.x0(), pa_papyrus.y0()), + }; + + if(j == 0) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(45); + } + else if(j == 1) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(-45); + } + else if(j == 2) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(135); + } + else if(j == 3) + { + for(u16 i=0; i<4; i++) + vertices[i].Pos.rotateXZBy(-135); + } + + for(u16 i=0; i<4; i++) + { + vertices[i].Pos *= 1.3; + vertices[i].Pos += intToFloat(p + blockpos_nodes, BS); + } + + u16 indices[] = {0,1,2,2,3,0}; + // Add to mesh collector + collector.append(material_junglegrass, vertices, 4, indices, 6); + } + } else if(n.d == CONTENT_RAIL) { u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio)); diff --git a/src/content_mapnode.cpp b/src/content_mapnode.cpp index 79e10fd61..be7f95adc 100644 --- a/src/content_mapnode.cpp +++ b/src/content_mapnode.cpp @@ -136,12 +136,34 @@ void content_mapnode_init() f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; setWoodLikeDiggingProperties(f->digging_properties, 1.0); + i = CONTENT_JUNGLETREE; + f = &content_features(i); + f->setAllTextures("jungletree.png"); + f->setTexture(0, "jungletree_top.png"); + f->setTexture(1, "jungletree_top.png"); + f->param_type = CPT_MINERAL; + //f->is_ground_content = true; + f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + setWoodLikeDiggingProperties(f->digging_properties, 1.0); + + i = CONTENT_JUNGLEGRASS; + f = &content_features(i); + f->setInventoryTexture("junglegrass.png"); + f->light_propagates = true; + f->param_type = CPT_LIGHT; + //f->is_ground_content = true; + f->air_equivalent = false; // grass grows underneath + f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + f->solidness = 0; // drawn separately, makes no faces + f->walkable = false; + setWoodLikeDiggingProperties(f->digging_properties, 0.10); + i = CONTENT_LEAVES; f = &content_features(i); f->light_propagates = true; //f->param_type = CPT_MINERAL; f->param_type = CPT_LIGHT; - f->is_ground_content = true; + //f->is_ground_content = true; if(new_style_leaves) { f->solidness = 0; // drawn separately, makes no faces diff --git a/src/content_mapnode.h b/src/content_mapnode.h index e53624c21..f7d3269ea 100644 --- a/src/content_mapnode.h +++ b/src/content_mapnode.h @@ -57,6 +57,8 @@ void content_mapnode_init(); #define CONTENT_PAPYRUS 28 #define CONTENT_BOOKSHELF 29 #define CONTENT_RAIL 30 +#define CONTENT_JUNGLETREE 31 +#define CONTENT_JUNGLEGRASS 32 #endif diff --git a/src/mapgen.cpp b/src/mapgen.cpp index 8dda93c96..0bb6560a8 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -152,6 +152,92 @@ static void make_tree(VoxelManipulator &vmanip, v3s16 p0) } } +static void make_jungletree(VoxelManipulator &vmanip, v3s16 p0) +{ + MapNode treenode(CONTENT_JUNGLETREE); + MapNode leavesnode(CONTENT_LEAVES); + + for(s16 x=-1; x<=1; x++) + for(s16 z=-1; z<=1; z++) + { + if(myrand_range(0, 2) == 0) + continue; + v3s16 p1 = p0 + v3s16(x,0,z); + v3s16 p2 = p0 + v3s16(x,-1,z); + if(vmanip.m_area.contains(p2) + && vmanip.m_data[vmanip.m_area.index(p2)] == CONTENT_AIR) + vmanip.m_data[vmanip.m_area.index(p2)] = treenode; + else if(vmanip.m_area.contains(p1)) + vmanip.m_data[vmanip.m_area.index(p1)] = treenode; + } + + s16 trunk_h = myrand_range(8, 12); + v3s16 p1 = p0; + for(s16 ii=0; ii leaves_d(new u8[leaves_a.getVolume()]); + Buffer leaves_d(leaves_a.getVolume()); + for(s32 i=0; i 1.0) + noise = 1.0; + return noise; +} + #if 0 double randomstone_amount_2d(u64 seed, v2s16 p) { @@ -1909,11 +2008,19 @@ void make_block(BlockMakeData *data) } /* - Add trees + Calculate some stuff */ + float surface_humidity = surface_humidity_2d(data->seed, p2d_center); + bool is_jungle = surface_humidity > 0.75; // Amount of trees u32 tree_count = block_area_nodes * tree_amount_2d(data->seed, p2d_center); + if(is_jungle) + tree_count *= 5; + + /* + Add trees + */ PseudoRandom treerandom(blockseed); // Put trees in random places on part of division for(u32 i=0; ivmanip->m_area.index(p); MapNode *n = &data->vmanip->m_data[i]; - if(n->d != CONTENT_AIR && n->d != CONTENT_WATERSOURCE && n->d != CONTENT_IGNORE) + //if(n->d != CONTENT_AIR && n->d != CONTENT_WATERSOURCE && n->d != CONTENT_IGNORE) + if(content_features(n->d).is_ground_content) { found = true; break; @@ -1965,7 +2073,11 @@ void make_block(BlockMakeData *data) else if((n->d == CONTENT_MUD || n->d == CONTENT_GRASS) && y > WATER_LEVEL + 2) { p.Y++; - make_tree(vmanip, p); + //if(surface_humidity_2d(data->seed, v2s16(x, y)) < 0.5) + if(is_jungle == false) + make_tree(vmanip, p); + else + make_jungletree(vmanip, p); } // Cactii grow only on sand, on land else if(n->d == CONTENT_SAND && y > WATER_LEVEL + 2) @@ -1976,6 +2088,54 @@ void make_block(BlockMakeData *data) } } + /* + Add jungle grass + */ + if(is_jungle) + { + PseudoRandom grassrandom(blockseed); + for(u32 i=0; iseed, v2s16(x,z), 4); + if(y < WATER_LEVEL) + continue; + if(y < node_min.Y || y > node_max.Y) + continue; + /* + Find exact ground level + */ + v3s16 p(x,y+6,z); + bool found = false; + for(; p.Y >= y-6; p.Y--) + { + u32 i = data->vmanip->m_area.index(p); + MapNode *n = &data->vmanip->m_data[i]; + if(content_features(n->d).is_ground_content + || n->d == CONTENT_JUNGLETREE) + { + found = true; + break; + } + } + // If not found, handle next one + if(found == false) + continue; + p.Y++; + if(vmanip.m_area.contains(p) == false) + continue; + if(vmanip.m_data[vmanip.m_area.index(p)].d != CONTENT_AIR) + continue; + /*p.Y--; + if(vmanip.m_area.contains(p)) + vmanip.m_data[vmanip.m_area.index(p)] = CONTENT_MUD; + p.Y++;*/ + if(vmanip.m_area.contains(p)) + vmanip.m_data[vmanip.m_area.index(p)] = CONTENT_JUNGLEGRASS; + } + } + #if 0 /* Add some kind of random stones diff --git a/src/mapnode.h b/src/mapnode.h index 33128049a..ebca3755a 100644 --- a/src/mapnode.h +++ b/src/mapnode.h @@ -119,7 +119,8 @@ struct ContentFeatures TileSpec tiles[6]; video::ITexture *inventory_texture; - + + // True for all ground-like things like stone and mud, false for eg. trees bool is_ground_content; bool light_propagates; bool sunlight_propagates; From d67cef0eb76c4c35cebb4c8f35d62f90c573b198 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sat, 23 Jul 2011 04:10:17 +0300 Subject: [PATCH 06/25] Made dark places tint slightly in blue --- src/content_mapblock.cpp | 21 +++++++++++---------- src/mapblock_mesh.cpp | 27 +++++++++++++++++++++------ src/mapblock_mesh.h | 4 ++++ 3 files changed, 36 insertions(+), 16 deletions(-) diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp index 730907222..e542cb335 100644 --- a/src/content_mapblock.cpp +++ b/src/content_mapblock.cpp @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "content_mapnode.h" #include "main.h" // For g_settings and g_texturesource #include "mineral.h" +#include "mapblock_mesh.h" // For MapBlock_LightColor() #ifndef SERVER // Create a cuboid. @@ -286,7 +287,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, else if(n.d == CONTENT_SIGN_WALL) { u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio)); - video::SColor c(255,l,l,l); + video::SColor c = MapBlock_LightColor(255, l); float d = (float)BS/16; // Wall at X+ of node @@ -352,7 +353,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, // Otherwise use the light of this node (the water) else l = decode_light(n.getLightBlend(data->m_daynight_ratio)); - video::SColor c(WATER_ALPHA,l,l,l); + video::SColor c = MapBlock_LightColor(WATER_ALPHA, l); // Neighbor water levels (key = relative position) // Includes current node @@ -618,7 +619,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, continue; u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio)); - video::SColor c(WATER_ALPHA,l,l,l); + video::SColor c = MapBlock_LightColor(WATER_ALPHA, l); video::S3DVertex vertices[4] = { @@ -653,7 +654,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, { /*u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));*/ u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); - video::SColor c(255,l,l,l); + video::SColor c = MapBlock_LightColor(255, l); for(u32 j=0; j<6; j++) { @@ -720,7 +721,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, else if(n.d == CONTENT_GLASS) { u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); - video::SColor c(255,l,l,l); + video::SColor c = MapBlock_LightColor(255, l); for(u32 j=0; j<6; j++) { @@ -783,7 +784,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, else if(n.d == CONTENT_FENCE) { u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); - video::SColor c(255,l,l,l); + video::SColor c = MapBlock_LightColor(255, l); const f32 post_rad=(f32)BS/10; const f32 bar_rad=(f32)BS/20; @@ -872,7 +873,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, else l = 255;*/ u8 l = 255; - video::SColor c(255,l,l,l); + video::SColor c = MapBlock_LightColor(255, l); // Get the right texture TileSpec ts = n.getTile(dir); @@ -930,7 +931,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, 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); + video::SColor c = MapBlock_LightColor(255, l); for(u32 j=0; j<4; j++) { @@ -980,7 +981,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, else if(n.d == CONTENT_JUNGLEGRASS) { u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); - video::SColor c(255,l,l,l); + video::SColor c = MapBlock_LightColor(255, l); for(u32 j=0; j<4; j++) { @@ -1031,7 +1032,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, else if(n.d == CONTENT_RAIL) { u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio)); - video::SColor c(255,l,l,l); + video::SColor c = MapBlock_LightColor(255, l); bool is_rail_x [] = { false, false }; /* x-1, x+1 */ bool is_rail_z [] = { false, false }; /* z-1, z+1 */ diff --git a/src/mapblock_mesh.cpp b/src/mapblock_mesh.cpp index 447716d00..bcbf37418 100644 --- a/src/mapblock_mesh.cpp +++ b/src/mapblock_mesh.cpp @@ -140,9 +140,24 @@ void getNodeVertexDirs(v3s16 dir, v3s16 *vertex_dirs) } } -inline video::SColor lightColor(u8 alpha, u8 light) +video::SColor MapBlock_LightColor(u8 alpha, u8 light) { +#if 0 return video::SColor(alpha,light,light,light); +#endif + //return video::SColor(alpha,light,light,MYMAX(0, (s16)light-25)+25); + /*return video::SColor(alpha,light,light,MYMAX(0, + pow((float)light/255.0, 0.8)*255.0));*/ +#if 1 + // Emphase blue a bit in darker places + float lim = 80; + float power = 0.7; + if(light > lim) + return video::SColor(alpha,light,light,light); + else + return video::SColor(alpha,light,light,MYMAX(0, + pow((float)light/lim, power)*lim)); +#endif } struct FastFace @@ -198,7 +213,7 @@ void makeFastFace(TileSpec tile, u8 li0, u8 li1, u8 li2, u8 li3, v3f p, float w = tile.texture.size.X; float h = tile.texture.size.Y; - /*video::SColor c = lightColor(alpha, li); + /*video::SColor c = MapBlock_LightColor(alpha, li); face.vertices[0] = video::S3DVertex(vertex_pos[0], v3f(0,1,0), c, core::vector2d(x0+w*abs_scale, y0+h)); @@ -210,16 +225,16 @@ void makeFastFace(TileSpec tile, u8 li0, u8 li1, u8 li2, u8 li3, v3f p, core::vector2d(x0+w*abs_scale, y0));*/ face.vertices[0] = video::S3DVertex(vertex_pos[0], v3f(0,1,0), - lightColor(alpha, li0), + MapBlock_LightColor(alpha, li0), core::vector2d(x0+w*abs_scale, y0+h)); face.vertices[1] = video::S3DVertex(vertex_pos[1], v3f(0,1,0), - lightColor(alpha, li1), + MapBlock_LightColor(alpha, li1), core::vector2d(x0, y0+h)); face.vertices[2] = video::S3DVertex(vertex_pos[2], v3f(0,1,0), - lightColor(alpha, li2), + MapBlock_LightColor(alpha, li2), core::vector2d(x0, y0)); face.vertices[3] = video::S3DVertex(vertex_pos[3], v3f(0,1,0), - lightColor(alpha, li3), + MapBlock_LightColor(alpha, li3), core::vector2d(x0+w*abs_scale, y0)); face.tile = tile; diff --git a/src/mapblock_mesh.h b/src/mapblock_mesh.h index 591172bc9..d43c19a25 100644 --- a/src/mapblock_mesh.h +++ b/src/mapblock_mesh.h @@ -121,6 +121,9 @@ private: core::array m_prebuffers; }; +// Helper functions +video::SColor MapBlock_LightColor(u8 alpha, u8 light); + class MapBlock; struct MeshMakeData @@ -137,6 +140,7 @@ struct MeshMakeData void fill(u32 daynight_ratio, MapBlock *block); }; +// This is the highest-level function in here scene::SMesh* makeMapBlockMesh(MeshMakeData *data); #endif From 98be7787660d81c1b5e0fd2408e754fdc3238288 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sat, 23 Jul 2011 16:08:07 +0300 Subject: [PATCH 07/25] switched my textures back --- data/player.png | Bin 652 -> 212 bytes data/player_back.png | Bin 292 -> 201 bytes data/unknown_block.png | Bin 287 -> 582 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/data/player.png b/data/player.png index 60ac4854ba00dc30c692e4fafdd6a0810d0806fb..90adf97476ecd3442dcd435201658ebfaef9d7ab 100644 GIT binary patch delta 172 zcmV;d08{^r1=InM90dRyiTKQsE*O7?Nkl569sGa~0-TA{S>tn2Gi5US)fn%_IB-w+G!_iCux}jBA8FpZ a2p}uF=p{1q#6|1?0000uX70004VQb$4nuFf3kks%m=2XskIMF-mj8Wt-G&1bc8 z0006WNkl za=B9FRR7YO=47|M4gl=;>I{HoZ9@B^V9|zNoh@5`FaVHc3*K+GGgCGJfGJ3a_+?QG zX_HhRx4&v9XTw$y^81d) zAnha>yo=2RB@qfcE+raX_;Q(WuSuj)>f-e2AX>csR?`{O#Y{~lnkAc}HcPb`&0+`5 zVn^$LB=HNH#mV{+oOgBSUFW3Uvk&K=R+>gxgWK91{{fAO1W^PJsc!%P002ovPDHLkV1jeR B8#n*} diff --git a/data/player_back.png b/data/player_back.png index 447c1fd8f149788f85f9aa350f27361d5e8459d8..530aa7519b95a650ce4fea2612b2dced58becdbc 100644 GIT binary patch delta 173 zcmV;e08;;?0?7f8B!3BTNLh0L01m_e01m_fl`9S#0001cNklf%00000NkvXXu0mjfat}zN delta 265 zcmV+k0rvjM0i*(uB!2;OQb$4nuFf3k0002qNkltn$piC43Xx-kl$iBc~N0|PJu@#W4uyc&%2juPR5|Nn^-V_;xl!5R1e|Kp2FxFn;D zy7B+;@>$r;V1zi3@&7-p@+&*jFv9>Pnc~nmnvk$0Bv@z@3V%Rs>R1>U7#PYW=fMTK zo+aRol`^RXaQ-Ul`u07gbEDUgvuFW@QNFkSHW(_ail?>_&}NI0>%W88Gi-<001BJ|6u?C00eVFNmK|32nc)#WQYI&010qNS#tmY4#WTe z4#WYKD-Ig~00HPpL_t(Ijb)QRiyBcB#ee=;B+VdGNlY0QlVU)GMMN0vbP&==rkM|s z$}W&LevWAdEXC;}5|L>{m_}J_B`#S8d5}^};oi$6`xmW$PjT!5rp4~Uv=EX!6FM|LH|OI$zn-2oc(GcOo&RVzDtGYiZJpiYfyy0JDsTAlGa(oaDfD{}*Vy%x*@;4R zKJ^0z%Q>;@=~p}uWkm_}w+Z0tUuZRG8-42D% zpZeGQ@*@MxLa5|%2v(+QP>mV7Eu}SyDuE+6oBNUmNbWboEay;FpGj=`2mjN|r zu$*hgaj6O~e*`U++51AhS%)fP&O&{`3)2;J^irAzE9 zYjQd!XKV7E1f|OZcMg=KSrFu{W&*)I8|y%Pk~EVZ0IxO#u76Ay1efWeZ)$G%yT&Y% z*pt$wSn|dV;gl-~RKBf-t$|4d2B%Sy(uX#jmw2S?TnAX?|mLcJefn}Xnkx!fRV zYjSJycpM(@S3C}0tdS?FHii54muafHR`S{0Am#{;Pt~=84m=Id>pFOEOTRwv54@^% VzM5#CCjbBd00>D%PDHLkV1j%wckciI From 976ec31c1faedc3a34935c3aafd6a868e222d1ad Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sat, 23 Jul 2011 16:46:34 +0300 Subject: [PATCH 08/25] switched to old transformLiquids, new one is not ready --- src/map.cpp | 437 +++++++++++++++++++++++++++------------------------- 1 file changed, 223 insertions(+), 214 deletions(-) diff --git a/src/map.cpp b/src/map.cpp index e1769b8ef..ab4acd4d5 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1540,17 +1540,6 @@ 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 & modified_blocks) { DSTACK(__FUNCTION_NAME); @@ -1570,220 +1559,240 @@ void Map::transformLiquids(core::map & modified_blocks) v3s16 p0 = m_transforming_liquid.pop_front(); MapNode n0 = getNodeNoEx(p0); - - /* - 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; - } - 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; - } - 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; - } - 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; - } - } - // 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; - } - - /* - 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))) + + // 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); + /* - 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; + 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"<= 7 - WATER_DROP_BOOST) + new_liquid_level = 7; + else + new_liquid_level = n2_liquid_level + WATER_DROP_BOOST; + } + else if(n2_liquid_level > 0) + { + new_liquid_level = n2_liquid_level - 1; + } + + if(new_liquid_level > new_liquid_level_max) + new_liquid_level_max = new_liquid_level; + } + } //for + + /* + If liquid level should be something else, update it and + add all the neighboring water nodes to the transform queue. + */ + if(new_liquid_level_max != liquid_level) + { + if(new_liquid_level_max == -1) + { + // Remove water alltoghether + n0.d = CONTENT_AIR; + n0.param2 = 0; + setNode(p0, n0); + } + else + { + n0.param2 = new_liquid_level_max; + setNode(p0, n0); + } + + // Block has been modified + { + v3s16 blockpos = getNodeBlockPos(p0); + MapBlock *block = getBlockNoCreateNoEx(blockpos); + if(block != NULL) + modified_blocks.insert(blockpos, block); + } + + /* + Add neighboring non-source liquid nodes to transform queue. + */ + v3s16 dirs[6] = { + v3s16(0,0,1), // back + v3s16(0,1,0), // top + v3s16(1,0,0), // right + v3s16(0,0,-1), // front + v3s16(0,-1,0), // bottom + v3s16(-1,0,0), // left + }; + for(u16 i=0; i<6; i++) + { + v3s16 p2 = p0 + dirs[i]; + + MapNode n2 = getNodeNoEx(p2); + if(content_flowing_liquid(n2.d)) + { + m_transforming_liquid.push_back(p2); + } + } + } } - setNode(p0, n0); - v3s16 blockpos = getNodeBlockPos(p0); - MapBlock *block = getBlockNoCreateNoEx(blockpos); - if(block != NULL) - modified_blocks.insert(blockpos, block); - + + // Get a new one from queue if the node has turned into non-water + if(content_liquid(n0.d) == false) + continue; + /* - 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); + 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< 0)) - m_transforming_liquid.push_back(airs[i].p); + bool n2_is_source = !content_flowing_liquid(n2.d); + u8 n2_liquid_level = 8; + if(n2_is_source == false) + n2_liquid_level = n2.param2 & 0x07; + + if(to_bottom) + { + flowed = true; } + + if(n2_is_source) + { + // Just flow into the source, nothing changes. + // n2_changed is not set because destination didn't change + flowed = true; + } + else + { + if(liquid_next_level > liquid_level) + { + n2.param2 = liquid_next_level; + setNode(p2, n2); + + n2_changed = true; + flowed = true; + } + } + } + else if(n2.d == CONTENT_AIR) + { + n2.d = nonsource_c; + n2.param2 = liquid_next_level; + setNode(p2, n2); + + n2_changed = true; + flowed = true; + } + + //dstream<<"[2] n2.param="<<(int)n2.param<= 100000) - if(loopcount >= initial_size * 10) { + if(loopcount >= initial_size * 1) break; - } } //dstream<<"Map::transformLiquids(): loopcount="< Date: Sat, 23 Jul 2011 16:55:26 +0300 Subject: [PATCH 09/25] extended content-type range --- src/collision.cpp | 3 +- src/content_craft.cpp | 5 +- src/content_inventory.cpp | 4 +- src/content_inventory.h | 5 +- src/content_mapblock.cpp | 46 ++++++++-------- src/content_mapnode.cpp | 55 ++++++++++++++++++- src/content_mapnode.h | 44 +++++++++------ src/environment.cpp | 38 ++++++------- src/game.cpp | 12 ++--- src/inventory.cpp | 2 +- src/inventory.h | 10 ++-- src/main.cpp | 20 ++++++- src/map.cpp | 70 ++++++++++++------------ src/mapblock.cpp | 24 ++++----- src/mapblock_mesh.cpp | 14 ++--- src/mapblockobject.cpp | 4 +- src/mapgen.cpp | 106 ++++++++++++++++++------------------ src/mapnode.cpp | 92 ++++++++++++++++--------------- src/mapnode.h | 110 +++++++++++++++++++++----------------- src/materials.cpp | 4 +- src/materials.h | 2 +- src/player.cpp | 12 ++--- src/serialization.h | 3 +- src/server.cpp | 14 ++--- src/test.cpp | 34 ++++++------ src/voxel.cpp | 2 +- util/minetestmapper.py | 11 ++-- 27 files changed, 428 insertions(+), 318 deletions(-) diff --git a/src/collision.cpp b/src/collision.cpp index 01d546284..3d322cf0c 100644 --- a/src/collision.cpp +++ b/src/collision.cpp @@ -78,7 +78,8 @@ collisionMoveResult collisionMoveSimple(Map *map, f32 pos_max_d, { try{ // Object collides into walkable nodes - if(content_walkable(map->getNode(v3s16(x,y,z)).d) == false) + MapNode n = map->getNode(v3s16(x,y,z)); + if(content_features(n).walkable == false) continue; } catch(InvalidPositionException &e) diff --git a/src/content_craft.cpp b/src/content_craft.cpp index 32d2e6d48..e4573a211 100644 --- a/src/content_craft.cpp +++ b/src/content_craft.cpp @@ -21,6 +21,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "inventory.h" #include "content_mapnode.h" #include "player.h" +#include "mapnode.h" // For content_t /* items: actually *items[9] @@ -347,7 +348,7 @@ void craft_set_creative_inventory(Player *player) */ // CONTENT_IGNORE-terminated list - u8 material_items[] = { + content_t material_items[] = { CONTENT_TORCH, CONTENT_COBBLE, CONTENT_MUD, @@ -366,7 +367,7 @@ void craft_set_creative_inventory(Player *player) CONTENT_IGNORE }; - u8 *mip = material_items; + content_t *mip = material_items; for(u16 i=0; i +#include "mapnode.h" // For content_t class InventoryItem; class ServerActiveObject; class ServerEnvironment; -bool item_material_is_cookable(u8 content); -InventoryItem* item_material_create_cook_result(u8 content); +bool item_material_is_cookable(content_t content); +InventoryItem* item_material_create_cook_result(content_t content); std::string item_craft_get_image_name(const std::string &subname); ServerActiveObject* item_craft_create_object(const std::string &subname, diff --git a/src/content_mapblock.cpp b/src/content_mapblock.cpp index bdc9baa2a..38bc9620c 100644 --- a/src/content_mapblock.cpp +++ b/src/content_mapblock.cpp @@ -199,7 +199,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, /* Add torches to mesh */ - if(n.d == CONTENT_TORCH) + if(n.getContent() == CONTENT_TORCH) { video::SColor c(255,255,255,255); @@ -212,7 +212,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 0,0), }; - v3s16 dir = unpackDir(n.dir); + v3s16 dir = unpackDir(n.param2); for(s32 i=0; i<4; i++) { @@ -262,7 +262,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, /* Signs on walls */ - else if(n.d == CONTENT_SIGN_WALL) + else if(n.getContent() == CONTENT_SIGN_WALL) { u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio)); video::SColor c(255,l,l,l); @@ -277,7 +277,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, video::S3DVertex(BS/2-d,BS/2,-BS/2, 0,0,0, c, 0,0), }; - v3s16 dir = unpackDir(n.dir); + v3s16 dir = unpackDir(n.param2); for(s32 i=0; i<4; i++) { @@ -317,16 +317,16 @@ void mapblock_mesh_generate_special(MeshMakeData *data, /* Add flowing water to mesh */ - else if(n.d == CONTENT_WATER) + else if(n.getContent() == CONTENT_WATER) { bool top_is_water = false; MapNode ntop = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z)); - if(ntop.d == CONTENT_WATER || ntop.d == CONTENT_WATERSOURCE) + if(ntop.getContent() == CONTENT_WATER || ntop.getContent() == CONTENT_WATERSOURCE) top_is_water = true; u8 l = 0; // Use the light of the node on top if possible - if(content_features(ntop.d).param_type == CPT_LIGHT) + if(content_features(ntop).param_type == CPT_LIGHT) l = decode_light(ntop.getLightBlend(data->m_daynight_ratio)); // Otherwise use the light of this node (the water) else @@ -336,7 +336,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, // Neighbor water levels (key = relative position) // Includes current node core::map neighbor_levels; - core::map neighbor_contents; + core::map neighbor_contents; core::map neighbor_flags; const u8 neighborflag_top_is_water = 0x01; v3s16 neighbor_dirs[9] = { @@ -358,13 +358,13 @@ void mapblock_mesh_generate_special(MeshMakeData *data, // Check neighbor v3s16 p2 = p + neighbor_dirs[i]; MapNode n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2); - if(n2.d != CONTENT_IGNORE) + if(n2.getContent() != CONTENT_IGNORE) { - content = n2.d; + content = n2.getContent(); - if(n2.d == CONTENT_WATERSOURCE) + if(n2.getContent() == CONTENT_WATERSOURCE) level = (-0.5+node_water_level) * BS; - else if(n2.d == CONTENT_WATER) + else if(n2.getContent() == CONTENT_WATER) level = (-0.5 + ((float)n2.param2 + 0.5) / 8.0 * node_water_level) * BS; @@ -373,7 +373,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, // doesn't exist p2.Y += 1; n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2); - if(n2.d == CONTENT_WATERSOURCE || n2.d == CONTENT_WATER) + if(n2.getContent() == CONTENT_WATERSOURCE || n2.getContent() == CONTENT_WATER) flags |= neighborflag_top_is_water; } @@ -581,14 +581,14 @@ void mapblock_mesh_generate_special(MeshMakeData *data, /* Add water sources to mesh if using new style */ - else if(n.d == CONTENT_WATERSOURCE && new_style_water) + else if(n.getContent() == CONTENT_WATERSOURCE && new_style_water) { //bool top_is_water = false; bool top_is_air = false; MapNode n = data->m_vmanip.getNodeNoEx(blockpos_nodes + v3s16(x,y+1,z)); - /*if(n.d == CONTENT_WATER || n.d == CONTENT_WATERSOURCE) + /*if(n.getContent() == CONTENT_WATER || n.getContent() == CONTENT_WATERSOURCE) top_is_water = true;*/ - if(n.d == CONTENT_AIR) + if(n.getContent() == CONTENT_AIR) top_is_air = true; /*if(top_is_water == true) @@ -628,7 +628,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, /* Add leaves if using new style */ - else if(n.d == CONTENT_LEAVES && new_style_leaves) + else if(n.getContent() == CONTENT_LEAVES && new_style_leaves) { /*u8 l = decode_light(n.getLightBlend(data->m_daynight_ratio));*/ u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); @@ -696,7 +696,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, /* Add glass */ - else if(n.d == CONTENT_GLASS) + else if(n.getContent() == CONTENT_GLASS) { u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); video::SColor c(255,l,l,l); @@ -759,7 +759,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, /* Add fence */ - else if(n.d == CONTENT_FENCE) + else if(n.getContent() == CONTENT_FENCE) { u8 l = decode_light(undiminish_light(n.getLightBlend(data->m_daynight_ratio))); video::SColor c(255,l,l,l); @@ -785,7 +785,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, v3s16 p2 = p; p2.X++; MapNode n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2); - if(n2.d == CONTENT_FENCE) + if(n2.getContent() == CONTENT_FENCE) { pos = intToFloat(p+blockpos_nodes, BS); pos.X += BS/2; @@ -811,7 +811,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, p2 = p; p2.Z++; n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + p2); - if(n2.d == CONTENT_FENCE) + if(n2.getContent() == CONTENT_FENCE) { pos = intToFloat(p+blockpos_nodes, BS); pos.Z += BS/2; @@ -838,7 +838,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, /* Add stones with minerals if stone is invisible */ - else if(n.d == CONTENT_STONE && invisible_stone && n.getMineral() != MINERAL_NONE) + else if(n.getContent() == CONTENT_STONE && invisible_stone && n.getMineral() != MINERAL_NONE) { for(u32 j=0; j<6; j++) { @@ -846,7 +846,7 @@ void mapblock_mesh_generate_special(MeshMakeData *data, v3s16 dir = g_6dirs[j]; /*u8 l = 0; MapNode n2 = data->m_vmanip.getNodeNoEx(blockpos_nodes + dir); - if(content_features(n2.d).param_type == CPT_LIGHT) + if(content_features(n2).param_type == CPT_LIGHT) l = decode_light(n2.getLightBlend(data->m_daynight_ratio)); else l = 255;*/ diff --git a/src/content_mapnode.cpp b/src/content_mapnode.cpp index d82ccc5c9..e2aed2458 100644 --- a/src/content_mapnode.cpp +++ b/src/content_mapnode.cpp @@ -31,6 +31,59 @@ void setStoneLikeDiggingProperties(DiggingPropertiesList &list, float toughness) void setDirtLikeDiggingProperties(DiggingPropertiesList &list, float toughness); void setWoodLikeDiggingProperties(DiggingPropertiesList &list, float toughness); +content_t trans_table_19[][2] = { + {CONTENT_GRASS, 1}, + {CONTENT_TREE, 4}, + {CONTENT_LEAVES, 5}, + {CONTENT_GRASS_FOOTSTEPS, 6}, + {CONTENT_MESE, 7}, + {CONTENT_MUD, 8}, + {CONTENT_CLOUD, 10}, + {CONTENT_COALSTONE, 11}, + {CONTENT_WOOD, 12}, + {CONTENT_SAND, 13}, + {CONTENT_COBBLE, 18}, + {CONTENT_STEEL, 19}, + {CONTENT_GLASS, 20}, + {CONTENT_MOSSYCOBBLE, 22}, + {CONTENT_GRAVEL, 23}, +}; + +MapNode mapnode_translate_from_internal(MapNode n_from, u8 version) +{ + MapNode result = n_from; + if(version <= 19) + { + content_t c_from = n_from.getContent(); + for(u32 i=0; igetNodeNoEx(p); - if(n.d == CONTENT_IGNORE) + if(n.getContent() == CONTENT_IGNORE) continue; - if(content_features(n.d).liquid_type != LIQUID_NONE) + if(content_features(n).liquid_type != LIQUID_NONE) continue; - if(content_features(n.d).walkable) + if(content_features(n).walkable) { last_node_walkable = true; continue; @@ -555,7 +555,7 @@ void spawnRandomObjects(MapBlock *block) if(last_node_walkable) { // If block contains light information - if(content_features(n.d).param_type == CPT_LIGHT) + if(content_features(n).param_type == CPT_LIGHT) { if(n.getLight(LIGHTBANK_DAY) <= 5) { @@ -624,15 +624,15 @@ void ServerEnvironment::activateBlock(MapBlock *block, u32 additional_dtime) #if 1 // Test something: // Convert all mud under proper day lighting to grass - if(n.d == CONTENT_MUD) + if(n.getContent() == CONTENT_MUD) { if(dtime_s > 300) { MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0)); - if(content_features(n_top.d).air_equivalent && + if(content_features(n_top).air_equivalent && n_top.getLight(LIGHTBANK_DAY) >= 13) { - n.d = CONTENT_GRASS; + n.setContent(CONTENT_GRASS); m_map->addNodeWithEvent(p, n); } } @@ -686,9 +686,9 @@ void ServerEnvironment::step(float dtime) v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0), BS); try{ MapNode n = m_map->getNode(bottompos); - if(n.d == CONTENT_GRASS) + if(n.getContent() == CONTENT_GRASS) { - n.d = CONTENT_GRASS_FOOTSTEPS; + n.setContent(CONTENT_GRASS_FOOTSTEPS); m_map->setNode(bottompos, n); } } @@ -859,15 +859,15 @@ void ServerEnvironment::step(float dtime) Test something: Convert mud under proper lighting to grass */ - if(n.d == CONTENT_MUD) + if(n.getContent() == CONTENT_MUD) { if(myrand()%20 == 0) { MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0)); - if(content_features(n_top.d).air_equivalent && + if(content_features(n_top).air_equivalent && n_top.getLightBlend(getDayNightRatio()) >= 13) { - n.d = CONTENT_GRASS; + n.setContent(CONTENT_GRASS); m_map->addNodeWithEvent(p, n); } } @@ -875,15 +875,15 @@ void ServerEnvironment::step(float dtime) /* Convert grass into mud if under something else than air */ - else if(n.d == CONTENT_GRASS) + else if(n.getContent() == CONTENT_GRASS) { //if(myrand()%20 == 0) { MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0)); - if(n_top.d != CONTENT_AIR - && n_top.d != CONTENT_IGNORE) + if(n_top.getContent() != CONTENT_AIR + && n_top.getContent() != CONTENT_IGNORE) { - n.d = CONTENT_MUD; + n.setContent(CONTENT_MUD); m_map->addNodeWithEvent(p, n); } } @@ -1632,9 +1632,9 @@ void ClientEnvironment::step(float dtime) v3s16 bottompos = floatToInt(playerpos + v3f(0,-BS/4,0), BS); try{ MapNode n = m_map->getNode(bottompos); - if(n.d == CONTENT_GRASS) + if(n.getContent() == CONTENT_GRASS) { - n.d = CONTENT_GRASS_FOOTSTEPS; + n.setContent(CONTENT_GRASS_FOOTSTEPS); m_map->setNode(bottompos, n); // Update mesh on client if(m_map->mapType() == MAPTYPE_CLIENT) @@ -1873,7 +1873,7 @@ void ClientEnvironment::drawPostFx(video::IVideoDriver* driver, v3f camera_pos) v3f pos_f = camera_pos; v3s16 p_nodes = floatToInt(pos_f, BS); MapNode n = m_map->getNodeNoEx(p_nodes); - if(n.d == CONTENT_WATER || n.d == CONTENT_WATERSOURCE) + if(n.getContent() == CONTENT_WATER || n.getContent() == CONTENT_WATERSOURCE) { v2u32 ss = driver->getScreenSize(); core::rect rect(0,0, ss.X, ss.Y); diff --git a/src/game.cpp b/src/game.cpp index faadd0fe7..7e2ee44fc 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -417,7 +417,7 @@ void getPointedNode(Client *client, v3f player_position, try { n = client->getNode(v3s16(x,y,z)); - if(content_pointable(n.d) == false) + if(content_pointable(n.getContent()) == false) continue; } catch(InvalidPositionException &e) @@ -442,9 +442,9 @@ void getPointedNode(Client *client, v3f player_position, /* Meta-objects */ - if(n.d == CONTENT_TORCH) + if(n.getContent() == CONTENT_TORCH) { - v3s16 dir = unpackDir(n.dir); + v3s16 dir = unpackDir(n.param2); v3f dir_f = v3f(dir.X, dir.Y, dir.Z); dir_f *= BS/2 - BS/6 - BS/20; v3f cpf = npf + dir_f; @@ -489,9 +489,9 @@ void getPointedNode(Client *client, v3f player_position, } } } - else if(n.d == CONTENT_SIGN_WALL) + else if(n.getContent() == CONTENT_SIGN_WALL) { - v3s16 dir = unpackDir(n.dir); + v3s16 dir = unpackDir(n.param2); v3f dir_f = v3f(dir.X, dir.Y, dir.Z); dir_f *= BS/2 - BS/6 - BS/20; v3f cpf = npf + dir_f; @@ -1722,7 +1722,7 @@ void the_game( } // Get digging properties for material and tool - u8 material = n.d; + content_t material = n.getContent(); DiggingProperties prop = getDiggingProperties(material, toolname); diff --git a/src/inventory.cpp b/src/inventory.cpp index fec51a759..7ef7f0138 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -61,7 +61,7 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is) is>>material; u16 count; is>>count; - if(material > 255) + if(material > MAX_CONTENT) throw SerializationError("Too large material number"); return new MaterialItem(material, count); } diff --git a/src/inventory.h b/src/inventory.h index 07d81a3f7..5c64f89bb 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -30,8 +30,8 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "common_irrlicht.h" #include "debug.h" #include "mapblockobject.h" -// For g_materials -#include "main.h" +#include "main.h" // For g_materials +#include "mapnode.h" // For content_t #define QUANTITY_ITEM_MAX_COUNT 99 @@ -113,7 +113,7 @@ protected: class MaterialItem : public InventoryItem { public: - MaterialItem(u8 content, u16 count): + MaterialItem(content_t content, u16 count): InventoryItem(count) { m_content = content; @@ -175,12 +175,12 @@ public: /* Special methods */ - u8 getMaterial() + content_t getMaterial() { return m_content; } private: - u8 m_content; + content_t m_content; }; //TODO: Remove diff --git a/src/main.cpp b/src/main.cpp index 698c5fc71..5aff62bf2 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,6 +54,24 @@ A list of "active blocks" in which stuff happens. (+=done) + This was left to be done by the old system and it sends only the nearest ones. +Vim conversion regexpes for moving to extended content type storage: +%s/\(\.\|->\)d \([!=]=\)/\1getContent() \2/g +%s/content_features(\([^.]*\)\.d)/content_features(\1)/g +%s/\(\.\|->\)d = \([^;]*\);/\1setContent(\2);/g +%s/\(getNodeNoExNoEmerge([^)]*)\)\.d/\1.getContent()/g +%s/\(getNodeNoExNoEmerge(.*)\)\.d/\1.getContent()/g +%s/\.d;/.getContent();/g +%s/\(content_liquid\|content_flowing_liquid\|make_liquid_flowing\|content_pointable\)(\([^.]*\).d)/\1(\2.getContent())/g +Other things to note: +- node.d = node.param0 (only in raw serialization; use getContent() otherwise) +- node.param = node.param1 +- node.dir = node.param2 +- content_walkable(node.d) etc should be changed to + content_features(node).walkable etc +- Also check for lines that store the result of getContent to a 8-bit + variable and fix them (result of getContent() must be stored in + content_t, which is 16-bit) + Old, wild and random suggestions that probably won't be done: ------------------------------------------------------------- @@ -337,7 +355,7 @@ TODO: Restart irrlicht completely when coming back to main menu from game. TODO: Merge bahamada's audio stuff (clean patch available) -TODO: Merge key configuration menu (no clean patch available) +TODO: Move content_features to mapnode_content_features.{h,cpp} or so Making it more portable: ------------------------ diff --git a/src/map.cpp b/src/map.cpp index 2a3e9f760..dd32e55ba 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -630,9 +630,9 @@ s16 Map::propagateSunlight(v3s16 start, else { /*// Turn mud into grass - if(n.d == CONTENT_MUD) + if(n.getContent() == CONTENT_MUD) { - n.d = CONTENT_GRASS; + n.setContent(CONTENT_GRASS); block->setNode(relpos, n); modified_blocks.insert(blockpos, block); }*/ @@ -920,15 +920,15 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, /* If the new node is solid and there is grass below, change it to mud */ - if(content_features(n.d).walkable == true) + if(content_features(n).walkable == true) { try{ MapNode bottomnode = getNode(bottompos); - if(bottomnode.d == CONTENT_GRASS - || bottomnode.d == CONTENT_GRASS_FOOTSTEPS) + if(bottomnode.getContent() == CONTENT_GRASS + || bottomnode.getContent() == CONTENT_GRASS_FOOTSTEPS) { - bottomnode.d = CONTENT_MUD; + bottomnode.setContent(CONTENT_MUD); setNode(bottompos, bottomnode); } } @@ -943,9 +943,9 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, If the new node is mud and it is under sunlight, change it to grass */ - if(n.d == CONTENT_MUD && node_under_sunlight) + if(n.getContent() == CONTENT_MUD && node_under_sunlight) { - n.d = CONTENT_GRASS; + n.setContent(CONTENT_GRASS); } #endif @@ -986,7 +986,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, If node lets sunlight through and is under sunlight, it has sunlight too. */ - if(node_under_sunlight && content_features(n.d).sunlight_propagates) + if(node_under_sunlight && content_features(n).sunlight_propagates) { n.setLight(LIGHTBANK_DAY, LIGHT_SUN); } @@ -1001,7 +1001,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, Add intial metadata */ - NodeMetadata *meta_proto = content_features(n.d).initial_metadata; + NodeMetadata *meta_proto = content_features(n).initial_metadata; if(meta_proto) { NodeMetadata *meta = meta_proto->clone(); @@ -1015,7 +1015,7 @@ void Map::addNodeAndUpdate(v3s16 p, MapNode n, TODO: This could be optimized by mass-unlighting instead of looping */ - if(node_under_sunlight && !content_features(n.d).sunlight_propagates) + if(node_under_sunlight && !content_features(n).sunlight_propagates) { s16 y = p.Y - 1; for(;; y--){ @@ -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.getContent())) { m_transforming_liquid.push_back(p2); } @@ -1111,7 +1111,7 @@ void Map::removeNodeAndUpdate(v3s16 p, v3s16 toppos = p + v3s16(0,1,0); // Node will be replaced with this - u8 replace_material = CONTENT_AIR; + content_t replace_material = CONTENT_AIR; /* If there is a node at top and it doesn't have sunlight, @@ -1158,7 +1158,7 @@ void Map::removeNodeAndUpdate(v3s16 p, */ MapNode n; - n.d = replace_material; + n.setContent(replace_material); setNode(p, n); for(s32 i=0; i<2; i++) @@ -1258,7 +1258,7 @@ void Map::removeNodeAndUpdate(v3s16 p, v3s16 p2 = p + dirs[i]; MapNode n2 = getNode(p2); - if(content_liquid(n2.d)) + if(content_liquid(n2.getContent())) { m_transforming_liquid.push_back(p2); } @@ -1559,17 +1559,17 @@ void Map::transformLiquids(core::map & modified_blocks) MapNode n0 = getNodeNoEx(p0); // Don't deal with non-liquids - if(content_liquid(n0.d) == false) + if(content_liquid(n0.getContent()) == false) continue; - bool is_source = !content_flowing_liquid(n0.d); + bool is_source = !content_flowing_liquid(n0.getContent()); u8 liquid_level = 8; if(is_source == false) liquid_level = n0.param2 & 0x0f; // Turn possible source into non-source - u8 nonsource_c = make_liquid_flowing(n0.d); + u8 nonsource_c = make_liquid_flowing(n0.getContent()); /* If not source, check that some node flows into this one @@ -1593,9 +1593,9 @@ void Map::transformLiquids(core::map & modified_blocks) v3s16 p2 = p0 + dirs_from[i]; MapNode n2 = getNodeNoEx(p2); - if(content_liquid(n2.d)) + if(content_liquid(n2.getContent())) { - u8 n2_nonsource_c = make_liquid_flowing(n2.d); + u8 n2_nonsource_c = make_liquid_flowing(n2.getContent()); // Check that the liquids are the same type if(n2_nonsource_c != nonsource_c) { @@ -1603,7 +1603,7 @@ void Map::transformLiquids(core::map & modified_blocks) " collide"< & modified_blocks) if(new_liquid_level_max == -1) { // Remove water alltoghether - n0.d = CONTENT_AIR; + n0.setContent(CONTENT_AIR); n0.param2 = 0; setNode(p0, n0); } @@ -1670,7 +1670,7 @@ void Map::transformLiquids(core::map & modified_blocks) v3s16 p2 = p0 + dirs[i]; MapNode n2 = getNodeNoEx(p2); - if(content_flowing_liquid(n2.d)) + if(content_flowing_liquid(n2.getContent())) { m_transforming_liquid.push_back(p2); } @@ -1679,7 +1679,7 @@ void Map::transformLiquids(core::map & modified_blocks) } // Get a new one from queue if the node has turned into non-water - if(content_liquid(n0.d) == false) + if(content_liquid(n0.getContent()) == false) continue; /* @@ -1722,9 +1722,9 @@ void Map::transformLiquids(core::map & modified_blocks) MapNode n2 = getNodeNoEx(p2); //dstream<<"[1] n2.param="<<(int)n2.param< & modified_blocks) " collide"< & modified_blocks) } } } - else if(n2.d == CONTENT_AIR) + else if(n2.getContent() == CONTENT_AIR) { - n2.d = nonsource_c; + n2.setContent(nonsource_c); n2.param2 = liquid_next_level; setNode(p2, n2); @@ -2362,7 +2362,7 @@ MapBlock * ServerMap::generateBlock( { v3s16 p(x0,y0,z0); MapNode n = block->getNode(p); - if(n.d == CONTENT_IGNORE) + if(n.getContent() == CONTENT_IGNORE) { dstream<<"CONTENT_IGNORE at " <<"("<setNode(v3s16(x0,y0,z0), n); } } @@ -2674,19 +2674,19 @@ s16 ServerMap::findGroundLevel(v2s16 p2d) for(; p.Y>min; p.Y--) { MapNode n = getNodeNoEx(p); - if(n.d != CONTENT_IGNORE) + if(n.getContent() != CONTENT_IGNORE) break; } if(p.Y == min) goto plan_b; // If this node is not air, go to plan b - if(getNodeNoEx(p).d != CONTENT_AIR) + if(getNodeNoEx(p).getContent() != CONTENT_AIR) goto plan_b; // Search existing walkable and return it for(; p.Y>min; p.Y--) { MapNode n = getNodeNoEx(p); - if(content_walkable(n.d) && n.d != CONTENT_IGNORE) + if(content_walkable(n.d) && n.getContent() != CONTENT_IGNORE) return p.Y; } diff --git a/src/mapblock.cpp b/src/mapblock.cpp index 647a17756..ead26dd1f 100644 --- a/src/mapblock.cpp +++ b/src/mapblock.cpp @@ -242,7 +242,7 @@ bool MapBlock::propagateSunlight(core::map & light_sources, // Check if node above block has sunlight try{ MapNode n = getNodeParent(v3s16(x, MAP_BLOCKSIZE, z)); - if(n.d == CONTENT_IGNORE || n.getLight(LIGHTBANK_DAY) != LIGHT_SUN) + if(n.getContent() == CONTENT_IGNORE || n.getLight(LIGHTBANK_DAY) != LIGHT_SUN) { no_sunlight = true; } @@ -260,8 +260,8 @@ bool MapBlock::propagateSunlight(core::map & light_sources, else { MapNode n = getNode(v3s16(x, MAP_BLOCKSIZE-1, z)); - //if(n.d == CONTENT_WATER || n.d == CONTENT_WATERSOURCE) - if(content_features(n.d).sunlight_propagates == false) + //if(n.getContent() == CONTENT_WATER || n.getContent() == CONTENT_WATERSOURCE) + if(content_features(n).sunlight_propagates == false) { no_sunlight = true; } @@ -322,14 +322,14 @@ bool MapBlock::propagateSunlight(core::map & light_sources, bool upper_is_air = false; try { - if(getNodeParent(pos+v3s16(0,1,0)).d == CONTENT_AIR) + if(getNodeParent(pos+v3s16(0,1,0)).getContent() == CONTENT_AIR) upper_is_air = true; } catch(InvalidPositionException &e) { } // Turn mud into grass - if(upper_is_air && n.d == CONTENT_MUD + if(upper_is_air && n.getContent() == CONTENT_MUD && current_light == LIGHT_SUN) { n.d = CONTENT_GRASS; @@ -473,7 +473,7 @@ void MapBlock::updateDayNightDiff() for(u32 i=0; i=0; y--) { - //if(is_ground_content(getNodeRef(p2d.X, y, p2d.Y).d)) - if(content_features(getNodeRef(p2d.X, y, p2d.Y).d).walkable) + MapNode n = getNodeRef(p2d.X, y, p2d.Y); + if(content_features(n).walkable) { if(y == MAP_BLOCKSIZE-1) return -2; @@ -560,7 +560,7 @@ void MapBlock::serialize(std::ostream &os, u8 version) SharedBuffer materialdata(nodecount); for(u32 i=0; i lightdata(nodecount); for(u32 i=0; igetNodeParent(v3s16(x,y,z)).d) - == false) + MapNode n = m_block->getNodeParent(v3s16(x,y,z)); + if(content_features(n).walkable == false) continue; } catch(InvalidPositionException &e) diff --git a/src/mapgen.cpp b/src/mapgen.cpp index acff3b963..d4143b6d6 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -67,8 +67,8 @@ static s16 find_ground_level_clever(VoxelManipulator &vmanip, v2s16 p2d) { MapNode &n = vmanip.m_data[i]; if(content_walkable(n.d) - && n.d != CONTENT_TREE - && n.d != CONTENT_LEAVES) + && n.getContent() != CONTENT_TREE + && n.getContent() != CONTENT_LEAVES) break; vmanip.m_area.add_y(em, i, -1); @@ -143,8 +143,8 @@ static void make_tree(VoxelManipulator &vmanip, v3s16 p0) if(vmanip.m_area.contains(p) == false) continue; u32 vi = vmanip.m_area.index(p); - if(vmanip.m_data[vi].d != CONTENT_AIR - && vmanip.m_data[vi].d != CONTENT_IGNORE) + if(vmanip.m_data[vi].getContent() != CONTENT_AIR + && vmanip.m_data[vi].getContent() != CONTENT_IGNORE) continue; u32 i = leaves_a.index(x,y,z); if(leaves_d[i] == 1) @@ -223,8 +223,8 @@ static void make_randomstone(VoxelManipulator &vmanip, v3s16 p0) if(vmanip.m_area.contains(p) == false) continue; u32 vi = vmanip.m_area.index(p); - if(vmanip.m_data[vi].d != CONTENT_AIR - && vmanip.m_data[vi].d != CONTENT_IGNORE) + if(vmanip.m_data[vi].getContent() != CONTENT_AIR + && vmanip.m_data[vi].getContent() != CONTENT_IGNORE) continue; u32 i = stone_a.index(x,y,z); if(stone_d[i] == 1) @@ -307,8 +307,8 @@ static void make_largestone(VoxelManipulator &vmanip, v3s16 p0) if(vmanip.m_area.contains(p) == false) continue; u32 vi = vmanip.m_area.index(p); - /*if(vmanip.m_data[vi].d != CONTENT_AIR - && vmanip.m_data[vi].d != CONTENT_IGNORE) + /*if(vmanip.m_data[vi].getContent() != CONTENT_AIR + && vmanip.m_data[vi].getContent() != CONTENT_IGNORE) continue;*/ u32 i = stone_a.index(x,y,z); if(stone_d[i] == 1) @@ -516,9 +516,9 @@ static void make_corridor(VoxelManipulator &vmanip, v3s16 doorplace, p.Y += make_stairs; /*// If already empty - if(vmanip.getNodeNoExNoEmerge(p).d + if(vmanip.getNodeNoExNoEmerge(p).getContent() == CONTENT_AIR - && vmanip.getNodeNoExNoEmerge(p+v3s16(0,1,0)).d + && vmanip.getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent() == CONTENT_AIR) { }*/ @@ -614,9 +614,9 @@ public: randomizeDir(); continue; } - if(vmanip.getNodeNoExNoEmerge(p).d + if(vmanip.getNodeNoExNoEmerge(p).getContent() == CONTENT_COBBLE - && vmanip.getNodeNoExNoEmerge(p1).d + && vmanip.getNodeNoExNoEmerge(p1).getContent() == CONTENT_COBBLE) { // Found wall, this is a good place! @@ -630,25 +630,25 @@ public: Determine where to move next */ // Jump one up if the actual space is there - if(vmanip.getNodeNoExNoEmerge(p+v3s16(0,0,0)).d + if(vmanip.getNodeNoExNoEmerge(p+v3s16(0,0,0)).getContent() == CONTENT_COBBLE - && vmanip.getNodeNoExNoEmerge(p+v3s16(0,1,0)).d + && vmanip.getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent() == CONTENT_AIR - && vmanip.getNodeNoExNoEmerge(p+v3s16(0,2,0)).d + && vmanip.getNodeNoExNoEmerge(p+v3s16(0,2,0)).getContent() == CONTENT_AIR) p += v3s16(0,1,0); // Jump one down if the actual space is there - if(vmanip.getNodeNoExNoEmerge(p+v3s16(0,1,0)).d + if(vmanip.getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent() == CONTENT_COBBLE - && vmanip.getNodeNoExNoEmerge(p+v3s16(0,0,0)).d + && vmanip.getNodeNoExNoEmerge(p+v3s16(0,0,0)).getContent() == CONTENT_AIR - && vmanip.getNodeNoExNoEmerge(p+v3s16(0,-1,0)).d + && vmanip.getNodeNoExNoEmerge(p+v3s16(0,-1,0)).getContent() == CONTENT_AIR) p += v3s16(0,-1,0); // Check if walking is now possible - if(vmanip.getNodeNoExNoEmerge(p).d + if(vmanip.getNodeNoExNoEmerge(p).getContent() != CONTENT_AIR - || vmanip.getNodeNoExNoEmerge(p+v3s16(0,1,0)).d + || vmanip.getNodeNoExNoEmerge(p+v3s16(0,1,0)).getContent() != CONTENT_AIR) { // Cannot continue walking here @@ -770,7 +770,7 @@ static void make_dungeon1(VoxelManipulator &vmanip, PseudoRandom &random) fits = false; break; } - if(vmanip.m_data[vi].d == CONTENT_IGNORE) + if(vmanip.m_data[vi].getContent() == CONTENT_IGNORE) { fits = false; break; @@ -1245,11 +1245,11 @@ void add_random_objects(MapBlock *block) { v3s16 p(x0,y0,z0); MapNode n = block->getNodeNoEx(p); - if(n.d == CONTENT_IGNORE) + if(n.getContent() == CONTENT_IGNORE) continue; - if(content_features(n.d).liquid_type != LIQUID_NONE) + if(content_features(n).liquid_type != LIQUID_NONE) continue; - if(content_features(n.d).walkable) + if(content_features(n).walkable) { last_node_walkable = true; continue; @@ -1257,7 +1257,7 @@ void add_random_objects(MapBlock *block) if(last_node_walkable) { // If block contains light information - if(content_features(n.d).param_type == CPT_LIGHT) + if(content_features(n).param_type == CPT_LIGHT) { if(n.getLight(LIGHTBANK_DAY) <= 3) { @@ -1363,7 +1363,7 @@ void make_block(BlockMakeData *data) for(s16 y=node_min.Y; y<=node_max.Y; y++) { // Only modify places that have no content - if(vmanip.m_data[i].d == CONTENT_IGNORE) + if(vmanip.m_data[i].getContent() == CONTENT_IGNORE) { if(y <= WATER_LEVEL) vmanip.m_data[i] = MapNode(CONTENT_WATERSOURCE); @@ -1468,7 +1468,7 @@ void make_block(BlockMakeData *data) for(s16 y=node_min.Y; y<=node_max.Y; y++) { // Only modify places that have no content - if(vmanip.m_data[i].d == CONTENT_IGNORE) + if(vmanip.m_data[i].getContent() == CONTENT_IGNORE) { // First priority: make air and water. // This avoids caves inside water. @@ -1513,7 +1513,7 @@ void make_block(BlockMakeData *data) { v3s16 p = v3s16(x,y,z) + g_27dirs[i]; u32 vi = vmanip.m_area.index(p); - if(vmanip.m_data[vi].d == CONTENT_STONE) + if(vmanip.m_data[vi].getContent() == CONTENT_STONE) if(mineralrandom.next()%8 == 0) vmanip.m_data[vi] = MapNode(CONTENT_MESE); } @@ -1554,13 +1554,13 @@ void make_block(BlockMakeData *data) { }*/ - if(new_content.d != CONTENT_IGNORE) + if(new_content.getContent() != CONTENT_IGNORE) { for(u16 i=0; i<27; i++) { v3s16 p = v3s16(x,y,z) + g_27dirs[i]; u32 vi = vmanip.m_area.index(p); - if(vmanip.m_data[vi].d == base_content) + if(vmanip.m_data[vi].getContent() == base_content) { if(mineralrandom.next()%sparseness == 0) vmanip.m_data[vi] = new_content; @@ -1591,7 +1591,7 @@ void make_block(BlockMakeData *data) { v3s16 p = v3s16(x,y,z) + g_27dirs[i]; u32 vi = vmanip.m_area.index(p); - if(vmanip.m_data[vi].d == CONTENT_STONE) + if(vmanip.m_data[vi].getContent() == CONTENT_STONE) if(mineralrandom.next()%8 == 0) vmanip.m_data[vi] = MapNode(CONTENT_STONE, MINERAL_COAL); } @@ -1617,7 +1617,7 @@ void make_block(BlockMakeData *data) { v3s16 p = v3s16(x,y,z) + g_27dirs[i]; u32 vi = vmanip.m_area.index(p); - if(vmanip.m_data[vi].d == CONTENT_STONE) + if(vmanip.m_data[vi].getContent() == CONTENT_STONE) if(mineralrandom.next()%8 == 0) vmanip.m_data[vi] = MapNode(CONTENT_STONE, MINERAL_IRON); } @@ -1640,7 +1640,7 @@ void make_block(BlockMakeData *data) u32 i = vmanip.m_area.index(v3s16(p2d.X, node_max.Y, p2d.Y)); for(s16 y=node_max.Y; y>=node_min.Y; y--) { - if(vmanip.m_data[i].d == CONTENT_STONE) + if(vmanip.m_data[i].getContent() == CONTENT_STONE) { if(noisebuf_ground_crumbleness.get(x,y,z) > 1.3) { @@ -1692,9 +1692,9 @@ void make_block(BlockMakeData *data) u32 i = vmanip.m_area.index(v3s16(p2d.X, full_node_max.Y, p2d.Y)); for(s16 y=full_node_max.Y; y>=full_node_min.Y; y--) { - if(vmanip.m_data[i].d == CONTENT_AIR) + if(vmanip.m_data[i].getContent() == CONTENT_AIR) vmanip.m_flags[i] |= VMANIP_FLAG_DUNGEON_PRESERVE; - else if(vmanip.m_data[i].d == CONTENT_WATERSOURCE) + else if(vmanip.m_data[i].getContent() == CONTENT_WATERSOURCE) vmanip.m_flags[i] |= VMANIP_FLAG_DUNGEON_PRESERVE; data->vmanip->m_area.add_y(em, i, -1); } @@ -1725,17 +1725,17 @@ void make_block(BlockMakeData *data) double d = noise3d_perlin((float)x/2.5, (float)y/2.5,(float)z/2.5, blockseed, 2, 1.4); - if(vmanip.m_data[i].d == CONTENT_COBBLE) + if(vmanip.m_data[i].getContent() == CONTENT_COBBLE) { if(d < wetness/3.0) { - vmanip.m_data[i].d = CONTENT_MOSSYCOBBLE; + vmanip.m_data[i].setContent(CONTENT_MOSSYCOBBLE); } } /*else if(vmanip.m_flags[i] & VMANIP_FLAG_DUNGEON_INSIDE) { if(wetness > 1.2) - vmanip.m_data[i].d = CONTENT_MUD; + vmanip.m_data[i].setContent(CONTENT_MUD); }*/ data->vmanip->m_area.add_y(em, i, -1); } @@ -1761,7 +1761,7 @@ void make_block(BlockMakeData *data) { if(water_found == false) { - if(vmanip.m_data[i].d == CONTENT_WATERSOURCE) + if(vmanip.m_data[i].getContent() == CONTENT_WATERSOURCE) { v3s16 p = v3s16(p2d.X, y, p2d.Y); data->transforming_liquid.push_back(p); @@ -1773,7 +1773,7 @@ void make_block(BlockMakeData *data) // This can be done because water_found can only // turn to true and end up here after going through // a single block. - if(vmanip.m_data[i+1].d != CONTENT_WATERSOURCE) + if(vmanip.m_data[i+1].getContent() != CONTENT_WATERSOURCE) { v3s16 p = v3s16(p2d.X, y+1, p2d.Y); data->transforming_liquid.push_back(p); @@ -1814,16 +1814,16 @@ void make_block(BlockMakeData *data) u32 i = vmanip.m_area.index(v3s16(p2d.X, start_y, p2d.Y)); for(s16 y=start_y; y>=node_min.Y-3; y--) { - if(vmanip.m_data[i].d == CONTENT_WATERSOURCE) + if(vmanip.m_data[i].getContent() == CONTENT_WATERSOURCE) water_detected = true; - if(vmanip.m_data[i].d == CONTENT_AIR) + if(vmanip.m_data[i].getContent() == CONTENT_AIR) air_detected = true; - if((vmanip.m_data[i].d == CONTENT_STONE - || vmanip.m_data[i].d == CONTENT_GRASS - || vmanip.m_data[i].d == CONTENT_MUD - || vmanip.m_data[i].d == CONTENT_SAND - || vmanip.m_data[i].d == CONTENT_GRAVEL + if((vmanip.m_data[i].getContent() == CONTENT_STONE + || vmanip.m_data[i].getContent() == CONTENT_GRASS + || vmanip.m_data[i].getContent() == CONTENT_MUD + || vmanip.m_data[i].getContent() == CONTENT_SAND + || vmanip.m_data[i].getContent() == CONTENT_GRAVEL ) && (air_detected || water_detected)) { if(current_depth == 0 && y <= WATER_LEVEL+2 @@ -1846,8 +1846,8 @@ void make_block(BlockMakeData *data) } else { - if(vmanip.m_data[i].d == CONTENT_MUD - || vmanip.m_data[i].d == CONTENT_GRASS) + if(vmanip.m_data[i].getContent() == CONTENT_MUD + || vmanip.m_data[i].getContent() == CONTENT_GRASS) vmanip.m_data[i] = MapNode(CONTENT_STONE); } @@ -1894,7 +1894,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->getContent() != CONTENT_AIR && n->getContent() != CONTENT_IGNORE) { found = true; break; @@ -1909,7 +1909,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_MUD && n->d != CONTENT_GRASS) + if(n->getContent() != CONTENT_MUD && n->getContent() != CONTENT_GRASS) continue; } // Tree will be placed one higher @@ -1942,7 +1942,7 @@ void make_block(BlockMakeData *data) /*{ u32 i = data->vmanip->m_area.index(v3s16(p)); MapNode *n = &data->vmanip->m_data[i]; - if(n->d != CONTENT_MUD && n->d != CONTENT_GRASS) + if(n->getContent() != CONTENT_MUD && n->getContent() != CONTENT_GRASS) continue; }*/ // Will be placed one higher @@ -1977,7 +1977,7 @@ void make_block(BlockMakeData *data) /*{ u32 i = data->vmanip->m_area.index(v3s16(p)); MapNode *n = &data->vmanip->m_data[i]; - if(n->d != CONTENT_MUD && n->d != CONTENT_GRASS) + if(n->getContent() != CONTENT_MUD && n->getContent() != CONTENT_GRASS) continue; }*/ // Will be placed one lower diff --git a/src/mapnode.cpp b/src/mapnode.cpp index 1e9b64989..c9f85c303 100644 --- a/src/mapnode.cpp +++ b/src/mapnode.cpp @@ -30,8 +30,6 @@ with this program; if not, write to the Free Software Foundation, Inc., ContentFeatures::~ContentFeatures() { - /*if(translate_to) - delete translate_to;*/ if(initial_metadata) delete initial_metadata; } @@ -83,12 +81,16 @@ void ContentFeatures::setInventoryTextureCube(std::string top, inventory_texture = g_texturesource->getTextureRaw(imgname_full); } -struct ContentFeatures g_content_features[256]; +struct ContentFeatures g_content_features[MAX_CONTENT+1]; -ContentFeatures & content_features(u8 i) +ContentFeatures & content_features(content_t i) { return g_content_features[i]; } +ContentFeatures & content_features(MapNode &n) +{ + return content_features(n.getContent()); +} /* See mapnode.h for description. @@ -128,7 +130,7 @@ void init_mapnode() initial_material_type = MATERIAL_ALPHA_SIMPLE; else initial_material_type = MATERIAL_ALPHA_NONE;*/ - for(u16 i=0; i<256; i++) + for(u16 i=0; i 0) - param = 0; + param1 = 0; else - param = source[1]; + param1 = source[1]; } else if(version <= 9) { - d = source[0]; - param = source[1]; + param0 = source[0]; + param1 = source[1]; } else { - d = source[0]; - param = source[1]; + param0 = source[0]; + param1 = source[1]; param2 = source[2]; } - // Convert from old version to new + // Convert special values from old version to new if(version <= 18) { // In these versions, CONTENT_IGNORE and CONTENT_AIR // are 255 and 254 - if(d == 255) - d = CONTENT_IGNORE; - else if(d == 254) - d = CONTENT_AIR; + if(param0 == 255) + param0 = CONTENT_IGNORE; + else if(param0 == 254) + param0 = CONTENT_AIR; } // version 19 is fucked up with sometimes the old values and sometimes not if(version == 19) { - if(d == 255) - d = CONTENT_IGNORE; - else if(d == 254) - d = CONTENT_AIR; + if(param0 == 255) + param0 = CONTENT_IGNORE; + else if(param0 == 254) + param0 = CONTENT_AIR; } + + // Translate to our known version + *this = mapnode_translate_to_internal(*this, version); } /* diff --git a/src/mapnode.h b/src/mapnode.h index 36d48fb9e..1b10a546b 100644 --- a/src/mapnode.h +++ b/src/mapnode.h @@ -32,16 +32,15 @@ with this program; if not, write to the Free Software Foundation, Inc., /* Naming scheme: - Material = irrlicht's Material class - - Content = (u8) content of a node + - Content = (content_t) content of a node - Tile = TileSpec at some side of a node of some content type -*/ -/* - Ranges: + Content ranges: 0x000...0x07f: param2 is fully usable 0x800...0xfff: param2 lower 4 bytes are free */ typedef u16 content_t; +#define MAX_CONTENT 0xfff /* Initializes all kind of stuff in here. @@ -102,10 +101,7 @@ class NodeMetadata; struct ContentFeatures { - // If non-NULL, content is translated to this when deserialized - //MapNode *translate_to; - - // Type of MapNode::param + // Type of MapNode::param1 ContentParamType param_type; /* @@ -151,7 +147,7 @@ struct ContentFeatures // If the content is liquid, this is the flowing version of the liquid. // If content is liquid, this is the same content. - u8 liquid_alternative_flowing; + content_t liquid_alternative_flowing; // Amount of light the node emits u8 light_source; @@ -163,7 +159,6 @@ struct ContentFeatures void reset() { - //translate_to = NULL; param_type = CPT_NONE; inventory_texture = NULL; is_ground_content = false; @@ -228,8 +223,8 @@ struct ContentFeatures /* Call this to access the ContentFeature list */ -ContentFeatures & content_features(u8 i); - +ContentFeatures & content_features(content_t i); +ContentFeatures & content_features(MapNode &n); /* Here is a bunch of DEPRECATED functions. @@ -240,7 +235,7 @@ ContentFeatures & content_features(u8 i); in param. NOTE: Don't use, use "content_features(m).whatever" instead */ -inline bool light_propagates_content(u8 m) +inline bool light_propagates_content(content_t m) { return content_features(m).light_propagates; } @@ -249,7 +244,7 @@ inline bool light_propagates_content(u8 m) NOTE: It doesn't seem to go through torches regardlessly of this NOTE: Don't use, use "content_features(m).whatever" instead */ -inline bool sunlight_propagates_content(u8 m) +inline bool sunlight_propagates_content(content_t m) { return content_features(m).sunlight_propagates; } @@ -261,35 +256,35 @@ inline bool sunlight_propagates_content(u8 m) 2: Opaque NOTE: Don't use, use "content_features(m).whatever" instead */ -inline u8 content_solidness(u8 m) +inline u8 content_solidness(content_t m) { return content_features(m).solidness; } // Objects collide with walkable contents // NOTE: Don't use, use "content_features(m).whatever" instead -inline bool content_walkable(u8 m) +inline bool content_walkable(content_t m) { return content_features(m).walkable; } // NOTE: Don't use, use "content_features(m).whatever" instead -inline bool content_liquid(u8 m) +inline bool content_liquid(content_t m) { return content_features(m).liquid_type != LIQUID_NONE; } // NOTE: Don't use, use "content_features(m).whatever" instead -inline bool content_flowing_liquid(u8 m) +inline bool content_flowing_liquid(content_t m) { return content_features(m).liquid_type == LIQUID_FLOWING; } // NOTE: Don't use, use "content_features(m).whatever" instead -inline bool content_liquid_source(u8 m) +inline bool content_liquid_source(content_t m) { return content_features(m).liquid_type == LIQUID_SOURCE; } // CONTENT_WATER || CONTENT_WATERSOURCE -> CONTENT_WATER // CONTENT_LAVA || CONTENT_LAVASOURCE -> CONTENT_LAVA // NOTE: Don't use, use "content_features(m).whatever" instead -inline u8 make_liquid_flowing(u8 m) +inline content_t make_liquid_flowing(content_t m) { u8 c = content_features(m).liquid_alternative_flowing; assert(c != CONTENT_IGNORE); @@ -297,17 +292,17 @@ inline u8 make_liquid_flowing(u8 m) } // Pointable contents can be pointed to in the map // NOTE: Don't use, use "content_features(m).whatever" instead -inline bool content_pointable(u8 m) +inline bool content_pointable(content_t m) { return content_features(m).pointable; } // NOTE: Don't use, use "content_features(m).whatever" instead -inline bool content_diggable(u8 m) +inline bool content_diggable(content_t m) { return content_features(m).diggable; } // NOTE: Don't use, use "content_features(m).whatever" instead -inline bool content_buildable_to(u8 m) +inline bool content_buildable_to(content_t m) { return content_features(m).buildable_to; } @@ -319,7 +314,7 @@ inline bool content_buildable_to(u8 m) 1: Face uses m1's content 2: Face uses m2's content */ -inline u8 face_contents(u8 m1, u8 m2) +inline u8 face_contents(content_t m1, content_t m2) { if(m1 == CONTENT_IGNORE || m2 == CONTENT_IGNORE) return 0; @@ -416,7 +411,7 @@ struct MapNode union { u8 param0; - u8 d; + //u8 d; }; /* @@ -431,17 +426,18 @@ struct MapNode union { u8 param1; - s8 param; + //s8 param; }; /* The second parameter. Initialized to 0. E.g. direction for torches and flowing water. + If param0 >= 0x80, bits 0xf0 of this is extended content type data */ union { u8 param2; - u8 dir; + //u8 dir; }; MapNode(const MapNode & n) @@ -449,28 +445,44 @@ struct MapNode *this = n; } - MapNode(u8 data=CONTENT_AIR, u8 a_param=0, u8 a_param2=0) + MapNode(content_t content=CONTENT_AIR, u8 a_param1=0, u8 a_param2=0) { - d = data; - param = a_param; + //param0 = a_param0; + param1 = a_param1; param2 = a_param2; + // Set after other params because this needs to override part of param2 + setContent(content); } bool operator==(const MapNode &other) { - return (d == other.d - && param == other.param + return (param0 == other.param0 + && param1 == other.param1 && param2 == other.param2); } // To be used everywhere content_t getContent() { - return d; + if(param0 < 0x80) + return param0; + else + return (param0<<4) + (param2>>4); } void setContent(content_t c) { - d = c; + if(c < 0x80) + { + if(param0 >= 0x80) + param2 &= ~(0xf0); + param0 = c; + } + else + { + param0 = c>>4; + param2 &= ~(0xf0); + param2 |= (c&0x0f)<<4; + } } /* @@ -478,19 +490,19 @@ struct MapNode */ bool light_propagates() { - return light_propagates_content(d); + return light_propagates_content(getContent()); } bool sunlight_propagates() { - return sunlight_propagates_content(d); + return sunlight_propagates_content(getContent()); } u8 solidness() { - return content_solidness(d); + return content_solidness(getContent()); } u8 light_source() { - return content_features(d).light_source; + return content_features(*this).light_source; } u8 getLightBanksWithSource() @@ -498,10 +510,10 @@ struct MapNode // Select the brightest of [light source, propagated light] u8 lightday = 0; u8 lightnight = 0; - if(content_features(d).param_type == CPT_LIGHT) + if(content_features(*this).param_type == CPT_LIGHT) { - lightday = param & 0x0f; - lightnight = (param>>4)&0x0f; + lightday = param1 & 0x0f; + lightnight = (param1>>4)&0x0f; } if(light_source() > lightday) lightday = light_source(); @@ -514,12 +526,12 @@ struct MapNode { // Select the brightest of [light source, propagated light] u8 light = 0; - if(content_features(d).param_type == CPT_LIGHT) + if(content_features(*this).param_type == CPT_LIGHT) { if(bank == LIGHTBANK_DAY) - light = param & 0x0f; + light = param1 & 0x0f; else if(bank == LIGHTBANK_NIGHT) - light = (param>>4)&0x0f; + light = (param1>>4)&0x0f; else assert(0); } @@ -557,17 +569,17 @@ struct MapNode void setLight(enum LightBank bank, u8 a_light) { // If node doesn't contain light data, ignore this - if(content_features(d).param_type != CPT_LIGHT) + if(content_features(*this).param_type != CPT_LIGHT) return; if(bank == LIGHTBANK_DAY) { - param &= 0xf0; - param |= a_light & 0x0f; + param1 &= 0xf0; + param1 |= a_light & 0x0f; } else if(bank == LIGHTBANK_NIGHT) { - param &= 0x0f; - param |= (a_light & 0x0f)<<4; + param1 &= 0x0f; + param1 |= (a_light & 0x0f)<<4; } else assert(0); diff --git a/src/materials.cpp b/src/materials.cpp index e3a24b9e3..24f300724 100644 --- a/src/materials.cpp +++ b/src/materials.cpp @@ -3,12 +3,12 @@ // NOTE: DEPRECATED -DiggingPropertiesList * getDiggingPropertiesList(u8 content) +DiggingPropertiesList * getDiggingPropertiesList(u16 content) { return &content_features(content).digging_properties; } -DiggingProperties getDiggingProperties(u8 content, const std::string &tool) +DiggingProperties getDiggingProperties(u16 content, const std::string &tool) { DiggingPropertiesList *mprop = getDiggingPropertiesList(content); if(mprop == NULL) diff --git a/src/materials.h b/src/materials.h index f061ecbfa..1439df194 100644 --- a/src/materials.h +++ b/src/materials.h @@ -97,7 +97,7 @@ private: }; // For getting the default properties, set tool="" -DiggingProperties getDiggingProperties(u8 material, const std::string &tool); +DiggingProperties getDiggingProperties(u16 material, const std::string &tool); #endif diff --git a/src/player.cpp b/src/player.cpp index 6bacb088d..d52d6b88f 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -342,13 +342,13 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, if(in_water) { v3s16 pp = floatToInt(position + v3f(0,BS*0.1,0), BS); - in_water = content_liquid(map.getNode(pp).d); + in_water = content_liquid(map.getNode(pp).getContent()); } // If not in water, the threshold of going in is at lower y else { v3s16 pp = floatToInt(position + v3f(0,BS*0.5,0), BS); - in_water = content_liquid(map.getNode(pp).d); + in_water = content_liquid(map.getNode(pp).getContent()); } } catch(InvalidPositionException &e) @@ -361,7 +361,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, */ try{ v3s16 pp = floatToInt(position + v3f(0,0,0), BS); - in_water_stable = content_liquid(map.getNode(pp).d); + in_water_stable = content_liquid(map.getNode(pp).getContent()); } catch(InvalidPositionException &e) { @@ -470,7 +470,7 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, { try{ // Player collides into walkable nodes - if(content_walkable(map.getNode(v3s16(x,y,z)).d) == false) + if(content_walkable(map.getNode(v3s16(x,y,z)).getContent()) == false) continue; } catch(InvalidPositionException &e) @@ -633,10 +633,10 @@ void LocalPlayer::move(f32 dtime, Map &map, f32 pos_max_d, try{ // The node to be sneaked on has to be walkable - if(content_walkable(map.getNode(p).d) == false) + if(content_walkable(map.getNode(p).getContent()) == false) continue; // And the node above it has to be nonwalkable - if(content_walkable(map.getNode(p+v3s16(0,1,0)).d) == true) + if(content_walkable(map.getNode(p+v3s16(0,1,0)).getContent()) == true) continue; } catch(InvalidPositionException &e) diff --git a/src/serialization.h b/src/serialization.h index 974ae95d8..d93e61892 100644 --- a/src/serialization.h +++ b/src/serialization.h @@ -55,11 +55,12 @@ with this program; if not, write to the Free Software Foundation, Inc., 17: MapBlocks contain timestamp 18: new generator (not really necessary, but it's there) 19: new content type handling + 20: many existing content types translated to extended ones */ // This represents an uninitialized or invalid format #define SER_FMT_VER_INVALID 255 // Highest supported serialization version -#define SER_FMT_VER_HIGHEST 19 +#define SER_FMT_VER_HIGHEST 20 // Lowest supported serialization version #define SER_FMT_VER_LOWEST 0 diff --git a/src/server.cpp b/src/server.cpp index c2433e1af..e3c6ce4d9 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2494,7 +2494,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) // Mandatory parameter; actually used for nothing core::map modified_blocks; - u8 material = CONTENT_IGNORE; + content_t material = CONTENT_IGNORE; u8 mineral = MINERAL_NONE; bool cannot_remove_node = false; @@ -2505,7 +2505,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) // Get mineral mineral = n.getMineral(); // Get material at position - material = n.d; + material = n.getContent(); // If not yet cancelled if(cannot_remove_node == false) { @@ -2705,7 +2705,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) <<" because privileges are "<getMaterial(); + n.setContent(mitem->getMaterial()); // Calculate direction for wall mounted stuff - if(content_features(n.d).wall_mounted) - n.dir = packDir(p_under - p_over); + if(content_features(n).wall_mounted) + n.param2 = packDir(p_under - p_over); // Calculate the direction for furnaces and chests and stuff - if(content_features(n.d).param_type == CPT_FACEDIR_SIMPLE) + if(content_features(n).param_type == CPT_FACEDIR_SIMPLE) { v3f playerpos = player->getPosition(); v3f blockpos = intToFloat(p_over, BS) - playerpos; diff --git a/src/test.cpp b/src/test.cpp index 0487f1436..3ff4dc807 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -219,14 +219,14 @@ struct TestMapNode MapNode n; // Default values - assert(n.d == CONTENT_AIR); + assert(n.getContent() == CONTENT_AIR); assert(n.getLight(LIGHTBANK_DAY) == 0); assert(n.getLight(LIGHTBANK_NIGHT) == 0); // Transparency - n.d = CONTENT_AIR; + n.setContent(CONTENT_AIR); assert(n.light_propagates() == true); - n.d = CONTENT_STONE; + n.setContent(CONTENT_STONE); assert(n.light_propagates() == false); } }; @@ -284,7 +284,7 @@ struct TestVoxelManipulator v.print(dstream); - assert(v.getNode(v3s16(-1,0,-1)).d == 2); + assert(v.getNode(v3s16(-1,0,-1)).getContent() == 2); dstream<<"*** Reading from inexistent (0,0,-1) ***"< light_sources; @@ -611,7 +611,7 @@ struct TestMapBlock for(u16 y=0; y 500: @@ -283,7 +286,7 @@ for n in range(len(xlist)): for (x, z) in reversed(pixellist): for y in reversed(range(16)): datapos = x + y * 16 + z * 256 - if(ord(mapdata[datapos]) != 254 and ord(mapdata[datapos]) in colors): + if(not data_is_air(ord(mapdata[datapos])) and ord(mapdata[datapos]) in colors): if(ord(mapdata[datapos]) == 2 or ord(mapdata[datapos]) == 9): water[(x, z)] += 1 # Add dummy stuff for drawing sea without seabed @@ -293,7 +296,7 @@ for n in range(len(xlist)): # Memorize information on the type and height of the block and for drawing the picture. stuff[(chunkxpos + x, chunkzpos + z)] = (chunkypos + y, ord(mapdata[datapos]), water[(x, z)]) break - elif(ord(mapdata[datapos]) != 254 and ord(mapdata[datapos]) not in colors): + elif(not data_is_air(ord(mapdata[datapos])) and ord(mapdata[datapos]) not in colors): print "strange block: " + xhex + "/" + zhex + "/" + yhex + " x: " + str(x) + " y: " + str(y) + " z: " + str(z) + " palikka: " + str(ord(mapdata[datapos])) # After finding all the pixels in the sector, we can move on to the next sector without having to continue the Y axis. @@ -324,7 +327,7 @@ for n in range(len(xlist)): for (x, z) in reversed(pixellist): for y in reversed(range(16)): datapos = x + y * 16 + z * 256 - if(ord(mapdata[datapos]) != 254 and ord(mapdata[datapos]) in colors): + if(not data_is_air(ord(mapdata[datapos])) and ord(mapdata[datapos]) in colors): if(ord(mapdata[datapos]) == 2 or ord(mapdata[datapos]) == 9): water[(x, z)] += 1 # Add dummy stuff for drawing sea without seabed @@ -334,7 +337,7 @@ for n in range(len(xlist)): # Memorize information on the type and height of the block and for drawing the picture. stuff[(chunkxpos + x, chunkzpos + z)] = (chunkypos + y, ord(mapdata[datapos]), water[(x, z)]) break - elif(ord(mapdata[datapos]) != 254 and ord(mapdata[datapos]) not in colors): + elif(not data_is_air(ord(mapdata[datapos])) and ord(mapdata[datapos]) not in colors): print "outo palikka: " + xhex + "/" + zhex + "/" + yhex + " x: " + str(x) + " y: " + str(y) + " z: " + str(z) + " palikka: " + str(ord(mapdata[datapos])) # After finding all the pixels in the sector, we can move on to the next sector without having to continue the Y axis. From a42d324142daae260c44bdca410d5fea1c59036e Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sat, 23 Jul 2011 19:05:06 +0300 Subject: [PATCH 10/25] changed rat texture to mine --- data/rat.png | Bin 276 -> 920 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/data/rat.png b/data/rat.png index 96d44c3fae171d9d1e59d8137315f0d61697abd5..d1a0e2ae26ad41a751c99ea84e79f45e58c1970b 100644 GIT binary patch literal 920 zcmZvaJ!n-y5QPULFCirUU?XA`wh*xjSlMWNAr450`asJBZ6q8>WvisK2!UfERspe) z1X7NzKa~VcD-76Jh=uTwfDaMIxi=8reb)=SJA2vL@64Hfy0o}3J$Y_YM5gsd_jazQ za!gEga_&ER{9I&AmTvaua~t)DdWqac^|`y5kp!Tsr4$!25sE-WMM`G1ez}X8kOGLR zl>Z%aaTB8u0u?QJQ!A~F4>KnXpejlU(g9Ot#(=9@2CANON)0zR8bK(uXt6LlVNhy8 zVGs^AEi4GA=ZT`BrOtOBp{dz05abav{W-*@mWrJGws{fePP0r@AWzU8W=duZ_q;y? zbKK%5-<(=)Bsg>TXmBGm~SI56h&E4I5{qp_WweKe$eqQ+98QWd!A3PXr aZfsua$n2l0vvp$^%if|TqL>4nJa0`Pl zBg3pY5H=O_S>w|46-Jwyp7yIp(&m&jv*T7k4{+2cgR4*%|AZTaa)>iRJ&4! zNE7?K8MES+J&QQRGdX2_fx1WiHHK-*`TMHh@&753X5Fw(U+=nf!;`Q6CArKFp|U|A zDy*10R+}J8FRZr-*8JVbup?^m vlrF`5-K From bc14898bf9d1020a71e811429aedc0e56c05232c Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sat, 23 Jul 2011 19:16:49 +0300 Subject: [PATCH 11/25] updated main.cpp comments a bit --- src/main.cpp | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 783faa4e2..75322847b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -330,7 +330,7 @@ Map: TODO: Mineral and ground material properties - This way mineral ground toughness can be calculated with just - some formula, as well as tool strengths + some formula, as well as tool strengths. Sounds too. - There are TODOs in appropriate files: material.h, content_mapnode.h TODO: Flowing water to actually contain flow direction information @@ -338,6 +338,9 @@ TODO: Flowing water to actually contain flow direction information TODO: Consider smoothening cave floors after generating them +TODO: Fix make_tree, make_* to use seed-position-consistent pseudorandom + - delta also + Misc. stuff: ------------ TODO: Make sure server handles removing grass when a block is placed (etc) @@ -350,19 +353,14 @@ TODO: Think about using same bits for material for fences and doors, for TODO: Move mineral to param2, increment map serialization version, add conversion -TODO: Restart irrlicht completely when coming back to main menu from game. +SUGG: Restart irrlicht completely when coming back to main menu from game. - This gets rid of everything that is stored in irrlicht's caches. + - This might be needed for texture pack selection in menu TODO: Merge bahamada's audio stuff (clean patch available) TODO: Move content_features to mapnode_content_features.{h,cpp} or so -TODO: Add some kind of content range validation to mapnode serialization - -TODO: Make sure menu text position is fixed - -TODO: Fix sector over limits error - Making it more portable: ------------------------ From f13fc82abecb0e6a867fd9d6f5e46ec799755336 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sat, 23 Jul 2011 19:17:39 +0300 Subject: [PATCH 12/25] converted main.cpp dos linefeeds to unix linefeeds. --- src/main.cpp | 3351 +++++++++++++++++++++++++------------------------- 1 file changed, 1676 insertions(+), 1675 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 75322847b..3bc7ca5f6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,1677 +1,1678 @@ -/* -Minetest-c55 -Copyright (C) 2010-2011 celeron55, Perttu Ahola - -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. -*/ - -/* -=============================== NOTES ============================== -NOTE: Things starting with TODO are sometimes only suggestions. - -NOTE: iostream.imbue(std::locale("C")) is very slow -NOTE: Global locale is now set at initialization - -NOTE: If VBO (EHM_STATIC) is used, remember to explicitly free the - hardware buffer (it is not freed automatically) - -NOTE: A random to-do list saved here as documentation: -A list of "active blocks" in which stuff happens. (+=done) - + Add a never-resetted game timer to the server - + Add a timestamp value to blocks - + The simple rule: All blocks near some player are "active" - - Do stuff in real time in active blocks - + Handle objects - - Grow grass, delete leaves without a tree - - Spawn some mobs based on some rules - - Transform cobble to mossy cobble near water - - Run a custom script - - ...And all kinds of other dynamic stuff - + Keep track of when a block becomes active and becomes inactive - + When a block goes inactive: - + Store objects statically to block - + Store timer value as the timestamp - + When a block goes active: - + Create active objects out of static objects - - Simulate the results of what would have happened if it would have - been active for all the time - - Grow a lot of grass and so on - + Initially it is fine to send information about every active object - to every player. Eventually it should be modified to only send info - about the nearest ones. - + This was left to be done by the old system and it sends only the - nearest ones. - -Vim conversion regexpes for moving to extended content type storage: -%s/\(\.\|->\)d \([!=]=\)/\1getContent() \2/g -%s/content_features(\([^.]*\)\.d)/content_features(\1)/g -%s/\(\.\|->\)d = \([^;]*\);/\1setContent(\2);/g -%s/\(getNodeNoExNoEmerge([^)]*)\)\.d/\1.getContent()/g -%s/\(getNodeNoExNoEmerge(.*)\)\.d/\1.getContent()/g -%s/\.d;/.getContent();/g -%s/\(content_liquid\|content_flowing_liquid\|make_liquid_flowing\|content_pointable\)(\([^.]*\).d)/\1(\2.getContent())/g -Other things to note: -- node.d = node.param0 (only in raw serialization; use getContent() otherwise) -- node.param = node.param1 -- node.dir = node.param2 -- content_walkable(node.d) etc should be changed to - content_features(node).walkable etc -- Also check for lines that store the result of getContent to a 8-bit - variable and fix them (result of getContent() must be stored in - content_t, which is 16-bit) - -Old, wild and random suggestions that probably won't be done: -------------------------------------------------------------- - -SUGG: If player is on ground, mainly fetch ground-level blocks - -SUGG: Expose Connection's seqnums and ACKs to server and client. - - This enables saving many packets and making a faster connection - - This also enables server to check if client has received the - most recent block sent, for example. -SUGG: Add a sane bandwidth throttling system to Connection - -SUGG: More fine-grained control of client's dumping of blocks from - memory - - ...What does this mean in the first place? - -SUGG: A map editing mode (similar to dedicated server mode) - -SUGG: Transfer more blocks in a single packet -SUGG: A blockdata combiner class, to which blocks are added and at - destruction it sends all the stuff in as few packets as possible. -SUGG: Make a PACKET_COMBINED which contains many subpackets. Utilize - it by sending more stuff in a single packet. - - Add a packet queue to RemoteClient, from which packets will be - combined with object data packets - - This is not exactly trivial: the object data packets are - sometimes very big by themselves - - This might not give much network performance gain though. - -SUGG: Precalculate lighting translation table at runtime (at startup) - - This is not doable because it is currently hand-made and not - based on some mathematical function. - - Note: This has been changing lately - -SUGG: A version number to blocks, which increments when the block is - modified (node add/remove, water update, lighting update) - - This can then be used to make sure the most recent version of - a block has been sent to client, for example - -SUGG: Make the amount of blocks sending to client and the total - amount of blocks dynamically limited. Transferring blocks is the - main network eater of this system, so it is the one that has - to be throttled so that RTTs stay low. - -SUGG: Meshes of blocks could be split into 6 meshes facing into - different directions and then only those drawn that need to be - -SUGG: Background music based on cellular automata? - http://www.earslap.com/projectslab/otomata - -SUGG: Simple light color information to air - -SUGG: Server-side objects could be moved based on nodes to enable very - lightweight operation and simple AI - - Not practical; client would still need to show smooth movement. - -SUGG: Make a system for pregenerating quick information for mapblocks, so - that the client can show them as cubes before they are actually sent - or even generated. - -SUGG: Erosion simulation at map generation time - - This might be plausible if larger areas of map were pregenerated - without lighting (which is slow) - - Simulate water flows, which would carve out dirt fast and - then turn stone into gravel and sand and relocate it. - - How about relocating minerals, too? Coal and gold in - downstream sand and gravel would be kind of cool - - This would need a better way of handling minerals, mainly - to have mineral content as a separate field. the first - parameter field is free for this. - - Simulate rock falling from cliffs when water has removed - enough solid rock from the bottom - -SUGG: For non-mapgen FarMesh: Add a per-sector database to store surface - stuff as simple flags/values - - Light? - - A building? - And at some point make the server send this data to the client too, - instead of referring to the noise functions - - Ground height - - Surface ground type - - Trees? - -Gaming ideas: -------------- - -- Aim for something like controlling a single dwarf in Dwarf Fortress -- The player could go faster by a crafting a boat, or riding an animal -- Random NPC traders. what else? - -Game content: -------------- - -- When furnace is destroyed, move items to player's inventory -- Add lots of stuff -- Glass blocks -- Growing grass, decaying leaves - - This can be done in the active blocks I guess. - - Lots of stuff can be done in the active blocks. - - Uh, is there an active block list somewhere? I think not. Add it. -- Breaking weak structures - - This can probably be accomplished in the same way as grass -- Player health points - - When player dies, throw items on map (needs better item-on-map - implementation) -- Cobble to get mossy if near water -- More slots in furnace source list, so that multiple ingredients - are possible. -- Keys to chests? - -- The Treasure Guard; a big monster with a hammer - - The hammer does great damage, shakes the ground and removes a block - - You can drop on top of it, and have some time to attack there - before he shakes you off - -- Maybe the difficulty could come from monsters getting tougher in - far-away places, and the player starting to need something from - there when time goes by. - - The player would have some of that stuff at the beginning, and - would need new supplies of it when it runs out - -- A bomb -- A spread-items-on-map routine for the bomb, and for dying players - -- Fighting: - - Proper sword swing simulation - - Player should get damage from colliding to a wall at high speed - -Documentation: --------------- - -Build system / running: ------------------------ - -Networking and serialization: ------------------------------ - -SUGG: Fix address to be ipv6 compatible - -User Interface: ---------------- - -Graphics: ---------- - -SUGG: Combine MapBlock's face caches to so big pieces that VBO - can be used - - That is >500 vertices - - This is not easy; all the MapBlocks close to the player would - still need to be drawn separately and combining the blocks - would have to happen in a background thread - -SUGG: Make fetching sector's blocks more efficient when rendering - sectors that have very large amounts of blocks (on client) - - Is this necessary at all? - -SUGG: Draw cubes in inventory directly with 3D drawing commands, so that - animating them is easier. - -SUGG: Option for enabling proper alpha channel for textures - -TODO: Flowing water animation - -TODO: A setting for enabling bilinear filtering for textures - -TODO: Better control of draw_control.wanted_max_blocks - -TODO: Further investigate the use of GPU lighting in addition to the - current one - -TODO: Artificial (night) light could be more yellow colored than sunlight. - - This is technically doable. - - Also the actual colors of the textures could be made less colorful - in the dark but it's a bit more difficult. - -SUGG: Somehow make the night less colorful - -TODO: Occlusion culling - - At the same time, move some of the renderMap() block choosing code - to the same place as where the new culling happens. - - Shoot some rays per frame and when ready, make a new list of - blocks for usage of renderMap and give it a new pointer to it. - -Configuration: --------------- - -Client: -------- - -TODO: Untie client network operations from framerate - - Needs some input queues or something - - This won't give much performance boost because calculating block - meshes takes so long - -SUGG: Make morning and evening transition more smooth and maybe shorter - -TODO: Don't update all meshes always on single node changes, but - check which ones should be updated - - implement Map::updateNodeMeshes() and the usage of it - - It will give almost always a 4x boost in mesh update performance. - -- A weapon engine - -- Tool/weapon visualization - -FIXME: When disconnected to the menu, memory is not freed properly - -TODO: Investigate how much the mesh generator thread gets used when - transferring map data - -Server: -------- - -SUGG: Make an option to the server to disable building and digging near - the starting position - -FIXME: Server sometimes goes into some infinite PeerNotFoundException loop - -* Fix the problem with the server constantly saving one or a few - blocks? List the first saved block, maybe it explains. - - It is probably caused by oscillating water - - TODO: Investigate if this still happens (this is a very old one) -* Make a small history check to transformLiquids to detect and log - continuous oscillations, in such detail that they can be fixed. - -FIXME: The new optimized map sending doesn't sometimes send enough blocks - from big caves and such -FIXME: Block send distance configuration does not take effect for some reason - -Environment: ------------- - -TODO: Add proper hooks to when adding and removing active blocks - -TODO: Finish the ActiveBlockModifier stuff and use it for something - -Objects: --------- - -TODO: Get rid of MapBlockObjects and use only ActiveObjects - - Skipping the MapBlockObject data is nasty - there is no "total - length" stored; have to make a SkipMBOs function which contains - enough of the current code to skip them properly. - -SUGG: MovingObject::move and Player::move are basically the same. - combine them. - - NOTE: This is a bit tricky because player has the sneaking ability - - NOTE: Player::move is more up-to-date. - - NOTE: There is a simple move implementation now in collision.{h,cpp} - - NOTE: MovingObject will be deleted (MapBlockObject) - -TODO: Add a long step function to objects that is called with the time - difference when block activates - -Map: ----- - -TODO: Mineral and ground material properties - - This way mineral ground toughness can be calculated with just - some formula, as well as tool strengths. Sounds too. - - There are TODOs in appropriate files: material.h, content_mapnode.h - -TODO: Flowing water to actually contain flow direction information - - There is a space for this - it just has to be implemented. - -TODO: Consider smoothening cave floors after generating them - -TODO: Fix make_tree, make_* to use seed-position-consistent pseudorandom - - delta also - -Misc. stuff: ------------- -TODO: Make sure server handles removing grass when a block is placed (etc) - - The client should not do it by itself - - NOTE: I think nobody does it currently... -TODO: Block cube placement around player's head -TODO: Protocol version field -TODO: Think about using same bits for material for fences and doors, for - example -TODO: Move mineral to param2, increment map serialization version, add - conversion - -SUGG: Restart irrlicht completely when coming back to main menu from game. - - This gets rid of everything that is stored in irrlicht's caches. +/* +Minetest-c55 +Copyright (C) 2010-2011 celeron55, Perttu Ahola + +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. +*/ + +/* +=============================== NOTES ============================== +NOTE: Things starting with TODO are sometimes only suggestions. + +NOTE: iostream.imbue(std::locale("C")) is very slow +NOTE: Global locale is now set at initialization + +NOTE: If VBO (EHM_STATIC) is used, remember to explicitly free the + hardware buffer (it is not freed automatically) + +NOTE: A random to-do list saved here as documentation: +A list of "active blocks" in which stuff happens. (+=done) + + Add a never-resetted game timer to the server + + Add a timestamp value to blocks + + The simple rule: All blocks near some player are "active" + - Do stuff in real time in active blocks + + Handle objects + - Grow grass, delete leaves without a tree + - Spawn some mobs based on some rules + - Transform cobble to mossy cobble near water + - Run a custom script + - ...And all kinds of other dynamic stuff + + Keep track of when a block becomes active and becomes inactive + + When a block goes inactive: + + Store objects statically to block + + Store timer value as the timestamp + + When a block goes active: + + Create active objects out of static objects + - Simulate the results of what would have happened if it would have + been active for all the time + - Grow a lot of grass and so on + + Initially it is fine to send information about every active object + to every player. Eventually it should be modified to only send info + about the nearest ones. + + This was left to be done by the old system and it sends only the + nearest ones. + +Vim conversion regexpes for moving to extended content type storage: +%s/\(\.\|->\)d \([!=]=\)/\1getContent() \2/g +%s/content_features(\([^.]*\)\.d)/content_features(\1)/g +%s/\(\.\|->\)d = \([^;]*\);/\1setContent(\2);/g +%s/\(getNodeNoExNoEmerge([^)]*)\)\.d/\1.getContent()/g +%s/\(getNodeNoExNoEmerge(.*)\)\.d/\1.getContent()/g +%s/\.d;/.getContent();/g +%s/\(content_liquid\|content_flowing_liquid\|make_liquid_flowing\|content_pointable\)(\([^.]*\).d)/\1(\2.getContent())/g +Other things to note: +- node.d = node.param0 (only in raw serialization; use getContent() otherwise) +- node.param = node.param1 +- node.dir = node.param2 +- content_walkable(node.d) etc should be changed to + content_features(node).walkable etc +- Also check for lines that store the result of getContent to a 8-bit + variable and fix them (result of getContent() must be stored in + content_t, which is 16-bit) + +Old, wild and random suggestions that probably won't be done: +------------------------------------------------------------- + +SUGG: If player is on ground, mainly fetch ground-level blocks + +SUGG: Expose Connection's seqnums and ACKs to server and client. + - This enables saving many packets and making a faster connection + - This also enables server to check if client has received the + most recent block sent, for example. +SUGG: Add a sane bandwidth throttling system to Connection + +SUGG: More fine-grained control of client's dumping of blocks from + memory + - ...What does this mean in the first place? + +SUGG: A map editing mode (similar to dedicated server mode) + +SUGG: Transfer more blocks in a single packet +SUGG: A blockdata combiner class, to which blocks are added and at + destruction it sends all the stuff in as few packets as possible. +SUGG: Make a PACKET_COMBINED which contains many subpackets. Utilize + it by sending more stuff in a single packet. + - Add a packet queue to RemoteClient, from which packets will be + combined with object data packets + - This is not exactly trivial: the object data packets are + sometimes very big by themselves + - This might not give much network performance gain though. + +SUGG: Precalculate lighting translation table at runtime (at startup) + - This is not doable because it is currently hand-made and not + based on some mathematical function. + - Note: This has been changing lately + +SUGG: A version number to blocks, which increments when the block is + modified (node add/remove, water update, lighting update) + - This can then be used to make sure the most recent version of + a block has been sent to client, for example + +SUGG: Make the amount of blocks sending to client and the total + amount of blocks dynamically limited. Transferring blocks is the + main network eater of this system, so it is the one that has + to be throttled so that RTTs stay low. + +SUGG: Meshes of blocks could be split into 6 meshes facing into + different directions and then only those drawn that need to be + +SUGG: Background music based on cellular automata? + http://www.earslap.com/projectslab/otomata + +SUGG: Simple light color information to air + +SUGG: Server-side objects could be moved based on nodes to enable very + lightweight operation and simple AI + - Not practical; client would still need to show smooth movement. + +SUGG: Make a system for pregenerating quick information for mapblocks, so + that the client can show them as cubes before they are actually sent + or even generated. + +SUGG: Erosion simulation at map generation time + - This might be plausible if larger areas of map were pregenerated + without lighting (which is slow) + - Simulate water flows, which would carve out dirt fast and + then turn stone into gravel and sand and relocate it. + - How about relocating minerals, too? Coal and gold in + downstream sand and gravel would be kind of cool + - This would need a better way of handling minerals, mainly + to have mineral content as a separate field. the first + parameter field is free for this. + - Simulate rock falling from cliffs when water has removed + enough solid rock from the bottom + +SUGG: For non-mapgen FarMesh: Add a per-sector database to store surface + stuff as simple flags/values + - Light? + - A building? + And at some point make the server send this data to the client too, + instead of referring to the noise functions + - Ground height + - Surface ground type + - Trees? + +Gaming ideas: +------------- + +- Aim for something like controlling a single dwarf in Dwarf Fortress +- The player could go faster by a crafting a boat, or riding an animal +- Random NPC traders. what else? + +Game content: +------------- + +- When furnace is destroyed, move items to player's inventory +- Add lots of stuff +- Glass blocks +- Growing grass, decaying leaves + - This can be done in the active blocks I guess. + - Lots of stuff can be done in the active blocks. + - Uh, is there an active block list somewhere? I think not. Add it. +- Breaking weak structures + - This can probably be accomplished in the same way as grass +- Player health points + - When player dies, throw items on map (needs better item-on-map + implementation) +- Cobble to get mossy if near water +- More slots in furnace source list, so that multiple ingredients + are possible. +- Keys to chests? + +- The Treasure Guard; a big monster with a hammer + - The hammer does great damage, shakes the ground and removes a block + - You can drop on top of it, and have some time to attack there + before he shakes you off + +- Maybe the difficulty could come from monsters getting tougher in + far-away places, and the player starting to need something from + there when time goes by. + - The player would have some of that stuff at the beginning, and + would need new supplies of it when it runs out + +- A bomb +- A spread-items-on-map routine for the bomb, and for dying players + +- Fighting: + - Proper sword swing simulation + - Player should get damage from colliding to a wall at high speed + +Documentation: +-------------- + +Build system / running: +----------------------- + +Networking and serialization: +----------------------------- + +SUGG: Fix address to be ipv6 compatible + +User Interface: +--------------- + +Graphics: +--------- + +SUGG: Combine MapBlock's face caches to so big pieces that VBO + can be used + - That is >500 vertices + - This is not easy; all the MapBlocks close to the player would + still need to be drawn separately and combining the blocks + would have to happen in a background thread + +SUGG: Make fetching sector's blocks more efficient when rendering + sectors that have very large amounts of blocks (on client) + - Is this necessary at all? + +SUGG: Draw cubes in inventory directly with 3D drawing commands, so that + animating them is easier. + +SUGG: Option for enabling proper alpha channel for textures + +TODO: Flowing water animation + +TODO: A setting for enabling bilinear filtering for textures + +TODO: Better control of draw_control.wanted_max_blocks + +TODO: Further investigate the use of GPU lighting in addition to the + current one + +TODO: Artificial (night) light could be more yellow colored than sunlight. + - This is technically doable. + - Also the actual colors of the textures could be made less colorful + in the dark but it's a bit more difficult. + +SUGG: Somehow make the night less colorful + +TODO: Occlusion culling + - At the same time, move some of the renderMap() block choosing code + to the same place as where the new culling happens. + - Shoot some rays per frame and when ready, make a new list of + blocks for usage of renderMap and give it a new pointer to it. + +Configuration: +-------------- + +Client: +------- + +TODO: Untie client network operations from framerate + - Needs some input queues or something + - This won't give much performance boost because calculating block + meshes takes so long + +SUGG: Make morning and evening transition more smooth and maybe shorter + +TODO: Don't update all meshes always on single node changes, but + check which ones should be updated + - implement Map::updateNodeMeshes() and the usage of it + - It will give almost always a 4x boost in mesh update performance. + +- A weapon engine + +- Tool/weapon visualization + +FIXME: When disconnected to the menu, memory is not freed properly + +TODO: Investigate how much the mesh generator thread gets used when + transferring map data + +Server: +------- + +SUGG: Make an option to the server to disable building and digging near + the starting position + +FIXME: Server sometimes goes into some infinite PeerNotFoundException loop + +* Fix the problem with the server constantly saving one or a few + blocks? List the first saved block, maybe it explains. + - It is probably caused by oscillating water + - TODO: Investigate if this still happens (this is a very old one) +* Make a small history check to transformLiquids to detect and log + continuous oscillations, in such detail that they can be fixed. + +FIXME: The new optimized map sending doesn't sometimes send enough blocks + from big caves and such +FIXME: Block send distance configuration does not take effect for some reason + +Environment: +------------ + +TODO: Add proper hooks to when adding and removing active blocks + +TODO: Finish the ActiveBlockModifier stuff and use it for something + +Objects: +-------- + +TODO: Get rid of MapBlockObjects and use only ActiveObjects + - Skipping the MapBlockObject data is nasty - there is no "total + length" stored; have to make a SkipMBOs function which contains + enough of the current code to skip them properly. + +SUGG: MovingObject::move and Player::move are basically the same. + combine them. + - NOTE: This is a bit tricky because player has the sneaking ability + - NOTE: Player::move is more up-to-date. + - NOTE: There is a simple move implementation now in collision.{h,cpp} + - NOTE: MovingObject will be deleted (MapBlockObject) + +TODO: Add a long step function to objects that is called with the time + difference when block activates + +Map: +---- + +TODO: Mineral and ground material properties + - This way mineral ground toughness can be calculated with just + some formula, as well as tool strengths. Sounds too. + - There are TODOs in appropriate files: material.h, content_mapnode.h + +TODO: Flowing water to actually contain flow direction information + - There is a space for this - it just has to be implemented. + +TODO: Consider smoothening cave floors after generating them + +TODO: Fix make_tree, make_* to use seed-position-consistent pseudorandom + - delta also + +Misc. stuff: +------------ +TODO: Make sure server handles removing grass when a block is placed (etc) + - The client should not do it by itself + - NOTE: I think nobody does it currently... +TODO: Block cube placement around player's head +TODO: Protocol version field +TODO: Think about using same bits for material for fences and doors, for + example +TODO: Move mineral to param2, increment map serialization version, add + conversion + +SUGG: Restart irrlicht completely when coming back to main menu from game. + - This gets rid of everything that is stored in irrlicht's caches. - This might be needed for texture pack selection in menu - -TODO: Merge bahamada's audio stuff (clean patch available) - -TODO: Move content_features to mapnode_content_features.{h,cpp} or so - -Making it more portable: ------------------------- - -Stuff to do before release: ---------------------------- - -Fixes to the current release: ------------------------------ - -Stuff to do after release: ---------------------------- - -Doing currently: ----------------- - -====================================================================== - -*/ - -#ifdef NDEBUG - #ifdef _WIN32 - #pragma message ("Disabling unit tests") - #else - #warning "Disabling unit tests" - #endif - // Disable unit tests - #define ENABLE_TESTS 0 -#else - // Enable unit tests - #define ENABLE_TESTS 1 -#endif - -#ifdef _MSC_VER - #pragma comment(lib, "Irrlicht.lib") - //#pragma comment(lib, "jthread.lib") - #pragma comment(lib, "zlibwapi.lib") - #pragma comment(lib, "Shell32.lib") - // This would get rid of the console window - //#pragma comment(linker, "/subsystem:windows /ENTRY:mainCRTStartup") -#endif - -#include -#include -#include -#include "main.h" -#include "common_irrlicht.h" -#include "debug.h" -#include "test.h" -#include "server.h" -#include "constants.h" -#include "porting.h" -#include "gettime.h" -#include "guiMessageMenu.h" -#include "filesys.h" -#include "config.h" -#include "guiMainMenu.h" -#include "mineral.h" -#include "materials.h" -#include "game.h" -#include "keycode.h" -#include "tile.h" - -#include "gettext.h" - -// This makes textures -ITextureSource *g_texturesource = NULL; - -/* - Settings. - These are loaded from the config file. -*/ - -Settings g_settings; -// This is located in defaultsettings.cpp -extern void set_default_settings(); - -// Global profiler -Profiler g_profiler; - -/* - Random stuff -*/ - -/* - GUI Stuff -*/ - -gui::IGUIEnvironment* guienv = NULL; -gui::IGUIStaticText *guiroot = NULL; - -MainMenuManager g_menumgr; - -bool noMenuActive() -{ - return (g_menumgr.menuCount() == 0); -} - -// Passed to menus to allow disconnecting and exiting - -MainGameCallback *g_gamecallback = NULL; - -/* - Debug streams -*/ - -// Connection -std::ostream *dout_con_ptr = &dummyout; -std::ostream *derr_con_ptr = &dstream_no_stderr; -//std::ostream *dout_con_ptr = &dstream_no_stderr; -//std::ostream *derr_con_ptr = &dstream_no_stderr; -//std::ostream *dout_con_ptr = &dstream; -//std::ostream *derr_con_ptr = &dstream; - -// Server -std::ostream *dout_server_ptr = &dstream; -std::ostream *derr_server_ptr = &dstream; - -// Client -std::ostream *dout_client_ptr = &dstream; -std::ostream *derr_client_ptr = &dstream; - -/* - gettime.h implementation -*/ - -// A small helper class -class TimeGetter -{ -public: - virtual u32 getTime() = 0; -}; - -// A precise irrlicht one -class IrrlichtTimeGetter: public TimeGetter -{ -public: - IrrlichtTimeGetter(IrrlichtDevice *device): - m_device(device) - {} - u32 getTime() - { - if(m_device == NULL) - return 0; - return m_device->getTimer()->getRealTime(); - } -private: - IrrlichtDevice *m_device; -}; -// Not so precise one which works without irrlicht -class SimpleTimeGetter: public TimeGetter -{ -public: - u32 getTime() - { - return porting::getTimeMs(); - } -}; - -// A pointer to a global instance of the time getter -// TODO: why? -TimeGetter *g_timegetter = NULL; - -u32 getTimeMs() -{ - if(g_timegetter == NULL) - return 0; - return g_timegetter->getTime(); -} - -/* - Event handler for Irrlicht - - NOTE: Everything possible should be moved out from here, - probably to InputHandler and the_game -*/ - -class MyEventReceiver : public IEventReceiver -{ -public: - // This is the one method that we have to implement - virtual bool OnEvent(const SEvent& event) - { - /* - React to nothing here if a menu is active - */ - if(noMenuActive() == false) - { - return false; - } - - // Remember whether each key is down or up - if(event.EventType == irr::EET_KEY_INPUT_EVENT) - { - keyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown; - - if(event.KeyInput.PressedDown) - keyWasDown[event.KeyInput.Key] = true; - } - - if(event.EventType == irr::EET_MOUSE_INPUT_EVENT) - { - if(noMenuActive() == false) - { - left_active = false; - middle_active = false; - right_active = false; - } - else - { - //dstream<<"MyEventReceiver: mouse input"<IsKeyDown(keyCode); - } - virtual bool wasKeyDown(EKEY_CODE keyCode) - { - return m_receiver->WasKeyDown(keyCode); - } - virtual v2s32 getMousePos() - { - return m_device->getCursorControl()->getPosition(); - } - virtual void setMousePos(s32 x, s32 y) - { - m_device->getCursorControl()->setPosition(x, y); - } - - virtual bool getLeftState() - { - return m_receiver->left_active; - } - virtual bool getRightState() - { - return m_receiver->right_active; - } - - virtual bool getLeftClicked() - { - return m_receiver->leftclicked; - } - virtual bool getRightClicked() - { - return m_receiver->rightclicked; - } - virtual void resetLeftClicked() - { - m_receiver->leftclicked = false; - } - virtual void resetRightClicked() - { - m_receiver->rightclicked = false; - } - - virtual bool getLeftReleased() - { - return m_receiver->leftreleased; - } - virtual bool getRightReleased() - { - return m_receiver->rightreleased; - } - virtual void resetLeftReleased() - { - m_receiver->leftreleased = false; - } - virtual void resetRightReleased() - { - m_receiver->rightreleased = false; - } - - virtual s32 getMouseWheel() - { - return m_receiver->getMouseWheel(); - } - - void clear() - { - m_receiver->clearInput(); - } -private: - IrrlichtDevice *m_device; - MyEventReceiver *m_receiver; -}; - -class RandomInputHandler : public InputHandler -{ -public: - RandomInputHandler() - { - leftdown = false; - rightdown = false; - leftclicked = false; - rightclicked = false; - leftreleased = false; - rightreleased = false; - for(u32 i=0; i map1; - tempf = -324; - const s16 ii=300; - for(s16 y=0; y=0; y--){ - for(s16 x=0; x screensize = driver->getScreenSize(); - - video::ITexture *bgtexture = - driver->getTexture(getTexturePath("mud.png").c_str()); - if(bgtexture) - { - s32 texturesize = 128; - s32 tiled_y = screensize.Height / texturesize + 1; - s32 tiled_x = screensize.Width / texturesize + 1; - - for(s32 y=0; y rect(0,0,texturesize,texturesize); - rect += v2s32(x*texturesize, y*texturesize); - driver->draw2DImage(bgtexture, rect, - core::rect(core::position2d(0,0), - core::dimension2di(bgtexture->getSize())), - NULL, NULL, true); - } - } - - video::ITexture *logotexture = - driver->getTexture(getTexturePath("menulogo.png").c_str()); - if(logotexture) - { - v2s32 logosize(logotexture->getOriginalSize().Width, - logotexture->getOriginalSize().Height); - logosize *= 4; - - video::SColor bgcolor(255,50,50,50); - core::rect bgrect(0, screensize.Height-logosize.Y-20, - screensize.Width, screensize.Height); - driver->draw2DRectangle(bgcolor, bgrect, NULL); - - core::rect rect(0,0,logosize.X,logosize.Y); - rect += v2s32(screensize.Width/2,screensize.Height-10-logosize.Y); - rect -= v2s32(logosize.X/2, 0); - driver->draw2DImage(logotexture, rect, - core::rect(core::position2d(0,0), - core::dimension2di(logotexture->getSize())), - NULL, NULL, true); - } -} - -int main(int argc, char *argv[]) -{ - /* - Initialization - */ - - // Set locale. This is for forcing '.' as the decimal point. - std::locale::global(std::locale("C")); - // This enables printing all characters in bitmap font - setlocale(LC_CTYPE, "en_US"); - - /* - Parse command line - */ - - // List all allowed options - core::map allowed_options; - allowed_options.insert("help", ValueSpec(VALUETYPE_FLAG)); - allowed_options.insert("server", ValueSpec(VALUETYPE_FLAG, - "Run server directly")); - allowed_options.insert("config", ValueSpec(VALUETYPE_STRING, - "Load configuration from specified file")); - allowed_options.insert("port", ValueSpec(VALUETYPE_STRING)); - allowed_options.insert("address", ValueSpec(VALUETYPE_STRING)); - allowed_options.insert("random-input", ValueSpec(VALUETYPE_FLAG)); - allowed_options.insert("disable-unittests", ValueSpec(VALUETYPE_FLAG)); - allowed_options.insert("enable-unittests", ValueSpec(VALUETYPE_FLAG)); - allowed_options.insert("map-dir", ValueSpec(VALUETYPE_STRING)); -#ifdef _WIN32 - allowed_options.insert("dstream-on-stderr", ValueSpec(VALUETYPE_FLAG)); -#endif - allowed_options.insert("speedtests", ValueSpec(VALUETYPE_FLAG)); - - Settings cmd_args; - - bool ret = cmd_args.parseCommandLine(argc, argv, allowed_options); - - if(ret == false || cmd_args.getFlag("help")) - { - dstream<<"Allowed options:"<::Iterator - i = allowed_options.getIterator(); - i.atEnd() == false; i++) - { - dstream<<" --"<getKey(); - if(i.getNode()->getValue().type == VALUETYPE_FLAG) - { - } - else - { - dstream<<" "; - } - dstream<getValue().help != NULL) - { - dstream<<" "<getValue().help - < +#include +#include +#include "main.h" +#include "common_irrlicht.h" +#include "debug.h" +#include "test.h" +#include "server.h" +#include "constants.h" +#include "porting.h" +#include "gettime.h" +#include "guiMessageMenu.h" +#include "filesys.h" +#include "config.h" +#include "guiMainMenu.h" +#include "mineral.h" +#include "materials.h" +#include "game.h" +#include "keycode.h" +#include "tile.h" + +#include "gettext.h" + +// This makes textures +ITextureSource *g_texturesource = NULL; + +/* + Settings. + These are loaded from the config file. +*/ + +Settings g_settings; +// This is located in defaultsettings.cpp +extern void set_default_settings(); + +// Global profiler +Profiler g_profiler; + +/* + Random stuff +*/ + +/* + GUI Stuff +*/ + +gui::IGUIEnvironment* guienv = NULL; +gui::IGUIStaticText *guiroot = NULL; + +MainMenuManager g_menumgr; + +bool noMenuActive() +{ + return (g_menumgr.menuCount() == 0); +} + +// Passed to menus to allow disconnecting and exiting + +MainGameCallback *g_gamecallback = NULL; + +/* + Debug streams +*/ + +// Connection +std::ostream *dout_con_ptr = &dummyout; +std::ostream *derr_con_ptr = &dstream_no_stderr; +//std::ostream *dout_con_ptr = &dstream_no_stderr; +//std::ostream *derr_con_ptr = &dstream_no_stderr; +//std::ostream *dout_con_ptr = &dstream; +//std::ostream *derr_con_ptr = &dstream; + +// Server +std::ostream *dout_server_ptr = &dstream; +std::ostream *derr_server_ptr = &dstream; + +// Client +std::ostream *dout_client_ptr = &dstream; +std::ostream *derr_client_ptr = &dstream; + +/* + gettime.h implementation +*/ + +// A small helper class +class TimeGetter +{ +public: + virtual u32 getTime() = 0; +}; + +// A precise irrlicht one +class IrrlichtTimeGetter: public TimeGetter +{ +public: + IrrlichtTimeGetter(IrrlichtDevice *device): + m_device(device) + {} + u32 getTime() + { + if(m_device == NULL) + return 0; + return m_device->getTimer()->getRealTime(); + } +private: + IrrlichtDevice *m_device; +}; +// Not so precise one which works without irrlicht +class SimpleTimeGetter: public TimeGetter +{ +public: + u32 getTime() + { + return porting::getTimeMs(); + } +}; + +// A pointer to a global instance of the time getter +// TODO: why? +TimeGetter *g_timegetter = NULL; + +u32 getTimeMs() +{ + if(g_timegetter == NULL) + return 0; + return g_timegetter->getTime(); +} + +/* + Event handler for Irrlicht + + NOTE: Everything possible should be moved out from here, + probably to InputHandler and the_game +*/ + +class MyEventReceiver : public IEventReceiver +{ +public: + // This is the one method that we have to implement + virtual bool OnEvent(const SEvent& event) + { + /* + React to nothing here if a menu is active + */ + if(noMenuActive() == false) + { + return false; + } + + // Remember whether each key is down or up + if(event.EventType == irr::EET_KEY_INPUT_EVENT) + { + keyIsDown[event.KeyInput.Key] = event.KeyInput.PressedDown; + + if(event.KeyInput.PressedDown) + keyWasDown[event.KeyInput.Key] = true; + } + + if(event.EventType == irr::EET_MOUSE_INPUT_EVENT) + { + if(noMenuActive() == false) + { + left_active = false; + middle_active = false; + right_active = false; + } + else + { + //dstream<<"MyEventReceiver: mouse input"<IsKeyDown(keyCode); + } + virtual bool wasKeyDown(EKEY_CODE keyCode) + { + return m_receiver->WasKeyDown(keyCode); + } + virtual v2s32 getMousePos() + { + return m_device->getCursorControl()->getPosition(); + } + virtual void setMousePos(s32 x, s32 y) + { + m_device->getCursorControl()->setPosition(x, y); + } + + virtual bool getLeftState() + { + return m_receiver->left_active; + } + virtual bool getRightState() + { + return m_receiver->right_active; + } + + virtual bool getLeftClicked() + { + return m_receiver->leftclicked; + } + virtual bool getRightClicked() + { + return m_receiver->rightclicked; + } + virtual void resetLeftClicked() + { + m_receiver->leftclicked = false; + } + virtual void resetRightClicked() + { + m_receiver->rightclicked = false; + } + + virtual bool getLeftReleased() + { + return m_receiver->leftreleased; + } + virtual bool getRightReleased() + { + return m_receiver->rightreleased; + } + virtual void resetLeftReleased() + { + m_receiver->leftreleased = false; + } + virtual void resetRightReleased() + { + m_receiver->rightreleased = false; + } + + virtual s32 getMouseWheel() + { + return m_receiver->getMouseWheel(); + } + + void clear() + { + m_receiver->clearInput(); + } +private: + IrrlichtDevice *m_device; + MyEventReceiver *m_receiver; +}; + +class RandomInputHandler : public InputHandler +{ +public: + RandomInputHandler() + { + leftdown = false; + rightdown = false; + leftclicked = false; + rightclicked = false; + leftreleased = false; + rightreleased = false; + for(u32 i=0; i map1; + tempf = -324; + const s16 ii=300; + for(s16 y=0; y=0; y--){ + for(s16 x=0; x screensize = driver->getScreenSize(); + + video::ITexture *bgtexture = + driver->getTexture(getTexturePath("mud.png").c_str()); + if(bgtexture) + { + s32 texturesize = 128; + s32 tiled_y = screensize.Height / texturesize + 1; + s32 tiled_x = screensize.Width / texturesize + 1; + + for(s32 y=0; y rect(0,0,texturesize,texturesize); + rect += v2s32(x*texturesize, y*texturesize); + driver->draw2DImage(bgtexture, rect, + core::rect(core::position2d(0,0), + core::dimension2di(bgtexture->getSize())), + NULL, NULL, true); + } + } + + video::ITexture *logotexture = + driver->getTexture(getTexturePath("menulogo.png").c_str()); + if(logotexture) + { + v2s32 logosize(logotexture->getOriginalSize().Width, + logotexture->getOriginalSize().Height); + logosize *= 4; + + video::SColor bgcolor(255,50,50,50); + core::rect bgrect(0, screensize.Height-logosize.Y-20, + screensize.Width, screensize.Height); + driver->draw2DRectangle(bgcolor, bgrect, NULL); + + core::rect rect(0,0,logosize.X,logosize.Y); + rect += v2s32(screensize.Width/2,screensize.Height-10-logosize.Y); + rect -= v2s32(logosize.X/2, 0); + driver->draw2DImage(logotexture, rect, + core::rect(core::position2d(0,0), + core::dimension2di(logotexture->getSize())), + NULL, NULL, true); + } +} + +int main(int argc, char *argv[]) +{ + /* + Initialization + */ + + // Set locale. This is for forcing '.' as the decimal point. + std::locale::global(std::locale("C")); + // This enables printing all characters in bitmap font + setlocale(LC_CTYPE, "en_US"); + + /* + Parse command line + */ + + // List all allowed options + core::map allowed_options; + allowed_options.insert("help", ValueSpec(VALUETYPE_FLAG)); + allowed_options.insert("server", ValueSpec(VALUETYPE_FLAG, + "Run server directly")); + allowed_options.insert("config", ValueSpec(VALUETYPE_STRING, + "Load configuration from specified file")); + allowed_options.insert("port", ValueSpec(VALUETYPE_STRING)); + allowed_options.insert("address", ValueSpec(VALUETYPE_STRING)); + allowed_options.insert("random-input", ValueSpec(VALUETYPE_FLAG)); + allowed_options.insert("disable-unittests", ValueSpec(VALUETYPE_FLAG)); + allowed_options.insert("enable-unittests", ValueSpec(VALUETYPE_FLAG)); + allowed_options.insert("map-dir", ValueSpec(VALUETYPE_STRING)); +#ifdef _WIN32 + allowed_options.insert("dstream-on-stderr", ValueSpec(VALUETYPE_FLAG)); +#endif + allowed_options.insert("speedtests", ValueSpec(VALUETYPE_FLAG)); + + Settings cmd_args; + + bool ret = cmd_args.parseCommandLine(argc, argv, allowed_options); + + if(ret == false || cmd_args.getFlag("help")) + { + dstream<<"Allowed options:"<::Iterator + i = allowed_options.getIterator(); + i.atEnd() == false; i++) + { + dstream<<" --"<getKey(); + if(i.getNode()->getValue().type == VALUETYPE_FLAG) + { + } + else + { + dstream<<" "; + } + dstream<getValue().help != NULL) + { + dstream<<" "<getValue().help + < filenames; - filenames.push_back(porting::path_userdata + "/minetest.conf"); -#ifdef RUN_IN_PLACE - filenames.push_back(porting::path_userdata + "/../minetest.conf"); -#endif - - for(u32 i=0; i(screenW, screenH), - 16, fullscreen, false, false, &receiver); - - if (device == 0) - return 1; // could not create selected driver. - - // Set device in game parameters - device = device; - - // Set the window caption - device->setWindowCaption(L"Minetest [Main Menu]"); - - // Create time getter - g_timegetter = new IrrlichtTimeGetter(device); - - // Create game callback for menus - g_gamecallback = new MainGameCallback(device); - - // Create texture source - g_texturesource = new TextureSource(device); - - /* - Speed tests (done after irrlicht is loaded to get timer) - */ - if(cmd_args.getFlag("speedtests")) - { - dstream<<"Running speed tests"<setResizable(true); - - bool random_input = g_settings.getBool("random_input") - || cmd_args.getFlag("random-input"); - InputHandler *input = NULL; - if(random_input) - input = new RandomInputHandler(); - else - input = new RealInputHandler(device, &receiver); - - /* - Continue initialization - */ - - //video::IVideoDriver* driver = device->getVideoDriver(); - - /* - This changes the minimum allowed number of vertices in a VBO. - Default is 500. - */ - //driver->setMinHardwareBufferVertexCount(50); - - scene::ISceneManager* smgr = device->getSceneManager(); - - guienv = device->getGUIEnvironment(); - gui::IGUISkin* skin = guienv->getSkin(); - gui::IGUIFont* font = guienv->getFont(getTexturePath("fontlucida.png").c_str()); - if(font) - skin->setFont(font); - else - dstream<<"WARNING: Font file was not found." - " Using default font."<getFont(); - assert(font); - - u32 text_height = font->getDimension(L"Hello, world!").Height; - dstream<<"text_height="<setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,0,0,0)); - skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,255,255,255)); - //skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(0,0,0,0)); - //skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(0,0,0,0)); - skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(255,0,0,0)); - skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(255,0,0,0)); - - /* - Preload some textures and stuff - */ - - init_mapnode(); // Second call with g_texturesource set - init_mineral(); - - /* - GUI stuff - */ - - /* - If an error occurs, this is set to something and the - menu-game loop is restarted. It is then displayed before - the menu. - */ - std::wstring error_message = L""; - - // The password entered during the menu screen, - std::string password; - - /* - Menu-game loop - */ - while(device->run() && kill == false) - { - - // This is used for catching disconnects - try - { - - /* - Clear everything from the GUIEnvironment - */ - guienv->clear(); - - /* - We need some kind of a root node to be able to add - custom gui elements directly on the screen. - Otherwise they won't be automatically drawn. - */ - guiroot = guienv->addStaticText(L"", - core::rect(0, 0, 10000, 10000)); - - /* - Out-of-game menu loop. - - Loop quits when menu returns proper parameters. - */ - while(kill == false) - { - // Cursor can be non-visible when coming from the game - device->getCursorControl()->setVisible(true); - // Some stuff are left to scene manager when coming from the game - // (map at least?) - smgr->clear(); - // Reset or hide the debug gui texts - /*guitext->setText(L"Minetest-c55"); - guitext2->setVisible(false); - guitext_info->setVisible(false); - guitext_chat->setVisible(false);*/ - - // Initialize menu data - MainMenuData menudata; - menudata.address = narrow_to_wide(address); - menudata.name = narrow_to_wide(playername); - menudata.port = narrow_to_wide(itos(port)); - menudata.fancy_trees = g_settings.getBool("new_style_leaves"); - menudata.smooth_lighting = g_settings.getBool("smooth_lighting"); - menudata.creative_mode = g_settings.getBool("creative_mode"); - menudata.enable_damage = g_settings.getBool("enable_damage"); - - GUIMainMenu *menu = - new GUIMainMenu(guienv, guiroot, -1, - &g_menumgr, &menudata, g_gamecallback); - menu->allowFocusRemoval(true); - - if(error_message != L"") - { - dstream<<"WARNING: error_message = " - <drop(); - error_message = L""; - } - - video::IVideoDriver* driver = device->getVideoDriver(); - - dstream<<"Created main menu"<run() && kill == false) - { - if(menu->getStatus() == true) - break; - - //driver->beginScene(true, true, video::SColor(255,0,0,0)); - driver->beginScene(true, true, video::SColor(255,128,128,128)); - - drawMenuBackground(driver); - - guienv->drawAll(); - - driver->endScene(); - - // On some computers framerate doesn't seem to be - // automatically limited - sleep_ms(25); - } - - // Break out of menu-game loop to shut down cleanly - if(device->run() == false || kill == true) - break; - - dstream<<"Dropping main menu"<drop(); - - // Delete map if requested - if(menudata.delete_map) - { - bool r = fs::RecursiveDeleteContent(map_dir); - if(r == false) - error_message = L"Delete failed"; - continue; - } - - playername = wide_to_narrow(menudata.name); - - password = translatePassword(playername, menudata.password); - - address = wide_to_narrow(menudata.address); - int newport = stoi(wide_to_narrow(menudata.port)); - if(newport != 0) - port = newport; - g_settings.set("new_style_leaves", itos(menudata.fancy_trees)); - g_settings.set("smooth_lighting", itos(menudata.smooth_lighting)); - g_settings.set("creative_mode", itos(menudata.creative_mode)); - g_settings.set("enable_damage", itos(menudata.enable_damage)); - - // NOTE: These are now checked server side; no need to do it - // here, so let's not do it here. - /*// Check for valid parameters, restart menu if invalid. - if(playername == "") - { - error_message = L"Name required."; - continue; - } - // Check that name has only valid chars - if(string_allowed(playername, PLAYERNAME_ALLOWED_CHARS)==false) - { - error_message = L"Characters allowed: " - +narrow_to_wide(PLAYERNAME_ALLOWED_CHARS); - continue; - }*/ - - // Save settings - g_settings.set("name", playername); - g_settings.set("address", address); - g_settings.set("port", itos(port)); - // Update configuration file - if(configpath != "") - g_settings.updateConfigFile(configpath.c_str()); - - // Continue to game - break; - } - - // Break out of menu-game loop to shut down cleanly - if(device->run() == false) - break; - - // Initialize mapnode again to enable changed graphics settings - init_mapnode(); - - /* - Run game - */ - the_game( - kill, - random_input, - input, - device, - font, - map_dir, - playername, - password, - address, - port, - error_message - ); - - } //try - catch(con::PeerNotFoundException &e) - { - dstream<drop(); - - END_DEBUG_EXCEPTION_HANDLER - - debugstreams_deinit(); - - return 0; -} - -//END + bindtextdomain("minetest", (porting::path_userdata+"/locale").c_str()); + textdomain("minetest"); + + // Initialize debug streams +#ifdef RUN_IN_PLACE + std::string debugfile = DEBUGFILE; +#else + std::string debugfile = porting::path_userdata+"/"+DEBUGFILE; +#endif + debugstreams_init(disable_stderr, debugfile.c_str()); + // Initialize debug stacks + debug_stacks_init(); + + DSTACK(__FUNCTION_NAME); + + // Init material properties table + //initializeMaterialProperties(); + + // Debug handler + BEGIN_DEBUG_EXCEPTION_HANDLER + + // Print startup message + dstream< filenames; + filenames.push_back(porting::path_userdata + "/minetest.conf"); +#ifdef RUN_IN_PLACE + filenames.push_back(porting::path_userdata + "/../minetest.conf"); +#endif + + for(u32 i=0; i(screenW, screenH), + 16, fullscreen, false, false, &receiver); + + if (device == 0) + return 1; // could not create selected driver. + + // Set device in game parameters + device = device; + + // Set the window caption + device->setWindowCaption(L"Minetest [Main Menu]"); + + // Create time getter + g_timegetter = new IrrlichtTimeGetter(device); + + // Create game callback for menus + g_gamecallback = new MainGameCallback(device); + + // Create texture source + g_texturesource = new TextureSource(device); + + /* + Speed tests (done after irrlicht is loaded to get timer) + */ + if(cmd_args.getFlag("speedtests")) + { + dstream<<"Running speed tests"<setResizable(true); + + bool random_input = g_settings.getBool("random_input") + || cmd_args.getFlag("random-input"); + InputHandler *input = NULL; + if(random_input) + input = new RandomInputHandler(); + else + input = new RealInputHandler(device, &receiver); + + /* + Continue initialization + */ + + //video::IVideoDriver* driver = device->getVideoDriver(); + + /* + This changes the minimum allowed number of vertices in a VBO. + Default is 500. + */ + //driver->setMinHardwareBufferVertexCount(50); + + scene::ISceneManager* smgr = device->getSceneManager(); + + guienv = device->getGUIEnvironment(); + gui::IGUISkin* skin = guienv->getSkin(); + gui::IGUIFont* font = guienv->getFont(getTexturePath("fontlucida.png").c_str()); + if(font) + skin->setFont(font); + else + dstream<<"WARNING: Font file was not found." + " Using default font."<getFont(); + assert(font); + + u32 text_height = font->getDimension(L"Hello, world!").Height; + dstream<<"text_height="<setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,0,0,0)); + skin->setColor(gui::EGDC_BUTTON_TEXT, video::SColor(255,255,255,255)); + //skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(0,0,0,0)); + //skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(0,0,0,0)); + skin->setColor(gui::EGDC_3D_HIGH_LIGHT, video::SColor(255,0,0,0)); + skin->setColor(gui::EGDC_3D_SHADOW, video::SColor(255,0,0,0)); + + /* + Preload some textures and stuff + */ + + init_mapnode(); // Second call with g_texturesource set + init_mineral(); + + /* + GUI stuff + */ + + /* + If an error occurs, this is set to something and the + menu-game loop is restarted. It is then displayed before + the menu. + */ + std::wstring error_message = L""; + + // The password entered during the menu screen, + std::string password; + + /* + Menu-game loop + */ + while(device->run() && kill == false) + { + + // This is used for catching disconnects + try + { + + /* + Clear everything from the GUIEnvironment + */ + guienv->clear(); + + /* + We need some kind of a root node to be able to add + custom gui elements directly on the screen. + Otherwise they won't be automatically drawn. + */ + guiroot = guienv->addStaticText(L"", + core::rect(0, 0, 10000, 10000)); + + /* + Out-of-game menu loop. + + Loop quits when menu returns proper parameters. + */ + while(kill == false) + { + // Cursor can be non-visible when coming from the game + device->getCursorControl()->setVisible(true); + // Some stuff are left to scene manager when coming from the game + // (map at least?) + smgr->clear(); + // Reset or hide the debug gui texts + /*guitext->setText(L"Minetest-c55"); + guitext2->setVisible(false); + guitext_info->setVisible(false); + guitext_chat->setVisible(false);*/ + + // Initialize menu data + MainMenuData menudata; + menudata.address = narrow_to_wide(address); + menudata.name = narrow_to_wide(playername); + menudata.port = narrow_to_wide(itos(port)); + menudata.fancy_trees = g_settings.getBool("new_style_leaves"); + menudata.smooth_lighting = g_settings.getBool("smooth_lighting"); + menudata.creative_mode = g_settings.getBool("creative_mode"); + menudata.enable_damage = g_settings.getBool("enable_damage"); + + GUIMainMenu *menu = + new GUIMainMenu(guienv, guiroot, -1, + &g_menumgr, &menudata, g_gamecallback); + menu->allowFocusRemoval(true); + + if(error_message != L"") + { + dstream<<"WARNING: error_message = " + <drop(); + error_message = L""; + } + + video::IVideoDriver* driver = device->getVideoDriver(); + + dstream<<"Created main menu"<run() && kill == false) + { + if(menu->getStatus() == true) + break; + + //driver->beginScene(true, true, video::SColor(255,0,0,0)); + driver->beginScene(true, true, video::SColor(255,128,128,128)); + + drawMenuBackground(driver); + + guienv->drawAll(); + + driver->endScene(); + + // On some computers framerate doesn't seem to be + // automatically limited + sleep_ms(25); + } + + // Break out of menu-game loop to shut down cleanly + if(device->run() == false || kill == true) + break; + + dstream<<"Dropping main menu"<drop(); + + // Delete map if requested + if(menudata.delete_map) + { + bool r = fs::RecursiveDeleteContent(map_dir); + if(r == false) + error_message = L"Delete failed"; + continue; + } + + playername = wide_to_narrow(menudata.name); + + password = translatePassword(playername, menudata.password); + + address = wide_to_narrow(menudata.address); + int newport = stoi(wide_to_narrow(menudata.port)); + if(newport != 0) + port = newport; + g_settings.set("new_style_leaves", itos(menudata.fancy_trees)); + g_settings.set("smooth_lighting", itos(menudata.smooth_lighting)); + g_settings.set("creative_mode", itos(menudata.creative_mode)); + g_settings.set("enable_damage", itos(menudata.enable_damage)); + + // NOTE: These are now checked server side; no need to do it + // here, so let's not do it here. + /*// Check for valid parameters, restart menu if invalid. + if(playername == "") + { + error_message = L"Name required."; + continue; + } + // Check that name has only valid chars + if(string_allowed(playername, PLAYERNAME_ALLOWED_CHARS)==false) + { + error_message = L"Characters allowed: " + +narrow_to_wide(PLAYERNAME_ALLOWED_CHARS); + continue; + }*/ + + // Save settings + g_settings.set("name", playername); + g_settings.set("address", address); + g_settings.set("port", itos(port)); + // Update configuration file + if(configpath != "") + g_settings.updateConfigFile(configpath.c_str()); + + // Continue to game + break; + } + + // Break out of menu-game loop to shut down cleanly + if(device->run() == false) + break; + + // Initialize mapnode again to enable changed graphics settings + init_mapnode(); + + /* + Run game + */ + the_game( + kill, + random_input, + input, + device, + font, + map_dir, + playername, + password, + address, + port, + error_message + ); + + } //try + catch(con::PeerNotFoundException &e) + { + dstream<drop(); + + END_DEBUG_EXCEPTION_HANDLER + + debugstreams_deinit(); + + return 0; +} + +//END + From 96fedb5cb0916305de0ea045bbe41df490d8de26 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sat, 23 Jul 2011 19:33:49 +0300 Subject: [PATCH 13/25] removed -delta namings --- CMakeLists.txt | 2 +- src/CMakeLists.txt | 3 ++- src/guiPauseMenu.cpp | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index aae390f38..b4a5bb02e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -5,7 +5,7 @@ if(${CMAKE_VERSION} STREQUAL "2.8.2") endif(${CMAKE_VERSION} STREQUAL "2.8.2") # This can be read from ${PROJECT_NAME} after project() is called -project(minetest-delta) +project(minetest) set(VERSION_MAJOR 0) set(VERSION_MINOR 2) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c93762cab..8ce69b2ad 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,6 +1,7 @@ -project(minetest-delta) cmake_minimum_required( VERSION 2.6 ) +project(minetest) + if(RUN_IN_PLACE) add_definitions ( -DRUN_IN_PLACE ) endif(RUN_IN_PLACE) diff --git a/src/guiPauseMenu.cpp b/src/guiPauseMenu.cpp index 61485518c..c10bcf039 100644 --- a/src/guiPauseMenu.cpp +++ b/src/guiPauseMenu.cpp @@ -172,7 +172,7 @@ void GUIPauseMenu::regenerateGui(v2u32 screensize) );*/ std::ostringstream os; - os<<"Minetest-delta\n"; + os<<"Minetest-c55\n"; os<<"by Perttu Ahola and contributors\n"; os<<"celeron55@gmail.com\n"; os< Date: Sat, 23 Jul 2011 20:22:04 +0300 Subject: [PATCH 14/25] Made hotbar a bit smaller --- src/game.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/game.cpp b/src/game.cpp index b26d48967..b3069d6f9 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -1038,9 +1038,9 @@ void the_game( //bool screensize_changed = screensize != last_screensize; // Resize hotbar - if(screensize.Y <= 600) + if(screensize.Y <= 800) hotbar_imagesize = 32; - else if(screensize.Y <= 1024) + else if(screensize.Y <= 1280) hotbar_imagesize = 48; else hotbar_imagesize = 64; From 26582e0e664f313fbf7cb963a986e32fc4b23d60 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sat, 23 Jul 2011 20:22:22 +0300 Subject: [PATCH 15/25] Fixed #21 Earth under torches oscillates between mud and grass --- src/environment.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/environment.cpp b/src/environment.cpp index f5e4b071a..d72369620 100644 --- a/src/environment.cpp +++ b/src/environment.cpp @@ -863,7 +863,7 @@ void ServerEnvironment::step(float dtime) { if(myrand()%20 == 0) { - MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0)); + MapNode n_top = m_map->getNodeNoEx(p+v3s16(0,1,0)); if(content_features(n_top).air_equivalent && n_top.getLightBlend(getDayNightRatio()) >= 13) { @@ -879,9 +879,8 @@ void ServerEnvironment::step(float dtime) { //if(myrand()%20 == 0) { - MapNode n_top = block->getNodeNoEx(p0+v3s16(0,1,0)); - if(n_top.getContent() != CONTENT_AIR - && n_top.getContent() != CONTENT_IGNORE) + MapNode n_top = m_map->getNodeNoEx(p+v3s16(0,1,0)); + if(content_features(n_top).air_equivalent == false) { n.setContent(CONTENT_MUD); m_map->addNodeWithEvent(p, n); From 68a9157b947f9d282384164d678dceb6d1fec9ec Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sat, 23 Jul 2011 20:28:05 +0300 Subject: [PATCH 16/25] Fixed issue #15: Glass blocks a lot of light --- src/content_mapnode.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/content_mapnode.cpp b/src/content_mapnode.cpp index 146b806ef..db036ebd9 100644 --- a/src/content_mapnode.cpp +++ b/src/content_mapnode.cpp @@ -272,6 +272,7 @@ void content_mapnode_init() i = CONTENT_GLASS; f = &content_features(i); f->light_propagates = true; + f->sunlight_propagates = true; f->param_type = CPT_LIGHT; f->is_ground_content = true; f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; From 73cf4b30165290dd4de229897d6720522ffa54fc Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sun, 24 Jul 2011 00:49:45 +0300 Subject: [PATCH 17/25] made shadows less blue --- src/mapblock_mesh.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/mapblock_mesh.cpp b/src/mapblock_mesh.cpp index 465170c2d..c625983b0 100644 --- a/src/mapblock_mesh.cpp +++ b/src/mapblock_mesh.cpp @@ -151,7 +151,7 @@ video::SColor MapBlock_LightColor(u8 alpha, u8 light) #if 1 // Emphase blue a bit in darker places float lim = 80; - float power = 0.7; + float power = 0.8; if(light > lim) return video::SColor(alpha,light,light,light); else From 8250d520cebb8768f77fce202f8223c18cddeed7 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sun, 24 Jul 2011 01:51:27 +0300 Subject: [PATCH 18/25] who put pnoise.py in my /? --- pnoise.py | 102 ------------------------------------------------------ 1 file changed, 102 deletions(-) delete mode 100644 pnoise.py diff --git a/pnoise.py b/pnoise.py deleted file mode 100644 index fcab5ac15..000000000 --- a/pnoise.py +++ /dev/null @@ -1,102 +0,0 @@ -# -# A python perlin noise implementation, from -# http://www.fundza.com/c4serious/noise/perlin/perlin.html -# -# This is used for testing how to create maps with a python script. -# - -import math -p = ( -151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103, -30,69,142,8,99,37,240,21,10,23,190,6,148,247,120,234,75,0,26,197, -62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87,174,20, -125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231, -83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,102, -143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,89,18,169,200, -196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226, -250,124,123,5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16, -58,17,182,189,28,42,223,183,170,213,119,248,152,2,44,154,163,70, -221,153,101,155,167,43,172,9,129,22,39,253,19,98,108,110,79,113, -224,232,178,185,112,104,218,246,97,228,251,34,242,193,238,210,144, -12,191,179,162,241,81,51,145,235,249,14,239,107,49,192,214,31,181, -199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236, -205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180, -151,160,137,91,90,15,131,13,201,95,96,53,194,233,7,225,140,36,103, -30,69,142,8,99,37,240,21,10,23,190,6,148,247,120,234,75,0,26,197, -62,94,252,219,203,117,35,11,32,57,177,33,88,237,149,56,87,174,20, -125,136,171,168,68,175,74,165,71,134,139,48,27,166,77,146,158,231, -83,111,229,122,60,211,133,230,220,105,92,41,55,46,245,40,244,102, -143,54,65,25,63,161,1,216,80,73,209,76,132,187,208,89,18,169,200, -196,135,130,116,188,159,86,164,100,109,198,173,186,3,64,52,217,226, -250,124,123,5,202,38,147,118,126,255,82,85,212,207,206,59,227,47,16, -58,17,182,189,28,42,223,183,170,213,119,248,152,2,44,154,163,70, -221,153,101,155,167,43,172,9,129,22,39,253,19,98,108,110,79,113, -224,232,178,185,112,104,218,246,97,228,251,34,242,193,238,210,144, -12,191,179,162,241,81,51,145,235,249,14,239,107,49,192,214,31,181, -199,106,157,184,84,204,176,115,121,50,45,127,4,150,254,138,236, -205,93,222,114,67,29,24,72,243,141,128,195,78,66,215,61,156,180) - -def lerp(t, a, b): - return a + t * (b - a) - -def fade(t): - return t * t * t * (t * (t * 6 - 15) + 10) - -def grad(hash, x, y, z): - h = hash & 15 - if h < 8: - u = x - else: - u = y - if h < 4: - v = y - elif h == 12 or h == 14: - v = x - else: - v = z - if h & 1 != 0: - u = -u - if h & 2 != 0: - v = -v - return u + v - -def pnoise(x, y, z): - global p - X = int(math.floor(x)) & 255 - Y = int(math.floor(y)) & 255 - Z = int(math.floor(z)) & 255 - x -= math.floor(x) - y -= math.floor(y) - z -= math.floor(z) - - u = fade(x) - v = fade(y) - w = fade(z) - - A = p[X] + Y - AA = p[A] + Z - AB = p[A + 1] + Z - B = p[X + 1] + Y - BA = p[B] + Z - BB = p[B + 1] + Z - - pAA = p[AA] - pAB = p[AB] - pBA = p[BA] - pBB = p[BB] - pAA1 = p[AA + 1] - pBA1 = p[BA + 1] - pAB1 = p[AB + 1] - pBB1 = p[BB + 1] - - gradAA = grad(pAA, x, y, z) - gradBA = grad(pBA, x-1, y, z) - gradAB = grad(pAB, x, y-1, z) - gradBB = grad(pBB, x-1, y-1, z) - gradAA1 = grad(pAA1,x, y, z-1) - gradBA1 = grad(pBA1,x-1, y, z-1) - gradAB1 = grad(pAB1,x, y-1, z-1) - gradBB1 = grad(pBB1,x-1, y-1, z-1) - return lerp(w, - lerp(v, lerp(u, gradAA, gradBA), lerp(u, gradAB, gradBB)), - lerp(v, lerp(u, gradAA1,gradBA1),lerp(u, gradAB1,gradBB1))) From 8d84086f35b714906be013d536c42cf9c3dd4828 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sun, 24 Jul 2011 10:12:08 +0300 Subject: [PATCH 19/25] removed unnecessary verbosity from debug output of tile.cpp --- src/tile.cpp | 103 +++++++++++++++++++++++++++------------------------ 1 file changed, 54 insertions(+), 49 deletions(-) diff --git a/src/tile.cpp b/src/tile.cpp index 23fa1129d..27f86c732 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -179,7 +179,7 @@ void TextureSource::processQueue() dstream<<"INFO: TextureSource::processQueue(): " <<"got texture request with " - <<"name="< @@ -194,7 +194,7 @@ void TextureSource::processQueue() u32 TextureSource::getTextureId(const std::string &name) { - //dstream<<"INFO: getTextureId(): name="< result_queue; @@ -226,8 +226,8 @@ u32 TextureSource::getTextureId(const std::string &name) // Throw a request in m_get_texture_queue.add(name, 0, 0, &result_queue); - dstream<<"INFO: Waiting for texture from main thread, name=" - <getValue(); } } - dstream<<"INFO: getTextureIdDirect(): name="<getVideoDriver(); assert(driver); @@ -708,8 +712,9 @@ video::IImage* generate_image_from_scratch(std::string name, { // Construct base name base_image_name = name.substr(0, last_separator_position); - dstream<<"INFO: generate_image_from_scratch(): Calling itself recursively" - " to get base image, name="<createImageFromFile(path.c_str()); if(image == NULL) { - dstream<<"WARNING: Could not load image \""< dim(2,2); @@ -782,7 +787,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg, // If base image is NULL, load as base. if(baseimg == NULL) { - dstream<<"INFO: Setting "< dim = image->getDimension(); //core::dimension2d dim(16,16); @@ -817,7 +822,7 @@ bool generate_image(std::string part_of_name, video::IImage *& baseimg, { // A special texture modification - dstream<<"INFO: getTextureIdDirect(): generating special " + dstream<<"INFO: generate_image(): generating special " <<"modification \""<createImageFromFile(path.c_str()); if(image == NULL) { - dstream<<"WARNING: getTextureIdDirect(): Loading path \"" + dstream<<"WARNING: generate_image(): Loading path \"" <queryFeature(video::EVDF_RENDER_TO_TARGET) == false) { - dstream<<"WARNING: getTextureIdDirect(): EVDF_RENDER_TO_TARGET" + dstream<<"WARNING: generate_image(): EVDF_RENDER_TO_TARGET" " not supported. Creating fallback image"< Date: Sun, 24 Jul 2011 11:40:14 +0300 Subject: [PATCH 20/25] changed jungletree/junglegrass content ids to extended range --- src/content_mapnode.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/content_mapnode.h b/src/content_mapnode.h index 51cf06496..5fdbf45f3 100644 --- a/src/content_mapnode.h +++ b/src/content_mapnode.h @@ -44,8 +44,6 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version); #define CONTENT_FURNACE 16 #define CONTENT_FENCE 21 #define CONTENT_RAIL 30 -#define CONTENT_JUNGLETREE 31 -#define CONTENT_JUNGLEGRASS 32 // 0x800...0xfff (2048...4095): higher 4 bytes of param2 are not usable #define CONTENT_GRASS 0x800 //1 @@ -70,6 +68,8 @@ MapNode mapnode_translate_to_internal(MapNode n_from, u8 version); #define CONTENT_CLAY 0x812 //27 #define CONTENT_PAPYRUS 0x813 //28 #define CONTENT_BOOKSHELF 0x814 //29 +#define CONTENT_JUNGLETREE 0x815 +#define CONTENT_JUNGLEGRASS 0x816 #endif From 29d905f98a8ce7db9ae78a572b51d479f04fb48d Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sun, 24 Jul 2011 12:09:33 +0300 Subject: [PATCH 21/25] Added a mapblock analyzing function for debugging use and fixed remaining mapgen bugs --- src/main.cpp | 6 +++ src/map.cpp | 21 +++++++- src/mapblock.cpp | 123 +++++++++++++++++++++++++++++++++++++++++++++++ src/mapblock.h | 5 ++ src/server.cpp | 43 ++++++++++------- 5 files changed, 179 insertions(+), 19 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 3bc7ca5f6..09c299004 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -72,6 +72,12 @@ Other things to note: variable and fix them (result of getContent() must be stored in content_t, which is 16-bit) +NOTE: Seeds in 1260:6c77e7dbfd29: +5721858502589302589: + Spawns you on a small sand island with a surface dungeon +2983455799928051958: + Enormous jungle + a surface dungeon at ~(250,0,0) + Old, wild and random suggestions that probably won't be done: ------------------------------------------------------------- diff --git a/src/map.cpp b/src/map.cpp index f0ea2f6f1..b205d9918 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -2264,7 +2264,26 @@ MapBlock* ServerMap::finishBlockMake(mapgen::BlockMakeData *data, /*dstream<<"finishBlockMake() done for ("<getPos()+v3s16(x,y,z); + MapBlock *block = getBlockNoCreateNoEx(p); + char spos[20]; + snprintf(spos, 20, "(%2d,%2d,%2d)", x, y, z); + dstream<<"Generated "<getPos(); + char spos[20]; + snprintf(spos, 20, "(%2d,%2d,%2d), ", p.X, p.Y, p.Z); + desc<getModified()) + { + case MOD_STATE_CLEAN: + desc<<"CLEAN, "; + break; + case MOD_STATE_WRITE_AT_UNLOAD: + desc<<"WRITE_AT_UNLOAD, "; + break; + case MOD_STATE_WRITE_NEEDED: + desc<<"WRITE_NEEDED, "; + break; + default: + desc<<"unknown getModified()="+itos(block->getModified())+", "; + } + + if(block->isGenerated()) + desc<<"is_gen [X], "; + else + desc<<"is_gen [ ], "; + + if(block->getIsUnderground()) + desc<<"is_ug [X], "; + else + desc<<"is_ug [ ], "; + + if(block->getMeshExpired()) + desc<<"mesh_exp [X], "; + else + desc<<"mesh_exp [ ], "; + + if(block->getLightingExpired()) + desc<<"lighting_exp [X], "; + else + desc<<"lighting_exp [ ], "; + + if(block->isDummy()) + { + desc<<"Dummy, "; + } + else + { + // We'll just define the numbers here, don't want to include + // content_mapnode.h + const content_t content_water = 2; + const content_t content_watersource = 9; + const content_t content_tree = 0x801; + const content_t content_leaves = 0x802; + const content_t content_jungletree = 0x815; + + bool full_ignore = true; + bool some_ignore = false; + bool full_air = true; + bool some_air = false; + bool trees = false; + bool water = false; + for(s16 z0=0; z0getNode(p); + content_t c = n.getContent(); + if(c == CONTENT_IGNORE) + some_ignore = true; + else + full_ignore = false; + if(c == CONTENT_AIR) + some_air = true; + else + full_air = false; + if(c == content_tree || c == content_jungletree + || c == content_leaves) + trees = true; + if(c == content_water + || c == content_watersource) + water = true; + } + + desc<<"content {"; + + std::ostringstream ss; + + if(full_ignore) + ss<<"IGNORE (full), "; + else if(some_ignore) + ss<<"IGNORE, "; + + if(full_air) + ss<<"AIR (full), "; + else if(some_air) + ss<<"AIR, "; + + if(trees) + ss<<"trees, "; + if(water) + ss<<"water, "; + + if(ss.str().size()>=2) + desc<::Iterator i; @@ -166,14 +166,15 @@ void * EmergeThread::Thread() // Check flags u8 flags = i.getNode()->getValue(); if((flags & BLOCK_EMERGE_FLAG_FROMDISK) == false) - optional = false; + only_from_disk = false; } } - - /*dstream<<"EmergeThread: p=" - <<"("<isGenerated() == false) + { + if(enable_mapgen_debug_info) + dstream<<"EmergeThread: generating"< Date: Sun, 24 Jul 2011 12:12:55 +0300 Subject: [PATCH 22/25] removed a remaining debug print --- src/map.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/map.cpp b/src/map.cpp index b205d9918..07ad08dcb 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -2012,8 +2012,9 @@ ServerMap::~ServerMap() void ServerMap::initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos) { - dstream<<"initBlockMake(): ("< Date: Sun, 24 Jul 2011 12:13:51 +0300 Subject: [PATCH 23/25] and now fixed a bug in removing that debug output --- src/map.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/map.cpp b/src/map.cpp index 07ad08dcb..830627066 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -2012,6 +2012,7 @@ ServerMap::~ServerMap() void ServerMap::initBlockMake(mapgen::BlockMakeData *data, v3s16 blockpos) { + bool enable_mapgen_debug_info = g_settings.getBool("enable_mapgen_debug_info"); if(enable_mapgen_debug_info) dstream<<"initBlockMake(): ("< Date: Sun, 24 Jul 2011 12:45:52 +0300 Subject: [PATCH 24/25] Updated the texture atlas a bit --- src/tile.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/tile.cpp b/src/tile.cpp index 27f86c732..9f6a6eb72 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -518,13 +518,11 @@ void TextureSource::buildMainAtlas() sourcelist.push_back("cobble.png"); sourcelist.push_back("mossycobble.png"); sourcelist.push_back("gravel.png"); + sourcelist.push_back("cactus.png"); + sourcelist.push_back("jungletree.png"); sourcelist.push_back("stone.png^mineral_coal.png"); sourcelist.push_back("stone.png^mineral_iron.png"); - sourcelist.push_back("mud.png^mineral_coal.png"); - sourcelist.push_back("mud.png^mineral_iron.png"); - sourcelist.push_back("sand.png^mineral_coal.png"); - sourcelist.push_back("sand.png^mineral_iron.png"); // Padding to disallow texture bleeding s32 padding = 16; From dbea511a6f877450cfd5adb86efa55a8f00cc9a1 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Sun, 24 Jul 2011 12:49:47 +0300 Subject: [PATCH 25/25] Lowered default viewing range minimum to such that it allows fairly good framerate in jungles with sucky hardware. Almost all computers stick to the minimum with the current farmesh range that someone has set up without asking from me, but farmesh is not used as default anyway so those that use it can raise the lower limit in their configuration as they wish. --- src/defaultsettings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/defaultsettings.cpp b/src/defaultsettings.cpp index cbc78ad3f..8326a0f0d 100644 --- a/src/defaultsettings.cpp +++ b/src/defaultsettings.cpp @@ -51,7 +51,7 @@ void set_default_settings() g_settings.setDefault("wanted_fps", "30"); g_settings.setDefault("fps_max", "60"); g_settings.setDefault("viewing_range_nodes_max", "300"); - g_settings.setDefault("viewing_range_nodes_min", "25"); + g_settings.setDefault("viewing_range_nodes_min", "15"); g_settings.setDefault("screenW", "800"); g_settings.setDefault("screenH", "600"); g_settings.setDefault("address", "");