crafting system!

This commit is contained in:
Perttu Ahola 2010-12-22 16:30:23 +02:00
parent 2e41a5e304
commit 3de176cc58
22 changed files with 703 additions and 143 deletions

View File

@ -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)

BIN
data/coalstone.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -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

View File

@ -198,6 +198,10 @@
RelativePath=".\src\filesys.cpp"
>
</File>
<File
RelativePath=".\src\guiInventoryMenu.cpp"
>
</File>
<File
RelativePath=".\src\guiPauseMenu.cpp"
>

View File

@ -1541,6 +1541,24 @@ void Client::sendSignText(v3s16 blockpos, s16 id, std::string text)
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()
{
JMutexAutoLock envlock(m_env_mutex);

View 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);

View 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)

View 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)));
}
void GUIInventoryMenu::update()
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::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();
}

View 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
{
public:
GUIInventorySlot(gui::IGUIEnvironment* env,
gui::IGUIElement* parent, s32 id, core::rect<s32> 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,
@ -60,10 +79,8 @@ public:
*/
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

View File

@ -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()

View 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

View 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

View File

@ -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)

View 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);
}
}
}
}
/*

View 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",
};

View 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

View 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()

View 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"));

View 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
&&

View 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)

View File

@ -39,6 +39,7 @@ enum TileID
TILE_TREE_TOP,
TILE_MUD_WITH_GRASS,
TILE_CLOUD,
TILE_COALSTONE,
// Count of tile ids
TILES_COUNT

View 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>