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;
}
InventoryItem * InventoryList::addItem(InventoryItem *newitem)
{
+ if(newitem == NULL)
+ return NULL;
+
/*
First try to find if it could be added to some existing items
*/
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)
/*
Other properties
*/
+ // Whether it can be cooked
+ virtual bool isCookable(){return false;}
// Time of cooking
virtual float getCookTime(){return 3.0;}
// Result of cooking
/*
Other properties
*/
+ bool isCookable();
InventoryItem *createCookResult();
/*
Special methods
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";
return 0;
return QUANTITY_ITEM_MAX_COUNT - m_count;
}
+ /*
+ Other properties
+ */
+ bool isCookable();
+ InventoryItem *createCookResult();
/*
Special methods
*/
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";
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;
/*
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);*/
//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");
}
}//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)
{
tunnel_routepoints = 5;
}
+ else
+ {
+ }
// Allowed route area size in nodes
v3s16 ar(
// 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);*/
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(
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;
}
else
{
- maxlen = v3s16(15, myrand_range(1, 20), 15);
+ maxlen = v3s16(rs*4, myrand_range(1, rs*3), rs*4);
}
v3f vec;
(float)(myrand()%(maxlen.Z*2))-(float)maxlen.Z
);
}
+
+ vec += main_direction;
v3f rp = orp + vec;
if(rp.X < 0)
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;
}//timer1
} // Aging loop
+ /***********************
+ END OF AGING LOOP
+ ************************/
{
//TimeTaker timer1("convert mud to sand");
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
//dstream<<"generateBlock(): Done"<<std::endl;
/*
- Generate dungeons
+ Generate caves
*/
// Initialize temporary table
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
// 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
{
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)
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;
}
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;
*/
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;
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];
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;
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)
#define CONTENT_CHEST 15
#define CONTENT_FURNACE 16
//#define CONTENT_WORKBENCH 17
+#define CONTENT_COBBLE 18
+#define CONTENT_STEEL 19
/*
Content feature list
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()
{
/*
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
*/
{
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
// 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;
}
//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;
}
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);
virtual std::string infoText();
virtual Inventory* getInventory() {return m_inventory;}
+ virtual bool nodeRemovalDisabled();
+
private:
Inventory *m_inventory;
};
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)
{
<<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;
}
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))
}
}
+ // 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)
{
}
}
- // 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];
}
}
+ // 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
// CONTENT_IGNORE-terminated list
u8 material_items[] = {
CONTENT_TORCH,
+ CONTENT_COBBLE,
CONTENT_MUD,
CONTENT_STONE,
CONTENT_SAND,