crafting system!
authorPerttu Ahola <celeron55@gmail.com>
Wed, 22 Dec 2010 14:30:23 +0000 (16:30 +0200)
committerPerttu Ahola <celeron55@gmail.com>
Wed, 22 Dec 2010 14:30:23 +0000 (16:30 +0200)
22 files changed:
Makefile
data/coalstone.png [new file with mode: 0644]
makepackage_binary.sh
minetest.vcproj
src/client.cpp
src/client.h
src/clientserver.h
src/guiInventoryMenu.cpp
src/guiInventoryMenu.h
src/guiPauseMenu.cpp
src/inventory.cpp
src/inventory.h
src/main.cpp
src/map.cpp
src/mapnode.cpp
src/mapnode.h
src/player.cpp
src/server.cpp
src/strfnd.h
src/tile.cpp
src/tile.h
src/utility.h

index aaeb9d7e3ed68e5534869f6f92f250301eca69ec..6da2e64d1dfef545868b7da5d3fc08a6a7a42214 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -6,16 +6,17 @@ SOURCE_FILES = guiInventoryMenu.cpp irrlichtwrapper.cpp guiPauseMenu.cpp default
 SOURCES = $(addprefix src/, $(SOURCE_FILES))\r
 BUILD_DIR = build\r
 OBJECTS = $(addprefix $(BUILD_DIR)/, $(SOURCE_FILES:.cpp=.o))\r
-#OBJECTS = $(SOURCES:.cpp=.o)\r
 \r
 FAST_TARGET = fasttest\r
+FAST_SOURCES = $(addprefix src/, $(SOURCE_FILES))\r
+FAST_BUILD_DIR = fastbuild\r
+FAST_OBJECTS = $(addprefix $(FAST_BUILD_DIR)/, $(SOURCE_FILES:.cpp=.o))\r
 \r
 SERVER_TARGET = server\r
 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\r
 SERVER_SOURCES = $(addprefix src/, $(SERVER_SOURCE_FILES))\r
 SERVER_BUILD_DIR = serverbuild\r
 SERVER_OBJECTS = $(addprefix $(SERVER_BUILD_DIR)/, $(SERVER_SOURCE_FILES:.cpp=.o))\r
-#SERVER_OBJECTS = $(SERVER_SOURCES:.cpp=.o)\r
 \r
 IRRLICHTPATH = ../irrlicht/irrlicht-1.7.1\r
 JTHREADPATH = ../jthread/jthread-1.2.1\r
@@ -58,19 +59,21 @@ SERVER_DESTPATH = bin/$(SERVER_TARGET)$(SUF)
 # Build commands\r
 \r
 all_linux all_win32: $(BUILD_DIR) $(DESTPATH)\r
-fast_linux: $(BUILD_DIR) $(FAST_DESTPATH)\r
+fast_linux: $(FAST_BUILD_DIR) $(FAST_DESTPATH)\r
 server_linux: $(SERVER_BUILD_DIR) $(SERVER_DESTPATH)\r
 \r
 $(BUILD_DIR):\r
        mkdir -p $(BUILD_DIR)\r
+$(FAST_BUILD_DIR):\r
+       mkdir -p $(FAST_BUILD_DIR)\r
 $(SERVER_BUILD_DIR):\r
        mkdir -p $(SERVER_BUILD_DIR)\r
 \r
 $(DESTPATH): $(OBJECTS)\r
        $(CXX) -o $@ $(OBJECTS) $(LDFLAGS)\r
 \r
-$(FAST_DESTPATH): $(OBJECTS)\r
-       $(CXX) -o $@ $(OBJECTS) $(LDFLAGS) -DUNITTEST_DISABLE\r
+$(FAST_DESTPATH): $(FAST_OBJECTS)\r
+       $(CXX) -o $@ $(FAST_OBJECTS) $(LDFLAGS) -DUNITTEST_DISABLE\r
 \r
 $(SERVER_DESTPATH): $(SERVER_OBJECTS)\r
        $(CXX) -o $@ $(SERVER_OBJECTS) $(LDFLAGS) -DSERVER -DUNITTEST_DISABLE\r
@@ -78,6 +81,9 @@ $(SERVER_DESTPATH): $(SERVER_OBJECTS)
 $(BUILD_DIR)/%.o: src/%.cpp\r
        $(CXX) -c -o $@ $< $(CPPFLAGS) $(CXXFLAGS)\r
 \r
+$(FAST_BUILD_DIR)/%.o: src/%.cpp\r
+       $(CXX) -c -o $@ $< $(CPPFLAGS) $(CXXFLAGS)\r
+\r
 $(SERVER_BUILD_DIR)/%.o: src/%.cpp\r
        $(CXX) -c -o $@ $< $(CPPFLAGS) $(CXXFLAGS)\r
 \r
