summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog13
-rw-r--r--src/Makefile.am4
-rw-r--r--src/account-server/main-account.cpp36
-rw-r--r--src/chat-server/chathandler.cpp94
-rw-r--r--src/chat-server/chathandler.hpp24
-rw-r--r--src/game-server/mapcomposite.cpp2
-rw-r--r--src/game-server/mapcomposite.hpp21
-rw-r--r--src/net/connectionhandler.cpp4
-rw-r--r--src/net/connectionhandler.hpp5
-rw-r--r--src/utils/timer.cpp22
-rw-r--r--src/utils/timer.h6
11 files changed, 138 insertions, 93 deletions
diff --git a/ChangeLog b/ChangeLog
index 8e9d2433..6df29252 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
{