00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <server/ScorchedServer.h>
00022 #include <server/ServerShotHolder.h>
00023 #include <server/TurnController.h>
00024 #include <tank/TankState.h>
00025 #include <tank/TankScore.h>
00026 #include <tank/TankPosition.h>
00027 #include <tank/TankAccessories.h>
00028 #include <tank/TankContainer.h>
00029 #include <target/TargetLife.h>
00030 #include <tankai/TankAIStrings.h>
00031 #include <engine/ActionController.h>
00032 #include <actions/TankMovement.h>
00033 #include <actions/TankResign.h>
00034 #include <landscapemap/LandscapeMaps.h>
00035 #include <landscapemap/MovementMap.h>
00036 #include <landscapedef/LandscapeDefn.h>
00037 #include <weapons/AccessoryStore.h>
00038 #include <coms/ComsMessageSender.h>
00039 #include <coms/ComsPlayerStatusMessage.h>
00040 #include <common/OptionsScorched.h>
00041 #include <common/OptionsTransient.h>
00042 #include <common/StatsLogger.h>
00043 #include <common/Defines.h>
00044
00045 ServerShotHolder *ServerShotHolder::instance_ = 0;
00046
00047 ServerShotHolder *ServerShotHolder::instance()
00048 {
00049 if (!instance_)
00050 {
00051 instance_ = new ServerShotHolder;
00052 }
00053 return instance_;
00054 }
00055
00056 ServerShotHolder::ServerShotHolder()
00057 {
00058 }
00059
00060 ServerShotHolder::~ServerShotHolder()
00061 {
00062 }
00063
00064 void ServerShotHolder::sendWaitingMessage()
00065 {
00066
00067 ComsPlayerStatusMessage statusMessage;
00068 std::list<unsigned int> &tanks =
00069 TurnController::instance()->getPlayersThisTurn();
00070 std::list<unsigned int>::iterator itor;
00071 for (itor = tanks.begin();
00072 itor != tanks.end();
00073 itor++)
00074 {
00075 unsigned int playerId = (*itor);
00076 Tank *tank =
00077 ScorchedServer::instance()->getTankContainer().getTankById(playerId);
00078 if (tank && tank->getState().getState() == TankState::sNormal)
00079 {
00080 if (!haveShot(tank->getPlayerId()))
00081 {
00082 statusMessage.getWaitingPlayers().push_back(playerId);
00083 }
00084 }
00085 }
00086 ComsMessageSender::sendToAllPlayingClients(statusMessage, NetInterfaceFlags::fAsync);
00087 }
00088
00089 bool ServerShotHolder::addShot(unsigned int playerId,
00090 ComsPlayedMoveMessage *message)
00091 {
00092
00093 Tank *tank = ScorchedServer::instance()->getTankContainer().getTankById(playerId);
00094 if (!tank) return false;
00095
00096
00097 if (tank->getState().getState() != TankState::sNormal)
00098 {
00099 return false;
00100 }
00101
00102
00103 if (message->getType() == ComsPlayedMoveMessage::eShot)
00104 {
00105
00106 if (!validateFiredMessage(ScorchedServer::instance()->getContext(), *message, tank)) return false;
00107 }
00108
00109
00110 if (haveShot(playerId))
00111 {
00112 return false;
00113 }
00114
00115 messages_[playerId] = message;
00116 sendWaitingMessage();
00117
00118 return true;
00119 }
00120
00121 bool ServerShotHolder::validateFiredMessage(
00122 ScorchedContext &context, ComsPlayedMoveMessage &message, Tank *tank)
00123 {
00124
00125 Accessory *accessory =
00126 context.getAccessoryStore().findByAccessoryId(
00127 message.getWeaponId());
00128 if (accessory && accessory->getType() != AccessoryPart::AccessoryWeapon)
00129 {
00130 return false;
00131 }
00132
00133
00134 if (!tank->getAccessories().canUse(accessory)) return false;
00135
00136
00137 if ((10 - accessory->getArmsLevel()) <=
00138 context.getOptionsTransient().getArmsLevel() ||
00139 context.getOptionsGame().getGiveAllWeapons()) {}
00140 else return false;
00141
00142
00143 if (accessory->getPositionSelect() != Accessory::ePositionSelectNone)
00144 {
00145 int arenaX = ScorchedServer::instance()->
00146 getLandscapeMaps().getDefinitions().getDefn()->getArenaX();
00147 int arenaY = ScorchedServer::instance()->
00148 getLandscapeMaps().getDefinitions().getDefn()->getArenaY();
00149 int arenaWidth = ScorchedServer::instance()->
00150 getLandscapeMaps().getDefinitions().getDefn()->getArenaWidth();
00151 int arenaHeight = ScorchedServer::instance()->
00152 getLandscapeMaps().getDefinitions().getDefn()->getArenaHeight();
00153
00154 if (message.getSelectPositionX() <= arenaX || message.getSelectPositionX() >= arenaX + arenaWidth &&
00155 message.getSelectPositionY() <= arenaY || message.getSelectPositionY() >= arenaY + arenaHeight)
00156 {
00157 return false;
00158 }
00159
00160 if (accessory->getPositionSelect() == Accessory::ePositionSelectLimit)
00161 {
00162 FixedVector position(
00163 message.getSelectPositionX(), message.getSelectPositionY(), 0);
00164 if ((position - tank->getLife().getTargetPosition()).Magnitude() >
00165 accessory->getPositionSelectLimit())
00166 {
00167 return false;
00168 }
00169 }
00170 else if (accessory->getPositionSelect() == Accessory::ePositionSelectFuelLimit)
00171 {
00172 MovementMap mmap(
00173 tank,
00174 ScorchedServer::instance()->getContext());
00175
00176 FixedVector position(
00177 message.getSelectPositionX(), message.getSelectPositionY(), 0);
00178 mmap.calculatePosition(position, fixed(accessory->getPositionSelectLimit()));
00179
00180 MovementMap::MovementMapEntry &entry = mmap.getEntry(
00181 message.getSelectPositionX(), message.getSelectPositionY());
00182 if (entry.type != MovementMap::eMovement) return false;
00183 }
00184 }
00185
00186 return true;
00187 }
00188
00189 bool ServerShotHolder::allSkipped()
00190 {
00191 if (messages_.empty()) return false;
00192
00193 std::map<unsigned int, ComsPlayedMoveMessage *>::iterator itor;
00194 for (itor = messages_.begin();
00195 itor != messages_.end();
00196 itor++)
00197 {
00198 unsigned int playerId = (*itor).first;
00199 ComsPlayedMoveMessage *message = (*itor).second;
00200 if (message->getType() != ComsPlayedMoveMessage::eSkip)
00201 {
00202 return false;
00203 }
00204 }
00205 return true;
00206 }
00207
00208 bool ServerShotHolder::haveAllTurnShots()
00209 {
00210 std::list<unsigned int> &tanks =
00211 TurnController::instance()->getPlayersThisTurn();
00212 std::list<unsigned int>::iterator itor;
00213 for (itor = tanks.begin();
00214 itor != tanks.end();
00215 itor++)
00216 {
00217 unsigned int playerId = (*itor);
00218 Tank *tank =
00219 ScorchedServer::instance()->getTankContainer().getTankById(playerId);
00220 if (tank &&
00221 tank->getState().getState() == TankState::sNormal &&
00222 tank->getDestinationId() != 0)
00223 {
00224 if (!haveShot(tank->getPlayerId())) return false;
00225 }
00226 }
00227 return true;
00228 }