diff options
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/account-server/main-account.cpp | 36 | ||||
-rw-r--r-- | src/chat-server/chathandler.cpp | 94 | ||||
-rw-r--r-- | src/chat-server/chathandler.hpp | 24 | ||||
-rw-r--r-- | src/game-server/mapcomposite.cpp | 2 | ||||
-rw-r--r-- | src/game-server/mapcomposite.hpp | 21 | ||||
-rw-r--r-- | src/net/connectionhandler.cpp | 4 | ||||
-rw-r--r-- | src/net/connectionhandler.hpp | 5 | ||||
-rw-r--r-- | src/utils/timer.cpp | 22 | ||||
-rw-r--r-- | src/utils/timer.h | 6 |
11 files changed, 138 insertions, 93 deletions
@@ -1,3 +1,16 @@ +2007-01-06 Bjørn Lindeijer <bjorn@lindeijer.nl> + + * src/game-server/mapcomposite.cpp: Fixed a compiler warning. + * src/chat-server/chathandler.hpp, src/chat-server/chathandler.cpp, + src/net/connectionhandler.hpp, src/net/connectionhandler.cpp, + src/account-server/main-account.cpp, src/game-server/mapcomposite.hpp, + src/Makefile.am: Allowed usage of timeout in + ConnectionHandler::process in order to reduce CPU usage. Now account + and chat servers no longer need to keep track of game time, but simply + listen for incoming messages to act on. + * src/utils/timer.cpp, src/utils/timer.h: Gracefully handle cases + where the computer time is set back. + 2007-01-05 Bjørn Lindeijer <bjorn@lindeijer.nl> * AUTHORS: Updated to include all current authors. diff --git a/src/Makefile.am b/src/Makefile.am index 8b60e54e..fde39ae7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -55,9 +55,7 @@ tmwserv_account_SOURCES = \ utils/logger.h \ utils/logger.cpp \ utils/stringfilter.h \ - utils/stringfilter.cpp \ - utils/timer.h \ - utils/timer.cpp + utils/stringfilter.cpp tmwserv_game_SOURCES = \ game-server/main-game.cpp \ diff --git a/src/account-server/main-account.cpp b/src/account-server/main-account.cpp index 195071d3..0bb550a1 100644 --- a/src/account-server/main-account.cpp +++ b/src/account-server/main-account.cpp @@ -43,15 +43,12 @@ #include "net/messageout.hpp" #include "utils/logger.h" #include "utils/stringfilter.h" -#include "utils/timer.h" // Default options that automake should be able to override. #define DEFAULT_LOG_FILE "tmwserv.log" #define DEFAULT_CONFIG_FILE "tmwserv.xml" #define DEFAULT_ITEMSDB_FILE "items.xml" -utils::Timer worldTimer(100, false); /**< Timer for world tics set to 100 ms */ -int worldTime = 0; /**< Current world time in 100ms ticks */ bool running = true; /**< Determines if server keeps running */ Skill skillTree("base"); /**< Skill tree */ @@ -178,9 +175,6 @@ void deinitialize() // Write configuration file config.write(); - // Stop world timer - worldTimer.stop(); - // Quit ENet enet_deinitialize(); @@ -263,8 +257,6 @@ void parseOptions(int argc, char *argv[]) */ int main(int argc, char *argv[]) { - int elapsedWorldTicks; - LOG_INFO("The Mana World Account+Chat Server v" << PACKAGE_VERSION); // Parse Command Line Options @@ -288,32 +280,10 @@ int main(int argc, char *argv[]) store.close(); store.open(); - // Initialize world timer - worldTimer.start(); - while (running) { - elapsedWorldTicks = worldTimer.poll(); - if (elapsedWorldTicks > 0) { - worldTime += elapsedWorldTicks; - - if (elapsedWorldTicks > 1) - { - LOG_WARN(elapsedWorldTicks - 1 << " World Tick(s) skipped " - "because of insufficient time. please buy a faster " - "machine ;-)"); - }; - - // Print world time at 10 second intervals to show we're alive - if (worldTime % 100 == 0) { - LOG_INFO("World time: " << worldTime); - } - - // Handle all messages that are in the message queues - accountHandler->process(); - chatHandler->process(); - serverHandler->process(); - } - worldTimer.sleep(); + accountHandler->process(50); + chatHandler->process(50); + serverHandler->process(50); } LOG_INFO("Received: Quit signal, closing down..."); diff --git a/src/chat-server/chathandler.cpp b/src/chat-server/chathandler.cpp index 2e8a9912..90193821 100644 --- a/src/chat-server/chathandler.cpp +++ b/src/chat-server/chathandler.cpp @@ -112,8 +112,9 @@ NetComputer *ChatHandler::computerConnected(ENetPeer *peer) void ChatHandler::computerDisconnected(NetComputer *computer) { - for (ChatPendingClients::iterator i = pendingClients.begin(), i_end = pendingClients.end(); - i != i_end; ++i) + ChatPendingClients::iterator i_end = pendingClients.end(); + for (ChatPendingClients::iterator i = pendingClients.begin(); + i != i_end; ++i) { if (i->second == computer) { @@ -124,9 +125,9 @@ void ChatHandler::computerDisconnected(NetComputer *computer) delete computer; } -void ChatHandler::process() +void ChatHandler::process(enet_uint32 timeout) { - ConnectionHandler::process(); + ConnectionHandler::process(timeout); removeOutdatedPending(); } @@ -135,13 +136,15 @@ void ChatHandler::processMessage(NetComputer *comp, MessageIn &message) ChatClient &computer = *static_cast< ChatClient * >(comp); MessageOut result; - if (computer.characterName.empty()) { + if (computer.characterName.empty()) + { if (message.getId() != PCMSG_CONNECT) return; std::string magic_token = message.readString(32); ChatPendingLogins::iterator i = pendingLogins.find(magic_token); if (i == pendingLogins.end()) { - for (ChatPendingClients::iterator i = pendingClients.begin(), i_end = pendingClients.end(); + ChatPendingClients::iterator i_end = pendingClients.end(); + for (ChatPendingClients::iterator i = pendingClients.begin(); i != i_end; ++i) { if (i->second == &computer) return; @@ -169,9 +172,13 @@ void ChatHandler::processMessage(NetComputer *comp, MessageIn &message) { short channel = message.readShort(); LOG_DEBUG("Say: (Channel " << channel << "): " << text); - if ( channel == 0 ) // Let's say that is the default channel for now. + // Let's say that channel 0 is the default channel for now. + if (channel == 0) { - if ( text.substr(0, 1) == "@" || text.substr(0, 1) == "#" || text.substr(0, 1) == "/" ) + // TODO: I think commands should be / only - BL + if (text.substr(0, 1) == "@" || + text.substr(0, 1) == "#" || + text.substr(0, 1) == "/" ) { // The message is a command. Deal with it. handleCommand(computer, text); @@ -179,7 +186,8 @@ void ChatHandler::processMessage(NetComputer *comp, MessageIn &message) } else { - // We send the message to the players registered in the channel. + // We send the message to the players registered in the + // channel. sayInChannel(computer, channel, text); } } @@ -196,8 +204,8 @@ void ChatHandler::processMessage(NetComputer *comp, MessageIn &message) // If it's slang's free. if (stringFilter->filterContent(text)) { - // We send the message to every players in the default channel - // as it is an annouce. + // We send the message to every players in the default + // channel as it is an annouce. announce(computer, text); } else @@ -265,24 +273,32 @@ void ChatHandler::processMessage(NetComputer *comp, MessageIn &message) // If it's slang's free. if (stringFilter->filterContent(channelName) && - stringFilter->filterContent(channelAnnouncement)) + stringFilter->filterContent(channelAnnouncement)) { // We attempt to create a new channel short channelId; - if (channelType) - channelId = chatChannelManager->registerPrivateChannel(channelName, - channelAnnouncement, - channelPassword); + if (channelType) { + channelId = chatChannelManager->registerPrivateChannel( + channelName, + channelAnnouncement, + channelPassword); + } else - channelId = chatChannelManager->registerPublicChannel(channelName, - channelAnnouncement, - channelPassword); + { + channelId = chatChannelManager->registerPublicChannel( + channelName, + channelAnnouncement, + channelPassword); + } + if (channelId != 0) { - // We add the player as admin of this channel as he created it. - // The user registering a private channel is the only one to be able - // to update the password and the announcement in it and also to remove it. - chatChannelManager->addUserInChannel(computer.characterName, channelId); + // We add the player as admin of this channel as he + // created it. The user registering a private channel + // is the only one to be able to update the password + // and the announcement in it and also to remove it. + chatChannelManager->addUserInChannel( + computer.characterName, channelId); result.writeByte(ERRMSG_OK); result.writeShort(channelId); @@ -314,7 +330,8 @@ void ChatHandler::processMessage(NetComputer *comp, MessageIn &message) { // Public channel if (computer.accountLevel == AL_ADMIN || computer.accountLevel == AL_GM) { - warnUsersAboutPlayerEventInChat(channelId, "", CHAT_EVENT_LEAVING_PLAYER); + warnUsersAboutPlayerEventInChat( + channelId, "", CHAT_EVENT_LEAVING_PLAYER); if (chatChannelManager->removeChannel(channelId)) result.writeByte(ERRMSG_OK); else @@ -327,7 +344,8 @@ void ChatHandler::processMessage(NetComputer *comp, MessageIn &message) } else { // Private channel - // We first see if the user is the admin (first user) of the channel + // We first see if the user is the admin (first user) of + // the channel std::vector< std::string > const &userList = chatChannelManager->getUserListInChannel(channelId); std::vector< std::string >::const_iterator i = userList.begin(); @@ -335,11 +353,15 @@ void ChatHandler::processMessage(NetComputer *comp, MessageIn &message) if (*i == computer.characterName) { // Make every user quit the channel - warnUsersAboutPlayerEventInChat(channelId, "", CHAT_EVENT_LEAVING_PLAYER); - if (chatChannelManager->removeChannel(channelId)) + warnUsersAboutPlayerEventInChat( + channelId, "", CHAT_EVENT_LEAVING_PLAYER); + if (chatChannelManager->removeChannel(channelId)) { result.writeByte(ERRMSG_OK); + } else + { result.writeByte(ERRMSG_FAILURE); + } } else { @@ -379,7 +401,8 @@ void ChatHandler::processMessage(NetComputer *comp, MessageIn &message) } // Send an CPMSG_UPDATE_CHANNEL to warn other clients a user went // in the channel. - warnUsersAboutPlayerEventInChat(channelId, computer.characterName, + warnUsersAboutPlayerEventInChat(channelId, + computer.characterName, CHAT_EVENT_NEW_PLAYER); } else @@ -403,9 +426,10 @@ void ChatHandler::processMessage(NetComputer *comp, MessageIn &message) if (chatChannelManager->removeUserFromChannel(computer.characterName, channelId)) { result.writeByte(ERRMSG_OK); - // Send an CPMSG_UPDATE_CHANNEL to warn other clients a user left - // the channel. - warnUsersAboutPlayerEventInChat(channelId, computer.characterName, + // Send an CPMSG_UPDATE_CHANNEL to warn other clients a + // user left the channel. + warnUsersAboutPlayerEventInChat(channelId, + computer.characterName, CHAT_EVENT_LEAVING_PLAYER); } else @@ -472,7 +496,9 @@ void ChatHandler::announce(ChatClient &computer, std::string const &text) } } -void ChatHandler::sayToPlayer(ChatClient &computer, std::string const &playerName, std::string const &text) +void +ChatHandler::sayToPlayer(ChatClient &computer, std::string const &playerName, + std::string const &text) { MessageOut result; LOG_DEBUG(computer.characterName << " says to " << playerName << ": " << text); @@ -490,7 +516,9 @@ void ChatHandler::sayToPlayer(ChatClient &computer, std::string const &playerNam } } -void ChatHandler::sayInChannel(ChatClient &computer, short channel, std::string const &text) +void +ChatHandler::sayInChannel(ChatClient &computer, short channel, + std::string const &text) { MessageOut result; LOG_DEBUG(computer.characterName << " says in channel " << channel << ": " << text); diff --git a/src/chat-server/chathandler.hpp b/src/chat-server/chathandler.hpp index 530a8115..19c5f464 100644 --- a/src/chat-server/chathandler.hpp +++ b/src/chat-server/chathandler.hpp @@ -36,10 +36,16 @@ class ChatClient; class ChatHandler : public ConnectionHandler { public: - void process(); + /** + * Overridden from ConnectionHandler to also clean connected clients + * that haven't sent in a magic token. + * + * @see ConnectionHandler::process + */ + void process(enet_uint32 timeout = 0); /** - * Start the handler + * Start the handler. */ bool startListen(enet_uint16 port); @@ -71,12 +77,14 @@ class ChatHandler : public ConnectionHandler /** * Say something private to a player. */ - void sayToPlayer(ChatClient &computer, std::string const &playerName, std::string const &text); + void sayToPlayer(ChatClient &computer, std::string const &playerName, + std::string const &text); /** * Say something in a specific channel. */ - void sayInChannel(ChatClient &computer, short channel, std::string const &); + void sayInChannel(ChatClient &computer, short channel, + std::string const &); /** * Send packet to every client in a registered channel. @@ -86,8 +94,14 @@ class ChatHandler : public ConnectionHandler /** * Tell a list of user about an event in a chatchannel about a player. */ - void warnUsersAboutPlayerEventInChat(short channelId, std::string const &userName, char eventId); + void warnUsersAboutPlayerEventInChat(short channelId, + std::string const &userName, + char eventId); + /** + * Removes outdated pending logins. These are connected clients that + * still haven't sent in their magic token. + */ void removeOutdatedPending(); }; diff --git a/src/game-server/mapcomposite.cpp b/src/game-server/mapcomposite.cpp index 043c7fa6..93ed2c37 100644 --- a/src/game-server/mapcomposite.cpp +++ b/src/game-server/mapcomposite.cpp @@ -265,7 +265,7 @@ ObjectBucket::ObjectBucket() { for (unsigned i = 0; i < 256 / int_bitsize; ++i) { - bitmap[i] = ~0; + bitmap[i] = ~0u; } } diff --git a/src/game-server/mapcomposite.hpp b/src/game-server/mapcomposite.hpp index 89f10c00..8de50962 100644 --- a/src/game-server/mapcomposite.hpp +++ b/src/game-server/mapcomposite.hpp @@ -142,14 +142,16 @@ struct ObjectIterator }; /** - * Pool of public IDs for MovingObjects on a map. + * Pool of public IDs for MovingObjects on a map. By maintaining public ID + * availability using bits, it can locate an available public ID fast while + * using minimal memory access. */ struct ObjectBucket { static int const int_bitsize = sizeof(unsigned) * 8; unsigned bitmap[256 / int_bitsize]; /**< Bitmap of free locations. */ - short free; /**< Number of empty places. */ - short next_object; /**< Next object to look at. */ + short free; /**< Number of empty places. */ + short next_object; /**< Next object to look at. */ MovingObject *objects[256]; ObjectBucket(); @@ -160,10 +162,17 @@ struct ObjectBucket /** * Combined map/entity structure. */ -class MapComposite { - +class MapComposite +{ public: + /** + * Constructor. + */ MapComposite(Map *); + + /** + * Destructor. + */ ~MapComposite(); Map *getMap() const @@ -264,7 +273,7 @@ class MapComposite { */ MapZone *zones; - unsigned short mapWidth; /**< Width with respect to zones. */ + unsigned short mapWidth; /**< Width with respect to zones. */ unsigned short mapHeight; /**< Height with respect to zones. */ friend class ZoneIterator; diff --git a/src/net/connectionhandler.cpp b/src/net/connectionhandler.cpp index 69ac9337..53ec3446 100644 --- a/src/net/connectionhandler.cpp +++ b/src/net/connectionhandler.cpp @@ -85,11 +85,11 @@ void ConnectionHandler::flush() enet_host_flush(host); } -void ConnectionHandler::process() +void ConnectionHandler::process(enet_uint32 timeout) { ENetEvent event; // Process Enet events and do not block. - while (enet_host_service(host, &event, 0) > 0) { + while (enet_host_service(host, &event, timeout) > 0) { switch (event.type) { case ENET_EVENT_TYPE_CONNECT: { diff --git a/src/net/connectionhandler.hpp b/src/net/connectionhandler.hpp index df22aacc..76bea198 100644 --- a/src/net/connectionhandler.hpp +++ b/src/net/connectionhandler.hpp @@ -60,8 +60,11 @@ class ConnectionHandler /** * Process outgoing messages and listen to the server socket for * incoming messages and new connections. + * + * @timeout an optional timeout in milliseconds to wait for something + * to happen when there is nothing to do */ - virtual void process(); + virtual void process(enet_uint32 timeout = 0); /** * Process outgoing messages. diff --git a/src/utils/timer.cpp b/src/utils/timer.cpp index b0a05bc5..a1d8bd46 100644 --- a/src/utils/timer.cpp +++ b/src/utils/timer.cpp @@ -19,9 +19,15 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include <time.h> #include "timer.h" +#include <time.h> +#include <sys/time.h> + +#ifdef _WIN32 +#include "wingettimeofday.h" +#endif + namespace utils { @@ -52,8 +58,18 @@ int Timer::poll() int elapsed = 0; if (active) { - elapsed = (getTimeInMillisec() - lastpulse) / interval; - lastpulse += interval * elapsed; + uint64_t now = getTimeInMillisec(); + if (now > lastpulse) + { + elapsed = (now - lastpulse) / interval; + lastpulse += interval * elapsed; + } + else + { + // Time has made a jump to the past. This should be a rare + // occurence, so just reset lastpulse to prevent problems. + lastpulse = now; + } }; return elapsed; } diff --git a/src/utils/timer.h b/src/utils/timer.h index 69ca634e..da3a1d07 100644 --- a/src/utils/timer.h +++ b/src/utils/timer.h @@ -22,8 +22,6 @@ #ifndef _TMWSERV_TIMER_H_ #define _TMWSERV_TIMER_H_ -#include <sys/time.h> - /* I need a 64-bit unsigned integer */ #ifdef _MSC_VER typedef __uint64 uint64_t // when using MSVC use its internal type @@ -31,10 +29,6 @@ #include <stdint.h> // on other compilers use the C99 official header #endif -#ifdef _WIN32 - #include "wingettimeofday.h" -#endif - namespace utils { |