00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <server/ServerAddPlayerHandler.h>
00022 #include <server/ServerConnectHandler.h>
00023 #include <server/ScorchedServer.h>
00024 #include <server/ScorchedServerUtil.h>
00025 #include <server/ServerState.h>
00026 #include <server/ServerChannelManager.h>
00027 #include <common/OptionsScorched.h>
00028 #include <common/OptionsTransient.h>
00029 #include <common/StatsLogger.h>
00030 #include <common/Logger.h>
00031 #include <common/Defines.h>
00032 #include <coms/ComsAddPlayerMessage.h>
00033 #include <coms/ComsPlayerStateMessage.h>
00034 #include <coms/ComsMessageSender.h>
00035 #include <net/NetLoopBack.h>
00036 #include <tankai/TankAIStore.h>
00037 #include <tank/TankModelStore.h>
00038 #include <tank/TankModelContainer.h>
00039 #include <tank/TankContainer.h>
00040 #include <tank/TankColorGenerator.h>
00041 #include <tank/TankState.h>
00042 #include <tank/TankAvatar.h>
00043
00044 ServerAddPlayerHandler *ServerAddPlayerHandler::instance_ = 0;
00045
00046 ServerAddPlayerHandler *ServerAddPlayerHandler::instance()
00047 {
00048 if (!instance_)
00049 {
00050 instance_ = new ServerAddPlayerHandler;
00051 }
00052 return instance_;
00053 }
00054
00055 ServerAddPlayerHandler::ServerAddPlayerHandler()
00056 {
00057 ScorchedServer::instance()->getComsMessageHandler().addHandler(
00058 "ComsAddPlayerMessage",
00059 this);
00060 }
00061
00062 ServerAddPlayerHandler::~ServerAddPlayerHandler()
00063 {
00064 }
00065
00066 bool ServerAddPlayerHandler::processMessage(NetMessage &netMessage,
00067 const char *messageType, NetBufferReader &reader)
00068 {
00069 ComsAddPlayerMessage message;
00070 if (!message.readMessage(reader)) return false;
00071
00072
00073 unsigned int playerId = message.getPlayerId();
00074 Tank *tank = ScorchedServer::instance()->getTankContainer().getTankById(playerId);
00075 if (!tank ||
00076 (tank->getState().getState() != TankState::sDead &&
00077 tank->getState().getState() != TankState::sPending &&
00078 tank->getState().getState() != TankState::sLoading &&
00079 tank->getState().getState() != TankState::sInitializing))
00080 {
00081 ServerChannelManager::instance()->sendText(
00082 ChannelText("info", "CHANGE_WHEN_DEAD",
00083 "Can only change tank when dead."),
00084 netMessage.getDestinationId(),
00085 false);
00086 return true;
00087 }
00088
00089
00090 if (0 != strcmp(message.getPlayerType(), "Human"))
00091 {
00092 if (ScorchedServer::instance()->getGameState().getState() !=
00093 ServerState::ServerStateTooFewPlayers)
00094 {
00095 ServerChannelManager::instance()->sendText(
00096 ChannelText("info", "CHANGE_WHEN_STARTED",
00097 "Can only change type before game starts."),
00098 netMessage.getDestinationId(),
00099 false);
00100 return true;
00101 }
00102
00103
00104 #ifdef S3D_SERVER
00105 return true;
00106 #endif // #ifdef S3D_SERVER
00107
00108
00109 TankAI *ai =
00110 ScorchedServer::instance()->getTankAIs().
00111 getAIByName(message.getPlayerType());
00112 if (!ai) return true;
00113
00114
00115 tank->setTankAI(ai->createCopy(tank));
00116 tank->setDestinationId(0);
00117 }
00118 else
00119 {
00120 tank->setDestinationId(netMessage.getDestinationId());
00121 tank->setTankAI(0);
00122 }
00123
00124
00125 LangString name(message.getPlayerName());
00126 filterName(tank, name);
00127
00128 #ifdef S3D_SERVER
00129
00130 if (name != tank->getTargetName())
00131 {
00132 Logger::log(S3D::formatStringBuffer(
00133 "Player playing dest=\"%i\" id=\"%i\" \"%s\"->\"%s\"",
00134 tank->getDestinationId(), tank->getPlayerId(),
00135 tank->getCStrName().c_str(), name.c_str()));
00136
00137 ServerChannelManager::instance()->sendText(
00138 ChannelText("info",
00139 "PLAYER_NAME_CHANGE",
00140 "Player \"{0}\" changed name to \"{1}\"",
00141 tank->getTargetName(), name),
00142 true);
00143 }
00144 #endif // #ifdef S3D_SERVER
00145
00146 tank->setName(name);
00147
00148
00149 if (tank->getTeam() == 0 &&
00150 message.getPlayerColor() != tank->getColor())
00151 {
00152
00153 std::map<unsigned int, Tank *> &tanks =
00154 ScorchedServer::instance()->getTankContainer().getPlayingTanks();
00155 if (TankColorGenerator::instance()->colorAvailable(
00156 message.getPlayerColor(), tanks, tank))
00157 {
00158
00159 tank->setColor(message.getPlayerColor());
00160 }
00161 }
00162
00163 bool noAvatar = !tank->getAvatar().getName()[0]
00164 && message.getPlayerIconName()[0];
00165 if (noAvatar)
00166 {
00167 if (message.getPlayerIcon().getBufferUsed() <=
00168 (unsigned) ScorchedServer::instance()->getOptionsGame().getMaxAvatarSize())
00169 {
00170 tank->getAvatar().setFromBuffer(
00171 message.getPlayerIconName(),
00172 message.getPlayerIcon());
00173
00174
00175
00176
00177
00178
00179 ComsMessageSender::sendToAllConnectedClients(message);
00180 }
00181 }
00182
00183
00184 StatsLogger::instance()->tankJoined(tank);
00185
00186 #ifdef S3D_SERVER
00187 {
00188 StatsLogger::TankRank rank = StatsLogger::instance()->tankRank(tank);
00189 if (rank.rank >= 0)
00190 {
00191 ServerChannelManager::instance()->sendText(
00192 ChannelText("info",
00193 "WELCOME_BACK",
00194 "Welcome back {0}, you are ranked {1}",
00195 tank->getTargetName(), rank.rank),
00196 true);
00197 }
00198
00199 if (tank->getState().getSpectator())
00200 {
00201 ServerChannelManager::instance()->sendText(
00202 ChannelText("info",
00203 "PLAYER_PLAYING",
00204 "Player playing \"{0}\"",
00205 tank->getTargetName()),
00206 true);
00207
00208 if (ScorchedServer::instance()->getGameState().getState() ==
00209 ServerState::ServerStateStarting)
00210 {
00211
00212 ScorchedServer::instance()->getGameState().stimulate(
00213 ServerState::ServerStimulusStarting);
00214 }
00215 }
00216 }
00217 #endif // #ifdef S3D_SERVER
00218
00219
00220
00221
00222 tank->getState().setSpectator(false);
00223
00224
00225 if (ScorchedServer::instance()->getOptionsGame().getTeams() > 1)
00226 {
00227 if (message.getPlayerTeam() > 0 && message.getPlayerTeam() <=
00228 (unsigned int) ScorchedServer::instance()->getOptionsGame().getTeams())
00229 {
00230 tank->setTeam(message.getPlayerTeam());
00231 }
00232 else
00233 {
00234 tank->setTeam(ScorchedServer::instance()->getOptionsTransient().getLeastUsedTeam(
00235 ScorchedServer::instance()->getTankContainer()));
00236 }
00237 }
00238
00239
00240
00241 TankModel *tankModel =
00242 ScorchedServer::instance()->getTankModels().
00243 getModelByName(message.getModelName(),
00244 tank->getTeam(),
00245 tank->isTemp());
00246 tank->getModelContainer().setTankModelName(
00247 tankModel->getName(), message.getModelName(), tankModel->getTypeName());
00248
00249
00250
00251 if (ScorchedServer::instance()->getGameState().getState() == ServerState::ServerStateTooFewPlayers ||
00252 ScorchedServer::instance()->getGameState().getState() == ServerState::ServerStateStarting)
00253 {
00254 ComsPlayerStateMessage message(false, false);
00255 ComsMessageSender::sendToAllConnectedClients(message);
00256 }
00257 return true;
00258 }
00259
00260 bool ServerAddPlayerHandler::filterName(Tank *tank,
00261 LangString &sentname)
00262 {
00263 LangString originalname = sentname;
00264
00265
00266 LangStringUtil::trim(sentname);
00267
00268
00269 ScorchedServerUtil::instance()->textFilter.filterString(sentname);
00270
00271
00272 for (unsigned int *c = (unsigned int *) sentname.c_str(); *c; c++)
00273 {
00274 if (*c == '\"') *c = '\'';
00275 else if (*c == ']') *c = ')';
00276 else if (*c == '[') *c = '(';
00277 else if (*c == '%') *c = '$';
00278 if (!ScorchedServer::instance()->getOptionsGame().getAllowMultiLingualNames())
00279 {
00280 if (*c > 127) *c = '?';
00281 }
00282 }
00283
00284
00285 LangString botPrefix =
00286 LANG_STRING(ScorchedServer::instance()->getOptionsGame().getBotNamePrefix());
00287 unsigned int *botPrefixPos = LangStringUtil::stristr(sentname.c_str(), botPrefix);
00288 if (botPrefixPos)
00289 {
00290 for (int i=0; i<(int) botPrefix.size(); i++, botPrefixPos++)
00291 {
00292 (*botPrefixPos) = '*';
00293 }
00294 }
00295
00296
00297
00298 if (sentname.size() == 0) sentname = LANG_STRING("NoName");
00299 if (sentname.size() > 22) sentname = sentname.substr(0, 22);
00300
00301
00302 for (;;)
00303 {
00304 bool found = false;
00305 std::map<unsigned int, Tank *>::iterator mainitor;
00306 std::map<unsigned int, Tank *> tanks =
00307 ScorchedServer::instance()->getTankContainer().getAllTanks();
00308 for (mainitor = tanks.begin();
00309 mainitor != tanks.end();
00310 mainitor++)
00311 {
00312 Tank *currentTank = (*mainitor).second;
00313 if (currentTank->getTargetName() == sentname &&
00314 tank != currentTank)
00315 {
00316 found = true;
00317 break;
00318 }
00319 }
00320
00321 if (!found) break;
00322 sentname += LANG_STRING("(2)");
00323 }
00324
00325
00326
00327 if (ScorchedServer::instance()->getOptionsGame().getRegisteredUserNames())
00328 {
00329 ServerAuthHandler *authHandler =
00330 ScorchedServerUtil::instance()->getAuthHandler();
00331 if (authHandler)
00332 {
00333 while (!authHandler->authenticateUserName(tank->getUniqueId(),
00334 sentname))
00335 {
00336 sentname += LANG_STRING("(2)");
00337 }
00338 }
00339 }
00340
00341 return (sentname != originalname);
00342 }