Changeset 53643ca in network-game


Ignore:
Timestamp:
Jul 19, 2014, 12:32:33 AM (10 years ago)
Author:
Dmitry Portnoy <dmp1488@…>
Branches:
master
Children:
4c00935
Parents:
cdb0e98
Message:

Server loads user profile and game history info from the database, saves game history to the db after every game, and uses a lua settings file to load db settings

Files:
4 added
8 edited

Legend:

Unmodified
Added
Removed
  • .gitignore

    rcdb0e98 r53643ca  
    88*.log
    99gameClient
    10 server
     10gameServer
    1111graphics_engine
  • common/Game.cpp

    rcdb0e98 r53643ca  
    217217   p->takeDamage(damage);
    218218
    219    if (p->isDead)
    220    {
     219   if (p->isDead) {
    221220      ObjectType flagType = OBJECT_NONE;
    222221      if (p->hasBlueFlag)
     
    240239   bool gameFinished = false;
    241240
    242    for (it = this->getPlayers().begin(); it != this->getPlayers().end(); it++)
    243    {
    244       gameFinished = gameFinished ||
    245          this->handlePlayerEvents(it->second);
     241   for (it = this->getPlayers().begin(); it != this->getPlayers().end(); it++) {
     242      gameFinished = gameFinished || this->handlePlayerEvents(it->second);
    246243   }
    247244
    248245   if (gameFinished) {
    249       for (it = this->players.begin(); it != this->players.end(); it++)
    250       {
     246      for (it = this->players.begin(); it != this->players.end(); it++) {
    251247         it->second->currentGame = NULL;
    252248      }
     
    279275      bool ownFlagAtBase = false;
    280276
    281       switch(this->worldMap->getStructure(p->pos.x/25, p->pos.y/25))
    282       {
     277      switch(this->worldMap->getStructure(p->pos.x/25, p->pos.y/25)) {
    283278         case STRUCTURE_BLUE_FLAG:
    284279         {
    285             if (p->team == 0 && p->hasRedFlag)
    286             {
     280            if (p->team == 0 && p->hasRedFlag) {
    287281               // check that your flag is at your base
    288282               pos = this->worldMap->getStructureLocation(STRUCTURE_BLUE_FLAG);
     
    291285               vector<WorldMap::Object>::iterator itObjects;
    292286
    293                for (itObjects = vctObjects->begin(); itObjects != vctObjects->end(); itObjects++)
    294                {
    295                   if (itObjects->type == OBJECT_BLUE_FLAG)
    296                   {
    297                      if (itObjects->pos.x == pos.x*25+12 && itObjects->pos.y == pos.y*25+12)
    298                      {
     287               for (itObjects = vctObjects->begin(); itObjects != vctObjects->end(); itObjects++) {
     288                  if (itObjects->type == OBJECT_BLUE_FLAG) {
     289                     if (itObjects->pos.x == pos.x*25+12 && itObjects->pos.y == pos.y*25+12) {
    299290                        ownFlagAtBase = true;
    300291                        break;
     
    303294               }
    304295
    305                if (ownFlagAtBase)
    306                {
     296               if (ownFlagAtBase) {
    307297                  p->hasRedFlag = false;
    308298                  flagType = OBJECT_RED_FLAG;
     
    317307         case STRUCTURE_RED_FLAG:
    318308         {
    319             if (p->team == 1 && p->hasBlueFlag)
    320             {
     309            if (p->team == 1 && p->hasBlueFlag) {
    321310               // check that your flag is at your base
    322311               pos = this->worldMap->getStructureLocation(STRUCTURE_RED_FLAG);
     
    325314               vector<WorldMap::Object>::iterator itObjects;
    326315
    327                for (itObjects = vctObjects->begin(); itObjects != vctObjects->end(); itObjects++)
    328                {
    329                   if (itObjects->type == OBJECT_RED_FLAG)
    330                   {
    331                      if (itObjects->pos.x == pos.x*25+12 && itObjects->pos.y == pos.y*25+12)
    332                      {
     316               for (itObjects = vctObjects->begin(); itObjects != vctObjects->end(); itObjects++) {
     317                  if (itObjects->type == OBJECT_RED_FLAG) {
     318                     if (itObjects->pos.x == pos.x*25+12 && itObjects->pos.y == pos.y*25+12) {
    333319                        ownFlagAtBase = true;
    334320                        break;
     
    337323               }
    338324
    339                if (ownFlagAtBase)
    340                {
     325               if (ownFlagAtBase) {
    341326                  p->hasBlueFlag = false;
    342327                  flagType = OBJECT_BLUE_FLAG;
     
    355340      }
    356341
    357       if (flagTurnedIn)
    358       {
     342      if (flagTurnedIn) {
    359343         unsigned int blueScore = this->blueScore;
    360344         unsigned int redScore = this->redScore;
     
    399383      POSITION structPos;
    400384
    401       for (itObjects = vctObjects->begin(); itObjects != vctObjects->end(); itObjects++)
    402       {
     385      for (itObjects = vctObjects->begin(); itObjects != vctObjects->end(); itObjects++) {
    403386         POSITION pos = itObjects->pos;
    404387
    405          if (posDistance(p->pos, pos.toFloat()) < 10)
    406          {
    407             if (p->team == 0 &&
    408                 itObjects->type == OBJECT_BLUE_FLAG)
    409             {
     388         if (posDistance(p->pos, pos.toFloat()) < 10) {
     389            if (p->team == 0 && itObjects->type == OBJECT_BLUE_FLAG) {
    410390               structPos = this->worldMap->getStructureLocation(STRUCTURE_BLUE_FLAG);
    411391               flagReturned = true;
    412392               break;
    413             }
    414             else if (p->team == 1 &&
    415                      itObjects->type == OBJECT_RED_FLAG)
    416             {
     393            } else if (p->team == 1 && itObjects->type == OBJECT_RED_FLAG) {
    417394               structPos = this->worldMap->getStructureLocation(STRUCTURE_RED_FLAG);
    418395               flagReturned = true;
     
    422399      }
    423400
    424       if (flagReturned)
    425       {
     401      if (flagReturned) {
    426402         itObjects->pos.x = structPos.x*25+12;
    427403         itObjects->pos.y = structPos.y*25+12;
     
    432408      }
    433409
    434       if (broadcastMove)
    435       {
     410      if (broadcastMove) {
    436411         serverMsg.type = MSG_TYPE_PLAYER;
    437412         p->serialize(serverMsg.buffer);
     
    443418
    444419   // check if the player's attack animation is complete
    445    if (p->isAttacking && p->timeAttackStarted+p->attackCooldown <= getCurrentMillis())
    446    {
     420   if (p->isAttacking && p->timeAttackStarted+p->attackCooldown <= getCurrentMillis()) {
    447421      p->isAttacking = false;
    448422      cout << "Attack animation is complete" << endl;
     
    451425      cout << "about to broadcast attack" << endl;
    452426
    453       if (p->attackType == Player::ATTACK_MELEE)
    454       {
     427      if (p->attackType == Player::ATTACK_MELEE) {
    455428         cout << "Melee attack" << endl;
    456429
    457430         Player* target = players[p->getTargetPlayer()];
    458431         this->dealDamageToPlayer(target, p->damage);
    459       }
    460       else if (p->attackType == Player::ATTACK_RANGED)
    461       {
     432      } else if (p->attackType == Player::ATTACK_RANGED) {
    462433         cout << "Ranged attack" << endl;
    463434
     
    476447         memcpy(serverMsg.buffer+12, &targetId, 4);
    477448         msgProcessor->broadcastMessage(serverMsg, players);
    478       }
    479       else
     449      } else
    480450         cout << "Invalid attack type: " << p->attackType << endl;
    481451   }
  • common/Player.cpp

    rcdb0e98 r53643ca  
    3333   this->hasBlueFlag = false;
    3434   this->hasRedFlag = false;
     35
     36   this->level = 0;
     37   this->experience = 0;
     38   this->honor = 0;
     39   this->wins = 0;
     40   this->losses = 0;
    3541
    3642   this->currentGame = NULL;
     
    6672   this->hasRedFlag = p.hasRedFlag;
    6773
     74   this->level = p.level;
     75   this->experience = p.experience;
     76   this->honor = p.honor;
     77   this->wins = p.wins;
     78   this->losses = p.losses;
     79
    6880   this->currentGame = p.currentGame;
    6981}
     
    95107   this->hasBlueFlag = false;
    96108   this->hasRedFlag = false;
     109
     110   this->level = 0;
     111   this->experience = 0;
     112   this->honor = 0;
     113   this->wins = 0;
     114   this->losses = 0;
    97115
    98116   this->currentGame = NULL;
  • common/Player.h

    rcdb0e98 r53643ca  
    8888   bool hasRedFlag;
    8989
     90   // permanent attributes
     91   unsigned int level;
     92   unsigned int experience;
     93   unsigned int honor;
     94   unsigned int wins;
     95   unsigned int losses;
     96
    9097   Game* currentGame;
    9198};
  • server/DataAccess.cpp

    rcdb0e98 r53643ca  
    66#include <crypt.h>
    77
     8#include "LuaLoader.h"
     9
    810using namespace std;
    911
    1012DataAccess::DataAccess()
    1113{
     14   LuaLoader luaLoader;
     15
     16   string database, username, password;
     17
     18   if (luaLoader.runScript("db_settings.lua")) {
     19       cout << "Loading settings" << endl;
     20
     21       database = luaLoader.getValue("database");
     22       username = luaLoader.getValue("username");
     23       password = luaLoader.getValue("password");
     24
     25       cout << database << endl;
     26       cout << username << endl;
     27       cout << password << endl;
     28   } else {
     29       cout << "Failed to load settings from lua script" << endl;
     30   }
     31
    1232   mysql_init(&mysql);
    1333   connection = mysql_real_connect(&mysql, "localhost", "pythonAdmin", "pyMaster09*", "pythondb", 0, 0, 0);
     
    5272}
    5373
     74// this is no longer used anywhere
    5475int DataAccess::updatePlayer(string username, string password)
    5576{
     
    85106      cout << "Creating a new player" << endl;
    86107      p = new Player(string(row[1]), string(row[2]));
     108      p->setId(atoi(row[0]));
    87109      if (row[3] == NULL) {
    88110         p->setClass(Player::CLASS_NONE);
     
    93115      }
    94116      cout << "Player class: " << p->playerClass << endl;
    95       cout << "Created new player" << endl;
     117      if (row[7] == NULL)
     118          cout << "wins: NULL" << endl;
     119      else
     120          cout << "wins: " << atoi(row[7]) << endl;
     121      if (row[8] == NULL)
     122          cout << "losses: NULL" << endl;
     123      else
     124          cout << "losses: " << atoi(row[8]) << endl;
     125      cout << "Loaded player from db" << endl;
    96126   }else {
    97127      cout << "Returned no results for some reason" << endl;
     
    112142   MYSQL_RES *result;
    113143   MYSQL_ROW row;
    114    ostringstream oss;
    115144
    116145   result = select("users", "");
     
    139168}
    140169
     170int* DataAccess::getPlayerRecord(int playerId) {
     171   MYSQL_RES *result;
     172   MYSQL_ROW row;
     173   ostringstream oss;
     174   int* record = new int[5];
     175
     176   oss << "id=" << playerId;
     177   result = select("users", oss.str());
     178
     179   if ( ( row = mysql_fetch_row(result)) != NULL ) {
     180      cout << "Retrieved player record successfully" << endl;
     181      record[0] = atoi(row[4]);   // level
     182      record[1] = atoi(row[5]);   // experience
     183      record[2] = atoi(row[6]);   // honor
     184      record[3] = atoi(row[7]);   // wins
     185      record[4] = atoi(row[8]);   // losses
     186      cout << "record[0]:" << record[0] << endl;
     187      cout << "record[1]:" << record[1] << endl;
     188      cout << "record[2]:" << record[2] << endl;
     189      cout << "record[3]:" << record[3] << endl;
     190      cout << "record[4]:" << record[4] << endl;
     191   }
     192
     193   if (result == NULL) {
     194      cout << mysql_error(connection) << endl;
     195      return NULL;
     196   }
     197
     198   mysql_free_result(result);
     199
     200   return record;
     201}
     202
     203int** DataAccess::getPlayerGameHistory(int playerId, unsigned int& numGames)
     204{
     205   // each array is the score for one game
     206   // the columns are result, team, blue score, and red score
     207   // for result 0 is defeat and 1 is victory
     208   // for team, 0 is blue and 1 is red
     209
     210   MYSQL_RES *result;
     211   MYSQL_ROW row;
     212   ostringstream oss;
     213
     214   int** gameHistory;
     215
     216   oss << "user_id=" << playerId;
     217   result = select("gameHistory", oss.str());
     218
     219   numGames = mysql_num_rows(result);
     220   gameHistory = (int**)malloc(sizeof(int*)*numGames);
     221   cout << "Result has " << numGames << " rows" << endl;
     222
     223   int i=0;
     224   while ( ( row = mysql_fetch_row(result)) != NULL ) {
     225      gameHistory[i] = new int[4];
     226
     227      int userTeam = atoi(row[2]);
     228      int blueScore = atoi(row[4]);
     229      int redScore = atoi(row[3]);
     230      int gameResult = -1;
     231
     232      if (blueScore == 3) {
     233         if (userTeam == 0)
     234            gameResult = 1;
     235         else
     236            gameResult = 0;
     237      }else if (redScore == 3) {
     238         if (userTeam == 1)
     239            gameResult = 1;
     240         else
     241            gameResult = 0;
     242      }else {
     243         cout << "Recorded game has no team with 3 points" << endl;
     244      }
     245
     246      gameHistory[i][0] = gameResult;
     247      gameHistory[i][1] = userTeam;
     248      gameHistory[i][2] = blueScore;
     249      gameHistory[i][3] = redScore;
     250
     251      i++;
     252   }
     253
     254   if (result == NULL) {
     255      cout << mysql_error(connection) << endl;
     256      return NULL;
     257   }
     258
     259   mysql_free_result(result);
     260
     261   return gameHistory;
     262}
     263
     264int DataAccess::saveGameHistory(int playerId, int team, int blueScore, int redScore)
     265{
     266   ostringstream oss;
     267
     268   cout << "Saving game to db" << endl;
     269   oss << playerId << ", " << team << ", " << blueScore << ", " << redScore;
     270
     271   return insert("gameHistory", "user_id, user_team, blue_score, red_score", oss.str());
     272}
     273
    141274int DataAccess::insert(string table, string columns, string values)
    142275{
     
    156289   if (query_state != 0) {
    157290      cout << mysql_error(connection) << endl;
    158       return 1;
     291      return -1;
    159292   }
    160293
     
    168301
    169302   if (connection == NULL) {
    170        cout << "Error: non database connection exists" << endl;
     303       cout << "Error: no database connection exists" << endl;
    171304       return -1;
    172305   }
     
    179312   if (query_state != 0) {
    180313      cout << mysql_error(connection) << endl;
    181       return 1;
     314      return -1;
    182315   }
    183316
     
    198331   if (!filter.empty())
    199332      oss << " WHERE " << filter;
     333   cout << "executing select query: " << oss.str() << endl;
    200334
    201335   query_state = mysql_query(connection, oss.str().c_str());
  • server/DataAccess.h

    rcdb0e98 r53643ca  
    1 #ifndef _DATA_ACCES_H
     1#ifndef _DATA_ACCESS_H
    22#define _DATA_ACCESS_H
    33
     
    1616   ~DataAccess();
    1717
    18    int insertPlayer(string username, string password, Player::PlayerClass playerClass);
    19    int updatePlayer(string username, string password);
    20 
    2118   Player* getPlayer(string username);
    2219   list<Player*>* getPlayers();
    2320   bool verifyPassword(string encrypted, string password);
     21   int insertPlayer(string username, string password, Player::PlayerClass playerClass);
     22   // this method needs to be more rebust. maybe pass in a player object amd
     23   // the method could use the player id to find the player and update any
     24   // attributes that changed
     25   int updatePlayer(string username, string password);
     26
     27   int* getPlayerRecord(int playerId);
     28   int** getPlayerGameHistory(int playerId, unsigned int& numGames);
     29   int saveGameHistory(int playerId, int team, int blueScore, int redScore);
    2430
    2531   int insert(string table, string rows, string values);
  • server/makefile

    rcdb0e98 r53643ca  
    11CC = g++
    22#LIB_FLAGS = -lssl -lmysqlclient -lcrypt -lrt
    3 LIB_FLAGS = -lmysqlclient -lcrypt -lrt
     3LIB_FLAGS = -lmysqlclient -lcrypt -lrt -llua5.2
    44FLAGS = -Wall -g
    55COMMON_PATH = ../common
    6 DEPENDENCIES = Common.o MessageContainer.o MessageProcessor.o Player.o WorldMap.o DataAccess.o Projectile.o Game.o GameSummary.o
     6DEPENDENCIES = Common.o MessageContainer.o MessageProcessor.o Player.o WorldMap.o DataAccess.o Projectile.o Game.o GameSummary.o LuaLoader.o
    77
    8 server : server.cpp $(DEPENDENCIES)
     8gameServer : server.cpp $(DEPENDENCIES)
    99        $(CC) -o $@ $+ $(FLAGS) $(LIB_FLAGS)
    1010
     
    3838clean:
    3939        rm *.o
    40         rm server
     40        rm gameServer
  • server/server.cpp

    rcdb0e98 r53643ca  
    4343// from used to be const. Removed that so I could take a reference
    4444// and use it to send messages
    45 void processMessage(const NETWORK_MSG& clientMsg, struct sockaddr_in& from, MessageProcessor& msgProcessor, map<unsigned int, Player*>& mapPlayers, map<string, Game*>& mapGames, unsigned int& unusedPlayerId, ofstream& outputLog);
    46 
    47 void updateUnusedPlayerId(unsigned int& id, map<unsigned int, Player*>& mapPlayers);
     45void processMessage(const NETWORK_MSG& clientMsg, struct sockaddr_in& from, MessageProcessor& msgProcessor, map<unsigned int, Player*>& mapPlayers, map<string, Game*>& mapGames, ofstream& outputLog);
     46
    4847Player *findPlayerByName(map<unsigned int, Player*> &m, string name);
    4948Player *findPlayerByAddr(map<unsigned int, Player*> &m, const sockaddr_in &addr);
     
    6362   map<unsigned int, Projectile> mapProjectiles;
    6463   map<string, Game*> mapGames;
    65    unsigned int unusedPlayerId = 1;
    6664   ofstream outputLog;
    6765
     
    117115
    118116         map<unsigned int, Player*>::iterator it;
    119 
    120          cout << "Updating player targets and respawning dead players" << endl;
    121117
    122118         // set targets for all chasing players (or make them attack if they're close enough)
     
    179175         }
    180176
    181          cout << "Processing players in a game" << endl;
    182 
    183177         // process players currently in a game
    184178         map<string, Game*>::iterator itGames;
     
    188182            game = itGames->second;
    189183            if (game->handleGameEvents()) {
     184               // save game record
     185               int winningTeam = -1;
     186               if (game->getBlueScore() == 3)
     187                  winningTeam = 0;
     188               else if (game->getRedScore() == 3)
     189                  winningTeam = 1;
     190
     191               if (winningTeam == -1)
     192                  cout << "Error: Game ended, but neither team has a score of 3" << endl;
     193               else {
     194                  map<unsigned int, Player*>::iterator it;
     195                  DataAccess da;
     196
     197                  for (it = game->getPlayers().begin(); it != game->getPlayers().end(); it++) {
     198                      da.saveGameHistory(it->second->getId(), winningTeam, game->getBlueScore(), game->getRedScore());
     199                  }
     200               }
     201
    190202               // send a GAME_INFO message with 0 players to force clients to delete the game
    191203               int numPlayers = 0;
     
    200212               itGames++;
    201213         }
    202 
    203          cout << "Processing projectiles"  << endl;
    204214
    205215         // move all projectiles
     
    230240      if (msgProcessor.receiveMessage(&clientMsg, &from) >= 0)
    231241      {
    232          processMessage(clientMsg, from, msgProcessor, mapPlayers, mapGames, unusedPlayerId, outputLog);
     242         processMessage(clientMsg, from, msgProcessor, mapPlayers, mapGames, outputLog);
    233243
    234244         cout << "Finished processing the message" << endl;
     
    255265}
    256266
    257 void processMessage(const NETWORK_MSG &clientMsg, struct sockaddr_in &from, MessageProcessor &msgProcessor, map<unsigned int, Player*>& mapPlayers, map<string, Game*>& mapGames, unsigned int& unusedPlayerId, ofstream& outputLog)
     267void processMessage(const NETWORK_MSG &clientMsg, struct sockaddr_in &from, MessageProcessor &msgProcessor, map<unsigned int, Player*>& mapPlayers, map<string, Game*>& mapGames, ofstream& outputLog)
    258268{
    259269   NETWORK_MSG serverMsg;
     
    331341         else
    332342         {
    333             updateUnusedPlayerId(unusedPlayerId, mapPlayers);
    334             p->setId(unusedPlayerId);
    335343            cout << "new player id: " << p->getId() << endl;
    336344            p->setAddr(from);
     
    369377            msgProcessor.broadcastMessage(serverMsg, mapPlayers);
    370378
    371             mapPlayers[unusedPlayerId] = p;
     379            mapPlayers[p->getId()] = p;
    372380         }
    373381
     
    403411
    404412            msgProcessor.broadcastMessage(serverMsg, mapPlayers);
    405 
    406             if (p->getId() < unusedPlayerId)
    407                unusedPlayerId = p->getId();
    408413
    409414            mapPlayers.erase(p->getId());
     
    569574      case MSG_TYPE_PROFILE:
    570575      {
     576         cout << "Received a PROFILE message" << endl;
     577
     578         unsigned int id;
     579
     580         memcpy(&id, clientMsg.buffer, 4);
     581
     582         cout << "Player id: " << id << endl;
     583         unsigned int numGames = 0;
     584         int** gameHistory = da.getPlayerGameHistory(id, numGames);
     585         int* playerRecord = da.getPlayerRecord(id);
     586
     587         int honorPoints = playerRecord[0];
     588         int wins = playerRecord[1];
     589         int losses = playerRecord[2];
     590
    571591         serverMsg.type = MSG_TYPE_PROFILE;
    572592
    573          // each array is the score for one game
    574          // the columns are result, team, blue score, and red score
    575          // for result 0 is defeat and 1 is victory
    576          // for team, 0 is blue and 1 is red
    577          int scores[][4] = {
    578             {1, 1, 2, 3},
    579             {1, 0, 3, 2},
    580             {0, 1, 3, 1},
    581             {1, 1, 0, 3},
    582             {0, 0, 2, 3},
    583             {1, 0, 3, 2},
    584             {1, 0, 3, 0},
    585             {0, 1, 3, 1},
    586             {1, 1, 1, 3},
    587             {1, 0, 3, 2}
    588          };
    589 
    590          int honorPoints = 1000;
    591          int numGames = 10;
    592593         memcpy(serverMsg.buffer, &honorPoints, 4);
    593          memcpy(serverMsg.buffer+4, &numGames, 4);
    594          for (unsigned int i=0; i<sizeof(scores)/sizeof(scores[0]); i++) {
    595             memcpy(serverMsg.buffer+8+i*16, &scores[i][0], 4);
    596             memcpy(serverMsg.buffer+12+i*16, &scores[i][1], 4);
    597             memcpy(serverMsg.buffer+16+i*16, &scores[i][2], 4);
    598             memcpy(serverMsg.buffer+20+i*16, &scores[i][3], 4);
    599          }
     594         memcpy(serverMsg.buffer+4, &wins, 4);
     595         memcpy(serverMsg.buffer+8, &losses, 4);
     596         memcpy(serverMsg.buffer+12, &numGames, 4);
     597         for (unsigned int i=0; i<numGames; i++) {
     598            memcpy(serverMsg.buffer+16+i*16, &gameHistory[i][0], 4);
     599            memcpy(serverMsg.buffer+20+i*16, &gameHistory[i][1], 4);
     600            memcpy(serverMsg.buffer+24+i*16, &gameHistory[i][2], 4);
     601            memcpy(serverMsg.buffer+28+i*16, &gameHistory[i][3], 4);
     602            delete[] gameHistory[i];
     603         }
     604
     605         //delete[] gameHistory;
     606         free(gameHistory);
     607         delete[] playerRecord;
    600608
    601609         msgProcessor.sendMessage(&serverMsg, &from);
     
    825833}
    826834
    827 void updateUnusedPlayerId(unsigned int& id, map<unsigned int, Player*>& mapPlayers)
    828 {
    829    while (mapPlayers.find(id) != mapPlayers.end())
    830       id++;
    831 }
    832 
    833835Player *findPlayerByName(map<unsigned int, Player*> &m, string name)
    834836{
Note: See TracChangeset for help on using the changeset viewer.