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
{}
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

View File

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

View File

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

View File

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

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
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,6 +2059,20 @@ int main(int argc, char *argv[])
static float dig_time = 0.0;
static u16 dig_index = 0;
hilightboxes.push_back(nodefacebox);
if(g_input->getLeftReleased())
{
client.clearTempMod(nodepos);
dig_time = 0.0;
}
if(nodig_delay_counter > 0.0)
{
nodig_delay_counter -= dtime;
}
else
{
if(nodepos != nodepos_old)
{
std::cout<<DTIME<<"Pointing at ("<<nodepos.X<<","
@ -2060,13 +2085,6 @@ int main(int argc, char *argv[])
}
}
hilightboxes.push_back(nodefacebox);
if(g_input->getLeftReleased())
{
client.clearTempMod(nodepos);
dig_time = 0.0;
}
if(g_input->getLeftClicked() ||
(g_input->getLeftState() && nodepos != nodepos_old))
{
@ -2083,8 +2101,28 @@ int main(int argc, char *argv[])
// 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;
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);
@ -2100,10 +2138,16 @@ int main(int argc, char *argv[])
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())
{

View File

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

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_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.
*/

View File

@ -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;
}
@ -1663,9 +1663,23 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
return;
}
// Add to inventory and send inventory
InventoryItem *item = new MapBlockObjectItem
/*
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
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,17 +2063,52 @@ 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
/*
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"
{
derr_server<<"WARNING: item resulted in NULL object, "
<<"not placing onto map"
<<std::endl;
}
else
{
block->addObject(obj);
//dout_server<<"Placed object"<<std::endl;
dout_server<<"Placed object"<<std::endl;
InventoryList *ilist = player->inventory.getList("main");
if(g_settings.getBool("creative_mode") == false && ilist)
@ -2077,6 +2119,7 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
SendInventory(peer_id);
}
}
}
} // action == 1
@ -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);