diff --git a/data/coalstone.png b/data/coalstone.png
new file mode 100644 (file)
index 0000000..c993a02
Binary files /dev/null and b/data/coalstone.png differ
index b921c9aeef736bf834b512867bf94a13f8fd8f23..67431c9579d5685f50fc6e58bc2384a3a65bec35 100755 (executable)
@@ -16,6 +16,7 @@ cp bin/Irrlicht.dll $PACKAGEPATH/bin/
 cp bin/zlibwapi.dll $PACKAGEPATH/bin/
 #cp bin/test $PACKAGEPATH/bin/
 cp bin/fasttest $PACKAGEPATH/bin/
+cp bin/server $PACKAGEPATH/bin/
 cp ../irrlicht/irrlicht-1.7.1/lib/Linux/libIrrlicht.a $PACKAGEPATH/bin/
 cp ../jthread/jthread-1.2.1/src/.libs/libjthread-1.2.1.so $PACKAGEPATH/bin/
 
@@ -42,8 +43,10 @@ cp -r data/skybox2.png $PACKAGEPATH/data/
 cp -r data/skybox3.png $PACKAGEPATH/data/
 cp -r data/tree_top.png $PACKAGEPATH/data/
 cp -r data/mud_with_grass.png $PACKAGEPATH/data/
+cp -r data/coalstone.png $PACKAGEPATH/data/
+cp -r data/crack.png $PACKAGEPATH/data/
 
-cp -r data/pauseMenu.gui $PACKAGEPATH/data/
+#cp -r data/pauseMenu.gui $PACKAGEPATH/data/
 
 cp -r doc/README.txt $PACKAGEPATH/doc/README.txt
 
index 4c99e6bb49939b11f49cb1be77c4d65c58bf7bcf..f27c4bcdcbf3a6a6744123619e667d17adf3e05d 100644 (file)
                                RelativePath=".\src\filesys.cpp"\r
                                >\r
                        </File>\r
+                       <File\r
+                               RelativePath=".\src\guiInventoryMenu.cpp"\r
+                               >\r
+                       </File>\r
                        <File\r
                                RelativePath=".\src\guiPauseMenu.cpp"\r
                                >\r
index a5d035d3f53ed3a044bcc074dff7810f379a740d..32f62e3babdd17206405446b8b958ee411288922 100644 (file)
@@ -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()
 {
index a3d43997c4ccc8bc49a111dfe249c12639a0b9ad..bfec7730ddccfa3e8fc92e9923f2b5f5151af293 100644 (file)
@@ -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);
        
index 5e919b2f7b94de19155617cdc091ac730be74a7c..c8a114841d940b320af6d801a00df6fee3b44d53 100644 (file)
@@ -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)
index 7bc5ca9e0ba0fd416dc3479c6bab9a0e0e3f0db5..88cb8c830592f80e01b9a3bb8c3821861918bd43 100644 (file)
@@ -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,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<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();
+}
+
 
index b581a1166a7ea0e9c35b521a9295c57fa0820e92..0032ce66aa64b15403b7d7db952a26ff906b827e 100644 (file)
@@ -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
index 73e406e18096f879949f2119e1e8bec00190f2fc..b8f0473e88c0b1e0240650fa8eae6692915b34c5 100644 (file)
@@ -22,6 +22,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
 \r
 #include "guiPauseMenu.h"\r
 #include "debug.h"\r
+#include "serialization.h"\r
 \r
 GUIPauseMenu::GUIPauseMenu(gui::IGUIEnvironment* env,\r
                gui::IGUIElement* parent, s32 id,\r
@@ -49,6 +50,9 @@ void GUIPauseMenu::resizeGui()
                return;\r
        m_screensize_old = screensize;\r
 \r
+       /*\r
+               Remove stuff\r
+       */\r
        {\r
                gui::IGUIElement *e = getElementFromId(256);\r
                if(e != NULL)\r
@@ -59,11 +63,21 @@ void GUIPauseMenu::resizeGui()
                if(e != NULL)\r
                        e->remove();\r
        }\r
+       {\r
+               gui::IGUIElement *e = getElementFromId(258);\r
+               if(e != NULL)\r
+                       e->remove();\r
+       }\r
+       {\r
+               gui::IGUIElement *e = getElementFromId(259);\r
+               if(e != NULL)\r
+                       e->remove();\r
+       }\r
 \r
        core::rect<s32> rect(\r
-                       screensize.X/2 - 560/2,\r
+                       screensize.X/2 - 580/2,\r
                        screensize.Y/2 - 300/2,\r
-                       screensize.X/2 + 560/2,\r
+                       screensize.X/2 + 580/2,\r
                        screensize.Y/2 + 300/2\r
        );\r
        \r
@@ -72,6 +86,9 @@ void GUIPauseMenu::resizeGui()
 \r
        v2s32 size = rect.getSize();\r
 \r
+       /*\r
+               Add stuff\r
+       */\r
        {\r
                core::rect<s32> rect(0, 0, 140, 30);\r
                rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2-25);\r
@@ -82,6 +99,34 @@ void GUIPauseMenu::resizeGui()
                rect = rect + v2s32(size.X/2-140/2, size.Y/2-30/2+25);\r
                Environment->addButton(rect, this, 257, L"Exit");\r
        }\r
