base stuff for item->object conversion
This commit is contained in:
parent
10b06419ab
commit
f15670379d
BIN
data/sign.png
BIN
data/sign.png
Binary file not shown.
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
123
src/client.cpp
123
src/client.cpp
|
@ -568,6 +568,39 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
|||
// 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)
|
||||
{
|
||||
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
|
||||
*/
|
||||
bool Client::AsyncProcessPacket(LazyMeshUpdater &mesh_updater)
|
||||
bool Client::AsyncProcessPacket()
|
||||
{
|
||||
DSTACK(__FUNCTION_NAME);
|
||||
|
||||
|
@ -1053,40 +1086,7 @@ bool Client::AsyncProcessPacket(LazyMeshUpdater &mesh_updater)
|
|||
|
||||
ToClientCommand command = (ToClientCommand)readU16(&data[0]);
|
||||
|
||||
if(command == TOCLIENT_REMOVENODE)
|
||||
{
|
||||
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)
|
||||
if(command == TOCLIENT_BLOCKDATA)
|
||||
{
|
||||
// Ignore too small packet
|
||||
if(datasize < 8)
|
||||
|
@ -1226,24 +1226,11 @@ bool Client::AsyncProcessData()
|
|||
{
|
||||
for(;;)
|
||||
{
|
||||
// We want to update the meshes as soon as a single packet has
|
||||
// been processed
|
||||
LazyMeshUpdater mesh_updater(&m_env);
|
||||
bool r = AsyncProcessPacket(mesh_updater);
|
||||
bool r = AsyncProcessPacket();
|
||||
if(r == false)
|
||||
break;
|
||||
}
|
||||
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)
|
||||
|
@ -1252,42 +1239,6 @@ void Client::Send(u16 channelnum, SharedBuffer<u8> data, bool 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()
|
||||
{
|
||||
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)
|
||||
[3] v3s16 block
|
||||
[9] s16 id
|
||||
|
|
34
src/client.h
34
src/client.h
|
@ -101,38 +101,6 @@ struct IncomingPacket
|
|||
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
|
||||
{
|
||||
public:
|
||||
|
@ -175,7 +143,7 @@ public:
|
|||
|
||||
void ProcessData(u8 *data, u32 datasize, u16 sender_peer_id);
|
||||
// Returns true if something was received
|
||||
bool AsyncProcessPacket(LazyMeshUpdater &mesh_updater);
|
||||
bool AsyncProcessPacket();
|
||||
bool AsyncProcessData();
|
||||
void Send(u16 channelnum, SharedBuffer<u8> data, bool reliable);
|
||||
|
||||
|
|
|
@ -66,6 +66,14 @@ InventoryItem* InventoryItem::deSerialize(std::istream &is)
|
|||
std::getline(is, 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
|
||||
{
|
||||
dstream<<"Unknown InventoryItem name=\""<<name<<"\""<<std::endl;
|
||||
|
@ -126,6 +134,19 @@ MapBlockObject * MapBlockObjectItem::createObject
|
|||
RatObject *obj = new RatObject(NULL, -1, pos);
|
||||
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
|
||||
{
|
||||
return NULL;
|
||||
|
|
|
@ -196,6 +196,78 @@ private:
|
|||
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
|
||||
{
|
||||
public:
|
||||
|
|
136
src/main.cpp
136
src/main.cpp
|
@ -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
|
||||
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
|
||||
- Needs some input queues or something
|
||||
- Not really necessary?
|
||||
|
@ -173,7 +177,9 @@ TODO: Check if the usage of Client::isFetchingBlocks() in
|
|||
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
|
||||
*/
|
||||
|
||||
//u16 g_selected_material = 0;
|
||||
u16 g_selected_item = 0;
|
||||
|
||||
IrrlichtDevice *g_device = 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
|
||||
Inventory local_inventory;
|
||||
|
||||
u16 g_selected_item = 0;
|
||||
|
||||
/*
|
||||
Debug streams
|
||||
*/
|
||||
|
@ -1833,6 +1838,10 @@ int main(int argc, char *argv[])
|
|||
MapBlockObject *selected_object = client.getSelectedObject
|
||||
(d*BS, camera_position, shootline);
|
||||
|
||||
/*
|
||||
If it's pointing to a MapBlockObject
|
||||
*/
|
||||
|
||||
if(selected_object != NULL)
|
||||
{
|
||||
//dstream<<"Client returned selected_object != NULL"<<std::endl;
|
||||
|
@ -2041,6 +2050,8 @@ int main(int argc, char *argv[])
|
|||
} // regular block
|
||||
} // for coords
|
||||
|
||||
static float nodig_delay_counter = 0.0;
|
||||
|
||||
if(nodefound)
|
||||
{
|
||||
static v3s16 nodepos_old(-32768,-32768,-32768);
|
||||
|
@ -2048,18 +2059,6 @@ int main(int argc, char *argv[])
|
|||
static float dig_time = 0.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);
|
||||
|
||||
if(g_input->getLeftReleased())
|
||||
|
@ -2067,42 +2066,87 @@ int main(int argc, char *argv[])
|
|||
client.clearTempMod(nodepos);
|
||||
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;
|
||||
client.groundAction(0, nodepos, neighbourpos, g_selected_item);
|
||||
nodig_delay_counter -= dtime;
|
||||
}
|
||||
if(g_input->getLeftClicked())
|
||||
else
|
||||
{
|
||||
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)
|
||||
dig_time_complete = 1.5;
|
||||
|
||||
dig_index = (u16)((float)CRACK_ANIMATION_LENGTH
|
||||
* dig_time/dig_time_complete);
|
||||
|
||||
if(dig_index < CRACK_ANIMATION_LENGTH)
|
||||
if(nodepos != nodepos_old)
|
||||
{
|
||||
//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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
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())
|
||||
|
|
|
@ -21,6 +21,8 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#include "mapblock.h"
|
||||
// Only for ::getNodeBox, TODO: Get rid of this
|
||||
#include "map.h"
|
||||
#include "inventory.h"
|
||||
#include "irrlichtwrapper.h"
|
||||
|
||||
/*
|
||||
MapBlockObject
|
||||
|
@ -293,10 +295,101 @@ void RatObject::addToScene(scene::ISceneManager *smgr)
|
|||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
ItemObject
|
||||
*/
|
||||
#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
|
||||
*/
|
||||
#ifndef SERVER
|
||||
void PlayerObject::addToScene(scene::ISceneManager *smgr)
|
||||
{
|
||||
if(m_node != NULL)
|
||||
|
@ -480,6 +573,10 @@ void MapBlockObjectList::update(std::istream &is, u8 version,
|
|||
{
|
||||
obj = new RatObject(m_block, id, pos);
|
||||
}
|
||||
else if(type_id == MAPBLOCKOBJECT_TYPE_ITEM)
|
||||
{
|
||||
obj = new ItemObject(m_block, id, pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is fatal because we cannot know the length
|
||||
|
|
|
@ -31,6 +31,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
|||
#define MAPBLOCKOBJECT_TYPE_PLAYER 0
|
||||
#define MAPBLOCKOBJECT_TYPE_SIGN 2
|
||||
#define MAPBLOCKOBJECT_TYPE_RAT 3
|
||||
#define MAPBLOCKOBJECT_TYPE_ITEM 4
|
||||
// Used for handling selecting special stuff
|
||||
//#define MAPBLOCKOBJECT_TYPE_PSEUDO 1000
|
||||
|
||||
|
@ -719,6 +720,182 @@ protected:
|
|||
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.
|
||||
*/
|
||||
|
|
117
src/server.cpp
117
src/server.cpp
|
@ -1635,7 +1635,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||
}
|
||||
catch(InvalidPositionException &e)
|
||||
{
|
||||
derr_server<<"PICK_OBJECT block not found"<<std::endl;
|
||||
derr_server<<"CLICK_OBJECT block not found"<<std::endl;
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1643,7 +1643,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||
|
||||
if(obj == NULL)
|
||||
{
|
||||
derr_server<<"PICK_OBJECT object not found"<<std::endl;
|
||||
derr_server<<"CLICK_OBJECT object not found"<<std::endl;
|
||||
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;
|
||||
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
|
||||
InventoryItem *item = new MapBlockObjectItem
|
||||
(obj->getInventoryString());
|
||||
ilist->addItem(item);
|
||||
SendInventory(player->peer_id);
|
||||
}
|
||||
|
@ -2021,17 +2035,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||
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);
|
||||
|
||||
MapBlock *block = NULL;
|
||||
|
@ -2056,25 +2063,61 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
|||
<<"("<<pos.X<<","<<pos.Y<<","<<pos.Z<<")"
|
||||
<<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)
|
||||
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
|
||||
ilist->deleteItem(item_i);
|
||||
// Send inventory
|
||||
SendInventory(peer_id);
|
||||
derr_server<<"WARNING: item resulted in NULL object, "
|
||||
<<"not placing onto map"
|
||||
<<std::endl;
|
||||
}
|
||||
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"))
|
||||
{
|
||||
// Give a good pick
|
||||
{
|
||||
InventoryItem *item = new ToolItem("STPick", 32000);
|
||||
bool r = player->inventory.addItem("main", item);
|
||||
assert(r == true);
|
||||
}
|
||||
// Give all materials
|
||||
assert(USEFUL_CONTENT_COUNT <= PLAYER_INVENTORY_SIZE);
|
||||
for(u16 i=0; i<USEFUL_CONTENT_COUNT; i++)
|
||||
|
@ -2471,6 +2520,16 @@ void Server::peerAdded(con::Peer *peer)
|
|||
}
|
||||
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
|
||||
{
|
||||
InventoryItem *item = new MaterialItem(CONTENT_TORCH, 999);
|
||||
|
|
Loading…
Reference in New Issue