ServerShotHolder.cpp

Go to the documentation of this file.
00001 ////////////////////////////////////////////////////////////////////////////////
00002 //    Scorched3D (c) 2000-2009
00003 //
00004 //    This file is part of Scorched3D.
00005 //
00006 //    Scorched3D is free software; you can redistribute it and/or modify
00007 //    it under the terms of the GNU General Public License as published by
00008 //    the Free Software Foundation; either version 2 of the License, or
00009 //    (at your option) any later version.
00010 //
00011 //    Scorched3D is distributed in the hope that it will be useful,
00012 //    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 //    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014 //    GNU General Public License for more details.
00015 //
00016 //    You should have received a copy of the GNU General Public License
00017 //    along with Scorched3D; if not, write to the Free Software
00018 //    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
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         // Tell the client who we are currently waiting on
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         // Check the tank exists for this player
00093         Tank *tank = ScorchedServer::instance()->getTankContainer().getTankById(playerId);
00094         if (!tank) return false;
00095 
00096         // Check the tank is alive
00097         if (tank->getState().getState() != TankState::sNormal)
00098         {
00099                 return false;
00100         }
00101 
00102         // Validate this message
00103         if (message->getType() == ComsPlayedMoveMessage::eShot)
00104         {
00105                 // Check this player can fire this weapon etc...
00106                 if (!validateFiredMessage(ScorchedServer::instance()->getContext(), *message, tank)) return false;
00107         }
00108 
00109         // Ensure each player can only add one message
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         // Check the weapon name exists and is a weapon
00125         Accessory *accessory = 
00126                 context.getAccessoryStore().findByAccessoryId(
00127                 message.getWeaponId());
00128         if (accessory && accessory->getType() != AccessoryPart::AccessoryWeapon)
00129         {
00130                 return false;
00131         }
00132 
00133         // Check this tank has these weapons
00134         if (!tank->getAccessories().canUse(accessory)) return false;
00135 
00136         // Check armslevel
00137         if ((10 - accessory->getArmsLevel()) <=
00138                 context.getOptionsTransient().getArmsLevel() ||
00139                 context.getOptionsGame().getGiveAllWeapons()) {}
00140         else return false;
00141 
00142         // Check weapons selection parameters
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;  // Do nothing
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 }

Generated on Mon Feb 16 15:14:53 2009 for Scorched3D by  doxygen 1.5.3