+       {\r
+               core::rect<s32> rect(0, 0, 180, 220);\r
+               rect = rect + v2s32(size.X/2 + 90, size.Y/2-rect.getHeight()/2);\r
+               const wchar_t *text =\r
+               L"Keys:\n"\r
+               L"- WASD: Walk\n"\r
+               L"- Mouse left: dig blocks\n"\r
+               L"- Mouse right: place blocks\n"\r
+               L"- Mouse wheel: select item\n"\r
+               L"- R: Toggle viewing all loaded chunks\n"\r
+               L"- I: Inventory menu\n"\r
+               L"- ESC: This menu\n"\r
+               L"\n"\r
+               L"To generate a new map, remove the map directory.\n";\r
+               Environment->addStaticText(text, rect, false, true, this, 258);\r
+       }\r
+       {\r
+               core::rect<s32> rect(0, 0, 180, 220);\r
+               rect = rect + v2s32(size.X/2 - 90 - rect.getWidth(), size.Y/2-rect.getHeight()/2);\r
+               wchar_t text[200];\r
+               swprintf(text, 200,\r
+                               L"Minetest-c55\n"\r
+                               L"SER_FMT_VER_HIGHEST=%i",\r
+                               (int)SER_FMT_VER_HIGHEST\r
+               );\r
+       \r
+               Environment->addStaticText(text, rect, false, true, this, 259);\r
+       }\r
 }\r
 \r
 void GUIPauseMenu::draw()\r
index 069355affeeee45fd8235c7ca9e766efadc2c0e2..073477dde4cc9a2f08323a6f5b52baa3660b5697 100644 (file)
@@ -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
index d37761cfedfc3906eaf4fcef49a693b3acc10f15..ad3b297e816de7132d1188a7879003edb75cf7c9 100644 (file)
@@ -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
 
index 7fecbe3bd9b68ce086a0c6476e9491b0261c63f9..cbca1df34023356de16f8619a1643c6339aadaab 100644 (file)
@@ -2304,7 +2304,16 @@ int main(int argc, char *argv[])
                        client.getLocalInventory(local_inventory);\r
                        quick_inventory->setSelection(g_selected_item);\r
                        quick_inventory->update();\r
-                       inventoryMenu->update();\r
+               }\r
+               \r
+               /*\r
+                       Send actions returned by the inventory menu\r
+               */\r
+               while(InventoryAction *a = inventoryMenu->getNextAction())\r
+               {\r
+                       client.sendInventoryAction(a);\r
+                       // Eat it\r
+                       delete a;\r
                }\r
 \r
                if(input_guitext != NULL)\r
index 839efbf5bd1cf9e048015332040d959b4efae3fb..700312fb236bf87429c024d57f5e2b94c38481a6 100644 (file)
@@ -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);
+                               }
+                       }
+               }
        }
        
        /*
index c41560ee5d465ae69276be3ab03e242af6a82c93..a8e9f07fc41fb2c313d616efd7d8aded71e28898 100644 (file)
@@ -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",
 };
 
index f52bd52e700273ca2f718eef304093e30da812c7..20634bf7673a3ab605d81002b4de212af5145d0a 100644 (file)
@@ -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
index e6caff03cdd92f06f24ae968ce85cc4420f8dd5d..ef09fae6a9eada42f8e470025c41532db92f4cd5 100644 (file)
@@ -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()
index 9952cb8ebb05a4444c81b1cdc51d0216fc070c8b..ddef11ae457177385e080b12be6b210628ce2783 100644 (file)
@@ -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"));
 
index bbd0fa1e090357aa93f6246ea73ef9491d9980ff..2be92d43b03d6b51dbf1c4907a1d16f5d268f948 100644 (file)
@@ -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
             &&
index f2b131f4d47ce7169c56070f6ad6063c9ffde99a..25d9c00d08ef235225759394a9e1aafdcfd19538 100644 (file)
@@ -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)
index 68e87a77d2542abe22aa0667692e10a9370bc292..9823160c237842a89942802671bf48c9e362e7fc 100644 (file)
@@ -39,6 +39,7 @@ enum TileID
        TILE_TREE_TOP,
        TILE_MUD_WITH_GRASS,
        TILE_CLOUD,
+       TILE_COALSTONE,
        
        // Count of tile ids
        TILES_COUNT
index 484b5828b12c74c3986bcce33343dca6a0325713..4e2e132e95e13b23d9b918407445748ca2b3b386 100644 (file)
@@ -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>