diff options
author | Perttu Ahola <celeron55@gmail.com> | 2011-04-05 02:56:29 +0300 |
---|---|---|
committer | Perttu Ahola <celeron55@gmail.com> | 2011-04-05 02:56:29 +0300 |
commit | d1d57cf5c34c9a4626fd8e3b40db3ea321b40335 (patch) | |
tree | e263dcc5268f514f43521d2df86640a96be94e96 /src | |
parent | 281f76b6a07393906cb532bed95d5d98f0791c3a (diff) | |
download | minetest-d1d57cf5c34c9a4626fd8e3b40db3ea321b40335.tar.gz minetest-d1d57cf5c34c9a4626fd8e3b40db3ea321b40335.tar.bz2 minetest-d1d57cf5c34c9a4626fd8e3b40db3ea321b40335.zip |
initial workings of the furnace
Diffstat (limited to 'src')
-rw-r--r-- | src/inventory.cpp | 149 | ||||
-rw-r--r-- | src/inventory.h | 52 | ||||
-rw-r--r-- | src/map.cpp | 29 | ||||
-rw-r--r-- | src/map.h | 2 | ||||
-rw-r--r-- | src/mapnode.cpp | 1 | ||||
-rw-r--r-- | src/mapnode.h | 2 | ||||
-rw-r--r-- | src/nodemetadata.cpp | 155 | ||||
-rw-r--r-- | src/nodemetadata.h | 14 | ||||
-rw-r--r-- | src/server.cpp | 184 |
9 files changed, 423 insertions, 165 deletions
diff --git a/src/inventory.cpp b/src/inventory.cpp index a610a4617..86e00877c 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -403,6 +403,28 @@ InventoryItem * InventoryList::addItem(u32 i, InventoryItem *newitem) } } +bool InventoryList::itemFits(u32 i, InventoryItem *newitem) +{ + // If it is an empty position, it's an easy job. + InventoryItem *to_item = m_items[i]; + if(to_item == NULL) + { + return true; + } + + // If not addable, return the item + if(newitem->addableTo(to_item) == false) + return false; + + // If the item fits fully in the slot, add counter and delete it + if(newitem->getCount() <= to_item->freeSpace()) + { + return true; + } + + return false; +} + InventoryItem * InventoryList::takeItem(u32 i, u32 count) { if(count == 0) @@ -698,5 +720,132 @@ void IMoveAction::apply(InventoryContext *c, InventoryManager *mgr) mgr->inventoryModified(c, to_inv); #endif } + +/* + Craft checking system +*/ + +bool ItemSpec::checkItem(InventoryItem *item) +{ + if(type == ITEM_NONE) + { + // Has to be no item + if(item != NULL) + return false; + return true; + } + + // There should be an item + if(item == NULL) + return false; + + std::string itemname = item->getName(); + + if(type == ITEM_MATERIAL) + { + if(itemname != "MaterialItem") + return false; + MaterialItem *mitem = (MaterialItem*)item; + if(mitem->getMaterial() != num) + return false; + } + else if(type == ITEM_CRAFT) + { + if(itemname != "CraftItem") + return false; + CraftItem *mitem = (CraftItem*)item; + if(mitem->getSubName() != name) + return false; + } + else if(type == ITEM_TOOL) + { + // Not supported yet + assert(0); + } + else if(type == ITEM_MBO) + { + // Not supported yet + assert(0); + } + else + { + // Not supported yet + assert(0); + } + return true; +} + +bool checkItemCombination(InventoryItem **items, ItemSpec *specs) +{ + u16 items_min_x = 100; + u16 items_max_x = 100; + u16 items_min_y = 100; + u16 items_max_y = 100; + for(u16 y=0; y<3; y++) + for(u16 x=0; x<3; x++) + { + if(items[y*3 + x] == NULL) + continue; + if(items_min_x == 100 || x < items_min_x) + items_min_x = x; + if(items_min_y == 100 || y < items_min_y) + items_min_y = y; + if(items_max_x == 100 || x > items_max_x) + items_max_x = x; + if(items_max_y == 100 || y > items_max_y) + items_max_y = y; + } + // No items at all, just return false + if(items_min_x == 100) + return false; + + u16 items_w = items_max_x - items_min_x + 1; + u16 items_h = items_max_y - items_min_y + 1; + + u16 specs_min_x = 100; + u16 specs_max_x = 100; + u16 specs_min_y = 100; + u16 specs_max_y = 100; + for(u16 y=0; y<3; y++) + for(u16 x=0; x<3; x++) + { + if(specs[y*3 + x].type == ITEM_NONE) + continue; + if(specs_min_x == 100 || x < specs_min_x) + specs_min_x = x; + if(specs_min_y == 100 || y < specs_min_y) + specs_min_y = y; + if(specs_max_x == 100 || x > specs_max_x) + specs_max_x = x; + if(specs_max_y == 100 || y > specs_max_y) + specs_max_y = y; + } + // No specs at all, just return false + if(specs_min_x == 100) + return false; + + u16 specs_w = specs_max_x - specs_min_x + 1; + u16 specs_h = specs_max_y - specs_min_y + 1; + + // Different sizes + if(items_w != specs_w || items_h != specs_h) + return false; + + for(u16 y=0; y<specs_h; y++) + for(u16 x=0; x<specs_w; x++) + { + u16 items_x = items_min_x + x; + u16 items_y = items_min_y + y; + u16 specs_x = specs_min_x + x; + u16 specs_y = specs_min_y + y; + InventoryItem *item = items[items_y * 3 + items_x]; + ItemSpec &spec = specs[specs_y * 3 + specs_x]; + + if(spec.checkItem(item) == false) + return false; + } + + return true; +} //END diff --git a/src/inventory.h b/src/inventory.h index 45bc488c5..0cbd97abc 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -435,6 +435,7 @@ public: InventoryItem * changeItem(u32 i, InventoryItem *newitem); // Delete item void deleteItem(u32 i); + // Adds an item to a suitable place. Returns leftover item. // If all went into the list, returns NULL. InventoryItem * addItem(InventoryItem *newitem); @@ -445,6 +446,9 @@ public: // If can be added fully, NULL is returned. InventoryItem * addItem(u32 i, InventoryItem *newitem); + // Checks whether the item could be added to the given slot + bool itemFits(u32 i, InventoryItem *newitem); + // Takes some items from a slot. // If there are not enough, takes as many as it can. // Returns NULL if couldn't take any. @@ -522,7 +526,7 @@ public: */ virtual Inventory* getInventory(InventoryContext *c, std::string id) {return NULL;} - // Used on the server by InventoryAction::apply + // Used on the server by InventoryAction::apply and other stuff virtual void inventoryModified(InventoryContext *c, std::string id) {} // Used on the client @@ -600,5 +604,51 @@ struct IMoveAction : public InventoryAction void apply(InventoryContext *c, InventoryManager *mgr); }; +/* + Craft checking system +*/ + +enum ItemSpecType +{ + ITEM_NONE, + ITEM_MATERIAL, + ITEM_CRAFT, + ITEM_TOOL, + ITEM_MBO +}; + +struct ItemSpec +{ + enum ItemSpecType type; + // Only other one of these is used + std::string name; + u16 num; + + ItemSpec(): + type(ITEM_NONE) + { + } + ItemSpec(enum ItemSpecType a_type, std::string a_name): + type(a_type), + name(a_name), + num(65535) + { + } + ItemSpec(enum ItemSpecType a_type, u16 a_num): + type(a_type), + name(""), + num(a_num) + { + } + + bool checkItem(InventoryItem *item); +}; + +/* + items: a pointer to an array of 9 pointers to items + specs: a pointer to an array of 9 ItemSpecs +*/ +bool checkItemCombination(InventoryItem **items, ItemSpec *specs); + #endif diff --git a/src/map.cpp b/src/map.cpp index f6115a62a..40274ae29 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1756,6 +1756,35 @@ void Map::removeNodeMetadata(v3s16 p) block->m_node_metadata.remove(p_rel); } +void Map::nodeMetadataStep(float dtime, + core::map<v3s16, MapBlock*> &changed_blocks) +{ + /* + NOTE: + Currently there is no way to ensure that all the necessary + blocks are loaded when this is run. (They might get unloaded) + NOTE: ^- Actually, that might not be so. In a quick test it + reloaded a block with a furnace when I walked back to it from + a distance. + */ + core::map<v2s16, MapSector*>::Iterator si; + si = m_sectors.getIterator(); + for(; si.atEnd() == false; si++) + { + MapSector *sector = si.getNode()->getValue(); + core::list< MapBlock * > sectorblocks; + sector->getBlocks(sectorblocks); + core::list< MapBlock * >::Iterator i; + for(i=sectorblocks.begin(); i!=sectorblocks.end(); i++) + { + MapBlock *block = *i; + bool changed = block->m_node_metadata.step(dtime); + if(changed) + changed_blocks[block->getPos()] = block; + } + } +} + /* ServerMap */ @@ -285,6 +285,8 @@ public: NodeMetadata* getNodeMetadata(v3s16 p); void setNodeMetadata(v3s16 p, NodeMetadata *meta); void removeNodeMetadata(v3s16 p); + void nodeMetadataStep(float dtime, + core::map<v3s16, MapBlock*> &changed_blocks); /* Variables diff --git a/src/mapnode.cpp b/src/mapnode.cpp index 8e968c811..187689c6f 100644 --- a/src/mapnode.cpp +++ b/src/mapnode.cpp @@ -25,6 +25,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "mineral.h" // For g_settings #include "main.h" +#include "nodemetadata.h" ContentFeatures::~ContentFeatures() { diff --git a/src/mapnode.h b/src/mapnode.h index ce233e8e3..04234830d 100644 --- a/src/mapnode.h +++ b/src/mapnode.h @@ -28,7 +28,6 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "serialization.h" #include "tile.h" #include "iirrlichtwrapper.h" -#include "nodemetadata.h" /* Initializes all kind of stuff in here. @@ -121,6 +120,7 @@ enum LiquidType }; class MapNode; +class NodeMetadata; struct ContentFeatures { diff --git a/src/nodemetadata.cpp b/src/nodemetadata.cpp index 2405e7601..21f55a0ca 100644 --- a/src/nodemetadata.cpp +++ b/src/nodemetadata.cpp @@ -178,6 +178,12 @@ FurnaceNodeMetadata::FurnaceNodeMetadata() m_inventory->addList("fuel", 1); m_inventory->addList("src", 1); 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; } FurnaceNodeMetadata::~FurnaceNodeMetadata() { @@ -197,24 +203,134 @@ NodeMetadata* FurnaceNodeMetadata::create(std::istream &is) { FurnaceNodeMetadata *d = new FurnaceNodeMetadata(); d->m_inventory->deSerialize(is); - /*std::string params; - std::getline(is, params, '\n');*/ + int temp; + is>>temp; + d->m_fuel_totaltime = (float)temp/10; + is>>temp; + d->m_fuel_time = (float)temp/10; return d; } void FurnaceNodeMetadata::serializeBody(std::ostream &os) { m_inventory->serialize(os); - // This line will contain the other parameters - //os<<"\n"; + os<<itos(m_fuel_totaltime*10)<<" "; + os<<itos(m_fuel_time*10)<<" "; } std::string FurnaceNodeMetadata::infoText() { - return "Furnace"; + //return "Furnace"; + if(m_fuel_time >= m_fuel_totaltime) + { + InventoryList *src_list = m_inventory->getList("src"); + assert(src_list); + InventoryItem *src_item = src_list->getItem(0); + + if(src_item) + return "Furnace is out of fuel"; + else + return "Furnace is inactive"; + } + else + { + std::string s = "Furnace is active ("; + s += itos(m_fuel_time/m_fuel_totaltime*100); + s += "%)"; + return s; + } } void FurnaceNodeMetadata::inventoryModified() { dstream<<"Furnace inventory modification callback"<<std::endl; } +bool FurnaceNodeMetadata::step(float dtime) +{ + // Update at a fixed frequency + const float interval = 0.5; + m_step_accumulator += dtime; + if(m_step_accumulator < interval) + return false; + m_step_accumulator -= interval; + dtime = interval; + + //dstream<<"Furnace step dtime="<<dtime<<std::endl; + + InventoryList *dst_list = m_inventory->getList("dst"); + assert(dst_list); + + InventoryList *src_list = m_inventory->getList("src"); + assert(src_list); + InventoryItem *src_item = src_list->getItem(0); + + if(ItemSpec(ITEM_MATERIAL, CONTENT_TREE).checkItem(src_item) + && dst_list->itemFits(0, new CraftItem("lump_of_coal", 1))) + { + m_src_totaltime = 3; + } + else + { + m_src_time = 0; + m_src_totaltime = 0; + } + + if(m_fuel_time < m_fuel_totaltime) + { + //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(ItemSpec(ITEM_MATERIAL, CONTENT_TREE).checkItem(src_item)) + { + src_list->decrementMaterials(1); + dst_list->addItem(0, new CraftItem("lump_of_coal", 1)); + m_src_time = 0; + m_src_totaltime = 0; + } + } + return true; + } + + if(src_item == NULL || m_src_totaltime < 0.001) + { + return false; + } + + bool changed = false; + + //dstream<<"Furnace is out of fuel"<<std::endl; + + InventoryList *fuel_list = m_inventory->getList("fuel"); + assert(fuel_list); + InventoryItem *fuel_item = fuel_list->getItem(0); + + if(ItemSpec(ITEM_MATERIAL, CONTENT_TREE).checkItem(fuel_item)) + { + m_fuel_totaltime = 10; + m_fuel_time = 0; + fuel_list->decrementMaterials(1); + changed = true; + } + else if(ItemSpec(ITEM_MATERIAL, CONTENT_WOOD).checkItem(fuel_item)) + { + m_fuel_totaltime = 5; + m_fuel_time = 0; + fuel_list->decrementMaterials(1); + changed = true; + } + else if(ItemSpec(ITEM_CRAFT, "lump_of_coal").checkItem(fuel_item)) + { + m_fuel_totaltime = 10; + m_fuel_time = 0; + fuel_list->decrementMaterials(1); + changed = true; + } + else + { + //dstream<<"No fuel found"<<std::endl; + } + + return changed; +} /* NodeMetadatalist @@ -318,3 +434,32 @@ void NodeMetadataList::set(v3s16 p, NodeMetadata *d) m_data.insert(p, d); } +bool NodeMetadataList::step(float dtime) +{ + bool something_changed = false; + for(core::map<v3s16, NodeMetadata*>::Iterator + i = m_data.getIterator(); + i.atEnd()==false; i++) + { + v3s16 p = i.getNode()->getKey(); + NodeMetadata *meta = i.getNode()->getValue(); + bool changed = meta->step(dtime); + if(changed) + something_changed = true; + /*if(res.inventory_changed) + { + std::string inv_id; + inv_id += "nodemeta:"; + inv_id += itos(p.X); + inv_id += ","; + inv_id += itos(p.Y); + inv_id += ","; + inv_id += itos(p.Z); + InventoryContext c; + c.current_player = NULL; + inv_mgr->inventoryModified(&c, inv_id); + }*/ + } + return something_changed; +} + diff --git a/src/nodemetadata.h b/src/nodemetadata.h index e8aa57622..c38ab1310 100644 --- a/src/nodemetadata.h +++ b/src/nodemetadata.h @@ -59,6 +59,8 @@ public: // This is called always after the inventory is modified, before // the changes are copied elsewhere virtual void inventoryModified(){} + // A step in time. Returns true if metadata changed. + virtual bool step(float dtime) {return false;} protected: static void registerType(u16 id, Factory f); @@ -115,15 +117,23 @@ public: virtual std::string infoText(); virtual Inventory* getInventory() {return m_inventory;} virtual void inventoryModified(); + virtual bool step(float dtime); private: Inventory *m_inventory; + float m_step_accumulator; + float m_fuel_totaltime; + float m_fuel_time; + float m_src_totaltime; + float m_src_time; }; /* List of metadata of all the nodes of a block */ +class InventoryManager; + class NodeMetadataList { public: @@ -138,6 +148,10 @@ public: void remove(v3s16 p); // Deletes old data and sets a new one void set(v3s16 p, NodeMetadata *d); + + // A step in time. Returns true if something changed. + bool step(float dtime); + private: core::map<v3s16, NodeMetadata*> m_data; }; diff --git a/src/server.cpp b/src/server.cpp index df712e07f..c405af3f5 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -1504,6 +1504,32 @@ void Server::AsyncRunStep() } /* + Step node metadata + */ + { + JMutexAutoLock envlock(m_env_mutex); + JMutexAutoLock conlock(m_con_mutex); + + core::map<v3s16, MapBlock*> changed_blocks; + m_env.getMap().nodeMetadataStep(dtime, changed_blocks); + + for(core::map<v3s16, MapBlock*>::Iterator + i = changed_blocks.getIterator(); + i.atEnd() == false; i++) + { + MapBlock *block = i.getNode()->getValue(); + + for(core::map<u16, RemoteClient*>::Iterator + i = m_clients.getIterator(); + i.atEnd()==false; i++) + { + RemoteClient *client = i.getNode()->getValue(); + client->SetBlockNotSent(block->getPos()); + } + } + } + + /* Trigger emergethread (it somehow gets to a non-triggered but bysy state sometimes) */ @@ -2740,7 +2766,6 @@ void Server::inventoryModified(InventoryContext *c, std::string id) p.X = stoi(fn.next(",")); p.Y = stoi(fn.next(",")); p.Z = stoi(fn.next(",")); - assert(c->current_player); v3s16 blockpos = getNodeBlockPos(p); NodeMetadata *meta = m_env.getMap().getNodeMetadata(p); @@ -2888,163 +2913,6 @@ void Server::SendPlayerInfos() m_con.SendToAll(0, data, true); } -/* - Craft checking system -*/ - -enum ItemSpecType -{ - ITEM_NONE, - ITEM_MATERIAL, - ITEM_CRAFT, - ITEM_TOOL, - ITEM_MBO -}; - -struct ItemSpec -{ - ItemSpec(): - type(ITEM_NONE) - { - } - ItemSpec(enum ItemSpecType a_type, std::string a_name): - type(a_type), - name(a_name), - num(65535) - { - } - ItemSpec(enum ItemSpecType a_type, u16 a_num): - type(a_type), - name(""), - num(a_num) - { - } - enum ItemSpecType type; - // Only other one of these is used - std::string name; - u16 num; -}; - -/* - items: a pointer to an array of 9 pointers to items - specs: a pointer to an array of 9 ItemSpecs -*/ -bool checkItemCombination(InventoryItem **items, ItemSpec *specs) -{ - u16 items_min_x = 100; - u16 items_max_x = 100; - u16 items_min_y = 100; - u16 items_max_y = 100; - for(u16 y=0; y<3; y++) - for(u16 x=0; x<3; x++) - { - if(items[y*3 + x] == NULL) - continue; - if(items_min_x == 100 || x < items_min_x) - items_min_x = x; - if(items_min_y == 100 || y < items_min_y) - items_min_y = y; - if(items_max_x == 100 || x > items_max_x) - items_max_x = x; - if(items_max_y == 100 || y > items_max_y) - items_max_y = y; - } - // No items at all, just return false - if(items_min_x == 100) - return false; - - u16 items_w = items_max_x - items_min_x + 1; - u16 items_h = items_max_y - items_min_y + 1; - - u16 specs_min_x = 100; - u16 specs_max_x = 100; - u16 specs_min_y = 100; - u16 specs_max_y = 100; - for(u16 y=0; y<3; y++) - for(u16 x=0; x<3; x++) - { - if(specs[y*3 + x].type == ITEM_NONE) - continue; - if(specs_min_x == 100 || x < specs_min_x) - specs_min_x = x; - if(specs_min_y == 100 || y < specs_min_y) - specs_min_y = y; - if(specs_max_x == 100 || x > specs_max_x) - specs_max_x = x; - if(specs_max_y == 100 || y > specs_max_y) - specs_max_y = y; - } - // No specs at all, just return false - if(specs_min_x == 100) - return false; - - u16 specs_w = specs_max_x - specs_min_x + 1; - u16 specs_h = specs_max_y - specs_min_y + 1; - - // Different sizes - if(items_w != specs_w || items_h != specs_h) - return false; - - for(u16 y=0; y<specs_h; y++) - for(u16 x=0; x<specs_w; x++) - { - u16 items_x = items_min_x + x; - u16 items_y = items_min_y + y; - u16 specs_x = specs_min_x + x; - u16 specs_y = specs_min_y + y; - InventoryItem *item = items[items_y * 3 + items_x]; - ItemSpec &spec = specs[specs_y * 3 + specs_x]; - - if(spec.type == ITEM_NONE) - { - // Has to be no item - if(item != NULL) - return false; - continue; - } - - // There should be an item - if(item == NULL) - return false; - - std::string itemname = item->getName(); - - if(spec.type == ITEM_MATERIAL) - { - if(itemname != "MaterialItem") - return false; - MaterialItem *mitem = (MaterialItem*)item; - if(mitem->getMaterial() != spec.num) - return false; - } - else if(spec.type == ITEM_CRAFT) - { - if(itemname != "CraftItem") - return false; - CraftItem *mitem = (CraftItem*)item; - if(mitem->getSubName() != spec.name) - return false; - } - else if(spec.type == ITEM_TOOL) - { - // Not supported yet - assert(0); - } - else if(spec.type == ITEM_MBO) - { - // Not supported yet - assert(0); - } - else - { - // Not supported yet - assert(0); - } - } - - return true; -} - void Server::SendInventory(u16 peer_id) { DSTACK(__FUNCTION_NAME); |