diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/client.cpp | 18 | ||||
-rw-r--r-- | src/client.h | 1 | ||||
-rw-r--r-- | src/clientserver.h | 5 | ||||
-rw-r--r-- | src/guiInventoryMenu.cpp | 235 | ||||
-rw-r--r-- | src/guiInventoryMenu.h | 82 | ||||
-rw-r--r-- | src/guiPauseMenu.cpp | 49 | ||||
-rw-r--r-- | src/inventory.cpp | 120 | ||||
-rw-r--r-- | src/inventory.h | 69 | ||||
-rw-r--r-- | src/main.cpp | 11 | ||||
-rw-r--r-- | src/map.cpp | 33 | ||||
-rw-r--r-- | src/mapnode.cpp | 2 | ||||
-rw-r--r-- | src/mapnode.h | 1 | ||||
-rw-r--r-- | src/player.cpp | 1 | ||||
-rw-r--r-- | src/server.cpp | 132 | ||||
-rw-r--r-- | src/strfnd.h | 5 | ||||
-rw-r--r-- | src/tile.cpp | 1 | ||||
-rw-r--r-- | src/tile.h | 1 | ||||
-rw-r--r-- | src/utility.h | 53 |
18 files changed, 683 insertions, 136 deletions
diff --git a/src/client.cpp b/src/client.cpp index a5d035d3f..32f62e3ba 100644 --- a/src/client.cpp +++ b/src/client.cpp @@ -1540,6 +1540,24 @@ void Client::sendSignText(v3s16 blockpos, s16 id, std::string text) // Send as reliable Send(0, data, true); } + +void Client::sendInventoryAction(InventoryAction *a) +{ + std::ostringstream os(std::ios_base::binary); + u8 buf[12]; + + // Write command + writeU16(buf, TOSERVER_INVENTORY_ACTION); + os.write((char*)buf, 2); + + a->serialize(os); + + // Make data buffer + std::string s = os.str(); + SharedBuffer<u8> data((u8*)s.c_str(), s.size()); + // Send as reliable + Send(0, data, true); +} void Client::sendPlayerPos() { diff --git a/src/client.h b/src/client.h index a3d43997c..bfec7730d 100644 --- a/src/client.h +++ b/src/client.h @@ -190,6 +190,7 @@ public: void clickObject(u8 button, v3s16 blockpos, s16 id, u16 item); void sendSignText(v3s16 blockpos, s16 id, std::string text); + void sendInventoryAction(InventoryAction *a); void updateCamera(v3f pos, v3f dir); diff --git a/src/clientserver.h b/src/clientserver.h index 5e919b2f7..c8a114841 100644 --- a/src/clientserver.h +++ b/src/clientserver.h @@ -191,6 +191,11 @@ enum ToServerCommand u16 textlen textdata */ + + TOSERVER_INVENTORY_ACTION = 0x31, + /* + See InventoryAction in inventory.h + */ }; inline SharedBuffer<u8> makePacket_TOCLIENT_TIME_OF_DAY(u16 time) diff --git a/src/guiInventoryMenu.cpp b/src/guiInventoryMenu.cpp index 7bc5ca9e0..88cb8c830 100644 --- a/src/guiInventoryMenu.cpp +++ b/src/guiInventoryMenu.cpp @@ -55,7 +55,8 @@ void drawInventoryItem(gui::IGUIEnvironment* env, if(item != NULL) { gui::IGUIFont *font = skin->getFont(); - if(font) + std::string text = item->getText(); + if(font && text != "") { core::rect<s32> rect2(rect.UpperLeftCorner, (core::dimension2d<u32>(rect.getWidth(), 15))); @@ -63,7 +64,7 @@ void drawInventoryItem(gui::IGUIEnvironment* env, video::SColor bgcolor(128,0,0,0); driver->draw2DRectangle(bgcolor, rect2, clip); - font->draw(item->getText().c_str(), rect2, + font->draw(text.c_str(), rect2, video::SColor(255,255,255,255), false, false, clip); } @@ -71,55 +72,6 @@ void drawInventoryItem(gui::IGUIEnvironment* env, } /* - GUIInventorySlot -*/ - -GUIInventorySlot::GUIInventorySlot(gui::IGUIEnvironment* env, - gui::IGUIElement* parent, s32 id, core::rect<s32> rect): - IGUIElement(gui::EGUIET_ELEMENT, env, parent, id, rect) -{ - m_item = NULL; -} - -void GUIInventorySlot::draw() -{ - if(!IsVisible) - return; - - drawInventoryItem(Environment, m_item, AbsoluteRect, - &AbsoluteClippingRect); - - gui::IGUIElement::draw(); -} - -bool GUIInventorySlot::OnEvent(const SEvent& event) -{ - /*if (!IsEnabled) - return IGUIElement::OnEvent(event);*/ - - switch(event.EventType) - { - case EET_MOUSE_INPUT_EVENT: - if (event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) - { - dstream<<"Slot pressed"<<std::endl; - //return true; - } - else - if (event.MouseInput.Event == EMIE_LMOUSE_LEFT_UP) - { - dstream<<"Slot released"<<std::endl; - //return true; - } - break; - default: - break; - } - - return Parent ? Parent->OnEvent(event) : false; -} - -/* GUIInventoryMenu */ @@ -131,14 +83,21 @@ GUIInventoryMenu::GUIInventoryMenu(gui::IGUIEnvironment* env, { m_inventory = inventory; m_screensize_old = v2u32(0,0); + m_selected_item = NULL; resizeGui(); setVisible(false); + + /*m_selected_item = new ItemSpec; + m_selected_item->listname = "main"; + m_selected_item->i = 3;*/ } GUIInventoryMenu::~GUIInventoryMenu() { + if(m_selected_item) + delete m_selected_item; } void GUIInventoryMenu::resizeGui() @@ -149,19 +108,90 @@ void GUIInventoryMenu::resizeGui() return; m_screensize_old = screensize; + padding = v2s32(24,24); + spacing = v2s32(60,56); + imgsize = v2s32(48,48); + + v2s32 size( + padding.X*2+spacing.X*(8-1)+imgsize.X, + padding.Y*2+spacing.Y*(7-1)+imgsize.Y + ); + core::rect<s32> rect( - screensize.X/2 - 560/2, - screensize.Y/2 - 480/2, - screensize.X/2 + 560/2, - screensize.Y/2 + 480/2 + screensize.X/2 - size.X/2, + screensize.Y/2 - size.Y/2, + screensize.X/2 + size.X/2, + screensize.Y/2 + size.Y/2 ); DesiredRect = rect; recalculateAbsolutePosition(false); + + v2s32 basepos = getBasePos(); + + m_draw_positions.clear(); + m_draw_positions.push_back(ListDrawSpec("main", + basepos + v2s32(spacing.X*0, spacing.Y*3), v2s32(8, 4))); + m_draw_positions.push_back(ListDrawSpec("craft", + basepos + v2s32(spacing.X*3, spacing.Y*0), v2s32(3, 3))); + m_draw_positions.push_back(ListDrawSpec("craftresult", + basepos + v2s32(spacing.X*7, spacing.Y*1), v2s32(1, 1))); +} + +GUIInventoryMenu::ItemSpec GUIInventoryMenu::getItemAtPos(v2s32 p) const +{ + core::rect<s32> imgrect(0,0,imgsize.X,imgsize.Y); + + for(u32 i=0; i<m_draw_positions.size(); i++) + { + const ListDrawSpec &s = m_draw_positions[i]; + + for(s32 i=0; i<s.geom.X*s.geom.Y; i++) + { + s32 x = (i%s.geom.X) * spacing.X; + s32 y = (i/s.geom.X) * spacing.Y; + v2s32 p0(x,y); + core::rect<s32> rect = imgrect + s.pos + p0; + if(rect.isPointInside(p)) + { + return ItemSpec(s.listname, i); + } + } + } + + return ItemSpec("", -1); } -void GUIInventoryMenu::update() +//void GUIInventoryMenu::drawList(const std::string &name, v2s32 pos, v2s32 geom) +void GUIInventoryMenu::drawList(const ListDrawSpec &s) { + video::IVideoDriver* driver = Environment->getVideoDriver(); + + InventoryList *ilist = m_inventory->getList(s.listname); + + core::rect<s32> imgrect(0,0,imgsize.X,imgsize.Y); + + for(s32 i=0; i<s.geom.X*s.geom.Y; i++) + { + s32 x = (i%s.geom.X) * spacing.X; + s32 y = (i/s.geom.X) * spacing.Y; + v2s32 p(x,y); + core::rect<s32> rect = imgrect + s.pos + p; + InventoryItem *item = NULL; + if(ilist) + item = ilist->getItem(i); + + if(m_selected_item != NULL && m_selected_item->listname == s.listname + && m_selected_item->i == i) + { + driver->draw2DRectangle(video::SColor(255,255,0,0), + core::rect<s32>(rect.UpperLeftCorner - v2s32(2,2), + rect.LowerRightCorner + v2s32(2,2)), + &AbsoluteClippingRect); + } + drawInventoryItem(Environment, item, + rect, &AbsoluteClippingRect); + } } void GUIInventoryMenu::draw() @@ -181,42 +211,10 @@ void GUIInventoryMenu::draw() Draw items */ + for(u32 i=0; i<m_draw_positions.size(); i++) { - InventoryList *ilist = m_inventory->getList("main"); - if(ilist != NULL) - { - core::rect<s32> imgsize(0,0,48,48); - v2s32 basepos(30, 210); - basepos += AbsoluteRect.UpperLeftCorner; - for(s32 i=0; i<PLAYER_INVENTORY_SIZE; i++) - { - s32 x = (i%8) * 64; - s32 y = (i/8) * 64; - v2s32 p(x,y); - core::rect<s32> rect = imgsize + basepos + p; - drawInventoryItem(Environment, ilist->getItem(i), - rect, &AbsoluteClippingRect); - } - } - } - - { - InventoryList *ilist = m_inventory->getList("craft"); - if(ilist != NULL) - { - core::rect<s32> imgsize(0,0,48,48); - v2s32 basepos(30, 30); - basepos += AbsoluteRect.UpperLeftCorner; - for(s32 i=0; i<9; i++) - { - s32 x = (i%3) * 64; - s32 y = (i/3) * 64; - v2s32 p(x,y); - core::rect<s32> rect = imgsize + basepos + p; - drawInventoryItem(Environment, ilist->getItem(i), - rect, &AbsoluteClippingRect); - } - } + ListDrawSpec &s = m_draw_positions[i]; + drawList(s); } /* @@ -244,6 +242,54 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event) { if(event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN) { + v2s32 p(event.MouseInput.X, event.MouseInput.Y); + //dstream<<"Mouse down at p=("<<p.X<<","<<p.Y<<")"<<std::endl; + ItemSpec s = getItemAtPos(p); + if(s.isValid()) + { + //dstream<<"Mouse down on "<<s.listname<<" "<<s.i<<std::endl; + if(m_selected_item) + { + InventoryList *list_from = + m_inventory->getList(m_selected_item->listname); + InventoryList *list_to = + m_inventory->getList(s.listname); + if(list_from && list_to + && list_from->getItem(m_selected_item->i) != NULL) + { + dstream<<"Queueing IACTION_MOVE"<<std::endl; + IMoveAction *a = + new IMoveAction(); + a->count = 1; + a->from_name = m_selected_item->listname; + a->from_i = m_selected_item->i; + a->to_name = s.listname; + a->to_i = s.i; + m_actions.push_back(a); + } + delete m_selected_item; + m_selected_item = NULL; + } + else + { + /* + Select if non-NULL + */ + InventoryList *list = m_inventory->getList(s.listname); + if(list->getItem(s.i) != NULL) + { + m_selected_item = new ItemSpec(s); + } + } + } + else + { + if(m_selected_item) + { + delete m_selected_item; + m_selected_item = NULL; + } + } } } if(event.EventType==EET_GUI_EVENT) @@ -276,4 +322,11 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event) return Parent ? Parent->OnEvent(event) : false; } +InventoryAction* GUIInventoryMenu::getNextAction() +{ + if(m_actions.size() == 0) + return NULL; + return m_actions.pop_front(); +} + diff --git a/src/guiInventoryMenu.h b/src/guiInventoryMenu.h index b581a1166..0032ce66a 100644 --- a/src/guiInventoryMenu.h +++ b/src/guiInventoryMenu.h @@ -23,32 +23,51 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "common_irrlicht.h" #include "inventory.h" +#include "utility.h" void drawInventoryItem(gui::IGUIEnvironment* env, InventoryItem *item, core::rect<s32> rect, const core::rect<s32> *clip=0); -class GUIInventorySlot: public gui::IGUIElement +class GUIInventoryMenu : public gui::IGUIElement { -public: - GUIInventorySlot(gui::IGUIEnvironment* env, - gui::IGUIElement* parent, s32 id, core::rect<s32> rect); - - void setItem(InventoryItem *item) + struct ItemSpec { - m_item = item; - } - - void draw(); - - bool OnEvent(const SEvent& event); - -private: - InventoryItem *m_item; -}; + ItemSpec() + { + i = -1; + } + ItemSpec(const std::string &a_name, s32 a_i) + { + listname = a_name; + i = a_i; + } + bool isValid() const + { + return i != -1; + } + + std::string listname; + s32 i; + }; + + struct ListDrawSpec + { + ListDrawSpec() + { + } + ListDrawSpec(const std::string &a_name, v2s32 a_pos, v2s32 a_geom) + { + listname = a_name; + pos = a_pos; + geom = a_geom; + } + + std::string listname; + v2s32 pos; + v2s32 geom; + }; -class GUIInventoryMenu : public gui::IGUIElement -{ public: GUIInventoryMenu(gui::IGUIEnvironment* env, gui::IGUIElement* parent, s32 id, @@ -59,11 +78,9 @@ public: Remove and re-add (or reposition) stuff */ void resizeGui(); - - // Updates stuff from inventory to screen - // TODO: Remove, not used - void update(); - + + ItemSpec getItemAtPos(v2s32 p) const; + void drawList(const ListDrawSpec &s); void draw(); void launch() @@ -79,9 +96,28 @@ public: bool OnEvent(const SEvent& event); + // Actions returned by this are sent to the server. + // Server replies by updating the inventory. + InventoryAction* getNextAction(); + private: + v2s32 getBasePos() const + { + return padding + AbsoluteRect.UpperLeftCorner; + } + + v2s32 padding; + v2s32 spacing; + v2s32 imgsize; + + core::array<ListDrawSpec> m_draw_positions; + Inventory *m_inventory; v2u32 m_screensize_old; + + ItemSpec *m_selected_item; + + Queue<InventoryAction*> m_actions; }; #endif diff --git a/src/guiPauseMenu.cpp b/src/guiPauseMenu.cpp index 73e406e18..b8f0473e8 100644 --- a/src/guiPauseMenu.cpp +++ b/src/guiPauseMenu.cpp @@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include "guiPauseMenu.h"
#include "debug.h"
+#include "serialization.h"
GUIPauseMenu::GUIPauseMenu(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id,
@@ -49,6 +50,9 @@ void GUIPauseMenu::resizeGui() return;
m_screensize_old = screensize;
+ /*
+ Remove stuff
+ */
{
gui::IGUIElement *e = getElementFromId(256);
if(e != NULL)
@@ -59,11 +63,21 @@ void GUIPauseMenu::resizeGui() if(e != NULL)
e->remove();
}
+ {
+ gui::IGUIElement *e = getElementFromId(258);
+ if(e != NULL)
+ e->remove();
+ }
+ {
+ gui::IGUIElement *e = getElementFromId(259);
+ if(e != NULL)
+ e->remove();
+ }
core::rect<s32> rect(
- screensize.X/2 - 560/2,
+ screensize.X/2 - 580/2,
screensize.Y/2 - 300/2,
- screensize.X/2 + 560/2,
+ screensize.X/2 + 580/2,
screensize.Y/2 + 300/2
);
@@ -72,6 +86,9 @@ void GUIPauseMenu::resizeGui() v2s32 size = rect.getSize();
+ /*
+ Add stuff
+ */
{
core::rect<s32> rect(0, 0, 140, 30);
rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2-25);
@@ -82,6 +99,34 @@ void GUIPauseMenu::resizeGui() rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2+25);
Environment->addButton(rect, this, 257, L"Exit");
}
+ {
+ core::rect<s32> rect(0, 0, 180, 220);
+ rect = rect + v2s32(size.X/2 + 90, size.Y/2-rect.getHeight()/2);
+ const wchar_t *text =
+ L"Keys:\n"
+ L"- WASD: Walk\n"
+ L"- Mouse left: dig blocks\n"
+ L"- Mouse right: place blocks\n"
+ L"- Mouse wheel: select item\n"
+ L"- R: Toggle viewing all loaded chunks\n"
+ L"- I: Inventory menu\n"
+ L"- ESC: This menu\n"
+ L"\n"
+ L"To generate a new map, remove the map directory.\n";
+ Environment->addStaticText(text, rect, false, true, this, 258);
+ }
+ {
+ core::rect<s32> rect(0, 0, 180, 220);
+ rect = rect + v2s32(size.X/2 - 90 - rect.getWidth(), size.Y/2-rect.getHeight()/2);
+ wchar_t text[200];
+ swprintf(text, 200,
+ L"Minetest-c55\n"
+ L"SER_FMT_VER_HIGHEST=%i",
+ (int)SER_FMT_VER_HIGHEST
+ );
+
+ Environment->addStaticText(text, rect, false, true, this, 259);
+ }
}
void GUIPauseMenu::draw()
diff --git a/src/inventory.cpp b/src/inventory.cpp index 069355aff..073477dde 100644 --- a/src/inventory.cpp +++ b/src/inventory.cpp @@ -348,6 +348,71 @@ bool InventoryList::addItem(InventoryItem *newitem) return false; } +bool InventoryList::addItem(u32 i, InventoryItem *newitem) +{ + // If it is an empty position, it's an easy job. + InventoryItem *item = m_items[i]; + if(item == NULL) + { + m_items[i] = newitem; + return true; + } + + // If it is a material item, try to + if(std::string("MaterialItem") == newitem->getName()) + { + u8 material = ((MaterialItem*)newitem)->getMaterial(); + u8 count = ((MaterialItem*)newitem)->getCount(); + InventoryItem *item2 = m_items[i]; + + if(item2 != NULL + && std::string("MaterialItem") == item2->getName()) + { + // Check if it is of the right material and has free space + MaterialItem *mitem2 = (MaterialItem*)item2; + if(mitem2->getMaterial() == material + && mitem2->freeSpace() >= count) + { + // Add to the counter + mitem2->add(count); + // Dump the parameter + delete newitem; + // Done + return true; + } + } + } + + return false; +} + +void InventoryList::decrementMaterials(u16 count) +{ + for(u32 i=0; i<m_items.size(); i++) + { + InventoryItem *item = m_items[i]; + if(item == NULL) + continue; + if(std::string("MaterialItem") == item->getName()) + { + MaterialItem *mitem = (MaterialItem*)item; + if(mitem->getCount() < count) + { + dstream<<__FUNCTION_NAME<<": decrementMaterials():" + <<" too small material count"<<std::endl; + } + else if(mitem->getCount() == count) + { + deleteItem(i); + } + else + { + mitem->remove(1); + } + } + } +} + void InventoryList::print(std::ostream &o) { o<<"InventoryList:"<<std::endl; @@ -487,5 +552,60 @@ s32 Inventory::getListIndex(const std::string &name) return -1; } +/* + InventoryAction +*/ + +InventoryAction * InventoryAction::deSerialize(std::istream &is) +{ + std::string type; + std::getline(is, type, ' '); + + InventoryAction *a = NULL; + + if(type == "Move") + { + a = new IMoveAction(is); + } + + return a; +} + +void IMoveAction::apply(Inventory *inventory) +{ + /*dstream<<"from_name="<<from_name<<" to_name="<<to_name<<std::endl; + dstream<<"from_i="<<from_i<<" to_i="<<to_i<<std::endl;*/ + InventoryList *list_from = inventory->getList(from_name); + InventoryList *list_to = inventory->getList(to_name); + /*dstream<<"list_from="<<list_from<<" list_to="<<list_to + <<std::endl;*/ + /*if(list_from) + dstream<<" list_from->getItem(from_i)="<<list_from->getItem(from_i) + <<std::endl; + if(list_to) + dstream<<" list_to->getItem(to_i)="<<list_to->getItem(to_i) + <<std::endl;*/ + + if(!list_from || !list_to || list_from->getItem(from_i) == NULL + || (list_from == list_to && from_i == to_i)) + { + dstream<<__FUNCTION_NAME<<": Operation not allowed"<<std::endl; + return; + } + + // Take item from source list + InventoryItem *item1 = list_from->changeItem(from_i, NULL); + // Try to add the item to destination list + if(list_to->addItem(to_i, item1)) + { + // Done. + return; + } + // Adding was not possible, switch it. + // Switch it to the destination list + InventoryItem *item2 = list_to->changeItem(to_i, item1); + // Put item from destination list to the source list + list_from->changeItem(from_i, item2); +} //END diff --git a/src/inventory.h b/src/inventory.h index d37761cfe..ad3b297e8 100644 --- a/src/inventory.h +++ b/src/inventory.h @@ -213,12 +213,20 @@ public: // Count used slots u32 getUsedSlots(); + // Get pointer to item InventoryItem * getItem(u32 i); // Returns old item (or NULL). Parameter can be NULL. InventoryItem * changeItem(u32 i, InventoryItem *newitem); + // Delete item void deleteItem(u32 i); // Adds an item to a suitable place. Returns false if failed. bool addItem(InventoryItem *newitem); + // If possible, adds item to given slot. Returns true on success. + // Fails when slot is populated by a different kind of item. + bool addItem(u32 i, InventoryItem *newitem); + + // Decrements amount of every material item + void decrementMaterials(u16 count); void print(std::ostream &o); @@ -261,5 +269,66 @@ private: core::array<InventoryList*> m_lists; }; +#define IACTION_MOVE 0 + +struct InventoryAction +{ + static InventoryAction * deSerialize(std::istream &is); + + virtual u16 getType() const = 0; + virtual void serialize(std::ostream &os) = 0; + virtual void apply(Inventory *inventory) = 0; +}; + +struct IMoveAction : public InventoryAction +{ + u16 count; + std::string from_name; + s16 from_i; + std::string to_name; + s16 to_i; + + IMoveAction() + { + count = 0; + from_i = -1; + to_i = -1; + } + IMoveAction(std::istream &is) + { + std::string ts; + + std::getline(is, ts, ' '); + count = stoi(ts); + + std::getline(is, from_name, ' '); + + std::getline(is, ts, ' '); + from_i = stoi(ts); + + std::getline(is, to_name, ' '); + + std::getline(is, ts, ' '); + to_i = stoi(ts); + } + + u16 getType() const + { + return IACTION_MOVE; + } + + void serialize(std::ostream &os) + { + os<<"Move "; + os<<count<<" "; + os<<from_name<<" "; + os<<from_i<<" "; + os<<to_name<<" "; + os<<to_i; + } + + void apply(Inventory *inventory); +}; + #endif diff --git a/src/main.cpp b/src/main.cpp index 7fecbe3bd..cbca1df34 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2304,7 +2304,16 @@ int main(int argc, char *argv[]) client.getLocalInventory(local_inventory);
quick_inventory->setSelection(g_selected_item);
quick_inventory->update();
- inventoryMenu->update();
+ }
+
+ /*
+ Send actions returned by the inventory menu
+ */
+ while(InventoryAction *a = inventoryMenu->getNextAction())
+ {
+ client.sendInventoryAction(a);
+ // Eat it
+ delete a;
}
if(input_guitext != NULL)
diff --git a/src/map.cpp b/src/map.cpp index 839efbf5b..700312fb2 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -1947,11 +1947,10 @@ MapBlock * ServerMap::emergeBlock( Add some minerals */ - //if(is_underground) if(some_part_underground) { s16 underground_level = (lowest_ground_y/MAP_BLOCKSIZE - block_y)+1; - for(s16 i=0; i<underground_level*3; i++) + for(s16 i=0; i<underground_level*1; i++) { if(rand()%2 == 0) { @@ -1978,6 +1977,36 @@ MapBlock * ServerMap::emergeBlock( } } } + + if(rand()%3 == 0) + { + for(s16 i=0; i<20; i++) + { + v3s16 cp( + (rand()%(MAP_BLOCKSIZE-2))+1, + (rand()%(MAP_BLOCKSIZE-2))+1, + (rand()%(MAP_BLOCKSIZE-2))+1 + ); + + MapNode n; + n.d = CONTENT_COALSTONE; + + //dstream<<"Adding coalstone"<<std::endl; + + //if(is_ground_content(block->getNode(cp).d)) + if(block->getNode(cp).d == CONTENT_STONE) + if(rand()%8 == 0) + block->setNode(cp, n); + + for(u16 i=0; i<26; i++) + { + //if(is_ground_content(block->getNode(cp+g_26dirs[i]).d)) + if(block->getNode(cp+g_26dirs[i]).d == CONTENT_STONE) + if(rand()%8 == 0) + block->setNode(cp+g_26dirs[i], n); + } + } + } } /* diff --git a/src/mapnode.cpp b/src/mapnode.cpp index c41560ee5..a8e9f07fc 100644 --- a/src/mapnode.cpp +++ b/src/mapnode.cpp @@ -42,6 +42,7 @@ u16 g_content_tiles[USEFUL_CONTENT_COUNT][6] = {TILE_MUD,TILE_MUD,TILE_MUD,TILE_MUD,TILE_MUD,TILE_MUD}, {TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER,TILE_WATER}, {TILE_CLOUD,TILE_CLOUD,TILE_CLOUD,TILE_CLOUD,TILE_CLOUD,TILE_CLOUD}, + {TILE_COALSTONE,TILE_COALSTONE,TILE_COALSTONE,TILE_COALSTONE,TILE_COALSTONE,TILE_COALSTONE}, }; const char * g_content_inventory_textures[USEFUL_CONTENT_COUNT] = @@ -57,5 +58,6 @@ const char * g_content_inventory_textures[USEFUL_CONTENT_COUNT] = "../data/mud.png", "../data/water.png", "../data/cloud.png", + "../data/coalstone.png", }; diff --git a/src/mapnode.h b/src/mapnode.h index f52bd52e7..20634bf76 100644 --- a/src/mapnode.h +++ b/src/mapnode.h @@ -76,6 +76,7 @@ enum Content CONTENT_MUD, CONTENT_OCEAN, CONTENT_CLOUD, + CONTENT_COALSTONE, // This is set to the number of the actual values in this enum USEFUL_CONTENT_COUNT diff --git a/src/player.cpp b/src/player.cpp index e6caff03c..ef09fae6a 100644 --- a/src/player.cpp +++ b/src/player.cpp @@ -36,6 +36,7 @@ Player::Player(): updateName("<not set>"); inventory.addList("main", PLAYER_INVENTORY_SIZE); inventory.addList("craft", 9); + inventory.addList("craftresult", 1); } Player::~Player() diff --git a/src/server.cpp b/src/server.cpp index 9952cb8eb..ddef11ae4 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -2027,6 +2027,79 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id) obj->getBlock()->setChangedFlag(); } + else if(command == TOSERVER_INVENTORY_ACTION) + { + // Ignore inventory changes if in creative mode + if(g_settings.getBool("creative_mode") == true) + { + dstream<<"TOSERVER_INVENTORY_ACTION: ignoring in creative mode" + <<std::endl; + return; + } + // Strip command and create a stream + std::string datastring((char*)&data[2], datasize-2); + dstream<<"TOSERVER_INVENTORY_ACTION: data="<<datastring<<std::endl; + std::istringstream is(datastring, std::ios_base::binary); + // Create an action + InventoryAction *a = InventoryAction::deSerialize(is); + if(a != NULL) + { + /* + Handle craftresult specially + */ + bool disable_action = false; + if(a->getType() == IACTION_MOVE) + { + IMoveAction *ma = (IMoveAction*)a; + // Don't allow moving anything to craftresult + if(ma->to_name == "craftresult") + { + // Do nothing + disable_action = true; + } + // When something is removed from craftresult + if(ma->from_name == "craftresult") + { + disable_action = true; + // Remove stuff from craft + InventoryList *clist = player->inventory.getList("craft"); + if(clist) + { + clist->decrementMaterials(ma->count); + } + // Do action + // Feed action to player inventory + a->apply(&player->inventory); + // Eat it + delete a; + // If something appeared in craftresult, throw it + // in the main list + InventoryList *rlist = player->inventory.getList("craftresult"); + InventoryList *mlist = player->inventory.getList("main"); + if(rlist && mlist && rlist->getUsedSlots() == 1) + { + InventoryItem *item1 = rlist->changeItem(0, NULL); + mlist->addItem(item1); + } + } + } + if(disable_action == false) + { + // Feed action to player inventory + a->apply(&player->inventory); + // Eat it + delete a; + } + // Send inventory + SendInventory(player->peer_id); + } + else + { + dstream<<"TOSERVER_INVENTORY_ACTION: " + <<"InventoryAction::deSerialize() returned NULL" + <<std::endl; + } + } else { derr_server<<"WARNING: Server::ProcessData(): Ignoring " @@ -2215,9 +2288,9 @@ void Server::peerAdded(con::Peer *peer) } else { - // Give some lights + /*// Give some lights { - InventoryItem *item = new MaterialItem(3, 999); + InventoryItem *item = new MaterialItem(CONTENT_TORCH, 999); bool r = player->inventory.addItem("main", item); assert(r == true); } @@ -2227,11 +2300,10 @@ void Server::peerAdded(con::Peer *peer) InventoryItem *item = new MapBlockObjectItem("Sign Example text"); bool r = player->inventory.addItem("main", item); assert(r == true); - } - /*// and some rats - for(u16 i=0; i<4; i++) + }*/ + /*// Give some other stuff { - InventoryItem *item = new MapBlockObjectItem("Rat"); + InventoryItem *item = new MaterialItem(CONTENT_TREE, 999); bool r = player->inventory.addItem("main", item); assert(r == true); }*/ @@ -2333,6 +2405,54 @@ void Server::SendInventory(u16 peer_id) Player* player = m_env.getPlayer(peer_id); + /* + Calculate crafting stuff + */ + + InventoryList *clist = player->inventory.getList("craft"); + InventoryList *rlist = player->inventory.getList("craftresult"); + if(rlist) + { + //rlist->clearItems(); + } + if(clist && rlist) + { + InventoryItem *items[9]; + for(u16 i=0; i<9; i++) + { + items[i] = clist->getItem(i); + } + // Sign + if(clist->getUsedSlots() == 1 && items[0]) + { + if((std::string)items[0]->getName() == "MaterialItem") + { + MaterialItem *mitem = (MaterialItem*)items[0]; + if(mitem->getMaterial() == CONTENT_TREE) + { + rlist->addItem(new MapBlockObjectItem("Sign")); + } + } + } + // Torch + if(clist->getUsedSlots() == 2 && items[0] && items[3]) + { + if( + (std::string)items[0]->getName() == "MaterialItem" + && ((MaterialItem*)items[0])->getMaterial() == CONTENT_COALSTONE + && (std::string)items[3]->getName() == "MaterialItem" + && ((MaterialItem*)items[3])->getMaterial() == CONTENT_TREE + ) + { + rlist->addItem(new MaterialItem(CONTENT_TORCH, 4)); + } + } + } + + /* + Serialize it + */ + std::ostringstream os; //os.imbue(std::locale("C")); diff --git a/src/strfnd.h b/src/strfnd.h index bbd0fa1e0..2be92d43b 100644 --- a/src/strfnd.h +++ b/src/strfnd.h @@ -22,7 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #include <string> -std::string trim(std::string str); +std::string trim(const std::string &str); class Strfnd{ std::string tek; @@ -74,8 +74,9 @@ public: } }; -inline std::string trim(std::string str) +inline std::string trim(const std::string &s) { + std::string str = s; while( str.length()>0 && diff --git a/src/tile.cpp b/src/tile.cpp index f2b131f4d..25d9c00d0 100644 --- a/src/tile.cpp +++ b/src/tile.cpp @@ -35,6 +35,7 @@ const char * g_tile_texture_paths[TILES_COUNT] = "../data/tree_top.png", "../data/mud_with_grass.png", "../data/cloud.png", + "../data/coalstone.png", }; const char * tile_texture_path_get(u32 i) diff --git a/src/tile.h b/src/tile.h index 68e87a77d..9823160c2 100644 --- a/src/tile.h +++ b/src/tile.h @@ -39,6 +39,7 @@ enum TileID TILE_TREE_TOP, TILE_MUD_WITH_GRASS, TILE_CLOUD, + TILE_COALSTONE, // Count of tile ids TILES_COUNT diff --git a/src/utility.h b/src/utility.h index 484b5828b..4e2e132e9 100644 --- a/src/utility.h +++ b/src/utility.h @@ -595,25 +595,28 @@ inline float wrapDegrees(float f) return f; } -inline std::string lowercase(std::string s) +inline std::string lowercase(const std::string &s) { + std::string s2; for(size_t i=0; i<s.size(); i++) { - if(s[i] >= 'A' && s[i] <= 'Z') - s[i] -= 'A' - 'a'; + char c = s[i]; + if(c >= 'A' && c <= 'Z') + c -= 'A' - 'a'; + s2 += c; } - return s; + return s2; } -inline bool is_yes(std::string s) +inline bool is_yes(const std::string &s) { - s = lowercase(trim(s)); - if(s == "y" || s == "yes" || s == "true") + std::string s2 = lowercase(trim(s)); + if(s2 == "y" || s2 == "yes" || s2 == "true") return true; return false; } -inline s32 stoi(std::string s, s32 min, s32 max) +inline s32 stoi(const std::string &s, s32 min, s32 max) { s32 i = atoi(s.c_str()); if(i < min) @@ -1067,7 +1070,39 @@ private: }; /* - A thread-safe queue + FIFO queue +*/ +template<typename T> +class Queue +{ +public: + void push_back(T t) + { + m_list.push_back(t); + } + + T pop_front() + { + if(m_list.size() == 0) + throw ItemNotFoundException("MutexedQueue: queue is empty"); + + typename core::list<T>::Iterator begin = m_list.begin(); + T t = *begin; + m_list.erase(begin); + return t; + } + + u32 size() + { + return m_list.size(); + } + +protected: + core::list<T> m_list; +}; + +/* + Thread-safe FIFO queue */ template<typename T> |