base stuff for item->object conversion

This commit is contained in:
Perttu Ahola 2010-12-24 03:08:05 +02:00
parent 10b06419ab
commit f15670379d
9 changed files with 583 additions and 194 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -568,6 +568,39 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
// making some copypasta // making some copypasta
{} {}
if(command == TOCLIENT_REMOVENODE)
{
if(datasize < 8)
return;
v3s16 p;
p.X = readS16(&data[2]);
p.Y = readS16(&data[4]);
p.Z = readS16(&data[6]);
//TimeTaker t1("TOCLIENT_REMOVENODE", g_device);
// This will clear the cracking animation after digging
((ClientMap&)m_env.getMap()).clearTempMod(p);
removeNode(p);
}
else if(command == TOCLIENT_ADDNODE)
{
if(datasize < 8 + MapNode::serializedLength(ser_version))
return;
v3s16 p;
p.X = readS16(&data[2]);
p.Y = readS16(&data[4]);
p.Z = readS16(&data[6]);
//TimeTaker t1("TOCLIENT_ADDNODE", g_device);
MapNode n;
n.deSerialize(&data[8], ser_version);
addNode(p, n);
}
if(command == TOCLIENT_PLAYERPOS) if(command == TOCLIENT_PLAYERPOS)
{ {
dstream<<"WARNING: Received deprecated TOCLIENT_PLAYERPOS" dstream<<"WARNING: Received deprecated TOCLIENT_PLAYERPOS"
@ -1023,7 +1056,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
/* /*
Returns true if there was something in queue Returns true if there was something in queue
*/ */
bool Client::AsyncProcessPacket(LazyMeshUpdater &mesh_updater) bool Client::AsyncProcessPacket()
{ {
DSTACK(__FUNCTION_NAME); DSTACK(__FUNCTION_NAME);
@ -1053,40 +1086,7 @@ bool Client::AsyncProcessPacket(LazyMeshUpdater &mesh_updater)
ToClientCommand command = (ToClientCommand)readU16(&data[0]); ToClientCommand command = (ToClientCommand)readU16(&data[0]);
if(command == TOCLIENT_REMOVENODE) if(command == TOCLIENT_BLOCKDATA)
{
if(datasize < 8)
return true;
v3s16 p;
p.X = readS16(&data[2]);
p.Y = readS16(&data[4]);
p.Z = readS16(&data[6]);
//TimeTaker t1("TOCLIENT_REMOVENODE", g_device);
// This will clear the cracking animation after digging
((ClientMap&)m_env.getMap()).clearTempMod(p);
removeNode(p);
}
else if(command == TOCLIENT_ADDNODE)
{
if(datasize < 8 + MapNode::serializedLength(ser_version))
return true;
v3s16 p;
p.X = readS16(&data[2]);
p.Y = readS16(&data[4]);
p.Z = readS16(&data[6]);
//TimeTaker t1("TOCLIENT_ADDNODE", g_device);
MapNode n;
n.deSerialize(&data[8], ser_version);
addNode(p, n);
}
else if(command == TOCLIENT_BLOCKDATA)
{ {
// Ignore too small packet // Ignore too small packet
if(datasize < 8) if(datasize < 8)
@ -1226,24 +1226,11 @@ bool Client::AsyncProcessData()
{ {
for(;;) for(;;)
{ {
// We want to update the meshes as soon as a single packet has bool r = AsyncProcessPacket();
// been processed
LazyMeshUpdater mesh_updater(&m_env);
bool r = AsyncProcessPacket(mesh_updater);
if(r == false) if(r == false)
break; break;
} }
return false; return false;
/*LazyMeshUpdater mesh_updater(&m_env);
for(;;)
{
bool r = AsyncProcessPacket(mesh_updater);
if(r == false)
break;
}
return false;*/
} }
void Client::Send(u16 channelnum, SharedBuffer<u8> data, bool reliable) void Client::Send(u16 channelnum, SharedBuffer<u8> data, bool reliable)
@ -1252,42 +1239,6 @@ void Client::Send(u16 channelnum, SharedBuffer<u8> data, bool reliable)
m_con.Send(PEER_ID_SERVER, channelnum, data, reliable); m_con.Send(PEER_ID_SERVER, channelnum, data, reliable);
} }
#if 0
void Client::fetchBlock(v3s16 p, u8 flags)
{
if(connectedAndInitialized() == false)
throw ClientNotReadyException
("ClientNotReadyException: connectedAndInitialized() == false");
/*dstream<<"Client::fetchBlock(): Sending GETBLOCK for ("
<<p.X<<","<<p.Y<<","<<p.Z<<")"<<std::endl;*/
JMutexAutoLock conlock(m_con_mutex);
SharedBuffer<u8> data(9);
writeU16(&data[0], TOSERVER_GETBLOCK);
writeS16(&data[2], p.X);
writeS16(&data[4], p.Y);
writeS16(&data[6], p.Z);
writeU8(&data[8], flags);
m_con.Send(PEER_ID_SERVER, 1, data, true);
}
/*
Calls fetchBlock() on some nearby missing blocks.
Returns when any of various network load indicators go over limit.
Does nearly the same thing as the old updateChangedVisibleArea()
*/
void Client::fetchBlocks()
{
if(connectedAndInitialized() == false)
throw ClientNotReadyException
("ClientNotReadyException: connectedAndInitialized() == false");
}
#endif
bool Client::isFetchingBlocks() bool Client::isFetchingBlocks()
{ {
JMutexAutoLock conlock(m_con_mutex); JMutexAutoLock conlock(m_con_mutex);
@ -1369,7 +1320,7 @@ void Client::clickObject(u8 button, v3s16 blockpos, s16 id, u16 item)
} }
/* /*
[0] u16 command [0] u16 command=TOSERVER_CLICK_OBJECT
[2] u8 button (0=left, 1=right) [2] u8 button (0=left, 1=right)
[3] v3s16 block [3] v3s16 block
[9] s16 id [9] s16 id

View File

@ -101,38 +101,6 @@ struct IncomingPacket
s32 *m_refcount; s32 *m_refcount;
}; };
// TODO: Remove this. It is not used as supposed.
class LazyMeshUpdater
{
public:
LazyMeshUpdater(Environment *env)
{
m_env = env;
}
~LazyMeshUpdater()
{
/*
TODO: This could be optimized. It will currently
double-update some blocks.
*/
for(core::map<v3s16, bool>::Iterator
i = m_blocks.getIterator();
i.atEnd() == false; i++)
{
v3s16 p = i.getNode()->getKey();
m_env->updateMeshes(p);
}
m_blocks.clear();
}
void add(v3s16 p)
{
m_blocks.insert(p, true);
}
private:
Environment *m_env;
core::map<v3s16, bool> m_blocks;
};
class Client : public con::PeerHandler class Client : public con::PeerHandler
{ {
public: public:
@ -175,7 +143,7 @@ public:
void ProcessData(u8 *data, u32 datasize, u16 sender_peer_id); void ProcessData(u8 *data, u32 datasize, u16 sender_peer_id);
// Returns true if something was received // Returns true if something was received
bool AsyncProcessPacket(LazyMeshUpdater &mesh_updater); bool AsyncProcessPacket();
bool AsyncProcessData(); bool AsyncProcessData();
void Send(u16 channelnum, SharedBuffer<u8> data, bool reliable); void Send(u16 channelnum, SharedBuffer<u8> data, bool reliable);

View File

@ -66,6 +66,14 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is)
std::getline(is, inventorystring, '|'); std::getline(is, inventorystring, '|');
return new MapBlockObjectItem(inventorystring); return new MapBlockObjectItem(inventorystring);
} }
else if(name == "ToolItem")
{
std::string toolname;
std::getline(is, toolname, ' ');
u16 wear;
is>>wear;
return new ToolItem(toolname, wear);
}
else else
{ {
dstream<<"Unknown InventoryItem name=\""<<name<<"\""<<std::endl; dstream<<"Unknown InventoryItem name=\""<<name<<"\""<<std::endl;
@ -126,6 +134,19 @@ MapBlockObject * MapBlockObjectItem::createObject
RatObject *obj = new RatObject(NULL, -1, pos); RatObject *obj = new RatObject(NULL, -1, pos);
return obj; return obj;
} }
else if(name == "ItemObj")
{
/*
Now we are an inventory item containing the serialization
string of an object that contains the serialization
string of an inventory item. Fuck this.
*/
//assert(0);
dstream<<__FUNCTION_NAME<<": WARNING: Ignoring ItemObj "
<<"because an item-object should never be inside "
<<"an object-item."<<std::endl;
return NULL;
}
else else
{ {
return NULL; return NULL;

View File

@ -196,6 +196,78 @@ private:
std::string m_inventorystring; std::string m_inventorystring;
}; };
class ToolItem : public InventoryItem
{
public:
ToolItem(std::string toolname, u16 wear)
{
m_toolname = toolname;
m_wear = wear;
}
/*
Implementation interface
*/
virtual const char* getName() const
{
return "ToolItem";
}
virtual void serialize(std::ostream &os)
{
os<<getName();
os<<" ";
os<<m_toolname;
os<<" ";
os<<m_wear;
}
virtual InventoryItem* clone()
{
return new ToolItem(m_toolname, m_wear);
}
#ifndef SERVER
video::ITexture * getImage()
{
if(m_toolname == "WPick")
return g_irrlicht->getTexture("../data/tool_wpick.png");
if(m_toolname == "STPick")
return g_irrlicht->getTexture("../data/tool_stpick.png");
// Default to cloud texture
return g_irrlicht->getTexture(tile_texture_path_get(TILE_CLOUD));
}
#endif
std::string getText()
{
std::ostringstream os;
u16 f = 4;
u16 d = 65535/f;
u16 i;
for(i=0; i<(65535-m_wear)/d; i++)
os<<'X';
for(; i<f; i++)
os<<'-';
return os.str();
/*std::ostringstream os;
os<<m_toolname;
os<<" ";
os<<(m_wear/655);
return os.str();*/
}
/*
Special methods
*/
std::string getToolName()
{
return m_toolname;
}
u16 getWear()
{
return m_wear;
}
private:
std::string m_toolname;
u16 m_wear;
};
class InventoryList class InventoryList
{ {
public: public:

View File

@ -105,6 +105,10 @@ SUGG: Make the amount of blocks sending to client and the total
main network eater of this system, so it is the one that has main network eater of this system, so it is the one that has
to be throttled so that RTTs stay low. to be throttled so that RTTs stay low.
SUGG: Meshes of blocks could be split into 6 meshes facing into
different directions and then only those drawn that need to be
- Also an 1-dimensional tile map would be nice probably
TODO: Untie client network operations from framerate TODO: Untie client network operations from framerate
- Needs some input queues or something - Needs some input queues or something
- Not really necessary? - Not really necessary?
@ -173,7 +177,9 @@ TODO: Check if the usage of Client::isFetchingBlocks() in
Doing now: Doing now:
====================================================================== ======================================================================
TODO: Convert the text input system to use a modal menu... or something TODO: Tool items
- Actually, tool items should be just a little special MapBlockItems
====================================================================== ======================================================================
@ -269,9 +275,6 @@ extern void set_default_settings();
Random stuff Random stuff
*/ */
//u16 g_selected_material = 0;
u16 g_selected_item = 0;
IrrlichtDevice *g_device = NULL; IrrlichtDevice *g_device = NULL;
Client *g_client = NULL; Client *g_client = NULL;
@ -292,6 +295,8 @@ Queue<InventoryAction*> inventory_action_queue;
// This is a copy of the inventory that the client's environment has // This is a copy of the inventory that the client's environment has
Inventory local_inventory; Inventory local_inventory;
u16 g_selected_item = 0;
/* /*
Debug streams Debug streams
*/ */
@ -1833,6 +1838,10 @@ int main(int argc, char *argv[])
MapBlockObject *selected_object = client.getSelectedObject MapBlockObject *selected_object = client.getSelectedObject
(d*BS, camera_position, shootline); (d*BS, camera_position, shootline);
/*
If it's pointing to a MapBlockObject
*/
if(selected_object != NULL) if(selected_object != NULL)
{ {
//dstream<<"Client returned selected_object != NULL"<<std::endl; //dstream<<"Client returned selected_object != NULL"<<std::endl;
@ -2041,6 +2050,8 @@ int main(int argc, char *argv[])
} // regular block } // regular block
} // for coords } // for coords
static float nodig_delay_counter = 0.0;
if(nodefound) if(nodefound)
{ {
static v3s16 nodepos_old(-32768,-32768,-32768); static v3s16 nodepos_old(-32768,-32768,-32768);
@ -2048,18 +2059,6 @@ int main(int argc, char *argv[])
static float dig_time = 0.0; static float dig_time = 0.0;
static u16 dig_index = 0; static u16 dig_index = 0;
if(nodepos != nodepos_old)
{
std::cout<<DTIME<<"Pointing at ("<<nodepos.X<<","
<<nodepos.Y<<","<<nodepos.Z<<")"<<std::endl;
if(nodepos_old != v3s16(-32768,-32768,-32768))
{
client.clearTempMod(nodepos_old);
dig_time = 0.0;
}
}
hilightboxes.push_back(nodefacebox); hilightboxes.push_back(nodefacebox);
if(g_input->getLeftReleased()) if(g_input->getLeftReleased())
@ -2067,42 +2066,87 @@ int main(int argc, char *argv[])
client.clearTempMod(nodepos); client.clearTempMod(nodepos);
dig_time = 0.0; dig_time = 0.0;
} }
if(g_input->getLeftClicked() ||
(g_input->getLeftState() && nodepos != nodepos_old)) if(nodig_delay_counter > 0.0)
{ {
dstream<<DTIME<<"Started digging"<<std::endl; nodig_delay_counter -= dtime;
client.groundAction(0, nodepos, neighbourpos, g_selected_item);
} }
if(g_input->getLeftClicked()) else
{ {
client.setTempMod(nodepos, NodeMod(NODEMOD_CRACK, 0)); if(nodepos != nodepos_old)
}
if(g_input->getLeftState())
{
MapNode n = client.getNode(nodepos);
// TODO: Get this from some table that is sent by server
float dig_time_complete = 0.5;
if(n.d == CONTENT_STONE)
dig_time_complete = 1.5;
dig_index = (u16)((float)CRACK_ANIMATION_LENGTH
* dig_time/dig_time_complete);
if(dig_index < CRACK_ANIMATION_LENGTH)
{ {
//dstream<<"dig_index="<<dig_index<<std::endl; std::cout<<DTIME<<"Pointing at ("<<nodepos.X<<","
client.setTempMod(nodepos, NodeMod(NODEMOD_CRACK, dig_index)); <<nodepos.Y<<","<<nodepos.Z<<")"<<std::endl;
}
else if(nodepos_old != v3s16(-32768,-32768,-32768))
{ {
dstream<<DTIME<<"Digging completed"<<std::endl; client.clearTempMod(nodepos_old);
client.groundAction(3, nodepos, neighbourpos, g_selected_item); dig_time = 0.0;
client.clearTempMod(nodepos); }
client.removeNode(nodepos);
} }
dig_time += dtime; if(g_input->getLeftClicked() ||
(g_input->getLeftState() && nodepos != nodepos_old))
{
dstream<<DTIME<<"Started digging"<<std::endl;
client.groundAction(0, nodepos, neighbourpos, g_selected_item);
}
if(g_input->getLeftClicked())
{
client.setTempMod(nodepos, NodeMod(NODEMOD_CRACK, 0));
}
if(g_input->getLeftState())
{
MapNode n = client.getNode(nodepos);
// TODO: Get this from some table that is sent by server
float dig_time_complete = 0.5;
if(n.d == CONTENT_STONE || n.d == CONTENT_COALSTONE)
{
dig_time_complete = 10.0;
InventoryList *mlist = local_inventory.getList("main");
if(mlist != NULL)
{
InventoryItem *item = mlist->getItem(g_selected_item);
if((std::string)item->getName() == "ToolItem")
{
ToolItem *titem = (ToolItem*)item;
if(titem->getToolName() == "WPick")
{
dig_time_complete = 1.2;
}
else if(titem->getToolName() == "STPick")
{
dig_time_complete = 0.6;
}
}
}
}
dig_index = (u16)((float)CRACK_ANIMATION_LENGTH
* dig_time/dig_time_complete);
if(dig_index < CRACK_ANIMATION_LENGTH)
{
//dstream<<"dig_index="<<dig_index<<std::endl;
client.setTempMod(nodepos, NodeMod(NODEMOD_CRACK, dig_index));
}
else
{
dstream<<DTIME<<"Digging completed"<<std::endl;
client.groundAction(3, nodepos, neighbourpos, g_selected_item);
client.clearTempMod(nodepos);
client.removeNode(nodepos);
dig_time = 0;
nodig_delay_counter = dig_time_complete
/ (float)CRACK_ANIMATION_LENGTH;
}
dig_time += dtime;
}
} }
if(g_input->getRightClicked()) if(g_input->getRightClicked())

View File

@ -21,6 +21,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#include "mapblock.h" #include "mapblock.h"
// Only for ::getNodeBox, TODO: Get rid of this // Only for ::getNodeBox, TODO: Get rid of this
#include "map.h" #include "map.h"
#include "inventory.h"
#include "irrlichtwrapper.h"
/* /*
MapBlockObject MapBlockObject
@ -293,10 +295,101 @@ void RatObject::addToScene(scene::ISceneManager *smgr)
} }
#endif #endif
/*
ItemObject
*/
#ifndef SERVER #ifndef SERVER
void ItemObject::addToScene(scene::ISceneManager *smgr)
{
if(m_node != NULL)
return;
//video::IVideoDriver* driver = smgr->getVideoDriver();
// Get image of item for showing
video::ITexture *texture = getItemImage();
/*
Create a mesh
*/
scene::SMesh *mesh = new scene::SMesh();
{
scene::IMeshBuffer *buf = new scene::SMeshBuffer();
video::SColor c(255,255,255,255);
video::S3DVertex vertices[4] =
{
/*video::S3DVertex(BS/2,-BS/2,0, 0,0,0, c, 0,1),
video::S3DVertex(-BS/2,-BS/2,0, 0,0,0, c, 1,1),
video::S3DVertex(-BS/2,BS/2,0, 0,0,0, c, 1,0),
video::S3DVertex(BS/2,BS/2,0, 0,0,0, c, 0,0),*/
video::S3DVertex(BS/3,-BS/2,0, 0,0,0, c, 0,1),
video::S3DVertex(-BS/3,-BS/2,0, 0,0,0, c, 1,1),
video::S3DVertex(-BS/3,-BS/2+BS*2/3,0, 0,0,0, c, 1,0),
video::S3DVertex(BS/3,-BS/2+BS*2/3,0, 0,0,0, c, 0,0),
};
u16 indices[] = {0,1,2,2,3,0};
buf->append(vertices, 4, indices, 6);
// Set material
buf->getMaterial().setFlag(video::EMF_LIGHTING, false);
buf->getMaterial().setFlag(video::EMF_BACK_FACE_CULLING, false);
buf->getMaterial().setTexture(0, texture);
buf->getMaterial().setFlag(video::EMF_BILINEAR_FILTER, false);
buf->getMaterial().setFlag(video::EMF_FOG_ENABLE, true);
buf->getMaterial().MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF;
// Add to mesh
mesh->addMeshBuffer(buf);
buf->drop();
}
m_node = smgr->addMeshSceneNode(mesh, NULL);
// Set it to use the materials of the meshbuffers directly.
// This is needed for changing the texture in the future
((scene::IMeshSceneNode*)m_node)->setReadOnlyMaterials(true);
mesh->drop();
updateSceneNode();
}
video::ITexture * ItemObject::getItemImage()
{
/*
Create an inventory item to see what is its image
*/
video::ITexture *texture = NULL;
InventoryItem *item = createInventoryItem();
if(item)
texture = item->getImage();
/*else
texture = g_irrlicht->getTexture("../data/cloud.png");*/
if(item)
delete item;
return texture;
}
#endif
InventoryItem * ItemObject::createInventoryItem()
{
try{
std::istringstream is(m_itemstring, std::ios_base::binary);
InventoryItem *item = InventoryItem::deSerialize(is);
dstream<<__FUNCTION_NAME<<": m_itemstring=\""
<<m_itemstring<<"\" -> item="<<item
<<std::endl;
return item;
}
catch(SerializationError &e)
{
dstream<<__FUNCTION_NAME<<": serialization error: "
<<"m_itemstring=\""<<m_itemstring<<"\""<<std::endl;
return NULL;
}
}
/* /*
PlayerObject PlayerObject
*/ */
#ifndef SERVER
void PlayerObject::addToScene(scene::ISceneManager *smgr) void PlayerObject::addToScene(scene::ISceneManager *smgr)
{ {
if(m_node != NULL) if(m_node != NULL)
@ -480,6 +573,10 @@ void MapBlockObjectList::update(std::istream &is, u8 version,
{ {
obj = new RatObject(m_block, id, pos); obj = new RatObject(m_block, id, pos);
} }
else if(type_id == MAPBLOCKOBJECT_TYPE_ITEM)
{
obj = new ItemObject(m_block, id, pos);
}
else else
{ {
// This is fatal because we cannot know the length // This is fatal because we cannot know the length

View File

@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#define MAPBLOCKOBJECT_TYPE_PLAYER 0 #define MAPBLOCKOBJECT_TYPE_PLAYER 0
#define MAPBLOCKOBJECT_TYPE_SIGN 2 #define MAPBLOCKOBJECT_TYPE_SIGN 2
#define MAPBLOCKOBJECT_TYPE_RAT 3 #define MAPBLOCKOBJECT_TYPE_RAT 3
#define MAPBLOCKOBJECT_TYPE_ITEM 4
// Used for handling selecting special stuff // Used for handling selecting special stuff
//#define MAPBLOCKOBJECT_TYPE_PSEUDO 1000 //#define MAPBLOCKOBJECT_TYPE_PSEUDO 1000
@ -719,6 +720,182 @@ protected:
float m_age; float m_age;
}; };
/*
An object on the map that represents an inventory item
*/
class InventoryItem;
class ItemObject : public MapBlockObject
{
public:
// The constructor of every MapBlockObject should be like this
ItemObject(MapBlock *block, s16 id, v3f pos):
MapBlockObject(block, id, pos),
m_node(NULL)
{
/*m_selection_box = new core::aabbox3d<f32>
(-BS*0.4,-BS*0.5,-BS*0.4, BS*0.4,BS*0.5,BS*0.4);*/
m_selection_box = new core::aabbox3d<f32>
(-BS/3,-BS/2,-BS/3, BS/3,-BS/2+BS*2/3,BS/3);
m_yaw = 0.0;
}
virtual ~ItemObject()
{
delete m_selection_box;
}
/*
Implementation interface
*/
virtual u16 getTypeId() const
{
return MAPBLOCKOBJECT_TYPE_ITEM;
}
virtual void serialize(std::ostream &os, u8 version)
{
serializeBase(os, version);
u8 buf[2];
// Write text length
writeU16(buf, m_itemstring.size());
os.write((char*)buf, 2);
// Write text
os.write(m_itemstring.c_str(), m_itemstring.size());
}
virtual void update(std::istream &is, u8 version)
{
u8 buf[2];
// Read text length
is.read((char*)buf, 2);
u16 size = readU16(buf);
// Read text
std::string old_itemstring = m_itemstring;
m_itemstring.clear();
for(u16 i=0; i<size; i++)
{
is.read((char*)buf, 1);
m_itemstring += buf[0];
}
#ifndef SERVER
if(m_itemstring != old_itemstring && m_node)
{
/*
Update texture
*/
video::ITexture *texture = getItemImage();
scene::IMesh *mesh = m_node->getMesh();
if(mesh->getMeshBufferCount() >= 1)
{
scene::IMeshBuffer *buf = mesh->getMeshBuffer(0);
//dstream<<"Setting texture "<<texture<<std::endl;
buf->getMaterial().setTexture(0, texture);
}
}
updateSceneNode();
#endif
}
virtual bool serverStep(float dtime, u32 daynight_ratio)
{
return false;
}
#ifndef SERVER
virtual void clientStep(float dtime)
{
m_yaw += dtime * 90;
if(m_yaw >= 360.)
m_yaw -= 360.;
updateSceneNode();
}
virtual void addToScene(scene::ISceneManager *smgr);
virtual void removeFromScene()
{
if(m_node != NULL)
{
m_node->remove();
m_node = NULL;
}
}
virtual void updateLight(u8 light_at_pos)
{
if(m_node == NULL)
return;
u8 li = decode_light(light_at_pos);
video::SColor color(255,li,li,li);
scene::IMesh *mesh = m_node->getMesh();
u16 mc = mesh->getMeshBufferCount();
for(u16 j=0; j<mc; j++)
{
scene::IMeshBuffer *buf = mesh->getMeshBuffer(j);
video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices();
u16 vc = buf->getVertexCount();
for(u16 i=0; i<vc; i++)
{
vertices[i].Color = color;
}
}
}
#endif
virtual std::string infoText()
{
return std::string("\"") + m_itemstring + "\"";
}
virtual std::string getInventoryString()
{
return std::string("ItemObj ")+m_itemstring;
}
/*
Special methods
*/
InventoryItem * createInventoryItem();
#ifndef SERVER
video::ITexture * getItemImage();
void updateSceneNode()
{
if(m_node != NULL)
{
m_node->setPosition(getAbsolutePos());
m_node->setRotation(v3f(0, m_yaw, 0));
}
}
#endif
void setItemString(std::string inventorystring)
{
m_itemstring = inventorystring;
setBlockChanged();
}
std::string getItemString()
{
return m_itemstring;
}
protected:
scene::IMeshSceneNode *m_node;
std::string m_itemstring;
f32 m_yaw;
};
/* /*
NOTE: Not used. NOTE: Not used.
*/ */

View File

@ -1635,7 +1635,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
} }
catch(InvalidPositionException &e) catch(InvalidPositionException &e)
{ {
derr_server<<"PICK_OBJECT block not found"<<std::endl; derr_server<<"CLICK_OBJECT block not found"<<std::endl;
return; return;
} }
@ -1643,7 +1643,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
if(obj == NULL) if(obj == NULL)
{ {
derr_server<<"PICK_OBJECT object not found"<<std::endl; derr_server<<"CLICK_OBJECT object not found"<<std::endl;
return; return;
} }
@ -1662,10 +1662,24 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
dout_server<<"Player inventory has no free space"<<std::endl; dout_server<<"Player inventory has no free space"<<std::endl;
return; return;
} }
/*
Create the inventory item
*/
InventoryItem *item = NULL;
// If it is an item-object, take the item from it
if(obj->getTypeId() == MAPBLOCKOBJECT_TYPE_ITEM)
{
item = ((ItemObject*)obj)->createInventoryItem();
}
// Else create an item of the object
else
{
item = new MapBlockObjectItem
(obj->getInventoryString());
}
// Add to inventory and send inventory // Add to inventory and send inventory
InventoryItem *item = new MapBlockObjectItem
(obj->getInventoryString());
ilist->addItem(item); ilist->addItem(item);
SendInventory(player->peer_id); SendInventory(player->peer_id);
} }
@ -2021,17 +2035,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
v.blitBack(modified_blocks); v.blitBack(modified_blocks);
} }
/* /*
Handle block object items Handle other items
*/ */
else if(std::string("MBOItem") == item->getName()) else
{ {
MapBlockObjectItem *oitem = (MapBlockObjectItem*)item;
/*dout_server<<"Trying to place a MapBlockObjectItem: "
"inventorystring=\""
<<oitem->getInventoryString()
<<"\""<<std::endl;*/
v3s16 blockpos = getNodeBlockPos(p_over); v3s16 blockpos = getNodeBlockPos(p_over);
MapBlock *block = NULL; MapBlock *block = NULL;
@ -2056,25 +2063,61 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
<<"("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")" <<"("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"
<<std::endl;*/ <<std::endl;*/
MapBlockObject *obj = NULL;
MapBlockObject *obj = oitem->createObject /*
(pos, player->getYaw(), player->getPitch()); Handle block object items
*/
if(std::string("MBOItem") == item->getName())
{
MapBlockObjectItem *oitem = (MapBlockObjectItem*)item;
/*dout_server<<"Trying to place a MapBlockObjectItem: "
"inventorystring=\""
<<oitem->getInventoryString()
<<"\""<<std::endl;*/
obj = oitem->createObject
(pos, player->getYaw(), player->getPitch());
}
/*
Handle other items
*/
else
{
dout_server<<"Placing a miscellaneous item on map"
<<std::endl;
/*
Create an ItemObject that contains the item.
*/
ItemObject *iobj = new ItemObject(NULL, -1, pos);
std::ostringstream os(std::ios_base::binary);
item->serialize(os);
dout_server<<"Item string is \""<<os.str()<<"\""<<std::endl;
iobj->setItemString(os.str());
obj = iobj;
}
if(obj == NULL) if(obj == NULL)
derr_server<<"WARNING: oitem created NULL object"
<<std::endl;
block->addObject(obj);
//dout_server<<"Placed object"<<std::endl;
InventoryList *ilist = player->inventory.getList("main");
if(g_settings.getBool("creative_mode") == false && ilist)
{ {
// Remove from inventory and send inventory derr_server<<"WARNING: item resulted in NULL object, "
ilist->deleteItem(item_i); <<"not placing onto map"
// Send inventory <<std::endl;
SendInventory(peer_id); }
else
{
block->addObject(obj);
dout_server<<"Placed object"<<std::endl;
InventoryList *ilist = player->inventory.getList("main");
if(g_settings.getBool("creative_mode") == false && ilist)
{
// Remove from inventory and send inventory
ilist->deleteItem(item_i);
// Send inventory
SendInventory(peer_id);
}
} }
} }
@ -2445,6 +2488,12 @@ void Server::peerAdded(con::Peer *peer)
if(g_settings.getBool("creative_mode")) if(g_settings.getBool("creative_mode"))
{ {
// Give a good pick
{
InventoryItem *item = new ToolItem("STPick", 32000);
bool r = player->inventory.addItem("main", item);
assert(r == true);
}
// Give all materials // Give all materials
assert(USEFUL_CONTENT_COUNT <= PLAYER_INVENTORY_SIZE); assert(USEFUL_CONTENT_COUNT <= PLAYER_INVENTORY_SIZE);
for(u16 i=0; i<USEFUL_CONTENT_COUNT; i++) for(u16 i=0; i<USEFUL_CONTENT_COUNT; i++)
@ -2471,6 +2520,16 @@ void Server::peerAdded(con::Peer *peer)
} }
else else
{ {
{
InventoryItem *item = new ToolItem("WPick", 32000);
bool r = player->inventory.addItem("main", item);
assert(r == true);
}
{
InventoryItem *item = new ToolItem("STPick", 32000);
bool r = player->inventory.addItem("main", item);
assert(r == true);
}
/*// Give some lights /*// Give some lights
{ {
InventoryItem *item = new MaterialItem(CONTENT_TORCH, 999); InventoryItem *item = new MaterialItem(CONTENT_TORCH, 999);