diff --git a/data/textures/bronze_ingot.png b/data/textures/bronze_ingot.png new file mode 100644 index 0000000..b9531c0 Binary files /dev/null and b/data/textures/bronze_ingot.png differ diff --git a/data/textures/sandstone.png b/data/textures/sandstone.png index bd9cb86..6ad472e 100644 Binary files a/data/textures/sandstone.png and b/data/textures/sandstone.png differ diff --git a/data/textures/sandstone_desert.png b/data/textures/sandstone_desert.png new file mode 100644 index 0000000..f75c9a7 Binary files /dev/null and b/data/textures/sandstone_desert.png differ diff --git a/src/content_burntimes.h b/src/content_burntimes.h index 844a58b..e795cac 100644 --- a/src/content_burntimes.h +++ b/src/content_burntimes.h @@ -27,10 +27,10 @@ /* Burning Time DEFAULT */ /* 1.0 == one item cooked */ -#define BT_BED 30.75 /* 3 wood + 3 cotton */ +#define BT_BED 8.0 /* Beds' heads and feet */ -#define BT_BOOKSHELF 5.0 /* half a wood */ +#define BT_BOOKSHELF 5.0 /* Book shelves */ #define BT_BUSH 0.1 /* 10 for an item */ @@ -42,16 +42,16 @@ #define BT_CAMP_FIRE 1.0 /* 1 item */ /* Camp fire */ -#define BT_CARPET 0.015625 /* 1/16th of a cotton */ +#define BT_CARPET 0.1 /* 1/16th of a cotton */ /* Carpets */ -#define BT_CACTUS 0.1 /* 10 for an item */ +#define BT_CACTUS 0.5 /* 10 for an item */ /* Cactus' trunk */ #define BT_CHAIR 2.5 /* 1/4th of a wood */ /* Wooden chairs */ -#define BT_CLOCK 3.0 /* something less than half a wood */ +#define BT_CLOCK 0.5 /* something less than half a wood */ /* Wall clock */ #define BT_COAL 10.0 /* 10 items */ @@ -60,7 +60,7 @@ #define BT_COAL_BLOCK 99.0 /* 1 stack */ /* Coal and charcoal blocks */ -#define BT_COLUMN 8.0 /* about 1 wood */ +#define BT_COLUMN 1.5 /* about 1 wood */ /* Wooden columns */ #define BT_COUCH 0.75 /* 3 cotton */ @@ -75,25 +75,25 @@ #define BT_DOOR_GLASS 1.50 /* somehow better than wooden door */ /* Glass right and left doors */ -#define BT_FENCE 3.333333 /* about 1/3rd of a wood */ +#define BT_FENCE 1.5 /* about 1/3rd of a wood */ /* Fences, gates, etc. */ -#define BT_FLOWER 0.003906 /* 1/4th of a carpet*/ +#define BT_FLOWER 0.1 /* 1/4th of a carpet*/ /* Blossoms, flowers, etc. */ -#define BT_FRUIT 0.08 /* slightly worse than a cactus */ +#define BT_FRUIT 0.1 /* slightly worse than a cactus */ /* Apples, cactus fruit, etc. */ -#define BT_GRASS 0.003906 /* 1/4th of a carpet*/ +#define BT_GRASS 0.1 /* 1/4th of a carpet*/ /* Wild grass, flower stem, etc.*/ -#define BT_HATCH 0.625 /* 1/16th of a wood */ +#define BT_HATCH 2.0 /* 1/16th of a wood */ /* Hatches, windowed or not */ #define BT_HAY 0.25 /* 4 for an item */ /* Hay */ -#define BT_LADDER 0.15625 /* 1/4th of a hatch */ +#define BT_LADDER 1.0 /* 1/4th of a hatch */ /* Wooden ladders */ #define BT_LAVA 99.0 /* 1 stack */ @@ -102,7 +102,7 @@ #define BT_LAVA_BUCKET 99.0 /* 1 stack */ /* Lava bucket*/ -#define BT_LEAF 0.003906 /* 1/4th of a carpet*/ +#define BT_LEAF 0.1 /* 1/4th of a carpet*/ /* Tree leaves */ #define BT_PAINTING 0.625 /* 1/16th of a wood */ @@ -111,47 +111,47 @@ #define BT_PLANK 0.1 /* 10 for an item */ /* Planks */ -#define BT_SAPLING 0.05 /* 20 for an item */ +#define BT_SAPLING 0.1 /* 20 for an item */ /* Tree saplings */ -#define BT_SCAFFOLDING 3.333333 /* 1/3rd of a wood */ +#define BT_SCAFFOLDING 1.5 /* 1/3rd of a wood */ /* Scaffoldings */ -#define BT_SEED 0.003125 /* 1/4th of a stick */ +#define BT_SEED 0.1 /* 1/4th of a stick */ /* Vegetable's seeds */ #define BT_SIGN 0.625 /* 1/16th of a wood */ /* Wooden signs, lockable or not */ -#define BT_SLAB 5.0 /* half a wood */ +#define BT_SLAB 1.0 /* half a wood */ /* Wooden slabs */ #define BT_SPONGE 0.2 /* 5 for an item */ /* Sponges */ -#define BT_STAIR 5.0 /* half a wood */ +#define BT_STAIR 2.0 /* half a wood */ /* Wooden stairs */ -#define BT_STICK 0.05 /* half a plank or 20 for an item */ +#define BT_STICK 0.1 /* half a plank or 20 for an item */ /* Sticks */ #define BT_TABLE 2.5 /* 1/4th of a wood */ /* Tables */ -#define BT_TILE 0.625 /* 1/16th of a wood */ +#define BT_TILE 0.5 /* 1/16th of a wood */ /* Wood tile */ -#define BT_TORCH 0.0125 /* 1/4th of a stick */ +#define BT_TORCH 0.1 /* 1/4th of a stick */ /* Torches */ -#define BT_TREE 99.0 /* one stack */ +#define BT_TREE 10.0 /* one stack */ /* Tree trunks */ -#define BT_TRELLIS 0.625 /* 1/16th of a wood */ +#define BT_TRELLIS 0.5 /* 1/16th of a wood */ /* Trellises */ -#define BT_WOOD 10.0 /* 10 items */ +#define BT_WOOD 2.0 /* 2 items */ /* Wood, jungle wood, etc. */ -#define BT_YOUNG_TREE 1.111111 /* 1/9th of a wood */ +#define BT_YOUNG_TREE 1.0 /* 1/9th of a wood */ /* Young tree trunks */ diff --git a/src/content_craft.cpp b/src/content_craft.cpp index 6e2cc8e..084555c 100644 --- a/src/content_craft.cpp +++ b/src/content_craft.cpp @@ -43,11 +43,17 @@ namespace crafting { std::vector shaped_recipes; std::vector shapeless_recipes; +craft_alloy_t *alloys; void initCrafting() { + craft_alloy_t *a; shaped_recipes.clear(); shapeless_recipes.clear(); + + while ((a = (craft_alloy_t*)list_pull(&alloys))) { + free(a); + } } static bool checkRecipe(content_t recipe[9], content_t result) @@ -70,6 +76,19 @@ static bool checkShapelessRecipe(content_t recipe[9], content_t result) return false; } +static bool checkAlloy(content_t recipe[2], content_t result) +{ + craft_alloy_t *a; + + a = alloys; + while (a) { + if (a->recipe[0] == recipe[0] && a->recipe[1] == recipe[1]) + return true; + a = a->next; + } + return false; +} + void setRecipe(content_t recipe[9], content_t result, u16 count, uint64_t privs) { if (checkRecipe(recipe,result)) @@ -98,6 +117,24 @@ void setShapelessRecipe(content_t recipe[9], content_t result, u16 count, uint64 shapeless_recipes.push_back(d); } +void setAlloy(content_t recipe[2], content_t result, uint16_t count) +{ + craft_alloy_t *a; + if (checkAlloy(recipe,result)) + return; + + a = (craft_alloy_t*)malloc(sizeof(craft_alloy_t)); + if (!a) + return; + + a->recipe[0] = recipe[0]; + a->recipe[1] = recipe[1]; + a->result = result; + a->result_count = count; + + alloys = (craft_alloy_t*)list_push(&alloys,a); +} + // one input yields one result void set1To1Recipe(u16 input, u16 result) { @@ -744,6 +781,21 @@ InventoryItem *getResult(InventoryItem **items, Player *player, Server *server) return NULL; } +InventoryItem *getAlloy(content_t c0, content_t c1) +{ + craft_alloy_t *a; + + a = alloys; + while (a) { + if (a->recipe[0] == c0 && a->recipe[1] == c1) { + return InventoryItem::create(a->result,a->result_count); + } + a = a->next; + } + + return NULL; +} + content_t *getRecipe(InventoryItem *item) { content_t r = item->getContent(); diff --git a/src/content_craft.h b/src/content_craft.h index 96e7255..54fab74 100644 --- a/src/content_craft.h +++ b/src/content_craft.h @@ -169,12 +169,21 @@ struct CraftDefShapeless { } }; +typedef struct craft_alloy_s { + struct craft_alloy_s *prev; + struct craft_alloy_s *next; + content_t recipe[2]; + content_t result; + uint16_t result_count; +} craft_alloy_t; + namespace crafting { void initCrafting(); // add recipes void setRecipe(u16 recipe[9], u16 result, u16 count, uint64_t privs = 0); void setShapelessRecipe(u16 recipe[9], u16 result, u16 count, uint64_t privs = 0); + void setAlloy(content_t recipe[2], content_t result, uint16_t count); // shortcuts // one input yields one result @@ -283,6 +292,7 @@ namespace crafting { void set4SpacedTo1Recipe(u16 input, u16 result); InventoryItem *getResult(InventoryItem **items, Player *player, Server *server); + InventoryItem *getAlloy(content_t c0, content_t c1); content_t *getRecipe(InventoryItem *item); content_t *getRecipe(InventoryItem *item, int i); int getResultCount(InventoryItem *item); diff --git a/src/content_craftitem.cpp b/src/content_craftitem.cpp index 4f2851d..c284fa4 100644 --- a/src/content_craftitem.cpp +++ b/src/content_craftitem.cpp @@ -238,6 +238,27 @@ void content_craftitem_init() f->description = gettext("Iron Ingot"); content_list_add("creative",i,1,0); + i = CONTENT_CRAFTITEM_BRONZE_INGOT; + f = &g_content_craftitem_features[(i&~CONTENT_CRAFTITEM_MASK)]; + f->content = CONTENT_CRAFTITEM_BRONZE_INGOT; + f->texture = "bronze_ingot.png"; + f->name = "bronze_ingot"; + f->description = gettext("Bronze Ingot"); + content_list_add("creative",i,1,0); + { + content_t r[2] = {CONTENT_CRAFTITEM_TIN,CONTENT_CRAFTITEM_COPPER}; + crafting::setAlloy(r,i,1); + r[0] = CONTENT_CRAFTITEM_COPPER; + r[1] = CONTENT_CRAFTITEM_TIN; + crafting::setAlloy(r,i,1); + r[0] = CONTENT_CRAFTITEM_TIN_INGOT; + r[1] = CONTENT_CRAFTITEM_COPPER_INGOT; + crafting::setAlloy(r,i,1); + r[0] = CONTENT_CRAFTITEM_COPPER_INGOT; + r[1] = CONTENT_CRAFTITEM_TIN_INGOT; + crafting::setAlloy(r,i,1); + } + i = CONTENT_CRAFTITEM_CLAY_BRICK; f = &g_content_craftitem_features[(i&~CONTENT_CRAFTITEM_MASK)]; f->content = CONTENT_CRAFTITEM_CLAY_BRICK; diff --git a/src/content_craftitem.h b/src/content_craftitem.h index ca10a9a..c477721 100644 --- a/src/content_craftitem.h +++ b/src/content_craftitem.h @@ -40,7 +40,7 @@ struct CraftItemFeatures { // the result of cooking this item content_t cook_result; // what type of cooking device this item needs - CookType cook_type; + uint16_t cook_type; // the result of crushing this item content_t crush_result; // what type of crushing device this item needs @@ -222,5 +222,6 @@ CraftItemFeatures *content_craftitem_features(content_t i); #define CONTENT_CRAFTITEM_RASPBERRY (CONTENT_CRAFTITEM_MASK | 0x8A) #define CONTENT_CRAFTITEM_UPGRADE_STORAGE (CONTENT_CRAFTITEM_MASK | 0x8B) #define CONTENT_CRAFTITEM_UPGRADE_EXO (CONTENT_CRAFTITEM_MASK | 0x8C) +#define CONTENT_CRAFTITEM_BRONZE_INGOT (CONTENT_CRAFTITEM_MASK | 0x8D) #endif diff --git a/src/content_nodemeta.h b/src/content_nodemeta.h index 0159978..816ec71 100644 --- a/src/content_nodemeta.h +++ b/src/content_nodemeta.h @@ -425,11 +425,11 @@ public: private: Inventory *m_inventory; - float m_step_accumulator; - float m_fuel_totaltime; - float m_fuel_time; - float m_src_totaltime; - float m_src_time; + float m_active_timer; + float m_burn_counter; + float m_burn_timer; + float m_cook_timer; + bool m_has_pots; }; class CrusherNodeMetadata : public NodeMetadata diff --git a/src/content_toolitem.h b/src/content_toolitem.h index 8b4f1f4..e3b0d19 100644 --- a/src/content_toolitem.h +++ b/src/content_toolitem.h @@ -34,7 +34,7 @@ struct ToolItemFeatures { // the result of cooking this item std::string cook_result; // what type of cooking device this item needs - CookType cook_type; + uint16_t cook_type; // the fuel value of this item std::string crush_result; // what type of crushing device this item needs diff --git a/src/guiFormSpecMenu.cpp b/src/guiFormSpecMenu.cpp index b086b63..25a7b90 100644 --- a/src/guiFormSpecMenu.cpp +++ b/src/guiFormSpecMenu.cpp @@ -639,10 +639,21 @@ void GUIFormSpecMenu::drawMenu() for (u32 i=0; i(spec.name.c_str()),1,buff,1024)) - texture = driver->getTexture(buff); + img_name = const_cast(spec.name.c_str()); + if (!strncmp(img_name,"inventory:",10)) { + content_t c = strtoul(img_name+10,NULL,10); + InventoryItem *itm = InventoryItem::create(c,1,0,0); + if (itm) { + texture = itm->getImage(); + delete itm; + } + }else{ + char buff[1024]; + if (path_get((char*)"texture",img_name,1,buff,1024)) + texture = driver->getTexture(buff); + } // Image size on screen core::rect imgrect(0, 0, spec.geom.X, spec.geom.Y); // Image rectangle on screen diff --git a/src/inventory.cpp b/src/inventory.cpp index be50a14..a83b1e3 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -274,12 +274,12 @@ std::wstring MaterialItem::getGuiText() return narrow_to_wide(txt); } -bool MaterialItem::isCookable(CookType type) const +bool MaterialItem::isCookable(uint16_t type) const { ContentFeatures *f = &content_features(m_content); if (!f) return false; - if (type != f->cook_type && f->cook_type != COOK_ANY) + if (f->cook_type != COOK_ANY && (type&f->cook_type) != f->cook_type) return false; if (f->cook_result == "") return false; @@ -459,12 +459,12 @@ u16 CraftItem::getDropCount() const return InventoryItem::getDropCount(); } -bool CraftItem::isCookable(CookType type) const +bool CraftItem::isCookable(uint16_t type) const { CraftItemFeatures *f = content_craftitem_features(m_content); if (!f) return false; - if (type != f->cook_type && f->cook_type != COOK_ANY) + if (f->cook_type != COOK_ANY && (type&f->cook_type) != f->cook_type) return false; if (f->cook_result == CONTENT_IGNORE) return false; @@ -671,12 +671,12 @@ std::wstring ToolItem::getGuiText() return narrow_to_wide(txt); } -bool ToolItem::isCookable(CookType type) const +bool ToolItem::isCookable(uint16_t type) const { ToolItemFeatures *f = &content_toolitem_features(m_content); if (!f) return false; - if (type != f->cook_type && f->cook_type != COOK_ANY) + if (f->cook_type != COOK_ANY && (type&f->cook_type) != f->cook_type) return false; if (f->cook_result == "") return false; diff --git a/src/inventory.h b/src/inventory.h index 49fd63f..55b56a4 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -134,7 +134,7 @@ public: */ // Whether it can be cooked - virtual bool isCookable(CookType type=COOK_ANY) const {return false;} + virtual bool isCookable(uint16_t type=COOK_ANY) const {return false;} // Whether it can be crushed virtual bool isCrushable(CrushType type=CRUSH_ANY) const {return false;} // Time of cooking @@ -225,7 +225,7 @@ public: /* Other properties */ - bool isCookable(CookType type) const; + bool isCookable(uint16_t type) const; InventoryItem *createCookResult() const; bool isCrushable(CrushType type) const; InventoryItem *createCrushResult() const; @@ -318,7 +318,7 @@ public: Other properties */ - bool isCookable(CookType type) const; + bool isCookable(uint16_t type) const; InventoryItem *createCookResult() const; bool isCrushable(CrushType type) const; InventoryItem *createCrushResult() const; @@ -391,7 +391,7 @@ public: ServerActiveObject* createSAO(ServerEnvironment *env, u16 id, v3f pos); - bool isCookable(CookType type) const; + bool isCookable(uint16_t type) const; InventoryItem *createCookResult() const; bool isCrushable(CrushType type) const; InventoryItem *createCrushResult() const; diff --git a/src/mapnode.h b/src/mapnode.h index ed8b9d3..e4ed008 100644 --- a/src/mapnode.h +++ b/src/mapnode.h @@ -158,12 +158,11 @@ enum LiquidType LIQUID_SOURCE }; -enum CookType -{ - COOK_ANY, - COOK_FIRE, - COOK_FURNACE -}; +#define COOK_ANY 0xFFFF +#define COOK_FIRE 0x0001 +#define COOK_CLAY_POT 0x0002 +#define COOK_FIRE_POT (COOK_FIRE | COOK_CLAY_POT) +#define COOK_FURNACE 0x0004 enum CrushType { @@ -264,6 +263,7 @@ public: v3s16 m_angle; v3f m_centre; aabb3f m_box; + std::string textures[6]; }; enum FaceTextType { @@ -463,7 +463,7 @@ struct ContentFeatures // the result of cooking this node std::string cook_result; // what type of cooking device this node needs - CookType cook_type; + uint16_t cook_type; // the fuel value of this node float fuel_time; diff --git a/src/nodemeta/content_nodemeta_cooking.cpp b/src/nodemeta/content_nodemeta_cooking.cpp index 6f1f8d2..0293247 100644 --- a/src/nodemeta/content_nodemeta_cooking.cpp +++ b/src/nodemeta/content_nodemeta_cooking.cpp @@ -27,6 +27,7 @@ #include "content_nodemeta.h" #include "inventory.h" #include "content_mapnode.h" +#include "content_craft.h" #include "environment.h" /* @@ -580,14 +581,16 @@ CampFireNodeMetadata::CampFireNodeMetadata() m_inventory = new Inventory(); m_inventory->addList("fuel", 1); - m_inventory->addList("src", 1); + m_inventory->addList("src", 3); m_inventory->addList("dst", 1); - m_step_accumulator = 0; - m_fuel_totaltime = 0; - m_fuel_time = 0; - m_src_totaltime = 0; - m_src_time = 0; + m_active_timer = 0.0; + m_burn_counter = 0.0; + m_burn_timer = 0.0; + m_cook_timer = 0.0; + m_has_pots = false; + + inventoryModified(); } CampFireNodeMetadata::~CampFireNodeMetadata() { @@ -601,31 +604,49 @@ NodeMetadata* CampFireNodeMetadata::clone() { CampFireNodeMetadata *d = new CampFireNodeMetadata(); *d->m_inventory = *m_inventory; - d->m_fuel_totaltime = m_fuel_totaltime; - d->m_fuel_time = m_fuel_time; - d->m_src_totaltime = m_src_totaltime; - d->m_src_time = m_src_time; + + d->m_active_timer = m_active_timer; + d->m_burn_counter = m_burn_counter; + d->m_burn_timer = m_burn_timer; + d->m_cook_timer = m_cook_timer; + d->m_has_pots = m_has_pots; + return d; } NodeMetadata* CampFireNodeMetadata::create(std::istream &is) { + std::string s; CampFireNodeMetadata *d = new CampFireNodeMetadata(); d->m_inventory->deSerialize(is); - int temp; - is>>temp; - d->m_fuel_totaltime = (float)temp/10; - is>>temp; - d->m_fuel_time = (float)temp/10; + s = deSerializeString(is); + d->m_active_timer = mystof(s); + + s = deSerializeString(is); + d->m_burn_counter = mystoi(s); + + s = deSerializeString(is); + d->m_burn_timer = mystoi(s); + + s = deSerializeString(is); + d->m_cook_timer = mystof(s); + + s = deSerializeString(is); + d->m_has_pots = !!mystoi(s); + + d->inventoryModified(); return d; } void CampFireNodeMetadata::serializeBody(std::ostream &os) { m_inventory->serialize(os); - os<= m_fuel_totaltime) { - const InventoryList *src_list = m_inventory->getList("src"); - assert(src_list); - const InventoryItem *src_item = src_list->getItem(0); - - if (src_item && src_item->isCookable(COOK_FIRE)) { - InventoryList *dst_list = m_inventory->getList("dst"); - if(!dst_list->roomForCookedItem(src_item)) { - s = gettext("CampFire is overloaded"); - }else{ - s = gettext("CampFire is out of fuel"); - } - }else{ - s = gettext("CampFire is inactive"); - } - }else{ + if (m_burn_counter > 0.0) { s = gettext("CampFire is active"); - // Do this so it doesn't always show (0%) for weak fuel - if (m_fuel_totaltime > 3) { - uint32_t tt = m_fuel_time/m_fuel_totaltime*100; + if (m_cook_timer > 0.0) { + uint32_t tt = m_cook_timer/4.0*100; snprintf(e,128, " (%d%%)",tt); } + }else{ + s = gettext("CampFire is inactive"); } snprintf(buff,256,"%s%s",s,e); @@ -666,8 +673,11 @@ bool CampFireNodeMetadata::nodeRemovalDisabled() /* Disable removal if furnace is not empty */ - InventoryList *list[3] = {m_inventory->getList("src"), - m_inventory->getList("dst"), m_inventory->getList("fuel")}; + InventoryList *list[3] = { + m_inventory->getList("src"), + m_inventory->getList("dst"), + m_inventory->getList("fuel") + }; for (int i = 0; i < 3; i++) { if (list[i] == NULL) @@ -676,148 +686,280 @@ bool CampFireNodeMetadata::nodeRemovalDisabled() continue; return true; } - return false; + return false; } void CampFireNodeMetadata::inventoryModified() { - vlprintf(CN_INFO,"CampFire inventory modification callback"); + InventoryList *src_list; + InventoryItem *src_item = NULL; + + src_list = m_inventory->getList("src"); + if (!src_list) + return; + + src_item = src_list->getItem(0); + if (!src_item) { + m_has_pots = false; + return; + } + + if (src_item->getContent() != CONTENT_CLAY_VESSEL) { + m_has_pots = false; + return; + } + + m_has_pots = true; } bool CampFireNodeMetadata::step(float dtime, v3s16 pos, ServerEnvironment *env) { - { - MapNode n = env->getMap().getNodeNoEx(pos).getContent(); - if (n.getContent() == CONTENT_FURNACE_ACTIVE) { - n.param1 = n.param2; - n.setContent(CONTENT_FURNACE); - env->setPostStepNodeSwap(pos,n); - } - } + float cook_time = 4.0; + bool changed = false; + bool is_cooking; + bool cook_ongoing; + bool room_available; + uint8_t pots_mode = 0; + InventoryList *dst_list; + InventoryList *src_list; + InventoryItem *src_item = NULL; + InventoryItem *src_item1 = NULL; + InventoryList *fuel_list; + InventoryItem *fuel_item; + uint16_t mode = COOK_FIRE; + + /* requires air above it (because why not?) */ + if (content_features(env->getMap().getNodeNoEx(pos+v3s16(0,1,0),NULL).getContent()).air_equivalent == false) + return false; if (dtime > 60.0) - vlprintf(CN_INFO,"CampFire stepping a long time (%f)",dtime); - // Update at a fixed frequency - const float interval = 2.0; - m_step_accumulator += dtime; - bool changed = false; - while (m_step_accumulator > interval) { - m_step_accumulator -= interval; - dtime = interval; + vlprintf(CN_INFO,"Campfire stepping a long time (%f)",dtime); - InventoryList *dst_list = m_inventory->getList("dst"); - assert(dst_list); + dst_list = m_inventory->getList("dst"); + if (!dst_list) + return false; - InventoryList *src_list = m_inventory->getList("src"); - assert(src_list); - InventoryItem *src_item = src_list->getItem(0); + src_list = m_inventory->getList("src"); + if (!src_list) + return false; - bool room_available = false; + if (m_has_pots) + mode = COOK_FIRE_POT; - if (src_item && src_item->isCookable(COOK_FIRE)) - room_available = dst_list->roomForCookedItem(src_item); + m_active_timer += dtime; - // Start only if there are free slots in dst, so that it can - // accomodate any result item - if (room_available) { - m_src_totaltime = 3; - }else{ - m_src_time = 0; - m_src_totaltime = 0; - } + while (m_active_timer > 1.0) { + m_active_timer -= 1.0; - /* - If fuel is burning, increment the burn counters. - If item finishes cooking, move it to result. - */ - if (m_fuel_time < m_fuel_totaltime) { - m_fuel_time += dtime; - m_src_time += dtime; - if (m_src_time >= m_src_totaltime && m_src_totaltime > 0.001 && src_item) { - InventoryItem *cookresult = src_item->createCookResult(); - dst_list->addItem(cookresult); - src_list->decrementMaterials(1); - m_src_time = 0; - m_src_totaltime = 0; + is_cooking = false; + cook_ongoing = false; + room_available = false; + + if (m_has_pots) { + src_item = src_list->getItem(1); + src_item1 = src_list->getItem(2); + if (src_item && src_item1) { + if (src_item->getContent() == src_item1->getContent()) { + if (src_item->isCookable(mode)) { + pots_mode = 1; + is_cooking = true; + room_available = dst_list->roomForCookedItem(src_item); + if (room_available) + cook_ongoing = true; + }else{ + m_cook_timer = 0.0; + } + }else{ + pots_mode = 0; + InventoryItem *alloy = crafting::getAlloy(src_item->getContent(),src_item1->getContent()); + if (alloy) { + is_cooking = true; + room_available = dst_list->roomForItem(alloy); + if (room_available && src_item->getCount() > 1 && src_item1->getCount() > 1) + cook_ongoing = true; + delete alloy; + }else{ + m_cook_timer = 0.0; + } + } + }else if (src_item) { + if (src_item->isCookable(mode)) { + pots_mode = 1; + is_cooking = true; + room_available = dst_list->roomForCookedItem(src_item); + if (room_available && src_item->getCount() > 1) + cook_ongoing = true; + }else{ + m_cook_timer = 0.0; + } + }else if (src_item1) { + if (src_item1->isCookable(mode)) { + pots_mode = 2; + is_cooking = true; + room_available = dst_list->roomForCookedItem(src_item1); + if (room_available && src_item1->getCount() > 1) + cook_ongoing = true; + }else{ + m_cook_timer = 0.0; + } + }else{ + m_cook_timer = 0.0; + } + }else{ + src_item = src_list->getItem(0); + if (src_item && src_item->isCookable(mode)) { + is_cooking = true; + room_available = dst_list->roomForCookedItem(src_item); + if (room_available && src_item->getCount() > 1) + cook_ongoing = true; + }else{ + m_cook_timer = 0.0; } - changed = true; - - // If the fuel was not used up this step, just keep burning it - if (m_fuel_time < m_fuel_totaltime) - continue; } - /* - Get the source again in case it has all burned - */ - src_item = src_list->getItem(0); + if (m_cook_timer > 4.0) + m_cook_timer = 4.0; - /* - If there is no source item, or the source item is not cookable, - or the furnace is still cooking, or the furnace became overloaded, stop loop. - */ - if ( - src_item == NULL - || !room_available - || m_fuel_time < m_fuel_totaltime - || dst_list->roomForCookedItem(src_item) == false - ) { - m_step_accumulator = 0; + if (m_burn_counter < 1.0 && is_cooking) { + if (m_cook_timer+1.0 < 4.0 || cook_ongoing) { + fuel_list = m_inventory->getList("fuel"); + if (!fuel_list) + break; + fuel_item = fuel_list->getItem(0); + if (fuel_item && fuel_item->isFuel()) { + content_t c = fuel_item->getContent(); + float v = 0.0; + if ((c&CONTENT_CRAFTITEM_MASK) == CONTENT_CRAFTITEM_MASK) { + v = ((CraftItem*)fuel_item)->getFuelTime(); + }else if ((c&CONTENT_TOOLITEM_MASK) == CONTENT_TOOLITEM_MASK) { + v = ((ToolItem*)fuel_item)->getFuelTime(); + }else{ + v = ((MaterialItem*)fuel_item)->getFuelTime(); + } + fuel_list->decrementMaterials(1); + if (c == CONTENT_TOOLITEM_IRON_BUCKET_LAVA) { + fuel_list->addItem(0,new ToolItem(CONTENT_TOOLITEM_IRON_BUCKET,0,0)); + } + m_burn_counter += v; + changed = true; + } + } + } + + if (m_burn_counter <= 0.0) { + m_active_timer = 0.0; + m_burn_counter = 0.0; + m_burn_timer = 0.0; break; } - //vlprintf(CN_INFO,"CampFire is out of fuel"); + if (m_burn_counter < 1.0) + continue; - InventoryList *fuel_list = m_inventory->getList("fuel"); - assert(fuel_list); - InventoryItem *fuel_item = fuel_list->getItem(0); - if (fuel_item && fuel_item->isFuel()) { - if ((fuel_item->getContent()&CONTENT_CRAFTITEM_MASK) == CONTENT_CRAFTITEM_MASK) { - m_fuel_totaltime = ((CraftItem*)fuel_item)->getFuelTime(); - }else if ((fuel_item->getContent()&CONTENT_TOOLITEM_MASK) == CONTENT_TOOLITEM_MASK) { - m_fuel_totaltime = ((ToolItem*)fuel_item)->getFuelTime(); + m_burn_timer += 1.0; + changed = true; + if (m_burn_timer >= 4.0) { + m_burn_counter -= 1.0; + m_burn_timer -= cook_time; + } + + if (!is_cooking) { + m_cook_timer = 0.0; + continue; + } + + m_cook_timer += 1.0; + + if (m_cook_timer >= 4.0) { + m_cook_timer -= 4.0; + if (m_has_pots) { + if (pots_mode == 1) { + if (src_item && src_item->isCookable(mode)) { + InventoryItem *result = src_item->createCookResult(); + dst_list->addItem(result); + InventoryItem *itm = src_list->takeItem(1,1); + if (itm) + delete itm; + src_list->addDiff(1,src_item); + } + }else if (pots_mode == 2) { + if (src_item1 && src_item1->isCookable(mode)) { + InventoryItem *result = src_item1->createCookResult(); + dst_list->addItem(result); + InventoryItem *itm = src_list->takeItem(2,1); + if (itm) + delete itm; + src_list->addDiff(2,src_item1); + } + }else if (src_item && src_item1) { + InventoryItem *alloy = crafting::getAlloy(src_item->getContent(),src_item1->getContent()); + dst_list->addItem(alloy); + { + InventoryItem *itm = src_list->takeItem(1,1); + if (itm) + delete itm; + src_list->addDiff(1,src_item); + } + { + InventoryItem *itm = src_list->takeItem(2,1); + if (itm) + delete itm; + src_list->addDiff(2,src_item1); + } + } }else{ - m_fuel_totaltime = ((MaterialItem*)fuel_item)->getFuelTime(); + if (src_item && src_item->isCookable(mode)) { + InventoryItem *crushresult = src_item->createCookResult(); + dst_list->addItem(crushresult); + src_list->decrementMaterials(1); + } } - m_fuel_totaltime *= 2.0; - m_fuel_time = 0; - content_t c = fuel_item->getContent(); - fuel_list->decrementMaterials(1); - if (c == CONTENT_TOOLITEM_IRON_BUCKET_LAVA) { - fuel_list->addItem(0,new ToolItem(CONTENT_TOOLITEM_IRON_BUCKET,0,0)); - } - changed = true; - }else{ - m_step_accumulator = 0; } } + return changed; } std::string CampFireNodeMetadata::getDrawSpecString(Player *player) { std::string spec("size[8,9]"); spec += "list[current_name;fuel;2,2;1,1;]"; - spec += "list[current_name;src;5,1;1,1;]"; + if (m_has_pots) { + InventoryList *src_list = m_inventory->getList("src"); + if (src_list && (src_list->getItem(1) || src_list->getItem(2))) { + char buff[10]; + snprintf(buff,10,"%u",CONTENT_CLAY_VESSEL); + spec += "image[5,0.5;1,1;inventory:"; + spec += buff; + spec += "]"; + }else{ + spec += "list[current_name;src;5,0.5;1,1;0,1;]"; + } + spec += "list[current_name;src;4.5,1.5;2,1;1,-1;]"; + }else{ + spec += "list[current_name;src;5,1;1,1;]"; + } spec += "list[current_name;dst;5,3;1,1;]"; - spec += "list[current_player;main;0,5;8,4;]"; + + spec += "list[current_player;main;0,4.8;8,1;0,8;]"; + spec += "list[current_player;main;0,6;8,3;8,-1;]"; + return spec; } std::vector CampFireNodeMetadata::getNodeBoxes(MapNode &n) { std::vector boxes; - boxes.clear(); - if (m_fuel_time < m_fuel_totaltime) { + if (m_burn_counter > 0.0) { boxes.push_back(NodeBox( -0.3125*BS,-0.25*BS,-0.4*BS,0.3125*BS,0.125*BS,-0.3*BS )); } - return transformNodeBox(n,boxes); + return boxes; } bool CampFireNodeMetadata::isActive() { - if (m_fuel_time >= m_fuel_totaltime) + if (m_burn_counter > 0.0) return false; return true; }