diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/inventory.cpp | 45 | ||||
-rw-r--r-- | src/inventory.h | 28 | ||||
-rw-r--r-- | src/map.cpp | 98 | ||||
-rw-r--r-- | src/mapnode.cpp | 23 | ||||
-rw-r--r-- | src/mapnode.h | 2 | ||||
-rw-r--r-- | src/materials.cpp | 80 | ||||
-rw-r--r-- | src/nodemetadata.cpp | 19 | ||||
-rw-r--r-- | src/nodemetadata.h | 3 | ||||
-rw-r--r-- | src/server.cpp | 220 |
9 files changed, 419 insertions, 99 deletions
diff --git a/src/inventory.cpp b/src/inventory.cpp index ccd55a79f..f9b9107a0 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -94,12 +94,51 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is) MaterialItem */ +bool MaterialItem::isCookable() +{ + if(m_content == CONTENT_TREE) + { + return true; + } + else if(m_content == CONTENT_COBBLE) + { + return true; + } + return false; +} + InventoryItem *MaterialItem::createCookResult() { if(m_content == CONTENT_TREE) { return new CraftItem("lump_of_coal", 1); } + else if(m_content == CONTENT_COBBLE) + { + return new MaterialItem(CONTENT_STONE, 1); + } + return NULL; +} + +/* + CraftItem +*/ + +bool CraftItem::isCookable() +{ + if(m_subname == "lump_of_iron") + { + return true; + } + return false; +} + +InventoryItem *CraftItem::createCookResult() +{ + if(m_subname == "lump_of_iron") + { + return new CraftItem("steel_ingot", 1); + } return NULL; } @@ -357,6 +396,9 @@ void InventoryList::deleteItem(u32 i) InventoryItem * InventoryList::addItem(InventoryItem *newitem) { + if(newitem == NULL) + return NULL; + /* First try to find if it could be added to some existing items */ @@ -391,6 +433,9 @@ InventoryItem * InventoryList::addItem(InventoryItem *newitem) InventoryItem * InventoryList::addItem(u32 i, InventoryItem *newitem) { + if(newitem == NULL) + return NULL; + // If it is an empty position, it's an easy job. InventoryItem *to_item = m_items[i]; if(to_item == NULL) diff --git a/src/inventory.h b/src/inventory.h index d110f92c0..761e664a9 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -91,6 +91,8 @@ public: /* Other properties */ + // Whether it can be cooked + virtual bool isCookable(){return false;} // Time of cooking virtual float getCookTime(){return 3.0;} // Result of cooking @@ -160,6 +162,7 @@ public: /* Other properties */ + bool isCookable(); InventoryItem *createCookResult(); /* Special methods @@ -272,6 +275,8 @@ public: name = "lump_of_coal.png"; else if(m_subname == "lump_of_iron") name = "lump_of_iron.png"; + else if(m_subname == "steel_ingot") + name = "steel_ingot.png"; else name = "cloud.png"; @@ -302,6 +307,11 @@ public: return QUANTITY_ITEM_MAX_COUNT - m_count; } /* + Other properties + */ + bool isCookable(); + InventoryItem *createCookResult(); + /* Special methods */ std::string getSubName() @@ -348,11 +358,25 @@ public: std::string basename; if(m_toolname == "WPick") - basename = "tool_wpick.png"; + basename = "tool_woodpick.png"; else if(m_toolname == "STPick") - basename = "tool_stpick.png"; + basename = "tool_stonepick.png"; + else if(m_toolname == "SteelPick") + basename = "tool_steelpick.png"; else if(m_toolname == "MesePick") basename = "tool_mesepick.png"; + else if(m_toolname == "WShovel") + basename = "tool_woodshovel.png"; + else if(m_toolname == "STShovel") + basename = "tool_stoneshovel.png"; + else if(m_toolname == "SteelShovel") + basename = "tool_steelshovel.png"; + else if(m_toolname == "WAxe") + basename = "tool_woodaxe.png"; + else if(m_toolname == "STAxe") + basename = "tool_stoneaxe.png"; + else if(m_toolname == "SteelAxe") + basename = "tool_steelaxe.png"; else basename = "cloud.png"; diff --git a/src/map.cpp b/src/map.cpp index 40274ae29..49ed2f5fe 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -2252,7 +2252,7 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos, TimeTaker timer_generate("generateChunkRaw() generate"); // Maximum height of the stone surface and obstacles. - // This is used to disable dungeon generation from going too high. + // This is used to disable cave generation from going too high. s16 stone_surface_max_y = 0; /* @@ -2320,12 +2320,12 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos, Randomize some parameters */ - s32 stone_obstacle_count = 0; + //s32 stone_obstacle_count = 0; /*s32 stone_obstacle_count = rangelim((1.0+noise2d(m_seed+897, sectorpos_base.X, sectorpos_base.Y))/2.0 * 30, 0, 100000);*/ - s16 stone_obstacle_max_height = 0; + //s16 stone_obstacle_max_height = 0; /*s16 stone_obstacle_max_height = rangelim((1.0+noise2d(m_seed+5902, sectorpos_base.X, sectorpos_base.Y))/2.0 * 30, 0, 100000);*/ @@ -2336,7 +2336,11 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos, //for(u32 i_age=0; i_age<1; i_age++) for(u32 i_age=0; i_age<2; i_age++) { // Aging loop + /****************************** + BEGINNING OF AGING LOOP + ******************************/ +#if 0 { // 8ms @cs=8 //TimeTaker timer1("stone obstacles"); @@ -2461,26 +2465,30 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos, } }//timer1 +#endif + { // 24ms @cs=8 - //TimeTaker timer1("dungeons"); + //TimeTaker timer1("caves"); /* - Make dungeons + Make caves */ - u32 dungeons_count = relative_volume / 600000; + u32 caves_count = relative_volume / 400000; u32 bruises_count = relative_volume * stone_surface_max_y / 40000000; if(stone_surface_max_y < WATER_LEVEL) bruises_count = 0; - /*u32 dungeons_count = 0; + /*u32 caves_count = 0; u32 bruises_count = 0;*/ - for(u32 jj=0; jj<dungeons_count+bruises_count; jj++) + for(u32 jj=0; jj<caves_count+bruises_count; jj++) { - s16 min_tunnel_diameter = 2; - s16 max_tunnel_diameter = 6; - u16 tunnel_routepoints = 25; + s16 min_tunnel_diameter = 3; + s16 max_tunnel_diameter = 5; + u16 tunnel_routepoints = 20; - bool bruise_surface = (jj < bruises_count); + v3f main_direction(0,0,0); + + bool bruise_surface = (jj > caves_count); if(bruise_surface) { @@ -2494,6 +2502,9 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos, tunnel_routepoints = 5; } + else + { + } // Allowed route area size in nodes v3s16 ar( @@ -2521,7 +2532,7 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos, // Allow half a diameter + 7 over stone surface s16 route_y_max = -of.Y + stone_surface_max_y + max_tunnel_diameter/2 + 7; - /*// If dungeons, don't go through surface too often + /*// If caves, don't go through surface too often if(bruise_surface == false) route_y_max -= myrand_range(0, max_tunnel_diameter*2);*/ @@ -2546,16 +2557,16 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos, s16 route_start_y_min = route_y_min; s16 route_start_y_max = route_y_max; - // Start every 2nd dungeon from surface + // Start every 2nd cave from surface bool coming_from_surface = (jj % 2 == 0 && bruise_surface == false); if(coming_from_surface) { - route_start_y_min = -of.Y + stone_surface_max_y + 5; + route_start_y_min = -of.Y + stone_surface_max_y + 10; } route_start_y_min = rangelim(route_start_y_min, 0, ar.Y-1); - route_start_y_max = rangelim(route_start_y_max, 0, ar.Y-1); + route_start_y_max = rangelim(route_start_y_max, route_start_y_min, ar.Y-1); // Randomize starting position v3f orp( @@ -2572,6 +2583,16 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos, for(u16 j=0; j<tunnel_routepoints; j++) { + if(j%7==0 && bruise_surface == false) + { + main_direction = v3f( + ((float)(myrand()%20)-(float)10)/10, + ((float)(myrand()%20)-(float)10)/30, + ((float)(myrand()%20)-(float)10)/10 + ); + main_direction *= (float)myrand_range(1, 3); + } + // Randomize size s16 min_d = min_tunnel_diameter; s16 max_d = max_tunnel_diameter; @@ -2584,7 +2605,7 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos, } else { - maxlen = v3s16(15, myrand_range(1, 20), 15); + maxlen = v3s16(rs*4, myrand_range(1, rs*3), rs*4); } v3f vec; @@ -2605,6 +2626,8 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos, (float)(myrand()%(maxlen.Z*2))-(float)maxlen.Z ); } + + vec += main_direction; v3f rp = orp + vec; if(rp.X < 0) @@ -3095,7 +3118,7 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos, break; } - // Make water only not in dungeons + // Make water only not in caves if(!(vmanip.m_flags[i]&VMANIP_FLAG_DUNGEON)) { n->d = CONTENT_WATERSOURCE; @@ -3119,6 +3142,9 @@ MapChunk* ServerMap::generateChunkRaw(v2s16 chunkpos, }//timer1 } // Aging loop + /*********************** + END OF AGING LOOP + ************************/ { //TimeTaker timer1("convert mud to sand"); @@ -3953,7 +3979,7 @@ MapBlock * ServerMap::generateBlock( else n.d = CONTENT_AIR; } - // Else it's ground or dungeons (air) + // Else it's ground or caves (air) else { // If it's surface_depth under ground, it's stone @@ -4034,7 +4060,7 @@ MapBlock * ServerMap::generateBlock( //dstream<<"generateBlock(): Done"<<std::endl; /* - Generate dungeons + Generate caves */ // Initialize temporary table @@ -4172,36 +4198,36 @@ MapBlock * ServerMap::generateBlock( continue_generating: /* - Choose whether to actually generate dungeon + Choose whether to actually generate cave */ - bool do_generate_dungeons = true; + bool do_generate_caves = true; // Don't generate if no part is underground if(!some_part_underground) { - do_generate_dungeons = false; + do_generate_caves = false; } // Don't generate if mostly underwater surface /*else if(mostly_underwater_surface) { - do_generate_dungeons = false; + do_generate_caves = false; }*/ // Partly underground = cave else if(!completely_underground) { - do_generate_dungeons = (rand() % 100 <= (s32)(caves_amount*100)); + do_generate_caves = (rand() % 100 <= (s32)(caves_amount*100)); } - // Found existing dungeon underground + // Found existing cave underground else if(found_existing && completely_underground) { - do_generate_dungeons = (rand() % 100 <= (s32)(caves_amount*100)); + do_generate_caves = (rand() % 100 <= (s32)(caves_amount*100)); } - // Underground and no dungeons found + // Underground and no caves found else { - do_generate_dungeons = (rand() % 300 <= (s32)(caves_amount*100)); + do_generate_caves = (rand() % 300 <= (s32)(caves_amount*100)); } - if(do_generate_dungeons) + if(do_generate_caves) { /* Generate some tunnel starting from orp and ors @@ -4253,7 +4279,7 @@ continue_generating: // Set to true if has caves. // Set when some non-air is changed to air when making caves. - bool has_dungeons = false; + bool has_caves = false; /* Apply temporary cave data to block @@ -4266,7 +4292,7 @@ continue_generating: { MapNode n = block->getNode(v3s16(x0,y0,z0)); - // Create dungeons + // Create caves if(underground_emptiness[ ued*ued*(z0*ued/MAP_BLOCKSIZE) +ued*(y0*ued/MAP_BLOCKSIZE) @@ -4275,7 +4301,7 @@ continue_generating: if(content_features(n.d).walkable/*is_ground_content(n.d)*/) { // Has now caves - has_dungeons = true; + has_caves = true; // Set air to node n.d = CONTENT_AIR; } @@ -4295,7 +4321,7 @@ continue_generating: Force lighting update if some part of block is partly underground and has caves. */ - /*if(some_part_underground && !completely_underground && has_dungeons) + /*if(some_part_underground && !completely_underground && has_caves) { //dstream<<"Half-ground caves"<<std::endl; lighting_invalidated_blocks[block->getPos()] = block; @@ -4440,11 +4466,11 @@ continue_generating: */ dstream <<"lighting_invalidated_blocks.size()" - <<", has_dungeons" + <<", has_caves" <<", completely_ug" <<", some_part_ug" <<" "<<lighting_invalidated_blocks.size() - <<", "<<has_dungeons + <<", "<<has_caves <<", "<<completely_underground <<", "<<some_part_underground <<std::endl; diff --git a/src/mapnode.cpp b/src/mapnode.cpp index 187689c6f..81408205f 100644 --- a/src/mapnode.cpp +++ b/src/mapnode.cpp @@ -141,7 +141,7 @@ void init_mapnode() f->setInventoryTextureCube("stone.png", "stone.png", "stone.png"); f->param_type = CPT_MINERAL; f->is_ground_content = true; - f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + f->dug_item = std::string("MaterialItem ")+itos(CONTENT_COBBLE)+" 1"; i = CONTENT_GRASS; f = &g_content_features[i]; @@ -284,6 +284,7 @@ void init_mapnode() f->setInventoryTexture("torch_on_floor.png"); f->param_type = CPT_LIGHT; f->light_propagates = true; + f->sunlight_propagates = true; f->solidness = 0; // drawn separately, makes no faces f->walkable = false; f->wall_mounted = true; @@ -321,10 +322,28 @@ void init_mapnode() f->setAllTextures("furnace_side.png"); f->setTexture(5, "furnace_front.png"); // Z- f->setInventoryTexture("furnace_front.png"); - f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + //f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + f->dug_item = std::string("MaterialItem ")+itos(CONTENT_COBBLE)+" 6"; if(f->initial_metadata == NULL) f->initial_metadata = new FurnaceNodeMetadata(); + i = CONTENT_COBBLE; + f = &g_content_features[i]; + f->setAllTextures("cobble.png"); + f->setInventoryTextureCube("cobble.png", "cobble.png", "cobble.png"); + f->param_type = CPT_NONE; + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + + i = CONTENT_STEEL; + f = &g_content_features[i]; + f->setAllTextures("steel_block.png"); + f->setInventoryTextureCube("steel_block.png", "steel_block.png", + "steel_block.png"); + f->param_type = CPT_NONE; + f->is_ground_content = true; + f->dug_item = std::string("MaterialItem ")+itos(i)+" 1"; + } v3s16 facedir_rotate(u8 facedir, v3s16 dir) diff --git a/src/mapnode.h b/src/mapnode.h index 04234830d..f359ecbbb 100644 --- a/src/mapnode.h +++ b/src/mapnode.h @@ -98,6 +98,8 @@ void init_content_inventory_texture_paths(); #define CONTENT_CHEST 15 #define CONTENT_FURNACE 16 //#define CONTENT_WORKBENCH 17 +#define CONTENT_COBBLE 18 +#define CONTENT_STEEL 19 /* Content feature list diff --git a/src/materials.cpp b/src/materials.cpp index 2e85950ec..2e33abeba 100644 --- a/src/materials.cpp +++ b/src/materials.cpp @@ -15,12 +15,40 @@ void setStoneLikeDiggingProperties(u8 material, float toughness) g_material_properties[material].setDiggingProperties("WPick", DiggingProperties(true, 1.3*toughness, 65535./30.*toughness)); g_material_properties[material].setDiggingProperties("STPick", - DiggingProperties(true, 0.65*toughness, 65535./100.*toughness)); + DiggingProperties(true, 0.75*toughness, 65535./100.*toughness)); + g_material_properties[material].setDiggingProperties("SteelPick", + DiggingProperties(true, 0.50*toughness, 65535./333.*toughness)); /*g_material_properties[material].setDiggingProperties("MesePick", DiggingProperties(true, 0.0*toughness, 65535./20.*toughness));*/ } +void setDirtLikeDiggingProperties(u8 material, float toughness) +{ + g_material_properties[material].setDiggingProperties("", + DiggingProperties(true, 0.75*toughness, 0)); + + g_material_properties[material].setDiggingProperties("WShovel", + DiggingProperties(true, 0.4*toughness, 65535./50.*toughness)); + g_material_properties[material].setDiggingProperties("STShovel", + DiggingProperties(true, 0.2*toughness, 65535./150.*toughness)); + g_material_properties[material].setDiggingProperties("SteelShovel", + DiggingProperties(true, 0.15*toughness, 65535./400.*toughness)); +} + +void setWoodLikeDiggingProperties(u8 material, float toughness) +{ + g_material_properties[material].setDiggingProperties("", + DiggingProperties(true, 3.0*toughness, 0)); + + g_material_properties[material].setDiggingProperties("WAxe", + DiggingProperties(true, 1.5*toughness, 65535./30.*toughness)); + g_material_properties[material].setDiggingProperties("STAxe", + DiggingProperties(true, 0.75*toughness, 65535./100.*toughness)); + g_material_properties[material].setDiggingProperties("SteelAxe", + DiggingProperties(true, 0.5*toughness, 65535./333.*toughness)); +} + void initializeMaterialProperties() { /* @@ -29,45 +57,29 @@ void initializeMaterialProperties() Add some digging properties to them. */ - - setStoneLikeDiggingProperties(CONTENT_STONE, 1.0); - - g_material_properties[CONTENT_GRASS].setDiggingProperties("", - DiggingProperties(true, 0.4, 0)); - - g_material_properties[CONTENT_TORCH].setDiggingProperties("", - DiggingProperties(true, 0.0, 0)); - - g_material_properties[CONTENT_TREE].setDiggingProperties("", - DiggingProperties(true, 1.5, 0)); - - g_material_properties[CONTENT_LEAVES].setDiggingProperties("", - DiggingProperties(true, 0.35, 0)); - - g_material_properties[CONTENT_GRASS_FOOTSTEPS].setDiggingProperties("", - DiggingProperties(true, 0.5, 0)); + setStoneLikeDiggingProperties(CONTENT_STONE, 1.0); setStoneLikeDiggingProperties(CONTENT_MESE, 0.5); - - g_material_properties[CONTENT_MUD].setDiggingProperties("", - DiggingProperties(true, 0.4, 0)); - setStoneLikeDiggingProperties(CONTENT_COALSTONE, 1.5); - - g_material_properties[CONTENT_WOOD].setDiggingProperties("", - DiggingProperties(true, 1.0, 0)); - - g_material_properties[CONTENT_SAND].setDiggingProperties("", - DiggingProperties(true, 0.4, 0)); - - g_material_properties[CONTENT_CHEST].setDiggingProperties("", - DiggingProperties(true, 1.0, 0)); - - setStoneLikeDiggingProperties(CONTENT_FURNACE, 1.0); + setStoneLikeDiggingProperties(CONTENT_FURNACE, 3.0); + setStoneLikeDiggingProperties(CONTENT_COBBLE, 1.0); + setStoneLikeDiggingProperties(CONTENT_STEEL, 5.0); + + setDirtLikeDiggingProperties(CONTENT_MUD, 1.0); + setDirtLikeDiggingProperties(CONTENT_GRASS, 1.0); + setDirtLikeDiggingProperties(CONTENT_GRASS_FOOTSTEPS, 1.0); + setDirtLikeDiggingProperties(CONTENT_SAND, 1.0); + setWoodLikeDiggingProperties(CONTENT_TREE, 1.0); + setWoodLikeDiggingProperties(CONTENT_LEAVES, 0.15); + setWoodLikeDiggingProperties(CONTENT_WOOD, 0.75); + setWoodLikeDiggingProperties(CONTENT_CHEST, 1.0); + g_material_properties[CONTENT_SIGN_WALL].setDiggingProperties("", + DiggingProperties(true, 0.5, 0)); + g_material_properties[CONTENT_TORCH].setDiggingProperties("", DiggingProperties(true, 0.0, 0)); - + /* Add MesePick to everything */ diff --git a/src/nodemetadata.cpp b/src/nodemetadata.cpp index 21b4ed01d..8b21856de 100644 --- a/src/nodemetadata.cpp +++ b/src/nodemetadata.cpp @@ -165,6 +165,18 @@ std::string ChestNodeMetadata::infoText() { return "Chest"; } +bool ChestNodeMetadata::nodeRemovalDisabled() +{ + /* + Disable removal if chest contains something + */ + InventoryList *list = m_inventory->getList("0"); + if(list == NULL) + return true; + if(list->getUsedSlots() == 0) + return true; + return false; +} /* FurnaceNodeMetadata @@ -266,7 +278,7 @@ bool FurnaceNodeMetadata::step(float dtime) // Start only if there are free slots in dst, so that it can // accomodate any result item - if(dst_list->getFreeSlots() > 0) + if(dst_list->getFreeSlots() > 0 && src_item && src_item->isCookable()) { m_src_totaltime = 3; } @@ -281,11 +293,12 @@ bool FurnaceNodeMetadata::step(float dtime) //dstream<<"Furnace is active"<<std::endl; m_fuel_time += dtime; m_src_time += dtime; - if(m_src_time >= m_src_totaltime && m_src_totaltime > 0.001) + if(m_src_time >= m_src_totaltime && m_src_totaltime > 0.001 + && src_item) { - src_list->decrementMaterials(1); InventoryItem *cookresult = src_item->createCookResult(); dst_list->addItem(cookresult); + src_list->decrementMaterials(1); m_src_time = 0; m_src_totaltime = 0; } diff --git a/src/nodemetadata.h b/src/nodemetadata.h index c38ab1310..e56bff17f 100644 --- a/src/nodemetadata.h +++ b/src/nodemetadata.h @@ -61,6 +61,7 @@ public: virtual void inventoryModified(){} // A step in time. Returns true if metadata changed. virtual bool step(float dtime) {return false;} + virtual bool nodeRemovalDisabled(){return false;} protected: static void registerType(u16 id, Factory f); @@ -100,6 +101,8 @@ public: virtual std::string infoText(); virtual Inventory* getInventory() {return m_inventory;} + virtual bool nodeRemovalDisabled(); + private: Inventory *m_inventory; }; diff --git a/src/server.cpp b/src/server.cpp index c405af3f5..9b3e6e3ec 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2033,31 +2033,40 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) u8 material; u8 mineral = MINERAL_NONE; + bool cannot_remove_node = false; + try { MapNode n = m_env.getMap().getNode(p_under); + // Get mineral + mineral = n.getMineral(); // Get material at position material = n.d; - // If it's not diggable, do nothing - if(content_diggable(material) == false) + // If not yet cancelled + if(cannot_remove_node == false) { - derr_server<<"Server: Not finishing digging: Node not diggable" - <<std::endl; - - // Client probably has wrong data. - // Set block not sent, so that client will get - // a valid one. - dstream<<"Client "<<peer_id<<" tried to dig " - <<"node from invalid position; setting" - <<" MapBlock not sent."<<std::endl; - RemoteClient *client = getClient(peer_id); - v3s16 blockpos = getNodeBlockPos(p_under); - client->SetBlockNotSent(blockpos); - - return; + // If it's not diggable, do nothing + if(content_diggable(material) == false) + { + derr_server<<"Server: Not finishing digging: " + <<"Node not diggable" + <<std::endl; + cannot_remove_node = true; + } + } + // If not yet cancelled + if(cannot_remove_node == false) + { + // Get node metadata + NodeMetadata *meta = m_env.getMap().getNodeMetadata(p_under); + if(meta && meta->nodeRemovalDisabled() == true) + { + derr_server<<"Server: Not finishing digging: " + <<"Node metadata disables removal" + <<std::endl; + cannot_remove_node = true; + } } - // Get mineral - mineral = n.getMineral(); } catch(InvalidPositionException &e) { @@ -2066,6 +2075,27 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) <<std::endl; m_emerge_queue.addBlock(peer_id, getNodeBlockPos(p_over), BLOCK_EMERGE_FLAG_FROMDISK); + cannot_remove_node = true; + } + + /* + If node can't be removed, set block to be re-sent to + client and quit. + */ + if(cannot_remove_node) + { + derr_server<<"Server: Not finishing digging."<<std::endl; + + // Client probably has wrong data. + // Set block not sent, so that client will get + // a valid one. + dstream<<"Client "<<peer_id<<" tried to dig " + <<"node; but node cannot be removed." + <<" setting MapBlock not sent."<<std::endl; + RemoteClient *client = getClient(peer_id); + v3s16 blockpos = getNodeBlockPos(p_under); + client->SetBlockNotSent(blockpos); + return; } @@ -3016,9 +3046,9 @@ void Server::SendInventory(u16 peer_id) if(!found) { ItemSpec specs[9]; - specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_STONE); - specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_STONE); - specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_STONE); + specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); if(checkItemCombination(items, specs)) @@ -3028,6 +3058,22 @@ void Server::SendInventory(u16 peer_id) } } + // Steel pick + if(!found) + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[1] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[2] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + rlist->addItem(new ToolItem("SteelPick", 0)); + found = true; + } + } + // Mese pick if(!found) { @@ -3044,7 +3090,97 @@ void Server::SendInventory(u16 peer_id) } } - // Chest1 + // Wooden showel + if(!found) + { + ItemSpec specs[9]; + specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); + specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + rlist->addItem(new ToolItem("WShovel", 0)); + found = true; + } + } + + // Stone showel + if(!found) + { + ItemSpec specs[9]; + specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_STONE); + specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + rlist->addItem(new ToolItem("STShovel", 0)); + found = true; + } + } + + // Steel showel + if(!found) + { + ItemSpec specs[9]; + specs[1] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + rlist->addItem(new ToolItem("SteelShovel", 0)); + found = true; + } + } + + // Wooden axe + if(!found) + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); + specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); + specs[3] = ItemSpec(ITEM_MATERIAL, CONTENT_WOOD); + specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + rlist->addItem(new ToolItem("WAxe", 0)); + found = true; + } + } + + // Stone axe + if(!found) + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[3] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + rlist->addItem(new ToolItem("STAxe", 0)); + found = true; + } + } + + // Steel axe + if(!found) + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[1] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[3] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[4] = ItemSpec(ITEM_CRAFT, "Stick"); + specs[7] = ItemSpec(ITEM_CRAFT, "Stick"); + if(checkItemCombination(items, specs)) + { + rlist->addItem(new ToolItem("SteelAxe", 0)); + found = true; + } + } + + // Chest if(!found) { ItemSpec specs[9]; @@ -3063,6 +3199,45 @@ void Server::SendInventory(u16 peer_id) } } + // Furnace + if(!found) + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[1] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[2] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[3] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[5] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[6] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[7] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + specs[8] = ItemSpec(ITEM_MATERIAL, CONTENT_COBBLE); + if(checkItemCombination(items, specs)) + { + rlist->addItem(new MaterialItem(CONTENT_FURNACE, 1)); + found = true; + } + } + + // Steel block + if(!found) + { + ItemSpec specs[9]; + specs[0] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[1] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[2] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[3] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[4] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[5] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[6] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[7] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + specs[8] = ItemSpec(ITEM_CRAFT, "steel_ingot"); + if(checkItemCombination(items, specs)) + { + rlist->addItem(new MaterialItem(CONTENT_STEEL, 1)); + found = true; + } + } + } } // if creative_mode == false @@ -3350,6 +3525,7 @@ void setCreativeInventory(Player *player) // CONTENT_IGNORE-terminated list u8 material_items[] = { CONTENT_TORCH, + CONTENT_COBBLE, CONTENT_MUD, CONTENT_STONE, CONTENT_SAND, |