aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/client.cpp18
-rw-r--r--src/client.h1
-rw-r--r--src/clientserver.h5
-rw-r--r--src/guiInventoryMenu.cpp235
-rw-r--r--src/guiInventoryMenu.h82
-rw-r--r--src/guiPauseMenu.cpp49
-rw-r--r--src/inventory.cpp120
-rw-r--r--src/inventory.h69
-rw-r--r--src/main.cpp11
-rw-r--r--src/map.cpp33
-rw-r--r--src/mapnode.cpp2
-rw-r--r--src/mapnode.h1
-rw-r--r--src/player.cpp1
-rw-r--r--src/server.cpp132
-rw-r--r--src/strfnd.h5
-rw-r--r--src/tile.cpp1
-rw-r--r--src/tile.h1
-rw-r--r--src/utility.h53
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>