2014-10-11 06:46:16 -07:00
|
|
|
/************************************************************************
|
|
|
|
* Minetest-c55
|
|
|
|
* Copyright (C) 2010-2011 celeron55, Perttu Ahola <celeron55@gmail.com>
|
|
|
|
*
|
|
|
|
* inventory.h
|
|
|
|
* voxelands - 3d voxel world sandbox game
|
|
|
|
* Copyright (C) Lisa 'darkrose' Milne 2013-2014 <lisa@ltmnet.com>
|
|
|
|
*
|
|
|
|
* This program is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful, but
|
|
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
|
* See the GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
|
|
|
*
|
|
|
|
* License updated from GPLv2 or later to GPLv3 or later by Lisa Milne
|
|
|
|
* for Voxelands.
|
|
|
|
************************************************************************/
|
2013-04-15 05:42:24 -07:00
|
|
|
|
|
|
|
|
|
|
|
#ifndef INVENTORY_HEADER
|
|
|
|
#define INVENTORY_HEADER
|
|
|
|
|
|
|
|
#include <iostream>
|
|
|
|
#include <sstream>
|
|
|
|
#include <string>
|
2014-05-30 22:07:11 -07:00
|
|
|
#include <map>
|
2013-04-15 05:42:24 -07:00
|
|
|
#include "common_irrlicht.h"
|
|
|
|
#include "debug.h"
|
|
|
|
#include "main.h" // For g_materials
|
|
|
|
#include "mapnode.h" // For content_t
|
2013-11-22 23:36:02 -08:00
|
|
|
// for mapping to old subname
|
|
|
|
#include "content_craftitem.h"
|
|
|
|
#include "content_toolitem.h"
|
2014-10-20 08:43:43 -07:00
|
|
|
#include "content_clothesitem.h"
|
2014-05-08 14:53:50 -07:00
|
|
|
#include "content_mapnode.h"
|
2013-04-15 05:42:24 -07:00
|
|
|
|
|
|
|
#define QUANTITY_ITEM_MAX_COUNT 99
|
|
|
|
|
|
|
|
class ServerActiveObject;
|
|
|
|
class ServerEnvironment;
|
|
|
|
class Player;
|
|
|
|
|
|
|
|
class InventoryItem
|
|
|
|
{
|
|
|
|
public:
|
2015-07-28 04:34:53 -07:00
|
|
|
InventoryItem(u16 count, u16 data);
|
2013-04-15 05:42:24 -07:00
|
|
|
virtual ~InventoryItem();
|
|
|
|
|
2015-07-28 04:34:53 -07:00
|
|
|
static content_t info(std::istream &is, u16 *count, u16 *wear, u16 *data);
|
2013-04-15 05:42:24 -07:00
|
|
|
static InventoryItem* deSerialize(std::istream &is);
|
2015-07-28 04:34:53 -07:00
|
|
|
static InventoryItem* create(content_t c, u16 count, u16 wear=0, u16 data=0);
|
2013-04-15 05:42:24 -07:00
|
|
|
|
|
|
|
virtual const char* getName() const = 0;
|
|
|
|
// Shall write the name and the parameters
|
|
|
|
virtual void serialize(std::ostream &os) const = 0;
|
|
|
|
// Shall make an exact clone of the item
|
|
|
|
virtual InventoryItem* clone() = 0;
|
|
|
|
#ifndef SERVER
|
|
|
|
// Return the name of the image for this item
|
|
|
|
virtual std::string getBasename() const { return ""; }
|
|
|
|
// Shall return an image of the item (or NULL)
|
|
|
|
virtual video::ITexture * getImage() const { return NULL; }
|
|
|
|
// Shall return an image of the item without embellishments (or NULL)
|
|
|
|
virtual video::ITexture * getImageRaw() const { return getImage(); }
|
|
|
|
#endif
|
2013-11-22 23:36:02 -08:00
|
|
|
// get the content type
|
|
|
|
content_t getContent() {return m_content;}
|
2013-08-31 04:38:23 -07:00
|
|
|
// this is used for tool tips
|
2014-09-23 12:21:20 -07:00
|
|
|
virtual std::wstring getGuiName() { return L""; }
|
2015-07-28 04:34:53 -07:00
|
|
|
// this is used for hover data / extended tool tips
|
|
|
|
virtual std::wstring getGuiText() { return L""; }
|
2013-04-15 05:42:24 -07:00
|
|
|
// Shall return a text to show in the GUI
|
|
|
|
virtual std::string getText() { return ""; }
|
|
|
|
// Returns the string used for inventory
|
|
|
|
virtual std::string getItemString();
|
|
|
|
// Creates an object from the item, to be placed in the world.
|
2016-01-27 08:02:42 -08:00
|
|
|
virtual ServerActiveObject* createSAO(ServerEnvironment *env, u16 id, v3f pos) {return NULL;}
|
2013-04-15 05:42:24 -07:00
|
|
|
// Gets amount of items that dropping one SAO will decrement
|
|
|
|
virtual u16 getDropCount() const { return getCount(); }
|
|
|
|
|
|
|
|
/*
|
|
|
|
Quantity methods
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Shall return true if the item can be add()ed to the other
|
|
|
|
virtual bool addableTo(const InventoryItem *other) const
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
u16 getCount() const
|
|
|
|
{
|
|
|
|
return m_count;
|
|
|
|
}
|
|
|
|
void setCount(u16 count)
|
|
|
|
{
|
|
|
|
m_count = count;
|
|
|
|
}
|
|
|
|
// This should return something else for stackable items
|
|
|
|
virtual u16 freeSpace() const
|
|
|
|
{
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
void add(u16 count)
|
|
|
|
{
|
2015-01-23 23:25:58 -08:00
|
|
|
if (m_count + count > QUANTITY_ITEM_MAX_COUNT)
|
|
|
|
return;
|
2013-04-15 05:42:24 -07:00
|
|
|
m_count += count;
|
|
|
|
}
|
|
|
|
void remove(u16 count)
|
|
|
|
{
|
2015-07-28 04:34:53 -07:00
|
|
|
if (m_count < count) {
|
|
|
|
m_count = 0;
|
|
|
|
}else{
|
|
|
|
m_count -= count;
|
|
|
|
}
|
2013-04-15 05:42:24 -07:00
|
|
|
}
|
2015-02-23 23:00:38 -08:00
|
|
|
virtual void setWear(u16 wear) {}
|
2015-02-27 07:09:12 -08:00
|
|
|
virtual u16 getWear() {return 0;}
|
2013-04-15 05:42:24 -07:00
|
|
|
|
2015-07-28 04:34:53 -07:00
|
|
|
void setData(u16 data) { m_data = data; }
|
|
|
|
void addData(u16 data) { m_data |= data; }
|
|
|
|
u16 getData() { return m_data; }
|
|
|
|
|
2013-04-15 05:42:24 -07:00
|
|
|
/*
|
|
|
|
Other properties
|
|
|
|
*/
|
|
|
|
|
|
|
|
// Whether it can be cooked
|
2017-08-04 12:20:13 -07:00
|
|
|
virtual bool isCookable(uint16_t type=COOK_ANY) const {return false;}
|
2017-07-03 13:09:59 -07:00
|
|
|
// Whether it can be crushed
|
|
|
|
virtual bool isCrushable(CrushType type=CRUSH_ANY) const {return false;}
|
2013-04-15 05:42:24 -07:00
|
|
|
// Time of cooking
|
2015-02-12 16:27:13 -08:00
|
|
|
virtual float getCookTime() const {return 3.0;}
|
2013-04-15 05:42:24 -07:00
|
|
|
// Result of cooking (can randomize)
|
|
|
|
virtual InventoryItem *createCookResult() const {return NULL;}
|
2017-07-03 13:09:59 -07:00
|
|
|
// Result of crushing (can randomize)
|
|
|
|
virtual InventoryItem *createCrushResult() const {return NULL;}
|
2013-11-23 06:26:02 -08:00
|
|
|
// Whether it can be used as fuel
|
|
|
|
virtual bool isFuel() const {return false;}
|
|
|
|
// the fuel time value
|
2015-02-12 16:27:13 -08:00
|
|
|
virtual float getFuelTime() const {return 0.0;}
|
2013-04-15 05:42:24 -07:00
|
|
|
|
|
|
|
// Eat, press, activate, whatever.
|
|
|
|
// Called when item is right-clicked when lying on ground.
|
|
|
|
// If returns true, item shall be deleted.
|
|
|
|
virtual bool use(ServerEnvironment *env,
|
|
|
|
Player *player){return false;}
|
|
|
|
|
|
|
|
protected:
|
|
|
|
u16 m_count;
|
2013-11-22 23:36:02 -08:00
|
|
|
content_t m_content;
|
2015-07-28 04:34:53 -07:00
|
|
|
u16 m_data;
|
2013-04-15 05:42:24 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
class MaterialItem : public InventoryItem
|
|
|
|
{
|
|
|
|
public:
|
2015-07-28 04:34:53 -07:00
|
|
|
MaterialItem(content_t content, u16 count, u16 data):
|
|
|
|
InventoryItem(count,data)
|
2013-04-15 05:42:24 -07:00
|
|
|
{
|
2014-05-08 14:53:50 -07:00
|
|
|
MapNode n(content);
|
|
|
|
n = mapnode_translate_to_internal(n,SER_FMT_VER_HIGHEST);
|
|
|
|
m_content = n.getContent();
|
2013-04-15 05:42:24 -07:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
Implementation interface
|
|
|
|
*/
|
|
|
|
virtual const char* getName() const
|
|
|
|
{
|
|
|
|
return "MaterialItem";
|
|
|
|
}
|
|
|
|
virtual void serialize(std::ostream &os) const
|
|
|
|
{
|
|
|
|
//os.imbue(std::locale("C"));
|
2015-07-28 04:34:53 -07:00
|
|
|
os<<"MaterialItem3";
|
2013-04-15 05:42:24 -07:00
|
|
|
os<<" ";
|
|
|
|
os<<(unsigned int)m_content;
|
|
|
|
os<<" ";
|
|
|
|
os<<m_count;
|
2015-07-28 04:34:53 -07:00
|
|
|
os<<" ";
|
|
|
|
os<<m_data;
|
2013-04-15 05:42:24 -07:00
|
|
|
}
|
|
|
|
virtual InventoryItem* clone()
|
|
|
|
{
|
2015-07-28 04:34:53 -07:00
|
|
|
return new MaterialItem(m_content, m_count, m_data);
|
2013-04-15 05:42:24 -07:00
|
|
|
}
|
|
|
|
#ifndef SERVER
|
2015-08-01 04:29:32 -07:00
|
|
|
video::ITexture * getImage() const;
|
2013-04-15 05:42:24 -07:00
|
|
|
#endif
|
2015-12-01 10:16:23 -08:00
|
|
|
std::wstring getGuiName();
|
2013-08-31 04:38:23 -07:00
|
|
|
|
2015-07-28 04:34:53 -07:00
|
|
|
std::wstring getGuiText();
|
|
|
|
|
2013-04-15 05:42:24 -07:00
|
|
|
std::string getText()
|
|
|
|
{
|
|
|
|
std::ostringstream os;
|
|
|
|
os<<m_count;
|
|
|
|
return os.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
virtual bool addableTo(const InventoryItem *other) const
|
|
|
|
{
|
2015-01-23 23:25:58 -08:00
|
|
|
content_t c = ((InventoryItem*)other)->getContent();
|
2015-07-28 04:34:53 -07:00
|
|
|
u16 d = ((InventoryItem*)other)->getData();
|
2015-01-23 23:25:58 -08:00
|
|
|
if (c != m_content)
|
2013-04-15 05:42:24 -07:00
|
|
|
return false;
|
2015-07-28 04:34:53 -07:00
|
|
|
if (m_data != d)
|
|
|
|
return false;
|
2013-04-15 05:42:24 -07:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
u16 freeSpace() const
|
|
|
|
{
|
2015-01-23 23:25:58 -08:00
|
|
|
if (m_count > QUANTITY_ITEM_MAX_COUNT)
|
2013-04-15 05:42:24 -07:00
|
|
|
return 0;
|
|
|
|
return QUANTITY_ITEM_MAX_COUNT - m_count;
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
Other properties
|
|
|
|
*/
|
2017-08-04 12:20:13 -07:00
|
|
|
bool isCookable(uint16_t type) const;
|
2013-04-15 05:42:24 -07:00
|
|
|
InventoryItem *createCookResult() const;
|
2017-07-03 13:09:59 -07:00
|
|
|
bool isCrushable(CrushType type) const;
|
|
|
|
InventoryItem *createCrushResult() const;
|
2013-11-23 06:26:02 -08:00
|
|
|
virtual bool isFuel() const;
|
|
|
|
virtual float getFuelTime() const;
|
2015-06-03 12:39:19 -07:00
|
|
|
|
|
|
|
bool use(ServerEnvironment *env, Player *player);
|
|
|
|
|
2013-04-15 05:42:24 -07:00
|
|
|
/*
|
|
|
|
Special methods
|
|
|
|
*/
|
|
|
|
content_t getMaterial()
|
|
|
|
{
|
|
|
|
return m_content;
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
An item that is used as a mid-product when crafting.
|
|
|
|
Subnames:
|
|
|
|
- Stick
|
|
|
|
*/
|
|
|
|
class CraftItem : public InventoryItem
|
|
|
|
{
|
|
|
|
public:
|
2015-07-28 04:34:53 -07:00
|
|
|
CraftItem(content_t content, u16 count, u16 data):
|
|
|
|
InventoryItem(count,data)
|
2013-11-22 23:36:02 -08:00
|
|
|
{
|
2017-04-05 09:44:59 -07:00
|
|
|
m_content = content_craftitem_features(content)->content;
|
2013-04-15 05:42:24 -07:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
Implementation interface
|
|
|
|
*/
|
|
|
|
virtual const char* getName() const
|
|
|
|
{
|
|
|
|
return "CraftItem";
|
|
|
|
}
|
|
|
|
virtual void serialize(std::ostream &os) const
|
|
|
|
{
|
2015-07-28 04:34:53 -07:00
|
|
|
os<<"CraftItem3";
|
2013-04-15 05:42:24 -07:00
|
|
|
os<<" ";
|
2014-05-04 01:51:35 -07:00
|
|
|
os<<(unsigned int)m_content;
|
2013-04-15 05:42:24 -07:00
|
|
|
os<<" ";
|
|
|
|
os<<m_count;
|
2015-07-28 04:34:53 -07:00
|
|
|
os<<" ";
|
|
|
|
os<<m_data;
|
2013-04-15 05:42:24 -07:00
|
|
|
}
|
|
|
|
virtual InventoryItem* clone()
|
|
|
|
{
|
2015-07-28 04:34:53 -07:00
|
|
|
return new CraftItem(m_content, m_count, m_data);
|
2013-04-15 05:42:24 -07:00
|
|
|
}
|
|
|
|
#ifndef SERVER
|
|
|
|
video::ITexture * getImage() const;
|
|
|
|
#endif
|
2013-08-31 04:38:23 -07:00
|
|
|
|
2014-09-23 12:21:20 -07:00
|
|
|
std::wstring getGuiName();
|
2015-07-28 04:34:53 -07:00
|
|
|
std::wstring getGuiText();
|
2013-08-31 04:38:23 -07:00
|
|
|
|
2013-04-15 05:42:24 -07:00
|
|
|
std::string getText()
|
|
|
|
{
|
|
|
|
std::ostringstream os;
|
|
|
|
os<<m_count;
|
|
|
|
return os.str();
|
|
|
|
}
|
|
|
|
|
|
|
|
ServerActiveObject* createSAO(ServerEnvironment *env, u16 id, v3f pos);
|
|
|
|
u16 getDropCount() const;
|
|
|
|
|
|
|
|
virtual bool addableTo(const InventoryItem *other) const
|
|
|
|
{
|
2015-01-23 23:25:58 -08:00
|
|
|
content_t c = ((InventoryItem*)other)->getContent();
|
2015-07-28 04:34:53 -07:00
|
|
|
u16 d = ((InventoryItem*)other)->getData();
|
2015-01-23 23:25:58 -08:00
|
|
|
if (c != m_content)
|
2013-04-15 05:42:24 -07:00
|
|
|
return false;
|
2015-07-28 04:34:53 -07:00
|
|
|
if (m_data != d)
|
|
|
|
return false;
|
2013-04-15 05:42:24 -07:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
u16 freeSpace() const
|
|
|
|
{
|
2017-04-05 09:44:59 -07:00
|
|
|
if (!content_craftitem_features(m_content)->stackable)
|
2015-06-04 02:15:22 -07:00
|
|
|
return 0;
|
2015-01-23 23:25:58 -08:00
|
|
|
if (m_count > QUANTITY_ITEM_MAX_COUNT)
|
2013-04-15 05:42:24 -07:00
|
|
|
return 0;
|
|
|
|
return QUANTITY_ITEM_MAX_COUNT - m_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Other properties
|
|
|
|
*/
|
|
|
|
|
2017-08-04 12:20:13 -07:00
|
|
|
bool isCookable(uint16_t type) const;
|
2013-04-15 05:42:24 -07:00
|
|
|
InventoryItem *createCookResult() const;
|
2017-07-03 13:09:59 -07:00
|
|
|
bool isCrushable(CrushType type) const;
|
|
|
|
InventoryItem *createCrushResult() const;
|
2013-11-23 18:34:11 -08:00
|
|
|
bool isFuel() const;
|
|
|
|
float getFuelTime() const;
|
2013-04-15 05:42:24 -07:00
|
|
|
|
|
|
|
bool use(ServerEnvironment *env, Player *player);
|
|
|
|
};
|
|
|
|
|
|
|
|
class ToolItem : public InventoryItem
|
|
|
|
{
|
|
|
|
public:
|
2015-07-28 04:34:53 -07:00
|
|
|
ToolItem(content_t content, u16 wear, u16 data):
|
|
|
|
InventoryItem(1,data)
|
2013-11-22 23:36:02 -08:00
|
|
|
{
|
|
|
|
m_wear = wear;
|
2014-05-04 01:51:35 -07:00
|
|
|
m_content = content_toolitem_features(content).content;
|
2013-11-22 23:36:02 -08:00
|
|
|
}
|
2013-04-15 05:42:24 -07:00
|
|
|
/*
|
|
|
|
Implementation interface
|
|
|
|
*/
|
|
|
|
virtual const char* getName() const
|
|
|
|
{
|
|
|
|
return "ToolItem";
|
|
|
|
}
|
|
|
|
virtual void serialize(std::ostream &os) const
|
|
|
|
{
|
2015-07-28 04:34:53 -07:00
|
|
|
os<<"ToolItem3";
|
2013-04-15 05:42:24 -07:00
|
|
|
os<<" ";
|
2014-05-04 01:51:35 -07:00
|
|
|
os<<(unsigned int)m_content;
|
2013-04-15 05:42:24 -07:00
|
|
|
os<<" ";
|
2014-05-26 02:23:39 -07:00
|
|
|
os<<m_wear;
|
2015-07-28 04:34:53 -07:00
|
|
|
os<<" ";
|
|
|
|
os<<m_data;
|
2013-04-15 05:42:24 -07:00
|
|
|
}
|
|
|
|
virtual InventoryItem* clone()
|
|
|
|
{
|
2015-07-28 04:34:53 -07:00
|
|
|
return new ToolItem(m_content, m_wear, m_data);
|
2013-04-15 05:42:24 -07:00
|
|
|
}
|
|
|
|
#ifndef SERVER
|
2015-07-31 13:04:02 -07:00
|
|
|
std::string getBasename() const;
|
2013-04-15 05:42:24 -07:00
|
|
|
|
2015-07-28 04:34:53 -07:00
|
|
|
video::ITexture * getImage() const;
|
2013-04-15 05:42:24 -07:00
|
|
|
|
|
|
|
video::ITexture * getImageRaw() const
|
|
|
|
{
|
|
|
|
if(g_texturesource == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
2013-04-15 06:09:42 -07:00
|
|
|
return g_texturesource->getTextureRaw(getBasename());
|
2013-04-15 05:42:24 -07:00
|
|
|
}
|
|
|
|
#endif
|
2015-07-28 04:34:53 -07:00
|
|
|
std::wstring getGuiName()
|
|
|
|
{
|
2017-05-09 22:37:26 -07:00
|
|
|
return narrow_to_wide(content_toolitem_features(m_content).description);
|
2013-08-31 04:38:23 -07:00
|
|
|
}
|
2015-07-28 04:34:53 -07:00
|
|
|
std::wstring getGuiText();
|
2013-04-15 05:42:24 -07:00
|
|
|
std::string getText()
|
|
|
|
{
|
|
|
|
return "";
|
|
|
|
}
|
2015-09-28 01:11:57 -07:00
|
|
|
|
|
|
|
ServerActiveObject* createSAO(ServerEnvironment *env, u16 id, v3f pos);
|
|
|
|
|
2017-08-04 12:20:13 -07:00
|
|
|
bool isCookable(uint16_t type) const;
|
2013-11-23 06:26:02 -08:00
|
|
|
InventoryItem *createCookResult() const;
|
2017-07-03 13:09:59 -07:00
|
|
|
bool isCrushable(CrushType type) const;
|
|
|
|
InventoryItem *createCrushResult() const;
|
2013-11-23 18:34:11 -08:00
|
|
|
bool isFuel() const;
|
|
|
|
float getFuelTime() const;
|
2013-04-15 05:42:24 -07:00
|
|
|
/*
|
|
|
|
Special methods
|
|
|
|
*/
|
2015-02-27 07:09:12 -08:00
|
|
|
virtual u16 getWear()
|
2013-04-15 05:42:24 -07:00
|
|
|
{
|
|
|
|
return m_wear;
|
|
|
|
}
|
2017-05-07 08:14:54 -07:00
|
|
|
// Returns true if worn out
|
2013-04-15 05:42:24 -07:00
|
|
|
bool addWear(u16 add)
|
|
|
|
{
|
2017-05-07 08:14:54 -07:00
|
|
|
if (m_wear < add) {
|
|
|
|
m_wear = 0;
|
2013-04-15 05:42:24 -07:00
|
|
|
return true;
|
|
|
|
}
|
2017-05-07 08:14:54 -07:00
|
|
|
|
|
|
|
m_wear -= add;
|
|
|
|
return false;
|
2013-04-15 05:42:24 -07:00
|
|
|
}
|
2015-02-23 23:00:38 -08:00
|
|
|
virtual void setWear(u16 wear) {m_wear = wear;}
|
2013-04-15 05:42:24 -07:00
|
|
|
private:
|
|
|
|
u16 m_wear;
|
|
|
|
};
|
|
|
|
|
2014-10-20 08:43:43 -07:00
|
|
|
class ClothesItem : public InventoryItem
|
|
|
|
{
|
|
|
|
public:
|
2015-07-28 04:34:53 -07:00
|
|
|
ClothesItem(content_t content, u16 wear, u16 data):
|
|
|
|
InventoryItem(1,data)
|
2014-10-20 08:43:43 -07:00
|
|
|
{
|
|
|
|
m_wear = wear;
|
2017-04-05 09:44:59 -07:00
|
|
|
m_content = content_clothesitem_features(content)->content;
|
2014-10-20 08:43:43 -07:00
|
|
|
}
|
|
|
|
/*
|
|
|
|
Implementation interface
|
|
|
|
*/
|
|
|
|
virtual const char* getName() const
|
|
|
|
{
|
|
|
|
return "ClothesItem";
|
|
|
|
}
|
|
|
|
virtual void serialize(std::ostream &os) const
|
|
|
|
{
|
2015-07-28 04:34:53 -07:00
|
|
|
os<<"ClothesItem2";
|
2014-10-20 08:43:43 -07:00
|
|
|
os<<" ";
|
|
|
|
os<<(unsigned int)m_content;
|
|
|
|
os<<" ";
|
|
|
|
os<<m_wear;
|
2015-07-28 04:34:53 -07:00
|
|
|
os<<" ";
|
|
|
|
os<<m_data;
|
2014-10-20 08:43:43 -07:00
|
|
|
}
|
|
|
|
virtual InventoryItem* clone()
|
|
|
|
{
|
2015-07-28 04:34:53 -07:00
|
|
|
return new ClothesItem(m_content, m_wear, m_data);
|
2014-10-20 08:43:43 -07:00
|
|
|
}
|
|
|
|
#ifndef SERVER
|
|
|
|
std::string getBasename() const {
|
2017-04-05 09:44:59 -07:00
|
|
|
return content_clothesitem_features(m_content)->texture;
|
2014-10-20 08:43:43 -07:00
|
|
|
}
|
|
|
|
|
2015-07-28 04:34:53 -07:00
|
|
|
video::ITexture * getImage() const;
|
2014-10-20 08:43:43 -07:00
|
|
|
|
|
|
|
video::ITexture * getImageRaw() const
|
|
|
|
{
|
|
|
|
if (g_texturesource == NULL)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
return g_texturesource->getTextureRaw(getBasename());
|
|
|
|
}
|
|
|
|
#endif
|
2015-07-28 04:34:53 -07:00
|
|
|
std::wstring getGuiName()
|
|
|
|
{
|
2017-05-09 22:37:26 -07:00
|
|
|
return narrow_to_wide(content_clothesitem_features(m_content)->description);
|
2014-10-20 08:43:43 -07:00
|
|
|
}
|
2015-07-28 04:34:53 -07:00
|
|
|
std::wstring getGuiText();
|
2014-10-20 08:43:43 -07:00
|
|
|
std::string getText()
|
|
|
|
{
|
|
|
|
return "";
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
Special methods
|
|
|
|
*/
|
2015-02-27 07:09:12 -08:00
|
|
|
virtual u16 getWear()
|
2014-10-20 08:43:43 -07:00
|
|
|
{
|
|
|
|
return m_wear;
|
|
|
|
}
|
|
|
|
// Returns true if weared out
|
|
|
|
bool addWear(u16 add)
|
|
|
|
{
|
|
|
|
if (m_wear >= 65535 - add) {
|
|
|
|
m_wear = 65535;
|
|
|
|
return true;
|
|
|
|
}else{
|
|
|
|
m_wear += add;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
2015-02-23 23:00:38 -08:00
|
|
|
virtual void setWear(u16 wear) {m_wear = wear;}
|
2014-10-20 08:43:43 -07:00
|
|
|
private:
|
|
|
|
u16 m_wear;
|
|
|
|
};
|
|
|
|
|
2015-03-15 04:25:09 -07:00
|
|
|
class InventoryDiffData
|
|
|
|
{
|
|
|
|
public:
|
2015-08-03 09:53:37 -07:00
|
|
|
InventoryDiffData(u32 i, content_t t, u16 c, u16 d):
|
2015-03-15 04:25:09 -07:00
|
|
|
index(i),
|
|
|
|
type(t),
|
2015-08-03 09:53:37 -07:00
|
|
|
wear_count(c),
|
|
|
|
data(d)
|
2015-03-15 04:25:09 -07:00
|
|
|
{
|
|
|
|
}
|
|
|
|
InventoryDiffData():
|
|
|
|
index(0),
|
|
|
|
type(CONTENT_IGNORE),
|
2015-08-03 09:53:37 -07:00
|
|
|
wear_count(0),
|
|
|
|
data(0)
|
2015-03-15 04:25:09 -07:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
u32 index;
|
|
|
|
content_t type;
|
|
|
|
u16 wear_count;
|
2015-08-03 09:53:37 -07:00
|
|
|
u16 data;
|
2015-03-15 04:25:09 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
class InventoryDiff
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
InventoryDiff()
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
}
|
|
|
|
~InventoryDiff()
|
|
|
|
{
|
|
|
|
clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
void clear()
|
|
|
|
{
|
|
|
|
m_data.clear();
|
|
|
|
}
|
|
|
|
|
2015-08-03 09:53:37 -07:00
|
|
|
void add(std::string list, u32 index, content_t type, u16 count_wear, u16 data)
|
2015-03-15 04:25:09 -07:00
|
|
|
{
|
2015-08-03 09:53:37 -07:00
|
|
|
m_data[list][index] = InventoryDiffData(index,type,count_wear,data);
|
2015-03-15 04:25:09 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
void add(std::string list, u32 index, InventoryItem *item)
|
|
|
|
{
|
|
|
|
if (item == NULL) {
|
2015-08-03 09:53:37 -07:00
|
|
|
add(list,index,CONTENT_IGNORE,0,0);
|
2015-03-15 04:25:09 -07:00
|
|
|
}else if (
|
|
|
|
(item->getContent()&CONTENT_TOOLITEM_MASK) == CONTENT_TOOLITEM_MASK
|
|
|
|
|| (item->getContent()&CONTENT_CLOTHESITEM_MASK) == CONTENT_CLOTHESITEM_MASK
|
|
|
|
) {
|
2015-08-03 09:53:37 -07:00
|
|
|
add(list,index,item->getContent(),item->getWear(),item->getData());
|
2015-03-15 04:25:09 -07:00
|
|
|
}else{
|
2015-08-03 09:53:37 -07:00
|
|
|
add(list,index,item->getContent(),item->getCount(),item->getData());
|
2015-03-15 04:25:09 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void merge(InventoryDiff &other)
|
|
|
|
{
|
|
|
|
for (std::map<std::string,std::map<u32,InventoryDiffData> >::iterator i = other.m_data.begin(); i != other.m_data.end(); i++) {
|
|
|
|
m_data[i->first].swap(i->second);
|
|
|
|
i->second.clear();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
std::map<std::string,std::map<u32,InventoryDiffData> > m_data;
|
|
|
|
};
|
|
|
|
|
2013-04-15 05:42:24 -07:00
|
|
|
class InventoryList
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
InventoryList(std::string name, u32 size);
|
|
|
|
~InventoryList();
|
|
|
|
void clearItems();
|
|
|
|
void serialize(std::ostream &os) const;
|
|
|
|
void deSerialize(std::istream &is);
|
|
|
|
|
|
|
|
InventoryList(const InventoryList &other);
|
|
|
|
InventoryList & operator = (const InventoryList &other);
|
|
|
|
|
|
|
|
const std::string &getName() const;
|
|
|
|
u32 getSize();
|
|
|
|
// Count used slots
|
|
|
|
u32 getUsedSlots();
|
|
|
|
u32 getFreeSlots();
|
|
|
|
|
2014-05-30 22:07:11 -07:00
|
|
|
// set specific nodes only allowed in inventory
|
|
|
|
void addAllowed(content_t c) {m_allowed[c] = true;}
|
|
|
|
void clearAllowed() {m_allowed.clear();}
|
|
|
|
|
|
|
|
// set specific nodes not allowed in inventory
|
|
|
|
void addDenied(content_t c) {m_denied[c] = true;}
|
|
|
|
void clearDenied() {m_denied.clear();}
|
|
|
|
|
|
|
|
// whether an item is allowed in inventory
|
|
|
|
bool isAllowed(content_t c)
|
|
|
|
{
|
|
|
|
if (m_allowed.size() > 0)
|
|
|
|
return m_allowed[c];
|
|
|
|
return !m_denied[c];
|
|
|
|
}
|
|
|
|
bool isAllowed(InventoryItem *item) {return isAllowed(item->getContent());}
|
|
|
|
|
|
|
|
// set whether items can be stacked (more than one per slot)
|
|
|
|
void setStackable(bool s=true) {m_stackable = s;}
|
|
|
|
bool getStackable() {return m_stackable;}
|
|
|
|
|
2013-04-15 05:42:24 -07:00
|
|
|
/*bool getDirty(){ return m_dirty; }
|
|
|
|
void setDirty(bool dirty=true){ m_dirty = dirty; }*/
|
|
|
|
|
|
|
|
// Get pointer to item
|
|
|
|
const InventoryItem * getItem(u32 i) const;
|
|
|
|
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 leftover item.
|
|
|
|
// If all went into the list, returns NULL.
|
|
|
|
InventoryItem * addItem(InventoryItem *newitem);
|
|
|
|
|
|
|
|
// If possible, adds item to given slot.
|
|
|
|
// If cannot be added at all, returns the item back.
|
|
|
|
// If can be added partly, decremented item is returned back.
|
|
|
|
// If can be added fully, NULL is returned.
|
|
|
|
InventoryItem * addItem(u32 i, InventoryItem *newitem);
|
|
|
|
|
2015-03-15 04:25:09 -07:00
|
|
|
// Updates item type/count/wear
|
2015-08-03 09:53:37 -07:00
|
|
|
void updateItem(u32 i, content_t type, u16 wear_count, u16 data);
|
2015-03-15 04:25:09 -07:00
|
|
|
|
2013-04-15 05:42:24 -07:00
|
|
|
// Checks whether the item could be added to the given slot
|
|
|
|
bool itemFits(const u32 i, const InventoryItem *newitem);
|
|
|
|
|
|
|
|
// Checks whether there is room for a given item
|
|
|
|
bool roomForItem(const InventoryItem *item);
|
|
|
|
|
2017-07-03 13:09:59 -07:00
|
|
|
// Checks whether there is room for a given item after it has been cooked
|
2013-04-15 05:42:24 -07:00
|
|
|
bool roomForCookedItem(const InventoryItem *item);
|
|
|
|
|
2017-07-03 13:09:59 -07:00
|
|
|
// Checks whether there is room for a given item aftr it has been crushed
|
|
|
|
bool roomForCrushedItem(const InventoryItem *item);
|
|
|
|
|
2013-04-15 05:42:24 -07:00
|
|
|
// Takes some items from a slot.
|
|
|
|
// If there are not enough, takes as many as it can.
|
|
|
|
// Returns NULL if couldn't take any.
|
|
|
|
InventoryItem * takeItem(u32 i, u32 count);
|
|
|
|
|
2014-11-21 11:51:31 -08:00
|
|
|
// find a stack containing an item
|
|
|
|
InventoryItem *findItem(content_t item, u16 *item_i = NULL);
|
|
|
|
|
2013-04-15 05:42:24 -07:00
|
|
|
// Decrements amount of every material item
|
|
|
|
void decrementMaterials(u16 count);
|
|
|
|
|
|
|
|
void print(std::ostream &o);
|
|
|
|
|
2015-03-15 04:25:09 -07:00
|
|
|
void addDiff(u32 index, InventoryItem *item) {m_diff.add(m_name,index,item);}
|
|
|
|
InventoryDiff &getDiff() {return m_diff;}
|
|
|
|
|
2013-04-15 05:42:24 -07:00
|
|
|
private:
|
2013-04-15 06:09:42 -07:00
|
|
|
core::array<InventoryItem*> m_items;
|
2013-04-15 05:42:24 -07:00
|
|
|
u32 m_size;
|
|
|
|
std::string m_name;
|
2014-05-30 22:07:11 -07:00
|
|
|
std::map<content_t,bool> m_allowed;
|
|
|
|
std::map<content_t,bool> m_denied;
|
|
|
|
bool m_stackable;
|
2015-03-15 04:25:09 -07:00
|
|
|
InventoryDiff m_diff;
|
2013-04-15 05:42:24 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
class Inventory
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
~Inventory();
|
|
|
|
|
|
|
|
void clear();
|
|
|
|
|
|
|
|
Inventory();
|
|
|
|
Inventory(const Inventory &other);
|
|
|
|
Inventory & operator = (const Inventory &other);
|
|
|
|
|
|
|
|
void serialize(std::ostream &os) const;
|
|
|
|
void deSerialize(std::istream &is);
|
|
|
|
|
|
|
|
InventoryList * addList(const std::string &name, u32 size);
|
|
|
|
InventoryList * getList(const std::string &name);
|
|
|
|
const InventoryList * getList(const std::string &name) const;
|
|
|
|
bool deleteList(const std::string &name);
|
|
|
|
// A shorthand for adding items.
|
|
|
|
// Returns NULL if the item was fully added, leftover otherwise.
|
|
|
|
InventoryItem * addItem(const std::string &listname, InventoryItem *newitem)
|
|
|
|
{
|
|
|
|
InventoryList *list = getList(listname);
|
2015-03-15 04:25:09 -07:00
|
|
|
if (list == NULL)
|
2013-04-15 05:42:24 -07:00
|
|
|
return newitem;
|
2013-04-15 06:09:42 -07:00
|
|
|
return list->addItem(newitem);
|
2013-04-15 05:42:24 -07:00
|
|
|
}
|
2015-03-15 04:25:09 -07:00
|
|
|
InventoryDiff &getDiff()
|
|
|
|
{
|
|
|
|
m_diff.clear();
|
|
|
|
for (u32 i=0; i<m_lists.size(); i++) {
|
|
|
|
InventoryDiff &diff = m_lists[i]->getDiff();
|
|
|
|
m_diff.merge(diff);
|
|
|
|
}
|
|
|
|
return m_diff;
|
|
|
|
}
|
2013-04-15 05:42:24 -07:00
|
|
|
|
|
|
|
private:
|
|
|
|
// -1 if not found
|
|
|
|
const s32 getListIndex(const std::string &name) const;
|
|
|
|
|
2013-04-15 06:09:42 -07:00
|
|
|
core::array<InventoryList*> m_lists;
|
2015-03-15 04:25:09 -07:00
|
|
|
InventoryDiff m_diff;
|
2013-04-15 05:42:24 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
class Player;
|
|
|
|
|
|
|
|
struct InventoryContext
|
|
|
|
{
|
|
|
|
Player *current_player;
|
|
|
|
|
|
|
|
InventoryContext():
|
|
|
|
current_player(NULL)
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
|
|
|
struct InventoryAction;
|
2014-03-02 02:44:02 -08:00
|
|
|
struct InventoryLocation;
|
2013-04-15 05:42:24 -07:00
|
|
|
|
|
|
|
class InventoryManager
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
InventoryManager(){}
|
|
|
|
virtual ~InventoryManager(){}
|
|
|
|
|
|
|
|
/*
|
|
|
|
Get a pointer to an inventory specified by id.
|
|
|
|
id can be:
|
|
|
|
- "current_player"
|
|
|
|
- "nodemeta:X,Y,Z"
|
|
|
|
*/
|
|
|
|
virtual Inventory* getInventory(InventoryContext *c, std::string id)
|
|
|
|
{return NULL;}
|
2014-03-02 02:44:02 -08:00
|
|
|
virtual Inventory* getInventory(const InventoryLocation *loc)
|
|
|
|
{return NULL;}
|
2013-04-15 05:42:24 -07:00
|
|
|
// Used on the server by InventoryAction::apply and other stuff
|
|
|
|
virtual void inventoryModified(InventoryContext *c, std::string id)
|
|
|
|
{}
|
|
|
|
// Used on the client
|
|
|
|
virtual void inventoryAction(InventoryAction *a)
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
|
|
|
#define IACTION_MOVE 0
|
|
|
|
|
|
|
|
struct InventoryAction
|
|
|
|
{
|
fire,tnt,stained clay, hay, sponges,terracotta, stained glass, flint, firestarter, gunpowder, walls, gates, more ores...
2013-10-26 07:31:02 -07:00
|
|
|
virtual ~InventoryAction() {}
|
2013-04-15 05:42:24 -07:00
|
|
|
static InventoryAction * deSerialize(std::istream &is);
|
|
|
|
|
|
|
|
virtual u16 getType() const = 0;
|
|
|
|
virtual void serialize(std::ostream &os) const = 0;
|
|
|
|
virtual void apply(InventoryContext *c, InventoryManager *mgr) = 0;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct IMoveAction : public InventoryAction
|
|
|
|
{
|
|
|
|
// count=0 means "everything"
|
|
|
|
u16 count;
|
|
|
|
std::string from_inv;
|
|
|
|
std::string from_list;
|
|
|
|
s16 from_i;
|
|
|
|
std::string to_inv;
|
|
|
|
std::string to_list;
|
|
|
|
s16 to_i;
|
|
|
|
|
|
|
|
IMoveAction()
|
|
|
|
{
|
|
|
|
count = 0;
|
|
|
|
from_i = -1;
|
|
|
|
to_i = -1;
|
|
|
|
}
|
|
|
|
IMoveAction(std::istream &is)
|
|
|
|
{
|
|
|
|
std::string ts;
|
|
|
|
|
|
|
|
std::getline(is, ts, ' ');
|
2014-09-02 08:45:14 -07:00
|
|
|
count = mystoi(ts);
|
2013-04-15 05:42:24 -07:00
|
|
|
|
|
|
|
std::getline(is, from_inv, ' ');
|
|
|
|
|
|
|
|
std::getline(is, from_list, ' ');
|
|
|
|
|
|
|
|
std::getline(is, ts, ' ');
|
2014-09-02 08:45:14 -07:00
|
|
|
from_i = mystoi(ts);
|
2013-04-15 05:42:24 -07:00
|
|
|
|
|
|
|
std::getline(is, to_inv, ' ');
|
|
|
|
|
|
|
|
std::getline(is, to_list, ' ');
|
|
|
|
|
|
|
|
std::getline(is, ts, ' ');
|
2014-09-02 08:45:14 -07:00
|
|
|
to_i = mystoi(ts);
|
2013-04-15 05:42:24 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
u16 getType() const
|
|
|
|
{
|
|
|
|
return IACTION_MOVE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void serialize(std::ostream &os) const
|
|
|
|
{
|
|
|
|
os<<"Move ";
|
|
|
|
os<<count<<" ";
|
|
|
|
os<<from_inv<<" ";
|
|
|
|
os<<from_list<<" ";
|
|
|
|
os<<from_i<<" ";
|
|
|
|
os<<to_inv<<" ";
|
|
|
|
os<<to_list<<" ";
|
|
|
|
os<<to_i;
|
|
|
|
}
|
|
|
|
|
|
|
|
void apply(InventoryContext *c, InventoryManager *mgr);
|
|
|
|
};
|
|
|
|
|
2014-03-02 02:44:02 -08:00
|
|
|
struct InventoryLocation
|
|
|
|
{
|
|
|
|
enum Type{
|
|
|
|
UNDEFINED,
|
|
|
|
CURRENT_PLAYER,
|
|
|
|
PLAYER,
|
|
|
|
NODEMETA,
|
|
|
|
} type;
|
|
|
|
|
|
|
|
std::string name; // PLAYER
|
|
|
|
v3s16 p; // NODEMETA
|
|
|
|
|
|
|
|
InventoryLocation()
|
|
|
|
{
|
|
|
|
setUndefined();
|
|
|
|
}
|
|
|
|
void setUndefined()
|
|
|
|
{
|
|
|
|
type = UNDEFINED;
|
|
|
|
}
|
|
|
|
void setCurrentPlayer()
|
|
|
|
{
|
|
|
|
type = CURRENT_PLAYER;
|
|
|
|
}
|
|
|
|
void setPlayer(const std::string &name_)
|
|
|
|
{
|
|
|
|
type = PLAYER;
|
|
|
|
name = name_;
|
|
|
|
}
|
|
|
|
void setNodeMeta(v3s16 p_)
|
|
|
|
{
|
|
|
|
type = NODEMETA;
|
|
|
|
p = p_;
|
|
|
|
}
|
|
|
|
|
|
|
|
void applyCurrentPlayer(const std::string &name_)
|
|
|
|
{
|
|
|
|
if (type == CURRENT_PLAYER)
|
|
|
|
setPlayer(name_);
|
|
|
|
}
|
|
|
|
std::string getName()
|
|
|
|
{
|
|
|
|
std::string l_name("");
|
|
|
|
if (type == PLAYER) {
|
|
|
|
l_name += "player:";
|
|
|
|
l_name += name;
|
|
|
|
}else if (type == NODEMETA) {
|
|
|
|
l_name += "nodemeta:";
|
|
|
|
l_name += itos(p.X);
|
|
|
|
l_name += ",";
|
|
|
|
l_name += itos(p.Y);
|
|
|
|
l_name += ",";
|
|
|
|
l_name += itos(p.Z);
|
|
|
|
}else if (type == CURRENT_PLAYER) {
|
|
|
|
l_name += "current_player";
|
|
|
|
}
|
|
|
|
return l_name;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::string dump() const;
|
|
|
|
void serialize(std::ostream &os) const;
|
|
|
|
void deSerialize(std::istream &is);
|
|
|
|
void deSerialize(std::string s);
|
|
|
|
};
|
|
|
|
|
2013-04-15 05:42:24 -07:00
|
|
|
#endif
|
|
|
|
|