disconnect method to connection to be used instead of just timing out
parent
705de63dcd
commit
a26c92d7dd
|
@ -117,6 +117,11 @@ Client::Client(
|
||||||
|
|
||||||
Client::~Client()
|
Client::~Client()
|
||||||
{
|
{
|
||||||
|
{
|
||||||
|
JMutexAutoLock conlock(m_con_mutex);
|
||||||
|
m_con.Disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
m_thread.setRun(false);
|
m_thread.setRun(false);
|
||||||
while(m_thread.IsRunning())
|
while(m_thread.IsRunning())
|
||||||
sleep_ms(100);
|
sleep_ms(100);
|
||||||
|
@ -601,7 +606,7 @@ void Client::ProcessData(u8 *data, u32 datasize, u16 sender_peer_id)
|
||||||
|
|
||||||
addNode(p, n);
|
addNode(p, n);
|
||||||
}
|
}
|
||||||
if(command == TOCLIENT_PLAYERPOS)
|
else if(command == TOCLIENT_PLAYERPOS)
|
||||||
{
|
{
|
||||||
dstream<<"WARNING: Received deprecated TOCLIENT_PLAYERPOS"
|
dstream<<"WARNING: Received deprecated TOCLIENT_PLAYERPOS"
|
||||||
<<std::endl;
|
<<std::endl;
|
||||||
|
|
|
@ -542,6 +542,23 @@ void Connection::Connect(Address address)
|
||||||
//m_waiting_new_peer_id = true;
|
//m_waiting_new_peer_id = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Connection::Disconnect()
|
||||||
|
{
|
||||||
|
// Create and send DISCO packet
|
||||||
|
SharedBuffer<u8> data(2);
|
||||||
|
writeU8(&data[0], TYPE_CONTROL);
|
||||||
|
writeU8(&data[1], CONTROLTYPE_DISCO);
|
||||||
|
|
||||||
|
// Send to all
|
||||||
|
core::map<u16, Peer*>::Iterator j;
|
||||||
|
j = m_peers.getIterator();
|
||||||
|
for(; j.atEnd() == false; j++)
|
||||||
|
{
|
||||||
|
Peer *peer = j.getNode()->getValue();
|
||||||
|
SendAsPacket(peer->id, 0, data, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool Connection::Connected()
|
bool Connection::Connected()
|
||||||
{
|
{
|
||||||
if(m_peers.size() != 1)
|
if(m_peers.size() != 1)
|
||||||
|
@ -645,7 +662,22 @@ SharedBuffer<u8> Channel::ProcessPacket(
|
||||||
// the timeout counter
|
// the timeout counter
|
||||||
con->PrintInfo();
|
con->PrintInfo();
|
||||||
dout_con<<"PING"<<std::endl;
|
dout_con<<"PING"<<std::endl;
|
||||||
throw ProcessedSilentlyException("Got a SET_PEER_ID");
|
throw ProcessedSilentlyException("Got a PING");
|
||||||
|
}
|
||||||
|
else if(controltype == CONTROLTYPE_DISCO)
|
||||||
|
{
|
||||||
|
// Just ignore it, the incoming data already reset
|
||||||
|
// the timeout counter
|
||||||
|
con->PrintInfo();
|
||||||
|
dout_con<<"DISCO: Removing peer "<<(peer_id)<<std::endl;
|
||||||
|
|
||||||
|
if(con->deletePeer(peer_id) == false)
|
||||||
|
{
|
||||||
|
con->PrintInfo(derr_con);
|
||||||
|
derr_con<<"DISCO: Peer not found"<<std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
throw ProcessedSilentlyException("Got a DISCO");
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
con->PrintInfo(derr_con);
|
con->PrintInfo(derr_con);
|
||||||
|
@ -1323,6 +1355,16 @@ core::list<Peer*> Connection::GetPeers()
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Connection::deletePeer(u16 peer_id)
|
||||||
|
{
|
||||||
|
if(m_peers.find(peer_id) == NULL)
|
||||||
|
return false;
|
||||||
|
m_peerhandler->deletingPeer(m_peers[peer_id], true);
|
||||||
|
delete m_peers[peer_id];
|
||||||
|
m_peers.remove(peer_id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void Connection::PrintInfo(std::ostream &out)
|
void Connection::PrintInfo(std::ostream &out)
|
||||||
{
|
{
|
||||||
out<<m_socket.GetHandle();
|
out<<m_socket.GetHandle();
|
||||||
|
|
|
@ -226,12 +226,15 @@ controltype and data description:
|
||||||
CONTROLTYPE_SET_PEER_ID
|
CONTROLTYPE_SET_PEER_ID
|
||||||
[2] u16 peer_id_new
|
[2] u16 peer_id_new
|
||||||
CONTROLTYPE_PING
|
CONTROLTYPE_PING
|
||||||
- This can be sent in a reliable packet to get a reply
|
- There is no actual reply, but this can be sent in a reliable
|
||||||
|
packet to get a reply
|
||||||
|
CONTROLTYPE_DISCO
|
||||||
*/
|
*/
|
||||||
#define TYPE_CONTROL 0
|
#define TYPE_CONTROL 0
|
||||||
#define CONTROLTYPE_ACK 0
|
#define CONTROLTYPE_ACK 0
|
||||||
#define CONTROLTYPE_SET_PEER_ID 1
|
#define CONTROLTYPE_SET_PEER_ID 1
|
||||||
#define CONTROLTYPE_PING 2
|
#define CONTROLTYPE_PING 2
|
||||||
|
#define CONTROLTYPE_DISCO 3
|
||||||
/*
|
/*
|
||||||
ORIGINAL: This is a plain packet with no control and no error
|
ORIGINAL: This is a plain packet with no control and no error
|
||||||
checking at all.
|
checking at all.
|
||||||
|
@ -442,12 +445,15 @@ public:
|
||||||
void Connect(Address address);
|
void Connect(Address address);
|
||||||
bool Connected();
|
bool Connected();
|
||||||
|
|
||||||
|
void Disconnect();
|
||||||
|
|
||||||
// Sets peer_id
|
// Sets peer_id
|
||||||
SharedBuffer<u8> GetFromBuffers(u16 &peer_id);
|
SharedBuffer<u8> GetFromBuffers(u16 &peer_id);
|
||||||
|
|
||||||
// The peer_id of sender is stored in peer_id
|
// The peer_id of sender is stored in peer_id
|
||||||
// Return value: I guess this always throws an exception or
|
// Return value: I guess this always throws an exception or
|
||||||
// actually gets data
|
// actually gets data
|
||||||
|
// May call PeerHandler methods
|
||||||
u32 Receive(u16 &peer_id, u8 *data, u32 datasize);
|
u32 Receive(u16 &peer_id, u8 *data, u32 datasize);
|
||||||
|
|
||||||
// These will automatically package the data as an original or split
|
// These will automatically package the data as an original or split
|
||||||
|
@ -460,12 +466,18 @@ public:
|
||||||
// Sends a raw packet
|
// Sends a raw packet
|
||||||
void RawSend(const BufferedPacket &packet);
|
void RawSend(const BufferedPacket &packet);
|
||||||
|
|
||||||
|
// May call PeerHandler methods
|
||||||
void RunTimeouts(float dtime);
|
void RunTimeouts(float dtime);
|
||||||
|
|
||||||
// Can throw a PeerNotFoundException
|
// Can throw a PeerNotFoundException
|
||||||
Peer* GetPeer(u16 peer_id);
|
Peer* GetPeer(u16 peer_id);
|
||||||
// returns NULL if failed
|
// returns NULL if failed
|
||||||
Peer* GetPeerNoEx(u16 peer_id);
|
Peer* GetPeerNoEx(u16 peer_id);
|
||||||
core::list<Peer*> GetPeers();
|
core::list<Peer*> GetPeers();
|
||||||
|
|
||||||
|
// Calls PeerHandler::deletingPeer
|
||||||
|
// Returns false if peer was not found
|
||||||
|
bool deletePeer(u16 peer_id);
|
||||||
|
|
||||||
void SetPeerID(u16 id){ m_peer_id = id; }
|
void SetPeerID(u16 id){ m_peer_id = id; }
|
||||||
u16 GetPeerID(){ return m_peer_id; }
|
u16 GetPeerID(){ return m_peer_id; }
|
||||||
|
|
|
@ -228,8 +228,10 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
|
||||||
}
|
}
|
||||||
if(event.EventType==EET_MOUSE_INPUT_EVENT)
|
if(event.EventType==EET_MOUSE_INPUT_EVENT)
|
||||||
{
|
{
|
||||||
if(event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN)
|
if(event.MouseInput.Event == EMIE_LMOUSE_PRESSED_DOWN
|
||||||
|
|| event.MouseInput.Event == EMIE_RMOUSE_PRESSED_DOWN)
|
||||||
{
|
{
|
||||||
|
bool right = (event.MouseInput.Event == EMIE_RMOUSE_PRESSED_DOWN);
|
||||||
v2s32 p(event.MouseInput.X, event.MouseInput.Y);
|
v2s32 p(event.MouseInput.X, event.MouseInput.Y);
|
||||||
//dstream<<"Mouse down at p=("<<p.X<<","<<p.Y<<")"<<std::endl;
|
//dstream<<"Mouse down at p=("<<p.X<<","<<p.Y<<")"<<std::endl;
|
||||||
ItemSpec s = getItemAtPos(p);
|
ItemSpec s = getItemAtPos(p);
|
||||||
|
@ -248,15 +250,21 @@ bool GUIInventoryMenu::OnEvent(const SEvent& event)
|
||||||
dstream<<"Queueing IACTION_MOVE"<<std::endl;
|
dstream<<"Queueing IACTION_MOVE"<<std::endl;
|
||||||
IMoveAction *a =
|
IMoveAction *a =
|
||||||
new IMoveAction();
|
new IMoveAction();
|
||||||
a->count = 1;
|
a->count = right ? 1 : 0;
|
||||||
a->from_name = m_selected_item->listname;
|
a->from_name = m_selected_item->listname;
|
||||||
a->from_i = m_selected_item->i;
|
a->from_i = m_selected_item->i;
|
||||||
a->to_name = s.listname;
|
a->to_name = s.listname;
|
||||||
a->to_i = s.i;
|
a->to_i = s.i;
|
||||||
m_actions->push_back(a);
|
m_actions->push_back(a);
|
||||||
}
|
}
|
||||||
delete m_selected_item;
|
bool source_empties = false;
|
||||||
m_selected_item = NULL;
|
if(list_from && list_from->getItem(m_selected_item->i)->getCount()==1)
|
||||||
|
source_empties = true;
|
||||||
|
if(right == false || source_empties)
|
||||||
|
{
|
||||||
|
delete m_selected_item;
|
||||||
|
m_selected_item = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,8 +32,9 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
InventoryItem
|
InventoryItem
|
||||||
*/
|
*/
|
||||||
|
|
||||||
InventoryItem::InventoryItem()
|
InventoryItem::InventoryItem(u16 count)
|
||||||
{
|
{
|
||||||
|
m_count = count;
|
||||||
}
|
}
|
||||||
|
|
||||||
InventoryItem::~InventoryItem()
|
InventoryItem::~InventoryItem()
|
||||||
|
@ -66,6 +67,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 == "CraftItem")
|
||||||
|
{
|
||||||
|
std::string subname;
|
||||||
|
std::getline(is, subname, ' ');
|
||||||
|
u16 count;
|
||||||
|
is>>count;
|
||||||
|
return new CraftItem(subname, count);
|
||||||
|
}
|
||||||
else if(name == "ToolItem")
|
else if(name == "ToolItem")
|
||||||
{
|
{
|
||||||
std::string toolname;
|
std::string toolname;
|
||||||
|
@ -325,83 +334,93 @@ void InventoryList::deleteItem(u32 i)
|
||||||
delete item;
|
delete item;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InventoryList::addItem(InventoryItem *newitem)
|
InventoryItem * InventoryList::addItem(InventoryItem *newitem)
|
||||||
{
|
{
|
||||||
// If it is a MaterialItem, try to find an already existing one
|
/*
|
||||||
// and just increment the counter
|
First try to find if it could be added to some existing items
|
||||||
if(std::string("MaterialItem") == newitem->getName())
|
*/
|
||||||
{
|
|
||||||
u8 material = ((MaterialItem*)newitem)->getMaterial();
|
|
||||||
u8 count = ((MaterialItem*)newitem)->getCount();
|
|
||||||
for(u32 i=0; i<m_items.size(); i++)
|
|
||||||
{
|
|
||||||
InventoryItem *item2 = m_items[i];
|
|
||||||
if(item2 == NULL)
|
|
||||||
continue;
|
|
||||||
if(std::string("MaterialItem") != item2->getName())
|
|
||||||
continue;
|
|
||||||
// Found one. Check if it is of the right material and has
|
|
||||||
// free space
|
|
||||||
MaterialItem *mitem2 = (MaterialItem*)item2;
|
|
||||||
if(mitem2->getMaterial() != material)
|
|
||||||
continue;
|
|
||||||
//TODO: Add all that can be added and add remaining part
|
|
||||||
// to another place
|
|
||||||
if(mitem2->freeSpace() < count)
|
|
||||||
continue;
|
|
||||||
// Add to the counter
|
|
||||||
mitem2->add(count);
|
|
||||||
// Dump the parameter
|
|
||||||
delete newitem;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Else find an empty position
|
|
||||||
for(u32 i=0; i<m_items.size(); i++)
|
for(u32 i=0; i<m_items.size(); i++)
|
||||||
{
|
{
|
||||||
InventoryItem *item = m_items[i];
|
// Ignore empty slots
|
||||||
if(item != NULL)
|
if(m_items[i] == NULL)
|
||||||
continue;
|
continue;
|
||||||
m_items[i] = newitem;
|
// Try adding
|
||||||
return true;
|
newitem = addItem(i, newitem);
|
||||||
|
if(newitem == NULL)
|
||||||
|
return NULL; // All was eaten
|
||||||
}
|
}
|
||||||
// Failed
|
|
||||||
return false;
|
/*
|
||||||
|
Then try to add it to empty slots
|
||||||
|
*/
|
||||||
|
for(u32 i=0; i<m_items.size(); i++)
|
||||||
|
{
|
||||||
|
// Ignore unempty slots
|
||||||
|
if(m_items[i] != NULL)
|
||||||
|
continue;
|
||||||
|
// Try adding
|
||||||
|
newitem = addItem(i, newitem);
|
||||||
|
if(newitem == NULL)
|
||||||
|
return NULL; // All was eaten
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return leftover
|
||||||
|
return newitem;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool InventoryList::addItem(u32 i, InventoryItem *newitem)
|
InventoryItem * InventoryList::addItem(u32 i, InventoryItem *newitem)
|
||||||
{
|
{
|
||||||
// If it is an empty position, it's an easy job.
|
// If it is an empty position, it's an easy job.
|
||||||
InventoryItem *item = m_items[i];
|
InventoryItem *to_item = m_items[i];
|
||||||
if(item == NULL)
|
if(to_item == NULL)
|
||||||
{
|
{
|
||||||
m_items[i] = newitem;
|
m_items[i] = newitem;
|
||||||
return true;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If it is a material item, try to
|
// If not addable, return the item
|
||||||
if(std::string("MaterialItem") == newitem->getName())
|
if(newitem->addableTo(to_item) == false)
|
||||||
|
return newitem;
|
||||||
|
|
||||||
|
// If the item fits fully in the slot, add counter and delete it
|
||||||
|
if(newitem->getCount() <= to_item->freeSpace())
|
||||||
{
|
{
|
||||||
u8 material = ((MaterialItem*)newitem)->getMaterial();
|
to_item->add(newitem->getCount());
|
||||||
u8 count = ((MaterialItem*)newitem)->getCount();
|
delete newitem;
|
||||||
InventoryItem *item2 = m_items[i];
|
return NULL;
|
||||||
|
}
|
||||||
|
// Else the item does not fit fully. Add all that fits and return
|
||||||
|
// the rest.
|
||||||
|
else
|
||||||
|
{
|
||||||
|
u16 freespace = to_item->freeSpace();
|
||||||
|
to_item->add(freespace);
|
||||||
|
newitem->remove(freespace);
|
||||||
|
return newitem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if(item2 != NULL
|
InventoryItem * InventoryList::takeItem(u32 i, u32 count)
|
||||||
&& std::string("MaterialItem") == item2->getName())
|
{
|
||||||
{
|
if(count == 0)
|
||||||
// Check if it is of the right material and has free space
|
return NULL;
|
||||||
MaterialItem *mitem2 = (MaterialItem*)item2;
|
|
||||||
if(mitem2->getMaterial() == material
|
InventoryItem *item = m_items[i];
|
||||||
&& mitem2->freeSpace() >= count)
|
// If it is an empty position, return NULL
|
||||||
{
|
if(item == NULL)
|
||||||
// Add to the counter
|
return NULL;
|
||||||
mitem2->add(count);
|
|
||||||
// Dump the parameter
|
if(count >= item->getCount())
|
||||||
delete newitem;
|
{
|
||||||
// Done
|
// Get the item by swapping NULL to its place
|
||||||
return true;
|
return changeItem(i, NULL);
|
||||||
}
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
InventoryItem *item2 = item->clone();
|
||||||
|
item->remove(count);
|
||||||
|
item2->setCount(count);
|
||||||
|
return item2;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -411,26 +430,9 @@ void InventoryList::decrementMaterials(u16 count)
|
||||||
{
|
{
|
||||||
for(u32 i=0; i<m_items.size(); i++)
|
for(u32 i=0; i<m_items.size(); i++)
|
||||||
{
|
{
|
||||||
InventoryItem *item = m_items[i];
|
InventoryItem *item = takeItem(i, count);
|
||||||
if(item == NULL)
|
if(item)
|
||||||
continue;
|
delete item;
|
||||||
if(std::string("MaterialItem") == item->getName())
|
|
||||||
{
|
|
||||||
MaterialItem *mitem = (MaterialItem*)item;
|
|
||||||
if(mitem->getCount() < count)
|
|
||||||
{
|
|
||||||
dstream<<__FUNCTION_NAME<<": decrementMaterials():"
|
|
||||||
<<" too small material count"<<std::endl;
|
|
||||||
}
|
|
||||||
else if(mitem->getCount() == count)
|
|
||||||
{
|
|
||||||
deleteItem(i);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
mitem->remove(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -607,6 +609,10 @@ void IMoveAction::apply(Inventory *inventory)
|
||||||
dstream<<" list_to->getItem(to_i)="<<list_to->getItem(to_i)
|
dstream<<" list_to->getItem(to_i)="<<list_to->getItem(to_i)
|
||||||
<<std::endl;*/
|
<<std::endl;*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
If a list doesn't exist or the source item doesn't exist
|
||||||
|
or the source and the destination slots are the same
|
||||||
|
*/
|
||||||
if(!list_from || !list_to || list_from->getItem(from_i) == NULL
|
if(!list_from || !list_to || list_from->getItem(from_i) == NULL
|
||||||
|| (list_from == list_to && from_i == to_i))
|
|| (list_from == list_to && from_i == to_i))
|
||||||
{
|
{
|
||||||
|
@ -615,18 +621,39 @@ void IMoveAction::apply(Inventory *inventory)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take item from source list
|
// Take item from source list
|
||||||
InventoryItem *item1 = list_from->changeItem(from_i, NULL);
|
InventoryItem *item1 = NULL;
|
||||||
|
if(count == 0)
|
||||||
|
item1 = list_from->changeItem(from_i, NULL);
|
||||||
|
else
|
||||||
|
item1 = list_from->takeItem(from_i, count);
|
||||||
|
|
||||||
// Try to add the item to destination list
|
// Try to add the item to destination list
|
||||||
if(list_to->addItem(to_i, item1))
|
InventoryItem *olditem = item1;
|
||||||
|
item1 = list_to->addItem(to_i, item1);
|
||||||
|
|
||||||
|
// If nothing is returned, the item was fully added
|
||||||
|
if(item1 == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If olditem is returned, nothing was added.
|
||||||
|
bool nothing_added = (item1 == olditem);
|
||||||
|
|
||||||
|
// If something else is returned, part of the item was left unadded.
|
||||||
|
// Add the other part back to the source item
|
||||||
|
list_from->addItem(from_i, item1);
|
||||||
|
|
||||||
|
// If olditem is returned, nothing was added.
|
||||||
|
// Swap the items
|
||||||
|
if(nothing_added)
|
||||||
{
|
{
|
||||||
// Done.
|
// Take item from source list
|
||||||
|
item1 = list_from->changeItem(from_i, NULL);
|
||||||
|
// Adding was not possible, swap the items.
|
||||||
|
InventoryItem *item2 = list_to->changeItem(to_i, item1);
|
||||||
|
// Put item from destination list to the source list
|
||||||
|
list_from->changeItem(from_i, item2);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Adding was not possible, switch it.
|
|
||||||
// Switch it to the destination list
|
|
||||||
InventoryItem *item2 = list_to->changeItem(to_i, item1);
|
|
||||||
// Put item from destination list to the source list
|
|
||||||
list_from->changeItem(from_i, item2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//END
|
//END
|
||||||
|
|
198
src/inventory.h
198
src/inventory.h
|
@ -33,10 +33,12 @@ with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
// For g_materials
|
// For g_materials
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
|
#define QUANTITY_ITEM_MAX_COUNT 99
|
||||||
|
|
||||||
class InventoryItem
|
class InventoryItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
InventoryItem();
|
InventoryItem(u16 count);
|
||||||
virtual ~InventoryItem();
|
virtual ~InventoryItem();
|
||||||
|
|
||||||
static InventoryItem* deSerialize(std::istream &is);
|
static InventoryItem* deSerialize(std::istream &is);
|
||||||
|
@ -53,18 +55,49 @@ public:
|
||||||
// Shall return a text to show in the GUI
|
// Shall return a text to show in the GUI
|
||||||
virtual std::string getText() { return ""; }
|
virtual std::string getText() { return ""; }
|
||||||
|
|
||||||
private:
|
// Shall return true if the item can be add()ed to the other
|
||||||
};
|
virtual bool addableTo(InventoryItem *other)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Quantity methods
|
||||||
|
*/
|
||||||
|
u16 getCount()
|
||||||
|
{
|
||||||
|
return m_count;
|
||||||
|
}
|
||||||
|
void setCount(u16 count)
|
||||||
|
{
|
||||||
|
m_count = count;
|
||||||
|
}
|
||||||
|
virtual u16 freeSpace()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
void add(u16 count)
|
||||||
|
{
|
||||||
|
assert(m_count + count <= QUANTITY_ITEM_MAX_COUNT);
|
||||||
|
m_count += count;
|
||||||
|
}
|
||||||
|
void remove(u16 count)
|
||||||
|
{
|
||||||
|
assert(m_count >= count);
|
||||||
|
m_count -= count;
|
||||||
|
}
|
||||||
|
|
||||||
#define MATERIAL_ITEM_MAX_COUNT 99
|
protected:
|
||||||
|
u16 m_count;
|
||||||
|
};
|
||||||
|
|
||||||
class MaterialItem : public InventoryItem
|
class MaterialItem : public InventoryItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
MaterialItem(u8 content, u16 count)
|
MaterialItem(u8 content, u16 count):
|
||||||
|
InventoryItem(count)
|
||||||
{
|
{
|
||||||
m_content = content;
|
m_content = content;
|
||||||
m_count = count;
|
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
Implementation interface
|
Implementation interface
|
||||||
|
@ -107,6 +140,22 @@ public:
|
||||||
os<<m_count;
|
os<<m_count;
|
||||||
return os.str();
|
return os.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual bool addableTo(InventoryItem *other)
|
||||||
|
{
|
||||||
|
if(std::string(other->getName()) != "MaterialItem")
|
||||||
|
return false;
|
||||||
|
MaterialItem *m = (MaterialItem*)other;
|
||||||
|
if(m->getMaterial() != m_content)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
u16 freeSpace()
|
||||||
|
{
|
||||||
|
if(m_count > QUANTITY_ITEM_MAX_COUNT)
|
||||||
|
return 0;
|
||||||
|
return QUANTITY_ITEM_MAX_COUNT - m_count;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
Special methods
|
Special methods
|
||||||
*/
|
*/
|
||||||
|
@ -114,39 +163,15 @@ public:
|
||||||
{
|
{
|
||||||
return m_content;
|
return m_content;
|
||||||
}
|
}
|
||||||
u16 getCount()
|
|
||||||
{
|
|
||||||
return m_count;
|
|
||||||
}
|
|
||||||
u16 freeSpace()
|
|
||||||
{
|
|
||||||
if(m_count > MATERIAL_ITEM_MAX_COUNT)
|
|
||||||
return 0;
|
|
||||||
return MATERIAL_ITEM_MAX_COUNT - m_count;
|
|
||||||
}
|
|
||||||
void add(u16 count)
|
|
||||||
{
|
|
||||||
assert(m_count + count <= MATERIAL_ITEM_MAX_COUNT);
|
|
||||||
m_count += count;
|
|
||||||
}
|
|
||||||
void remove(u16 count)
|
|
||||||
{
|
|
||||||
assert(m_count >= count);
|
|
||||||
m_count -= count;
|
|
||||||
}
|
|
||||||
private:
|
private:
|
||||||
u8 m_content;
|
u8 m_content;
|
||||||
u16 m_count;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class MapBlockObjectItem : public InventoryItem
|
class MapBlockObjectItem : public InventoryItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/*MapBlockObjectItem(MapBlockObject *obj)
|
MapBlockObjectItem(std::string inventorystring):
|
||||||
{
|
InventoryItem(1)
|
||||||
m_inventorystring = obj->getInventoryString();
|
|
||||||
}*/
|
|
||||||
MapBlockObjectItem(std::string inventorystring)
|
|
||||||
{
|
{
|
||||||
m_inventorystring = inventorystring;
|
m_inventorystring = inventorystring;
|
||||||
}
|
}
|
||||||
|
@ -196,10 +221,90 @@ private:
|
||||||
std::string m_inventorystring;
|
std::string m_inventorystring;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
An item that is used as a mid-product when crafting.
|
||||||
|
Subnames:
|
||||||
|
- Stick
|
||||||
|
*/
|
||||||
|
class CraftItem : public InventoryItem
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CraftItem(std::string subname, u16 count):
|
||||||
|
InventoryItem(count)
|
||||||
|
{
|
||||||
|
m_subname = subname;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Implementation interface
|
||||||
|
*/
|
||||||
|
virtual const char* getName() const
|
||||||
|
{
|
||||||
|
return "CraftItem";
|
||||||
|
}
|
||||||
|
virtual void serialize(std::ostream &os)
|
||||||
|
{
|
||||||
|
os<<getName();
|
||||||
|
os<<" ";
|
||||||
|
os<<m_subname;
|
||||||
|
os<<" ";
|
||||||
|
os<<m_count;
|
||||||
|
}
|
||||||
|
virtual InventoryItem* clone()
|
||||||
|
{
|
||||||
|
return new CraftItem(m_subname, m_count);
|
||||||
|
}
|
||||||
|
#ifndef SERVER
|
||||||
|
video::ITexture * getImage()
|
||||||
|
{
|
||||||
|
std::string basename;
|
||||||
|
if(m_subname == "Stick")
|
||||||
|
basename = "../data/stick.png";
|
||||||
|
// Default to cloud texture
|
||||||
|
else
|
||||||
|
basename = tile_texture_path_get(TILE_CLOUD);
|
||||||
|
|
||||||
|
// Get such a texture
|
||||||
|
return g_irrlicht->getTexture(basename);
|
||||||
|
//return g_irrlicht->getTexture(TextureSpec(finalname, basename, mod));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
std::string getText()
|
||||||
|
{
|
||||||
|
std::ostringstream os;
|
||||||
|
os<<m_count;
|
||||||
|
return os.str();
|
||||||
|
}
|
||||||
|
virtual bool addableTo(InventoryItem *other)
|
||||||
|
{
|
||||||
|
if(std::string(other->getName()) != "CraftItem")
|
||||||
|
return false;
|
||||||
|
CraftItem *m = (CraftItem*)other;
|
||||||
|
if(m->m_subname != m_subname)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
u16 freeSpace()
|
||||||
|
{
|
||||||
|
if(m_count > QUANTITY_ITEM_MAX_COUNT)
|
||||||
|
return 0;
|
||||||
|
return QUANTITY_ITEM_MAX_COUNT - m_count;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Special methods
|
||||||
|
*/
|
||||||
|
std::string getSubName()
|
||||||
|
{
|
||||||
|
return m_subname;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
std::string m_subname;
|
||||||
|
};
|
||||||
|
|
||||||
class ToolItem : public InventoryItem
|
class ToolItem : public InventoryItem
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
ToolItem(std::string toolname, u16 wear)
|
ToolItem(std::string toolname, u16 wear):
|
||||||
|
InventoryItem(1)
|
||||||
{
|
{
|
||||||
m_toolname = toolname;
|
m_toolname = toolname;
|
||||||
m_wear = wear;
|
m_wear = wear;
|
||||||
|
@ -313,11 +418,20 @@ public:
|
||||||
InventoryItem * changeItem(u32 i, InventoryItem *newitem);
|
InventoryItem * changeItem(u32 i, InventoryItem *newitem);
|
||||||
// Delete item
|
// Delete item
|
||||||
void deleteItem(u32 i);
|
void deleteItem(u32 i);
|
||||||
// Adds an item to a suitable place. Returns false if failed.
|
// Adds an item to a suitable place. Returns leftover item.
|
||||||
bool addItem(InventoryItem *newitem);
|
// If all went into the list, returns NULL.
|
||||||
// If possible, adds item to given slot. Returns true on success.
|
InventoryItem * addItem(InventoryItem *newitem);
|
||||||
// Fails when slot is populated by a different kind of item.
|
|
||||||
bool addItem(u32 i, 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);
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
// Decrements amount of every material item
|
// Decrements amount of every material item
|
||||||
void decrementMaterials(u16 count);
|
void decrementMaterials(u16 count);
|
||||||
|
@ -347,12 +461,13 @@ public:
|
||||||
InventoryList * addList(const std::string &name, u32 size);
|
InventoryList * addList(const std::string &name, u32 size);
|
||||||
InventoryList * getList(const std::string &name);
|
InventoryList * getList(const std::string &name);
|
||||||
bool deleteList(const std::string &name);
|
bool deleteList(const std::string &name);
|
||||||
// A shorthand for adding items
|
// A shorthand for adding items.
|
||||||
bool addItem(const std::string &listname, InventoryItem *newitem)
|
// Returns NULL if the item was fully added, leftover otherwise.
|
||||||
|
InventoryItem * addItem(const std::string &listname, InventoryItem *newitem)
|
||||||
{
|
{
|
||||||
InventoryList *list = getList(listname);
|
InventoryList *list = getList(listname);
|
||||||
if(list == NULL)
|
if(list == NULL)
|
||||||
return false;
|
return newitem;
|
||||||
return list->addItem(newitem);
|
return list->addItem(newitem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,6 +491,7 @@ struct InventoryAction
|
||||||
|
|
||||||
struct IMoveAction : public InventoryAction
|
struct IMoveAction : public InventoryAction
|
||||||
{
|
{
|
||||||
|
// count=0 means "everything"
|
||||||
u16 count;
|
u16 count;
|
||||||
std::string from_name;
|
std::string from_name;
|
||||||
s16 from_i;
|
s16 from_i;
|
||||||
|
|
10
src/main.cpp
10
src/main.cpp
|
@ -1513,6 +1513,10 @@ int main(int argc, char *argv[])
|
||||||
// Test the text input system
|
// Test the text input system
|
||||||
/*(new GUITextInputMenu(guienv, guiroot, -1, &g_active_menu_count,
|
/*(new GUITextInputMenu(guienv, guiroot, -1, &g_active_menu_count,
|
||||||
NULL))->drop();*/
|
NULL))->drop();*/
|
||||||
|
|
||||||
|
// Launch pause menu
|
||||||
|
(new GUIPauseMenu(guienv, guiroot, -1, g_device,
|
||||||
|
&g_active_menu_count))->drop();
|
||||||
|
|
||||||
// First line of debug text
|
// First line of debug text
|
||||||
gui::IGUIStaticText *guitext = guienv->addStaticText(
|
gui::IGUIStaticText *guitext = guienv->addStaticText(
|
||||||
|
@ -2164,9 +2168,11 @@ int main(int argc, char *argv[])
|
||||||
}
|
}
|
||||||
// We want a slight delay to very little
|
// We want a slight delay to very little
|
||||||
// time consuming nodes
|
// time consuming nodes
|
||||||
if(nodig_delay_counter < 0.15)
|
//float mindelay = 0.15;
|
||||||
|
float mindelay = 0.20;
|
||||||
|
if(nodig_delay_counter < mindelay)
|
||||||
{
|
{
|
||||||
nodig_delay_counter = 0.15;
|
nodig_delay_counter = mindelay;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
413
src/server.cpp
413
src/server.cpp
|
@ -849,40 +849,6 @@ void RemoteClient::SetBlocksNotSent(core::map<v3s16, MapBlock*> &blocks)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*void RemoteClient::BlockEmerged()
|
|
||||||
{
|
|
||||||
SharedPtr<JMutexAutoLock> lock(m_num_blocks_in_emerge_queue.getLock());
|
|
||||||
assert(m_num_blocks_in_emerge_queue.m_value > 0);
|
|
||||||
m_num_blocks_in_emerge_queue.m_value--;
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*void RemoteClient::RunSendingTimeouts(float dtime, float timeout)
|
|
||||||
{
|
|
||||||
JMutexAutoLock sendinglock(m_blocks_sending_mutex);
|
|
||||||
|
|
||||||
core::list<v3s16> remove_queue;
|
|
||||||
for(core::map<v3s16, float>::Iterator
|
|
||||||
i = m_blocks_sending.getIterator();
|
|
||||||
i.atEnd()==false; i++)
|
|
||||||
{
|
|
||||||
v3s16 p = i.getNode()->getKey();
|
|
||||||
float t = i.getNode()->getValue();
|
|
||||||
t += dtime;
|
|
||||||
i.getNode()->setValue(t);
|
|
||||||
|
|
||||||
if(t > timeout)
|
|
||||||
{
|
|
||||||
remove_queue.push_back(p);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for(core::list<v3s16>::Iterator
|
|
||||||
i = remove_queue.begin();
|
|
||||||
i != remove_queue.end(); i++)
|
|
||||||
{
|
|
||||||
m_blocks_sending.remove(*i);
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
PlayerInfo
|
PlayerInfo
|
||||||
*/
|
*/
|
||||||
|
@ -931,7 +897,8 @@ Server::Server(
|
||||||
m_emergethread(this),
|
m_emergethread(this),
|
||||||
m_time_of_day(8000),
|
m_time_of_day(8000),
|
||||||
m_time_counter(0),
|
m_time_counter(0),
|
||||||
m_time_of_day_send_timer(0)
|
m_time_of_day_send_timer(0),
|
||||||
|
m_uptime(0)
|
||||||
{
|
{
|
||||||
m_flowwater_timer = 0.0;
|
m_flowwater_timer = 0.0;
|
||||||
m_print_info_timer = 0.0;
|
m_print_info_timer = 0.0;
|
||||||
|
@ -1026,10 +993,20 @@ void Server::AsyncRunStep()
|
||||||
if(dtime < 0.001)
|
if(dtime < 0.001)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
//dstream<<"Server steps "<<dtime<<std::endl;
|
||||||
|
//dstream<<"Server::AsyncRunStep(): dtime="<<dtime<<std::endl;
|
||||||
|
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock1(m_step_dtime_mutex);
|
JMutexAutoLock lock1(m_step_dtime_mutex);
|
||||||
m_step_dtime -= dtime;
|
m_step_dtime -= dtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Update uptime
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
m_uptime.set(m_uptime.get() + dtime);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Update m_time_of_day
|
Update m_time_of_day
|
||||||
|
@ -1070,16 +1047,18 @@ void Server::AsyncRunStep()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//dstream<<"Server steps "<<dtime<<std::endl;
|
|
||||||
|
|
||||||
//dstream<<"Server::AsyncRunStep(): dtime="<<dtime<<std::endl;
|
|
||||||
{
|
{
|
||||||
// Has to be locked for peerAdded/Removed
|
|
||||||
JMutexAutoLock lock1(m_env_mutex);
|
|
||||||
// Process connection's timeouts
|
// Process connection's timeouts
|
||||||
JMutexAutoLock lock2(m_con_mutex);
|
JMutexAutoLock lock2(m_con_mutex);
|
||||||
m_con.RunTimeouts(dtime);
|
m_con.RunTimeouts(dtime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
// This has to be called so that the client list gets synced
|
||||||
|
// with the peer list of the connection
|
||||||
|
handlePeerChanges();
|
||||||
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
// Step environment
|
// Step environment
|
||||||
// This also runs Map's timers
|
// This also runs Map's timers
|
||||||
|
@ -1355,9 +1334,14 @@ void Server::Receive()
|
||||||
u32 datasize;
|
u32 datasize;
|
||||||
try{
|
try{
|
||||||
{
|
{
|
||||||
JMutexAutoLock lock(m_con_mutex);
|
JMutexAutoLock conlock(m_con_mutex);
|
||||||
datasize = m_con.Receive(peer_id, *data, data_maxsize);
|
datasize = m_con.Receive(peer_id, *data, data_maxsize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This has to be called so that the client list gets synced
|
||||||
|
// with the peer list of the connection
|
||||||
|
handlePeerChanges();
|
||||||
|
|
||||||
ProcessData(*data, datasize, peer_id);
|
ProcessData(*data, datasize, peer_id);
|
||||||
}
|
}
|
||||||
catch(con::InvalidIncomingDataException &e)
|
catch(con::InvalidIncomingDataException &e)
|
||||||
|
@ -1499,6 +1483,36 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
m_time_of_day.get());
|
m_time_of_day.get());
|
||||||
m_con.Send(peer->id, 0, data, true);
|
m_con.Send(peer->id, 0, data, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send information about server to player in chat
|
||||||
|
{
|
||||||
|
std::wostringstream os(std::ios_base::binary);
|
||||||
|
os<<L"# Server: ";
|
||||||
|
// Uptime
|
||||||
|
os<<L"uptime="<<m_uptime.get();
|
||||||
|
// Information about clients
|
||||||
|
os<<L", clients={";
|
||||||
|
for(core::map<u16, RemoteClient*>::Iterator
|
||||||
|
i = m_clients.getIterator();
|
||||||
|
i.atEnd() == false; i++)
|
||||||
|
{
|
||||||
|
// Get client and check that it is valid
|
||||||
|
RemoteClient *client = i.getNode()->getValue();
|
||||||
|
assert(client->peer_id == i.getNode()->getKey());
|
||||||
|
if(client->serialization_version == SER_FMT_VER_INVALID)
|
||||||
|
continue;
|
||||||
|
// Get name of player
|
||||||
|
std::wstring name = L"unknown";
|
||||||
|
Player *player = m_env.getPlayer(client->peer_id);
|
||||||
|
if(player != NULL)
|
||||||
|
name = narrow_to_wide(player->getName());
|
||||||
|
// Add name to information string
|
||||||
|
os<<name<<L",";
|
||||||
|
}
|
||||||
|
os<<L"}";
|
||||||
|
// Send message
|
||||||
|
SendChatMessage(peer_id, os.str());
|
||||||
|
}
|
||||||
|
|
||||||
// Send information about joining in chat
|
// Send information about joining in chat
|
||||||
{
|
{
|
||||||
|
@ -1722,52 +1736,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
*/
|
*/
|
||||||
if(action == 0)
|
if(action == 0)
|
||||||
{
|
{
|
||||||
/*
|
|
||||||
NOTE: This can be used in the future to check if
|
|
||||||
somebody is cheating, by checking the timing.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
u8 content;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Get content at position
|
|
||||||
content = m_env.getMap().getNode(p_under).d;
|
|
||||||
// If it's not diggable, do nothing
|
|
||||||
if(content_diggable(content) == false)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch(InvalidPositionException &e)
|
|
||||||
{
|
|
||||||
derr_server<<"Server: Not starting digging: Node not found"
|
|
||||||
<<std::endl;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Set stuff in RemoteClient
|
NOTE: This can be used in the future to check if
|
||||||
|
somebody is cheating, by checking the timing.
|
||||||
*/
|
*/
|
||||||
RemoteClient *client = getClient(peer->id);
|
|
||||||
JMutexAutoLock(client->m_dig_mutex);
|
|
||||||
client->m_dig_tool_item = 0;
|
|
||||||
client->m_dig_position = p_under;
|
|
||||||
float dig_time = 0.5;
|
|
||||||
if(content == CONTENT_STONE)
|
|
||||||
{
|
|
||||||
dig_time = 1.5;
|
|
||||||
}
|
|
||||||
else if(content == CONTENT_TORCH)
|
|
||||||
{
|
|
||||||
dig_time = 0.0;
|
|
||||||
}
|
|
||||||
client->m_dig_time_remaining = dig_time;
|
|
||||||
|
|
||||||
// Reset build time counter
|
|
||||||
getClient(peer->id)->m_time_from_building.set(0.0);
|
|
||||||
#endif
|
|
||||||
} // action == 0
|
} // action == 0
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -2240,7 +2212,10 @@ void Server::ProcessData(u8 *data, u32 datasize, u16 peer_id)
|
||||||
InventoryList *clist = player->inventory.getList("craft");
|
InventoryList *clist = player->inventory.getList("craft");
|
||||||
if(clist)
|
if(clist)
|
||||||
{
|
{
|
||||||
clist->decrementMaterials(ma->count);
|
u16 count = ma->count;
|
||||||
|
if(count == 0)
|
||||||
|
count = 1;
|
||||||
|
clist->decrementMaterials(count);
|
||||||
}
|
}
|
||||||
// Do action
|
// Do action
|
||||||
// Feed action to player inventory
|
// Feed action to player inventory
|
||||||
|
@ -2424,8 +2399,15 @@ void Server::peerAdded(con::Peer *peer)
|
||||||
dout_server<<"Server::peerAdded(): peer->id="
|
dout_server<<"Server::peerAdded(): peer->id="
|
||||||
<<peer->id<<std::endl;
|
<<peer->id<<std::endl;
|
||||||
|
|
||||||
// Connection is already locked when this is called.
|
PeerChange c;
|
||||||
//JMutexAutoLock lock(m_con_mutex);
|
c.type = PEER_ADDED;
|
||||||
|
c.peer_id = peer->id;
|
||||||
|
c.timeout = false;
|
||||||
|
m_peer_change_queue.push_back(c);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// NOTE: Connection is already locked when this is called.
|
||||||
|
// NOTE: Environment is already locked when this is called.
|
||||||
|
|
||||||
// Error check
|
// Error check
|
||||||
core::map<u16, RemoteClient*>::Node *n;
|
core::map<u16, RemoteClient*>::Node *n;
|
||||||
|
@ -2440,9 +2422,6 @@ void Server::peerAdded(con::Peer *peer)
|
||||||
|
|
||||||
// Create player
|
// Create player
|
||||||
{
|
{
|
||||||
// Already locked when called
|
|
||||||
//JMutexAutoLock envlock(m_env_mutex);
|
|
||||||
|
|
||||||
Player *player = m_env.getPlayer(peer->id);
|
Player *player = m_env.getPlayer(peer->id);
|
||||||
|
|
||||||
// The player shouldn't already exist
|
// The player shouldn't already exist
|
||||||
|
@ -2491,8 +2470,8 @@ void Server::peerAdded(con::Peer *peer)
|
||||||
// Give a good pick
|
// Give a good pick
|
||||||
{
|
{
|
||||||
InventoryItem *item = new ToolItem("STPick", 32000);
|
InventoryItem *item = new ToolItem("STPick", 32000);
|
||||||
bool r = player->inventory.addItem("main", item);
|
void* r = player->inventory.addItem("main", item);
|
||||||
assert(r == true);
|
assert(r == NULL);
|
||||||
}
|
}
|
||||||
// Give all materials
|
// Give all materials
|
||||||
assert(USEFUL_CONTENT_COUNT <= PLAYER_INVENTORY_SIZE);
|
assert(USEFUL_CONTENT_COUNT <= PLAYER_INVENTORY_SIZE);
|
||||||
|
@ -2508,8 +2487,8 @@ void Server::peerAdded(con::Peer *peer)
|
||||||
// Sign
|
// Sign
|
||||||
{
|
{
|
||||||
InventoryItem *item = new MapBlockObjectItem("Sign Example text");
|
InventoryItem *item = new MapBlockObjectItem("Sign Example text");
|
||||||
bool r = player->inventory.addItem("main", item);
|
void* r = player->inventory.addItem("main", item);
|
||||||
assert(r == true);
|
assert(r == NULL);
|
||||||
}
|
}
|
||||||
/*// Rat
|
/*// Rat
|
||||||
{
|
{
|
||||||
|
@ -2520,15 +2499,20 @@ void Server::peerAdded(con::Peer *peer)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
{
|
||||||
|
InventoryItem *item = new CraftItem("Stick", 4);
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
{
|
{
|
||||||
InventoryItem *item = new ToolItem("WPick", 32000);
|
InventoryItem *item = new ToolItem("WPick", 32000);
|
||||||
bool r = player->inventory.addItem("main", item);
|
void* r = player->inventory.addItem("main", item);
|
||||||
assert(r == true);
|
assert(r == NULL);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
InventoryItem *item = new ToolItem("STPick", 32000);
|
InventoryItem *item = new ToolItem("STPick", 32000);
|
||||||
bool r = player->inventory.addItem("main", item);
|
void* r = player->inventory.addItem("main", item);
|
||||||
assert(r == true);
|
assert(r == NULL);
|
||||||
}
|
}
|
||||||
/*// Give some lights
|
/*// Give some lights
|
||||||
{
|
{
|
||||||
|
@ -2551,6 +2535,7 @@ void Server::peerAdded(con::Peer *peer)
|
||||||
}*/
|
}*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::deletingPeer(con::Peer *peer, bool timeout)
|
void Server::deletingPeer(con::Peer *peer, bool timeout)
|
||||||
|
@ -2559,8 +2544,18 @@ void Server::deletingPeer(con::Peer *peer, bool timeout)
|
||||||
dout_server<<"Server::deletingPeer(): peer->id="
|
dout_server<<"Server::deletingPeer(): peer->id="
|
||||||
<<peer->id<<", timeout="<<timeout<<std::endl;
|
<<peer->id<<", timeout="<<timeout<<std::endl;
|
||||||
|
|
||||||
// Connection is already locked when this is called.
|
PeerChange c;
|
||||||
//JMutexAutoLock lock(m_con_mutex);
|
c.type = PEER_REMOVED;
|
||||||
|
c.peer_id = peer->id;
|
||||||
|
c.timeout = timeout;
|
||||||
|
m_peer_change_queue.push_back(c);
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
// NOTE: Connection is already locked when this is called.
|
||||||
|
|
||||||
|
// NOTE: Environment is already locked when this is called.
|
||||||
|
// NOTE: Locking environment cannot be moved here because connection
|
||||||
|
// is already locked and env has to be locked before
|
||||||
|
|
||||||
// Error check
|
// Error check
|
||||||
core::map<u16, RemoteClient*>::Node *n;
|
core::map<u16, RemoteClient*>::Node *n;
|
||||||
|
@ -2568,10 +2563,22 @@ void Server::deletingPeer(con::Peer *peer, bool timeout)
|
||||||
// The client should exist
|
// The client should exist
|
||||||
assert(n != NULL);
|
assert(n != NULL);
|
||||||
|
|
||||||
|
// Send information about leaving in chat
|
||||||
|
{
|
||||||
|
std::wstring name = L"unknown";
|
||||||
|
Player *player = m_env.getPlayer(peer->id);
|
||||||
|
if(player != NULL)
|
||||||
|
name = narrow_to_wide(player->getName());
|
||||||
|
|
||||||
|
std::wstring message;
|
||||||
|
message += L"*** ";
|
||||||
|
message += name;
|
||||||
|
message += L" left game";
|
||||||
|
BroadcastChatMessage(message);
|
||||||
|
}
|
||||||
|
|
||||||
// Delete player
|
// Delete player
|
||||||
{
|
{
|
||||||
// Already locked when called
|
|
||||||
//JMutexAutoLock envlock(m_env_mutex);
|
|
||||||
m_env.removePlayer(peer->id);
|
m_env.removePlayer(peer->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2581,6 +2588,7 @@ void Server::deletingPeer(con::Peer *peer, bool timeout)
|
||||||
|
|
||||||
// Send player info to all clients
|
// Send player info to all clients
|
||||||
SendPlayerInfos();
|
SendPlayerInfos();
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Server::SendObjectData(float dtime)
|
void Server::SendObjectData(float dtime)
|
||||||
|
@ -2848,6 +2856,205 @@ void Server::UpdateBlockWaterPressure(MapBlock *block,
|
||||||
|
|
||||||
v.blitBack(modified_blocks);
|
v.blitBack(modified_blocks);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Server::handlePeerChange(PeerChange &c)
|
||||||
|
{
|
||||||
|
JMutexAutoLock envlock(m_env_mutex);
|
||||||
|
JMutexAutoLock conlock(m_con_mutex);
|
||||||
|
|
||||||
|
if(c.type == PEER_ADDED)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Add
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Error check
|
||||||
|
core::map<u16, RemoteClient*>::Node *n;
|
||||||
|
n = m_clients.find(c.peer_id);
|
||||||
|
// The client shouldn't already exist
|
||||||
|
assert(n == NULL);
|
||||||
|
|
||||||
|
// Create client
|
||||||
|
RemoteClient *client = new RemoteClient();
|
||||||
|
client->peer_id = c.peer_id;
|
||||||
|
m_clients.insert(client->peer_id, client);
|
||||||
|
|
||||||
|
// Create player
|
||||||
|
{
|
||||||
|
Player *player = m_env.getPlayer(c.peer_id);
|
||||||
|
|
||||||
|
// The player shouldn't already exist
|
||||||
|
assert(player == NULL);
|
||||||
|
|
||||||
|
player = new ServerRemotePlayer();
|
||||||
|
player->peer_id = c.peer_id;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Set player position
|
||||||
|
*/
|
||||||
|
|
||||||
|
// We're going to throw the player to this position
|
||||||
|
//v2s16 nodepos(29990,29990);
|
||||||
|
//v2s16 nodepos(9990,9990);
|
||||||
|
v2s16 nodepos(0,0);
|
||||||
|
v2s16 sectorpos = getNodeSectorPos(nodepos);
|
||||||
|
// Get zero sector (it could have been unloaded to disk)
|
||||||
|
m_env.getMap().emergeSector(sectorpos);
|
||||||
|
// Get ground height at origin
|
||||||
|
f32 groundheight = m_env.getMap().getGroundHeight(nodepos, true);
|
||||||
|
// The sector should have been generated -> groundheight exists
|
||||||
|
assert(groundheight > GROUNDHEIGHT_VALID_MINVALUE);
|
||||||
|
// Don't go underwater
|
||||||
|
if(groundheight < WATER_LEVEL)
|
||||||
|
groundheight = WATER_LEVEL;
|
||||||
|
|
||||||
|
player->setPosition(intToFloat(v3s16(
|
||||||
|
nodepos.X,
|
||||||
|
groundheight + 1,
|
||||||
|
nodepos.Y
|
||||||
|
)));
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add player to environment
|
||||||
|
*/
|
||||||
|
|
||||||
|
m_env.addPlayer(player);
|
||||||
|
|
||||||
|
/*
|
||||||
|
Add stuff to inventory
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(g_settings.getBool("creative_mode"))
|
||||||
|
{
|
||||||
|
// Give a good pick
|
||||||
|
{
|
||||||
|
InventoryItem *item = new ToolItem("STPick", 32000);
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
|
// Give all materials
|
||||||
|
assert(USEFUL_CONTENT_COUNT <= PLAYER_INVENTORY_SIZE);
|
||||||
|
for(u16 i=0; i<USEFUL_CONTENT_COUNT; i++)
|
||||||
|
{
|
||||||
|
// Skip some materials
|
||||||
|
if(i == CONTENT_OCEAN)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
InventoryItem *item = new MaterialItem(i, 1);
|
||||||
|
player->inventory.addItem("main", item);
|
||||||
|
}
|
||||||
|
// Sign
|
||||||
|
{
|
||||||
|
InventoryItem *item = new MapBlockObjectItem("Sign Example text");
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
|
/*// Rat
|
||||||
|
{
|
||||||
|
InventoryItem *item = new MapBlockObjectItem("Rat");
|
||||||
|
bool r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == true);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
{
|
||||||
|
InventoryItem *item = new CraftItem("Stick", 4);
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
InventoryItem *item = new ToolItem("WPick", 32000);
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
InventoryItem *item = new ToolItem("STPick", 32000);
|
||||||
|
void* r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == NULL);
|
||||||
|
}
|
||||||
|
/*// Give some lights
|
||||||
|
{
|
||||||
|
InventoryItem *item = new MaterialItem(CONTENT_TORCH, 999);
|
||||||
|
bool r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == true);
|
||||||
|
}
|
||||||
|
// and some signs
|
||||||
|
for(u16 i=0; i<4; i++)
|
||||||
|
{
|
||||||
|
InventoryItem *item = new MapBlockObjectItem("Sign Example text");
|
||||||
|
bool r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == true);
|
||||||
|
}*/
|
||||||
|
/*// Give some other stuff
|
||||||
|
{
|
||||||
|
InventoryItem *item = new MaterialItem(CONTENT_TREE, 999);
|
||||||
|
bool r = player->inventory.addItem("main", item);
|
||||||
|
assert(r == true);
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // PEER_ADDED
|
||||||
|
else if(c.type == PEER_REMOVED)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
Delete
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Error check
|
||||||
|
core::map<u16, RemoteClient*>::Node *n;
|
||||||
|
n = m_clients.find(c.peer_id);
|
||||||
|
// The client should exist
|
||||||
|
assert(n != NULL);
|
||||||
|
|
||||||
|
// Collect information about leaving in chat
|
||||||
|
std::wstring message;
|
||||||
|
{
|
||||||
|
std::wstring name = L"unknown";
|
||||||
|
Player *player = m_env.getPlayer(c.peer_id);
|
||||||
|
if(player != NULL)
|
||||||
|
name = narrow_to_wide(player->getName());
|
||||||
|
|
||||||
|
message += L"*** ";
|
||||||
|
message += name;
|
||||||
|
message += L" left game";
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete player
|
||||||
|
{
|
||||||
|
m_env.removePlayer(c.peer_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delete client
|
||||||
|
delete m_clients[c.peer_id];
|
||||||
|
m_clients.remove(c.peer_id);
|
||||||
|
|
||||||
|
// Send player info to all remaining clients
|
||||||
|
SendPlayerInfos();
|
||||||
|
|
||||||
|
// Send leave chat message to all remaining clients
|
||||||
|
BroadcastChatMessage(message);
|
||||||
|
|
||||||
|
} // PEER_REMOVED
|
||||||
|
else
|
||||||
|
{
|
||||||
|
assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::handlePeerChanges()
|
||||||
|
{
|
||||||
|
while(m_peer_change_queue.size() > 0)
|
||||||
|
{
|
||||||
|
PeerChange c = m_peer_change_queue.pop_front();
|
||||||
|
|
||||||
|
dout_server<<"Server: Handling peer change: "
|
||||||
|
<<"id="<<c.peer_id<<", timeout="<<c.timeout
|
||||||
|
<<std::endl;
|
||||||
|
|
||||||
|
handlePeerChange(c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
22
src/server.h
22
src/server.h
|
@ -434,6 +434,11 @@ private:
|
||||||
void UpdateBlockWaterPressure(MapBlock *block,
|
void UpdateBlockWaterPressure(MapBlock *block,
|
||||||
core::map<v3s16, MapBlock*> &modified_blocks);
|
core::map<v3s16, MapBlock*> &modified_blocks);
|
||||||
|
|
||||||
|
// Locks environment and connection by its own
|
||||||
|
struct PeerChange;
|
||||||
|
void handlePeerChange(PeerChange &c);
|
||||||
|
void handlePeerChanges();
|
||||||
|
|
||||||
float m_flowwater_timer;
|
float m_flowwater_timer;
|
||||||
float m_print_info_timer;
|
float m_print_info_timer;
|
||||||
float m_objectdata_timer;
|
float m_objectdata_timer;
|
||||||
|
@ -466,6 +471,23 @@ private:
|
||||||
float m_time_counter;
|
float m_time_counter;
|
||||||
float m_time_of_day_send_timer;
|
float m_time_of_day_send_timer;
|
||||||
|
|
||||||
|
MutexedVariable<float> m_uptime;
|
||||||
|
|
||||||
|
enum PeerChangeType
|
||||||
|
{
|
||||||
|
PEER_ADDED,
|
||||||
|
PEER_REMOVED
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PeerChange
|
||||||
|
{
|
||||||
|
PeerChangeType type;
|
||||||
|
u16 peer_id;
|
||||||
|
bool timeout;
|
||||||
|
};
|
||||||
|
|
||||||
|
Queue<PeerChange> m_peer_change_queue;
|
||||||
|
|
||||||
friend class EmergeThread;
|
friend class EmergeThread;
|
||||||
friend class RemoteClient;
|
friend class RemoteClient;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue