diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/content_sao.h | 2 | ||||
-rw-r--r-- | src/network/connection.cpp | 27 | ||||
-rw-r--r-- | src/network/connection.h | 5 | ||||
-rw-r--r-- | src/network/networkpacket.cpp | 9 | ||||
-rw-r--r-- | src/network/networkpacket.h | 2 | ||||
-rw-r--r-- | src/object_properties.cpp | 1 | ||||
-rw-r--r-- | src/object_properties.h | 1 | ||||
-rw-r--r-- | src/script/common/c_content.cpp | 5 | ||||
-rw-r--r-- | src/server.cpp | 78 |
9 files changed, 98 insertions, 32 deletions
diff --git a/src/content_sao.h b/src/content_sao.h index 0dad54805..9444ee758 100644 --- a/src/content_sao.h +++ b/src/content_sao.h @@ -102,6 +102,8 @@ public: const std::string &data); void step(float dtime, bool send_recommended); std::string getClientInitializationData(u16 protocol_version); + bool isStaticAllowed() const + { return m_prop.static_save; } void getStaticData(std::string *result) const; int punch(v3f dir, const ToolCapabilities *toolcap=NULL, diff --git a/src/network/connection.cpp b/src/network/connection.cpp index fb3ba92ae..a504bbc08 100644 --- a/src/network/connection.cpp +++ b/src/network/connection.cpp @@ -2884,16 +2884,21 @@ void Connection::Disconnect() putCommand(c); } -void Connection::Receive(NetworkPacket* pkt) +bool Connection::Receive(NetworkPacket *pkt, u32 timeout) { + /* + Note that this function can potentially wait infinitely if non-data + events keep happening before the timeout expires. + This is not considered to be a problem (is it?) + */ for(;;) { - ConnectionEvent e = waitEvent(m_bc_receive_timeout); + ConnectionEvent e = waitEvent(timeout); if (e.type != CONNEVENT_NONE) LOG(dout_con << getDesc() << ": Receive: got event: " << e.describe() << std::endl); switch(e.type) { case CONNEVENT_NONE: - throw NoIncomingDataException("No incoming data"); + return false; case CONNEVENT_DATA_RECEIVED: // Data size is lesser than command size, ignoring packet if (e.data.getSize() < 2) { @@ -2901,7 +2906,7 @@ void Connection::Receive(NetworkPacket* pkt) } pkt->putRawPacket(*e.data, e.data.getSize(), e.peer_id); - return; + return true; case CONNEVENT_PEER_ADDED: { UDPPeer tmp(e.peer_id, e.address, this); if (m_bc_peerhandler) @@ -2919,7 +2924,19 @@ void Connection::Receive(NetworkPacket* pkt) "(port already in use?)"); } } - throw NoIncomingDataException("No incoming data"); + return false; +} + +void Connection::Receive(NetworkPacket *pkt) +{ + bool any = Receive(pkt, m_bc_receive_timeout); + if (!any) + throw NoIncomingDataException("No incoming data"); +} + +bool Connection::TryReceive(NetworkPacket *pkt) +{ + return Receive(pkt, 0); } void Connection::Send(u16 peer_id, u8 channelnum, diff --git a/src/network/connection.h b/src/network/connection.h index 8b7ed9773..a202fa2f5 100644 --- a/src/network/connection.h +++ b/src/network/connection.h @@ -1016,6 +1016,7 @@ public: bool Connected(); void Disconnect(); void Receive(NetworkPacket* pkt); + bool TryReceive(NetworkPacket* pkt); void Send(u16 peer_id, u8 channelnum, NetworkPacket* pkt, bool reliable); u16 GetPeerID() { return m_peer_id; } Address GetPeerAddress(u16 peer_id); @@ -1050,6 +1051,8 @@ protected: UDPSocket m_udpSocket; MutexedQueue<ConnectionCommand> m_command_queue; + bool Receive(NetworkPacket *pkt, u32 timeout); + void putEvent(ConnectionEvent &e); void TriggerSend() @@ -1074,7 +1077,7 @@ private: // Backwards compatibility PeerHandler *m_bc_peerhandler; int m_bc_receive_timeout; - + bool m_shutting_down; u16 m_next_remote_peer_id; diff --git a/src/network/networkpacket.cpp b/src/network/networkpacket.cpp index c4fcf9600..7c2c7d0f9 100644 --- a/src/network/networkpacket.cpp +++ b/src/network/networkpacket.cpp @@ -65,6 +65,15 @@ void NetworkPacket::putRawPacket(u8 *data, u32 datasize, u16 peer_id) memcpy(m_data.data(), &data[2], m_datasize); } +void NetworkPacket::clear() +{ + m_data.clear(); + m_datasize = 0; + m_read_offset = 0; + m_command = 0; + m_peer_id = 0; +} + const char* NetworkPacket::getString(u32 from_offset) { checkReadOffset(from_offset, 0); diff --git a/src/network/networkpacket.h b/src/network/networkpacket.h index 83dc33f6f..fc14d61d8 100644 --- a/src/network/networkpacket.h +++ b/src/network/networkpacket.h @@ -35,7 +35,7 @@ public: ~NetworkPacket(); void putRawPacket(u8 *data, u32 datasize, u16 peer_id); - + void clear(); // Getters u32 getSize() { return m_datasize; } u16 getPeerId() { return m_peer_id; } diff --git a/src/object_properties.cpp b/src/object_properties.cpp index a77368151..543c0e876 100644 --- a/src/object_properties.cpp +++ b/src/object_properties.cpp @@ -72,6 +72,7 @@ std::string ObjectProperties::dump() } os<<"]"; os<<", spritediv="<<PP2(spritediv); + os << ", static_save=" << static_save; os<<", initial_sprite_basepos="<<PP2(initial_sprite_basepos); os<<", is_visible="<<is_visible; os<<", makes_footstep_sound="<<makes_footstep_sound; diff --git a/src/object_properties.h b/src/object_properties.h index 908757a64..9bfe7ea7b 100644 --- a/src/object_properties.h +++ b/src/object_properties.h @@ -54,6 +54,7 @@ struct ObjectProperties std::string infotext; //! For dropped items, this contains item information. std::string wield_item; + bool static_save = true; ObjectProperties(); std::string dump(); diff --git a/src/script/common/c_content.cpp b/src/script/common/c_content.cpp index c0e29abf0..24b84e0d0 100644 --- a/src/script/common/c_content.cpp +++ b/src/script/common/c_content.cpp @@ -273,7 +273,10 @@ void read_object_properties(lua_State *L, int index, prop->automatic_face_movement_max_rotation_per_sec = luaL_checknumber(L, -1); } lua_pop(L, 1); + getstringfield(L, -1, "infotext", prop->infotext); + getboolfield(L, -1, "static_save", prop->static_save); + lua_getfield(L, -1, "wield_item"); if (!lua_isnil(L, -1)) prop->wield_item = read_item(L, -1, idef).getItemString(); @@ -346,6 +349,8 @@ void push_object_properties(lua_State *L, ObjectProperties *prop) lua_setfield(L, -2, "automatic_face_movement_max_rotation_per_sec"); lua_pushlstring(L, prop->infotext.c_str(), prop->infotext.size()); lua_setfield(L, -2, "infotext"); + lua_pushboolean(L, prop->static_save); + lua_setfield(L, -2, "static_save"); lua_pushlstring(L, prop->wield_item.c_str(), prop->wield_item.size()); lua_setfield(L, -2, "wield_item"); } diff --git a/src/server.cpp b/src/server.cpp index 71a349b08..4b54c2398 100644 --- a/src/server.cpp +++ b/src/server.cpp @@ -90,6 +90,15 @@ void *ServerThread::run() DSTACK(FUNCTION_NAME); BEGIN_DEBUG_EXCEPTION_HANDLER + /* + * The real business of the server happens on the ServerThread. + * How this works: + * AsyncRunStep() runs an actual server step as soon as enough time has + * passed (dedicated_server_loop keeps track of that). + * Receive() blocks at least(!) 30ms waiting for a packet (so this loop + * doesn't busy wait) and will process any remaining packets. + */ + m_server->AsyncRunStep(true); while (!stopRequested()) { @@ -100,7 +109,6 @@ void *ServerThread::run() m_server->Receive(); - } catch (con::NoIncomingDataException &e) { } catch (con::PeerNotFoundException &e) { infostream<<"Server: PeerNotFoundException"<<std::endl; } catch (ClientNotFoundException &e) { @@ -1052,30 +1060,45 @@ void Server::Receive() DSTACK(FUNCTION_NAME); SharedBuffer<u8> data; u16 peer_id; - try { - NetworkPacket pkt; - m_con.Receive(&pkt); - peer_id = pkt.getPeerId(); - ProcessData(&pkt); - } - catch(con::InvalidIncomingDataException &e) { - infostream<<"Server::Receive(): " - "InvalidIncomingDataException: what()=" - <<e.what()<<std::endl; - } - catch(SerializationError &e) { - infostream<<"Server::Receive(): " - "SerializationError: what()=" - <<e.what()<<std::endl; - } - catch(ClientStateError &e) { - errorstream << "ProcessData: peer=" << peer_id << e.what() << std::endl; - DenyAccess_Legacy(peer_id, L"Your client sent something server didn't expect." - L"Try reconnecting or updating your client"); - } - catch(con::PeerNotFoundException &e) { - // Do nothing - } + bool first = true; + NetworkPacket pkt; + for (;;) { + pkt.clear(); + peer_id = 0; + try { + /* + In the first iteration *wait* for a packet, afterwards process + all packets that are immediately available (no waiting). + */ + if (first) { + m_con.Receive(&pkt); + first = false; + } else { + if (!m_con.TryReceive(&pkt)) + return; + } + + peer_id = pkt.getPeerId(); + ProcessData(&pkt); + + } catch (const con::InvalidIncomingDataException &e) { + infostream << "Server::Receive(): InvalidIncomingDataException: what()=" + << e.what() << std::endl; + } catch (const SerializationError &e) { + infostream << "Server::Receive(): SerializationError: what()=" + << e.what() << std::endl; + } catch (const ClientStateError &e) { + errorstream << "ProcessData: peer=" << peer_id << " what()=" + << e.what() << std::endl; + DenyAccess_Legacy(peer_id, L"Your client sent something server didn't expect." + L"Try reconnecting or updating your client"); + } catch (const con::PeerNotFoundException &e) { + // Do nothing + } catch (const con::NoIncomingDataException &e) { + return; + } + } + } PlayerSAO* Server::StageTwoClientInit(u16 peer_id) @@ -3682,6 +3705,11 @@ void dedicated_server_loop(Server &server, bool &kill) static const float profiler_print_interval = g_settings->getFloat("profiler_print_interval"); + /* + * The dedicated server loop only does time-keeping (in Server::step) and + * provides a way to main.cpp to kill the server externally (bool &kill). + */ + for(;;) { // This is kind of a hack but can be done like this // because server.step() is very light |