From 3de176cc587c4e0601c3c3f5a049e30db6bd2c17 Mon Sep 17 00:00:00 2001 From: Perttu Ahola Date: Wed, 22 Dec 2010 16:30:23 +0200 Subject: [PATCH] crafting system! --- Makefile | 16 ++- data/coalstone.png | Bin 0 -> 1557 bytes makepackage_binary.sh | 5 +- minetest.vcproj | 4 + src/client.cpp | 18 +++ src/client.h | 1 + src/clientserver.h | 5 + src/guiInventoryMenu.cpp | 235 ++++++++++++++++++++++++--------------- src/guiInventoryMenu.h | 84 ++++++++++---- src/guiPauseMenu.cpp | 49 +++++++- src/inventory.cpp | 120 ++++++++++++++++++++ src/inventory.h | 69 ++++++++++++ src/main.cpp | 11 +- src/map.cpp | 33 +++++- src/mapnode.cpp | 2 + src/mapnode.h | 1 + src/player.cpp | 1 + src/server.cpp | 132 +++++++++++++++++++++- src/strfnd.h | 5 +- src/tile.cpp | 1 + src/tile.h | 1 + src/utility.h | 53 +++++++-- 22 files changed, 703 insertions(+), 143 deletions(-) create mode 100644 data/coalstone.png diff --git a/Makefile b/Makefile index aaeb9d7e3..6da2e64d1 100644 --- a/Makefile +++ b/Makefile @@ -6,16 +6,17 @@ SOURCE_FILES = guiInventoryMenu.cpp irrlichtwrapper.cpp guiPauseMenu.cpp default SOURCES = $(addprefix src/, $(SOURCE_FILES)) BUILD_DIR = build OBJECTS = $(addprefix $(BUILD_DIR)/, $(SOURCE_FILES:.cpp=.o)) -#OBJECTS = $(SOURCES:.cpp=.o) FAST_TARGET = fasttest +FAST_SOURCES = $(addprefix src/, $(SOURCE_FILES)) +FAST_BUILD_DIR = fastbuild +FAST_OBJECTS = $(addprefix $(FAST_BUILD_DIR)/, $(SOURCE_FILES:.cpp=.o)) SERVER_TARGET = server SERVER_SOURCE_FILES = defaultsettings.cpp mapnode.cpp voxel.cpp mapblockobject.cpp inventory.cpp debug.cpp serialization.cpp light.cpp filesys.cpp connection.cpp environment.cpp server.cpp socket.cpp mapblock.cpp mapsector.cpp heightmap.cpp map.cpp player.cpp utility.cpp servermain.cpp test.cpp SERVER_SOURCES = $(addprefix src/, $(SERVER_SOURCE_FILES)) SERVER_BUILD_DIR = serverbuild SERVER_OBJECTS = $(addprefix $(SERVER_BUILD_DIR)/, $(SERVER_SOURCE_FILES:.cpp=.o)) -#SERVER_OBJECTS = $(SERVER_SOURCES:.cpp=.o) IRRLICHTPATH = ../irrlicht/irrlicht-1.7.1 JTHREADPATH = ../jthread/jthread-1.2.1 @@ -58,19 +59,21 @@ SERVER_DESTPATH = bin/$(SERVER_TARGET)$(SUF) # Build commands all_linux all_win32: $(BUILD_DIR) $(DESTPATH) -fast_linux: $(BUILD_DIR) $(FAST_DESTPATH) +fast_linux: $(FAST_BUILD_DIR) $(FAST_DESTPATH) server_linux: $(SERVER_BUILD_DIR) $(SERVER_DESTPATH) $(BUILD_DIR): mkdir -p $(BUILD_DIR) +$(FAST_BUILD_DIR): + mkdir -p $(FAST_BUILD_DIR) $(SERVER_BUILD_DIR): mkdir -p $(SERVER_BUILD_DIR) $(DESTPATH): $(OBJECTS) $(CXX) -o $@ $(OBJECTS) $(LDFLAGS) -$(FAST_DESTPATH): $(OBJECTS) - $(CXX) -o $@ $(OBJECTS) $(LDFLAGS) -DUNITTEST_DISABLE +$(FAST_DESTPATH): $(FAST_OBJECTS) + $(CXX) -o $@ $(FAST_OBJECTS) $(LDFLAGS) -DUNITTEST_DISABLE $(SERVER_DESTPATH): $(SERVER_OBJECTS) $(CXX) -o $@ $(SERVER_OBJECTS) $(LDFLAGS) -DSERVER -DUNITTEST_DISABLE @@ -78,6 +81,9 @@ $(SERVER_DESTPATH): $(SERVER_OBJECTS) $(BUILD_DIR)/%.o: src/%.cpp $(CXX) -c -o $@ $< $(CPPFLAGS) $(CXXFLAGS) +$(FAST_BUILD_DIR)/%.o: src/%.cpp + $(CXX) -c -o $@ $< $(CPPFLAGS) $(CXXFLAGS) + $(SERVER_BUILD_DIR)/%.o: src/%.cpp $(CXX) -c -o $@ $< $(CPPFLAGS) $(CXXFLAGS) diff --git a/data/coalstone.png b/data/coalstone.png new file mode 100644 index 0000000000000000000000000000000000000000..c993a02f04648f724961ca602c489a917d54fb86 GIT binary patch literal 1557 zcmZuv3s99s6h0s($YTT~9~ch!SCABFrG|h47ir;2cmpLx1w|$G=!GH?(^2#~0#16j z!4NM#c&Y@6F>8bwK}w(qN`$)Dn3#ct7@3+nY{yJ!D7XTQfesbQf()+5J{ z1ORLDu1X`%QO0F%D)+tmxM={xAWR(|D6gV#iM~U~n=pQybH*5@6cGs_ilT4;20#H2 zfB-16YRE6nfia*I5P=X-{x69GXTT^>1SCKd`O=WGq40t+PANmAgrK4bN;x7UgvuC^ z6T)Ob2$#F0DmdeeGKv%l5``#CFv=-1B$OzqP(hI+VML({3M5=+C`1sYub%TkXoRu; zfJo_cOzF=vSjokREb)h$Cj{f1GA0WNqRgP2BV&Y886)TNeHjqW<*tY!>;)5?a)yi& zijprC962M5N*yRT;Y{iyf=k`T>VaU=nf`dvz~_*%xzA7~6$#u2Kg2m0=$yRvmtt(P zpo}AB1gSz06h6pnkVO004aoSQ3PPDc$_dIIP*8B7T;q&T!H`qJWakK=)H!e(2n_6x zBng}XLy+kL7zfG#sT^A-fO1IzBv9Yi@S3R^fN3L9`GvbSB<`K5wvUH%q9)s?q~*c2 zs!NwIzc{ic*L&@@`Tl8fvGMn8)w@zHrnKLRy%{}L9c7hnnfk*~3pR}8DYOHr}td<`EEzwqum?7Z>w0mAS|;`6RfrUtj(!mp?1B8 zR-}ool1iqMgt@&(*nM;(`Bh+iIV$G34kH;3H=jLl7^51T7n)Pu_l1{TE#d6zci*ChwQ%Whvnfixz&l(az=Iu8wdW_ZxpUAv?6fzj$kMvXkob-E*>Lb$^im z@YIJDj!)C?KDl12%BuXa@ya8|iCv$RM|J(-k@JnVgSX7seWCtBiU8|9R@OGBz0V8> zZRbU_s-8DCJM)C@eM58HE$7M!uRM5IZRcj=bEmVuC(7%fA*Hs5dm>Y_>W3cmh(Vg9zNgyD;)uk$iE zwUebD2QJ=AF}RO-sq}Pdfs0-GI_xsnRkbY7jYuq*SQ4l^o~QomdMp2VOh)y1ti503 z7I7x0IXSt$`@kd5{Yww~ns+&=mM0eMjO=M_U7KOM?2Y|;I(6g0o-rZW-s + + 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 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 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 rect2(rect.UpperLeftCorner, (core::dimension2d(rect.getWidth(), 15))); @@ -63,62 +64,13 @@ 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); } } } -/* - GUIInventorySlot -*/ - -GUIInventorySlot::GUIInventorySlot(gui::IGUIEnvironment* env, - gui::IGUIElement* parent, s32 id, core::rect 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"<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 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))); } -void GUIInventoryMenu::update() +GUIInventoryMenu::ItemSpec GUIInventoryMenu::getItemAtPos(v2s32 p) const { + core::rect imgrect(0,0,imgsize.X,imgsize.Y); + + for(u32 i=0; i rect = imgrect + s.pos + p0; + if(rect.isPointInside(p)) + { + return ItemSpec(s.listname, i); + } + } + } + + return ItemSpec("", -1); +} + +//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 imgrect(0,0,imgsize.X,imgsize.Y); + + for(s32 i=0; i 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(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; igetList("main"); - if(ilist != NULL) - { - core::rect imgsize(0,0,48,48); - v2s32 basepos(30, 210); - basepos += AbsoluteRect.UpperLeftCorner; - for(s32 i=0; i rect = imgsize + basepos + p; - drawInventoryItem(Environment, ilist->getItem(i), - rect, &AbsoluteClippingRect); - } - } - } - - { - InventoryList *ilist = m_inventory->getList("craft"); - if(ilist != NULL) - { - core::rect 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 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=("<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"<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 rect, const core::rect *clip=0); -class GUIInventorySlot: public gui::IGUIElement -{ -public: - GUIInventorySlot(gui::IGUIEnvironment* env, - gui::IGUIElement* parent, s32 id, core::rect rect); - - void setItem(InventoryItem *item) - { - m_item = item; - } - - void draw(); - - bool OnEvent(const SEvent& event); - -private: - InventoryItem *m_item; -}; - class GUIInventoryMenu : public gui::IGUIElement { + struct ItemSpec + { + 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; + }; + 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 m_draw_positions; + Inventory *m_inventory; v2u32 m_screensize_old; + + ItemSpec *m_selected_item; + + Queue 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 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 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 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 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; igetName()) + { + MaterialItem *mitem = (MaterialItem*)item; + if(mitem->getCount() < count) + { + dstream<<__FUNCTION_NAME<<": decrementMaterials():" + <<" too small material count"<getCount() == count) + { + deleteItem(i); + } + else + { + mitem->remove(1); + } + } + } +} + void InventoryList::print(std::ostream &o) { o<<"InventoryList:"<getItem(from_i)="<getItem(from_i) + <getItem(to_i)="<getItem(to_i) + <getItem(from_i) == NULL + || (list_from == list_to && from_i == to_i)) + { + dstream<<__FUNCTION_NAME<<": Operation not allowed"<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 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<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; igetNode(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(""); 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" + <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" + <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 -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= '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 +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::Iterator begin = m_list.begin(); + T t = *begin; + m_list.erase(begin); + return t; + } + + u32 size() + { + return m_list.size(); + } + +protected: + core::list m_list; +}; + +/* + Thread-safe FIFO queue */ template