src/include/action.cpp

Go to the documentation of this file.
00001 /******************************************************************************
00002  *  Wormux is a convivial mass murder game.
00003  *  Copyright (C) 2001-2004 Lawrence Azzoug.
00004  *
00005  *  This program is free software; you can redistribute it and/or modify
00006  *  it under the terms of the GNU General Public License as published by
00007  *  the Free Software Foundation; either version 2 of the License, or
00008  *  (at your option) any later version.
00009  *
00010  *  This program is distributed in the hope that it will be useful,
00011  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013  *  GNU General Public License for more details.
00014  *
00015  *  You should have received a copy of the GNU General Public License
00016  *  along with this program; if not, write to the Free Software
00017  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
00018  ******************************************************************************
00019  * Define all Wormux actions.
00020  *****************************************************************************/
00021 
00022 #include "action.h"
00023 //-----------------------------------------------------------------------------
00024 #include <SDL_net.h>
00025 #include "action_handler.h"
00026 #include "../tool/debug.h"
00027 #include "../game/time.h"
00028 #include "../character/character.h"
00029 #include "../team/teams_list.h"
00030 
00031 //-----------------------------------------------------------------------------
00032 // Action without parameter
00033 Action::Action (Action_t type)
00034 {
00035   var.clear();
00036   m_type = type;
00037   m_timestamp = Time::GetInstance()->Read();
00038 }
00039 
00040 // Action with various parameters
00041 Action::Action (Action_t type, int value) : m_type(type)
00042 {
00043   var.clear();
00044   Push(value);
00045   m_timestamp = Time::GetInstance()->Read();
00046 }
00047 
00048 Action::Action (Action_t type, double value) : m_type(type)
00049 {
00050   var.clear();
00051   Push(value);
00052   m_timestamp = Time::GetInstance()->Read();
00053 }
00054 
00055 Action::Action (Action_t type, const std::string& value) : m_type(type)
00056 {
00057   var.clear();
00058   Push(value);
00059   m_timestamp = Time::GetInstance()->Read();
00060 }
00061 
00062 Action::Action (Action_t type, double value1, double value2) : m_type(type)
00063 {
00064   var.clear();
00065   Push(value1);
00066   Push(value2);
00067   m_timestamp = Time::GetInstance()->Read();
00068 }
00069 
00070 Action::Action (Action_t type, double value1, int value2) : m_type(type)
00071 {
00072   var.clear();
00073   Push(value1);
00074   Push(value2);
00075   m_timestamp = Time::GetInstance()->Read();
00076 }
00077 
00078 // Build an action from a network packet
00079 Action::Action (const char *is)
00080 {
00081   var.clear();
00082   m_type = (Action_t)SDLNet_Read32(is);
00083   is += 4;
00084   m_timestamp = (Action_t)SDLNet_Read32(is);
00085   is += 4;
00086   int m_lenght = SDLNet_Read32(is);
00087   is += 4;
00088 
00089   for(int i=0; i < m_lenght; i++)
00090   {
00091     Uint32 val = SDLNet_Read32(is);
00092     var.push_back(val);
00093     is += 4;
00094   }
00095 }
00096 
00097 Action::~Action ()
00098 {
00099 }
00100 
00101 Action::Action_t Action::GetType() const
00102 {
00103   return m_type;
00104 }
00105 
00106 bool Action::IsEmpty() const
00107 {
00108   return var.empty();
00109 }
00110 
00111 void Action::SetTimestamp(uint timestamp)
00112 {
00113   m_timestamp = timestamp;
00114 }
00115 
00116 uint Action::GetTimestamp()
00117 {
00118   return m_timestamp;
00119 }
00120 
00121 // Convert the action to a packet
00122 void Action::WritePacket(char* &packet, int & size)
00123 {
00124   size = 4  //Size of the type;
00125         + 4 //Size of the timestamp
00126         + 4 //Size of the number of variable
00127         + int(var.size()) * 4;
00128 
00129   packet = (char*)malloc(size);
00130   char* os = packet;
00131 
00132   SDLNet_Write32(m_type, os);
00133   os += 4;
00134   SDLNet_Write32(m_timestamp, os);
00135   os += 4;
00136   Uint32 param_size = (Uint32)var.size();
00137   SDLNet_Write32(param_size, os);
00138   os += 4;
00139 
00140   for(std::list<Uint32>::iterator val = var.begin(); val!=var.end(); val++)
00141   {
00142     SDLNet_Write32(*val, os);
00143     os += 4;
00144   }
00145 }
00146 
00147 //-------------  Add datas to the action  ----------------
00148 void Action::Push(int val)
00149 {
00150   Uint32 tmp;
00151   memcpy(&tmp, &val, 4);
00152   var.push_back(tmp);
00153   MSG_DEBUG( "action", " (%s) Pushing int : %i",
00154         ActionHandler::GetInstance()->GetActionName(m_type).c_str(), val);
00155 
00156 }
00157 
00158 void Action::Push(double val)
00159 {
00160   Uint32 tmp[2];
00161   memcpy(&tmp, &val, 8);
00162 #if (SDL_BYTEORDER == SDL_LIL_ENDIAN)
00163   var.push_back(tmp[0]);
00164   var.push_back(tmp[1]);
00165 #else
00166   var.push_back(tmp[1]);
00167   var.push_back(tmp[0]);
00168 #endif
00169 
00170   MSG_DEBUG( "action", " (%s) Pushing double : %f",
00171         ActionHandler::GetInstance()->GetActionName(m_type).c_str(), val);
00172 }
00173 
00174 void Action::Push(const Point2i& val)
00175 {
00176   Push(val.x);
00177   Push(val.y);
00178 }
00179 
00180 void Action::Push(const Point2d& val)
00181 {
00182   Push(val.x);
00183   Push(val.y);
00184 }
00185 
00186 void Action::Push(std::string val)
00187 {
00188   //Cut the string into 32bit values
00189   //But first, we write the size of the string:
00190   Push((int)val.size());
00191   char* ch = (char*)val.c_str();
00192 
00193   int count = val.size();
00194   while(count > 0)
00195   {
00196     Uint32 tmp = 0;
00197     // Fix-me : We are reading out of the c_str() buffer there :
00198 #if (SDL_BYTEORDER == SDL_LIL_ENDIAN)
00199     strncpy((char*)&tmp, ch, 4);
00200     var.push_back(tmp);
00201     ch += 4;
00202     count -= 4;
00203 #else
00204     char* c_tmp = (char*)&tmp;
00205     c_tmp +=3;
00206     for(int i=0; i < 4; i++)
00207       *(c_tmp--) = *(ch++);
00208 
00209     var.push_back(tmp);
00210     count -= 4;
00211 #endif
00212   }
00213   MSG_DEBUG( "action", " (%s) Pushing string : %s",
00214   ActionHandler::GetInstance()->GetActionName(m_type).c_str(), val.c_str());
00215 }
00216 
00217 //-------------  Retrieve datas from the action  ----------------
00218 int Action::PopInt()
00219 {
00220   assert(var.size() > 0);
00221   if(var.size() <= 0)
00222         return 0;
00223   int val;
00224   Uint32 tmp = var.front();
00225   memcpy(&val, &tmp, 4);
00226   var.pop_front();
00227   MSG_DEBUG( "action", " (%s) Poping int : %i",
00228         ActionHandler::GetInstance()->GetActionName(m_type).c_str(), val);
00229   return val;
00230 }
00231 
00232 double Action::PopDouble()
00233 {
00234   assert(var.size() > 0);
00235   if(var.size() <= 0)
00236     return 0.0;
00237   double val;
00238   Uint32 tmp[2];
00239 #if (SDL_BYTEORDER == SDL_LIL_ENDIAN)
00240   tmp[0] = var.front();
00241   var.pop_front();
00242   tmp[1] = var.front();
00243   var.pop_front();
00244   memcpy(&val, &tmp, 8);
00245 #else
00246   tmp[1] = var.front();
00247   var.pop_front();
00248   tmp[0] = var.front();
00249   var.pop_front();
00250   memcpy(&val, &tmp, 8);
00251 #endif
00252 
00253   MSG_DEBUG( "action", " (%s) Poping double : %f",
00254         ActionHandler::GetInstance()->GetActionName(m_type).c_str(), val);
00255   return val;
00256 }
00257 
00258 std::string Action::PopString()
00259 {
00260   assert(var.size() > 1);
00261   if(var.size() <= 1)
00262     return "";
00263   int lenght = PopInt();
00264 
00265   std::string str="";
00266 
00267   assert((int)var.size() >= lenght/4);
00268   if((int)var.size() < lenght/4)
00269     return "";
00270 
00271   while(lenght > 0)
00272   {
00273     Uint32 tmp = var.front();
00274     var.pop_front();
00275     char tmp_str[5] = {0, 0, 0, 0, 0};
00276 #if (SDL_BYTEORDER == SDL_LIL_ENDIAN)
00277     memcpy(tmp_str, &tmp, 4);
00278     str += tmp_str;
00279     lenght -= 4;
00280 #else
00281     char* c_tmp_str = (char*)(&tmp_str) + 3;
00282     char* c_tmp = (char*)&tmp;
00283     for(int i=0; i < 4; i++)
00284       *(c_tmp_str--) = *(c_tmp++);
00285 
00286     str += tmp_str;
00287     lenght -= 4;
00288 #endif
00289     }
00290   MSG_DEBUG( "action", " (%s) Poping string : %s",
00291         ActionHandler::GetInstance()->GetActionName(m_type).c_str(), str.c_str());
00292   return str;
00293 }
00294 
00295 Point2i Action::PopPoint2i()
00296 {
00297   int x, y;
00298   x = PopInt();
00299   y = PopInt();
00300   return Point2i(x, y);
00301 }
00302 
00303 Point2d Action::PopPoint2d()
00304 {
00305   double x, y;
00306   x = PopDouble();
00307   y = PopDouble();
00308   return Point2d(x, y);
00309 }
00310 
00311 
00312 void Action::StoreActiveCharacter()
00313 {
00314   StoreCharacter(ActiveCharacter().GetTeamIndex() ,ActiveCharacter().GetCharacterIndex());
00315 }
00316 
00317 void Action::StoreCharacter(uint team_no, uint char_no)
00318 {
00319   Push((int)team_no);
00320   Push((int)char_no);
00321   Character * c = teams_list.FindPlayingByIndex(team_no)->FindByIndex(char_no);
00322   Push(c->GetPosition());
00323   Push((int)c->GetDirection());
00324   Push(c->GetAbsFiringAngle());
00325   Push(c->GetEnergy());
00326   Push((int)c->GetDiseaseDamage());
00327   Push((int)c->GetDiseaseDuration());
00328   Push(c->GetSpeed());
00329   if(c->IsActiveCharacter()) { // If active character, store step animation
00330     Push((int)true);
00331     Push(ActiveTeam().ActiveCharacter().GetBody()->GetClothe());
00332     Push(ActiveTeam().ActiveCharacter().GetBody()->GetMovement());
00333     Push((int)ActiveTeam().ActiveCharacter().GetBody()->GetFrame());
00334   } else {
00335     Push((int)false);
00336   }
00337 }
00338 
00339 void Action::RetrieveCharacter()
00340 {
00341   int team_no = PopInt();
00342   int char_no = PopInt();
00343   Character * c = teams_list.FindPlayingByIndex(team_no)->FindByIndex(char_no);
00344   c->SetXY(PopPoint2i());
00345   c->SetDirection((Body::Direction_t)PopInt());
00346   c->SetFiringAngle(PopDouble());
00347   c->SetEnergy(PopInt());
00348   int disease_damage_per_turn = PopInt();
00349   int disease_duration = PopInt();
00350   c->SetDiseaseDamage(disease_damage_per_turn, disease_duration);
00351   c->SetSpeedXY(PopPoint2d());
00352   if((bool)PopInt()) { // If active characters, retrieve stored animation
00353     if(c->GetTeam().IsActiveTeam())
00354       ActiveTeam().SelectCharacter(char_no);
00355     c->SetClothe(PopString());
00356     c->SetMovement(PopString());
00357     c->GetBody()->SetFrame((uint)PopInt());
00358   }
00359 }
00360 
00361 
00362 //-----------------------------------------------------------------------------

Generated on Mon Jan 1 13:10:57 2007 for Wormux by  doxygen 1.4.7