Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

Ignore:
Timestamp:
Dec 31, 2007, 7:40:23 PM (16 years ago)
Author:
rgrieder
Message:
  • added dll support to the network library
  • improved header file dependency in network
File:
1 edited

Legend:

Unmodified
Added
Removed
  • code/branches/FICN/src/network/GameStateManager.cc

    r656 r777  
    11/*
    2  *   ORXONOX - the hottest 3D action shooter ever to exist
    3  *
    4  *
    5  *   License notice:
    6  *
    7  *   This program is free software; you can redistribute it and/or
    8  *   modify it under the terms of the GNU General Public License
    9  *   as published by the Free Software Foundation; either version 2
    10  *   of the License, or (at your option) any later version.
    11  *
    12  *   This program is distributed in the hope that it will be useful,
    13  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
    14  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    15  *   GNU General Public License for more details.
    16  *
    17  *   You should have received a copy of the GNU General Public License
    18  *   along with this program; if not, write to the Free Software
    19  *   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
    20  *
    21  *   Author:
    22  *      Oliver Scheuss, (C) 2007
    23  *   Co-authors:
    24  *      ...
    25  *
    26  */
     2*   ORXONOX - the hottest 3D action shooter ever to exist
     3*
     4*
     5*   License notice:
     6*
     7*   This program is free software; you can redistribute it and/or
     8*   modify it under the terms of the GNU General Public License
     9*   as published by the Free Software Foundation; either version 2
     10*   of the License, or (at your option) any later version.
     11*
     12*   This program is distributed in the hope that it will be useful,
     13*   but WITHOUT ANY WARRANTY; without even the implied warranty of
     14*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15*   GNU General Public License for more details.
     16*
     17*   You should have received a copy of the GNU General Public License
     18*   along with this program; if not, write to the Free Software
     19*   Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
     20*
     21*   Author:
     22*      Oliver Scheuss, (C) 2007
     23*   Co-authors:
     24*      ...
     25*
     26*/
    2727
    2828//
     
    3737//
    3838//
     39
     40#include <utility>
     41#include <iostream>
     42#include <zlib.h>
     43
     44#include "core/CoreIncludes.h"
     45#include "ClientInformation.h"
     46#include "Synchronisable.h"
    3947#include "GameStateManager.h"
    4048
    41 namespace network {
    42 
    43 GameStateManager::GameStateManager(ClientInformation *head)
     49namespace network
    4450{
    45   id=0;
    46   head_=head;
     51  GameStateManager::GameStateManager(ClientInformation *head) {
     52    id=0;
     53    head_=head;
     54  }
     55
     56  GameStateManager::~GameStateManager() {
     57  }
     58
     59  void GameStateManager::update(){
     60    reference = getSnapshot(id);
     61    gameStateMap.insert(std::pair<int, GameState*>(id, reference));
     62    gameStateUsed[id]=0;
     63    ++id;
     64    return;
     65  }
     66
     67  GameStateCompressed GameStateManager::popGameState(int clientID) {
     68    int gID = head_->findClient(clientID)->getGamestateID();
     69    std::cout << "popgamestate: sending gstate id: " << id << "diffed from: " << gID << std::endl;
     70    if(gID!=GAMESTATEID_INITIAL){
     71      GameState *client = gameStateMap[gID];
     72      GameState *server = reference;
     73      //head_->findClient(clientID)->setGamestateID(id);
     74      return encode(client, server);
     75    } else {
     76      GameState *server = reference;
     77      //head_->findClient(clientID)->setGamestateID(id);
     78      return encode(server);
     79      // return an undiffed gamestate and set appropriate flags
     80    }
     81  }
     82
     83  /**
     84  * This function goes through the whole list of synchronisables and
     85  * saves all the synchronisables to a flat "list".
     86  * @return struct of type gamestate containing the size of the whole gamestate and a pointer linking to the flat list
     87  */
     88  GameState *GameStateManager::getSnapshot(int id)
     89  {
     90    //the size of the gamestate
     91    int totalsize=0;
     92    int memsize=1000;
     93    //the size of one specific synchronisable
     94    int tempsize=0;
     95    // get the start of the Synchronisable list
     96    orxonox::Iterator<Synchronisable> it;
     97    // struct for return value of Synchronisable::getData()
     98    syncData sync;
     99
     100    GameState *retval=new GameState; //return value
     101    retval->id=id++;
     102    std::cout << "producing gamestate with id: " << retval->id << std::endl;
     103    // reserve a little memory and increase it later on
     104    //COUT(2) << "mallocing" << std::endl;
     105    retval->data = (unsigned char*)malloc(memsize);
     106    //COUT(2) << "malloced" << std::endl;
     107
     108    // offset of memory functions
     109    int offset=0;
     110    // go through all Synchronisables
     111    for(it = orxonox::ObjectList<Synchronisable>::start(); it != 0; ++it){
     112      //std::cout << "gamestatemanager: in for loop" << std::endl;
     113      //get size of the synchronisable
     114      tempsize=it->getSize();
     115      //std::cout << "size of temp gamestate: " << tempsize << std::endl;
     116      //COUT(2) << "size of synchronisable: " << tempsize << std::endl;
     117      // add place for data and 3 ints (length,classid,objectid)
     118      totalsize+=tempsize+3*sizeof(int);
     119      //std::cout << "totalsize: " << totalsize << std::endl;
     120      // allocate additional space
     121      if(totalsize+tempsize>memsize){
     122        if(tempsize<1000){
     123          retval->data = (unsigned char *)realloc((void *)retval->data, totalsize+1000);
     124          memsize+=1000;
     125        } else {
     126          retval->data = (unsigned char *)realloc((void *)retval->data, totalsize+1000);
     127          memsize+=tempsize+1000;
     128        }
     129      }
     130
     131      // run Synchronisable::getData with offset and additional place for 3 ints in between (for ids and length)
     132      sync=it->getData((retval->data)+offset+3*sizeof(int));
     133      *(retval->data+offset)=sync.length;
     134      *(retval->data+offset+sizeof(int))=sync.objectID;
     135      *(retval->data+offset+2*sizeof(int))=sync.classID;
     136      // increase data pointer
     137      offset+=tempsize+3*sizeof(int);
     138    }
     139    retval->size=totalsize;
     140    return retval;
     141  }
     142
     143  GameStateCompressed GameStateManager::encode(GameState *a, GameState *b) {
     144    //GameState r = diff(a,b);
     145    //r.diffed = true;
     146    GameState r = *b;
     147    r.diffed = false;
     148    return compress_(&r);
     149  }
     150
     151  GameStateCompressed GameStateManager::encode(GameState *a) {
     152    a->diffed=false;
     153    return compress_(a);
     154  }
     155
     156  GameState GameStateManager::diff(GameState *a, GameState *b) {
     157    unsigned char *ap = a->data, *bp = b->data;
     158    int of=0; // pointers offset
     159    int dest_length=0;
     160    if(a->size>=b->size)
     161      dest_length=a->size;
     162    else
     163      dest_length=b->size;
     164    unsigned char *dp = (unsigned char *)malloc(dest_length*sizeof(unsigned char));
     165    while(of<a->size && of<b->size){
     166      *(dp+of)=*(ap+of)^*(bp+of); // do the xor
     167      ++of;
     168    }
     169    if(a->size!=b->size){ // do we have to fill up ?
     170      unsigned char n=0;
     171      if(a->size<b->size){
     172        while(of<dest_length){
     173          *(dp+of)=n^*(bp+of);
     174          of++;
     175        }
     176      } else{
     177        while(of<dest_length){
     178          *(dp+of)=*(ap+of)^n;
     179          of++;
     180        }
     181      }
     182    }
     183    // should be finished now
     184    GameState r = {b->id, dest_length, dp};
     185    return r;
     186  }
     187
     188  GameStateCompressed GameStateManager::compress_(GameState *a) {
     189    //COUT(2) << "compressing gamestate" << std::endl;
     190    int size = a->size;
     191    uLongf buffer = (uLongf)((a->size + 12)*1.01)+1;
     192    unsigned char* dest = (unsigned char*)malloc( buffer );
     193    int retval;
     194    //std::cout << "before ziped " << buffer << std::endl;
     195    retval = compress( dest, &buffer, a->data, (uLong)size );
     196    //std::cout << "after ziped " << buffer << std::endl;
     197
     198    switch ( retval ) {
     199      case Z_OK: std::cout << "successfully compressed" << std::endl; break;
     200      case Z_MEM_ERROR: std::cout << "not enough memory available" << std::endl; break;
     201      case Z_BUF_ERROR: std::cout << "not enough memory available in the buffer" << std::endl; break;
     202      case Z_DATA_ERROR: std::cout << "decompress: data corrupted" << std::endl; break;
     203    }
     204
     205    GameStateCompressed compressedGamestate;
     206    compressedGamestate.compsize = buffer;
     207    //std::cout << "compressedGamestate.compsize = buffer; " << buffer << std::endl;
     208    compressedGamestate.normsize = size;
     209    //std::cout << "compressedGamestate.normsize = size; " << size << std::endl;
     210    compressedGamestate.id = a->id;
     211    compressedGamestate.data = dest;
     212    compressedGamestate.diffed = a->diffed;
     213
     214    return compressedGamestate;
     215  }
     216
     217  void GameStateManager::ackGameState(int clientID, int gamestateID) {
     218    ClientInformation *temp = head_->findClient(clientID);
     219    int curid = temp->getID();
     220    // decrease usage of gamestate and save it
     221    deleteUnusedGameState(curid);
     222    //increase gamestateused
     223    ++gameStateUsed.find(gamestateID)->second;
     224    temp->setGamestateID(gamestateID);
     225    /*
     226    GameState *old = clientGameState[clientID];
     227    deleteUnusedGameState(old);
     228    clientGameState[clientID]=idGameState[gamestateID];*/
     229  }
     230
     231  bool GameStateManager::deleteUnusedGameState(int gamestateID) {
     232    int used = --(gameStateUsed.find(gamestateID)->second);
     233    if(id-gamestateID>KEEP_GAMESTATES && used==0){
     234      // delete gamestate
     235      delete gameStateMap.find(gamestateID)->second;
     236      gameStateMap.erase(gamestateID);
     237      return true;
     238    }
     239    return false;
     240  }
     241
    47242}
    48 
    49 GameStateManager::~GameStateManager()
    50 {
    51 }
    52 
    53 void GameStateManager::update(){
    54   reference = getSnapshot(id);
    55   gameStateMap.insert(std::pair<int, GameState*>(id, reference));
    56   gameStateUsed[id]=0;
    57   ++id;
    58   return;
    59 }
    60 
    61 GameStateCompressed GameStateManager::popGameState(int clientID){
    62   int gID = head_->findClient(clientID)->getGamestateID();
    63   std::cout << "popgamestate: sending gstate id: " << id << "diffed from: " << gID << std::endl;
    64   if(gID!=GAMESTATEID_INITIAL){
    65     GameState *client = gameStateMap[gID];
    66     GameState *server = reference;
    67     //head_->findClient(clientID)->setGamestateID(id);
    68     return encode(client, server);
    69   } else {
    70     GameState *server = reference;
    71     //head_->findClient(clientID)->setGamestateID(id);
    72     return encode(server);
    73     // return an undiffed gamestate and set appropriate flags
    74   }
    75 }
    76 
    77 
    78 
    79 /**
    80  * This function goes through the whole list of synchronisables and
    81  * saves all the synchronisables to a flat "list".
    82  * @return struct of type gamestate containing the size of the whole gamestate and a pointer linking to the flat list
    83  */
    84 GameState *GameStateManager::getSnapshot(int id)
    85 {
    86   //the size of the gamestate
    87   int totalsize=0;
    88   int memsize=1000;
    89   //the size of one specific synchronisable
    90   int tempsize=0;
    91   // get the start of the Synchronisable list
    92   orxonox::Iterator<Synchronisable> it;
    93   // struct for return value of Synchronisable::getData()
    94   syncData sync;
    95 
    96   GameState *retval=new GameState; //return value
    97   retval->id=id++;
    98   std::cout << "producing gamestate with id: " << retval->id << std::endl;
    99   // reserve a little memory and increase it later on
    100   //COUT(2) << "mallocing" << std::endl;
    101   retval->data = (unsigned char*)malloc(memsize);
    102   //COUT(2) << "malloced" << std::endl;
    103 
    104   // offset of memory functions
    105   int offset=0;
    106   // go through all Synchronisables
    107   for(it = orxonox::ObjectList<Synchronisable>::start(); it != 0; ++it){
    108     //std::cout << "gamestatemanager: in for loop" << std::endl;
    109     //get size of the synchronisable
    110     tempsize=it->getSize();
    111     //std::cout << "size of temp gamestate: " << tempsize << std::endl;
    112     //COUT(2) << "size of synchronisable: " << tempsize << std::endl;
    113     // add place for data and 3 ints (length,classid,objectid)
    114     totalsize+=tempsize+3*sizeof(int);
    115     //std::cout << "totalsize: " << totalsize << std::endl;
    116     // allocate additional space
    117     if(totalsize+tempsize>memsize){
    118       if(tempsize<1000){
    119         retval->data = (unsigned char *)realloc((void *)retval->data, totalsize+1000);
    120         memsize+=1000;
    121       } else {
    122         retval->data = (unsigned char *)realloc((void *)retval->data, totalsize+1000);
    123         memsize+=tempsize+1000;
    124       }
    125     }
    126 
    127     // run Synchronisable::getData with offset and additional place for 3 ints in between (for ids and length)
    128     sync=it->getData((retval->data)+offset+3*sizeof(int));
    129     *(retval->data+offset)=sync.length;
    130     *(retval->data+offset+sizeof(int))=sync.objectID;
    131     *(retval->data+offset+2*sizeof(int))=sync.classID;
    132     // increase data pointer
    133     offset+=tempsize+3*sizeof(int);
    134   }
    135   retval->size=totalsize;
    136   return retval;
    137 }
    138 
    139 
    140 
    141 GameStateCompressed GameStateManager::encode(GameState *a, GameState *b){
    142   //GameState r = diff(a,b);
    143   //r.diffed = true;
    144   GameState r = *b;
    145   r.diffed = false;
    146   return compress_(&r);
    147 }
    148 
    149 GameStateCompressed GameStateManager::encode(GameState *a){
    150   a->diffed=false;
    151   return compress_(a);
    152 }
    153 
    154 GameState GameStateManager::diff(GameState *a, GameState *b){
    155   unsigned char *ap = a->data, *bp = b->data;
    156   int of=0; // pointers offset
    157   int dest_length=0;
    158   if(a->size>=b->size)
    159     dest_length=a->size;
    160   else
    161     dest_length=b->size;
    162   unsigned char *dp = (unsigned char *)malloc(dest_length*sizeof(unsigned char));
    163   while(of<a->size && of<b->size){
    164     *(dp+of)=*(ap+of)^*(bp+of); // do the xor
    165     ++of;
    166   }
    167   if(a->size!=b->size){ // do we have to fill up ?
    168     unsigned char n=0;
    169     if(a->size<b->size){
    170       while(of<dest_length){
    171         *(dp+of)=n^*(bp+of);
    172         of++;
    173       }
    174     } else{
    175       while(of<dest_length){
    176         *(dp+of)=*(ap+of)^n;
    177         of++;
    178       }
    179     }
    180   }
    181   // should be finished now
    182   GameState r = {b->id, dest_length, dp};
    183   return r;
    184 }
    185 
    186 GameStateCompressed GameStateManager::compress_(GameState *a) {
    187   //COUT(2) << "compressing gamestate" << std::endl;
    188   int size = a->size;
    189   uLongf buffer = (uLongf)((a->size + 12)*1.01)+1;
    190   unsigned char* dest = (unsigned char*)malloc( buffer );
    191   int retval;
    192   //std::cout << "before ziped " << buffer << std::endl;
    193   retval = compress( dest, &buffer, a->data, (uLong)size );
    194   //std::cout << "after ziped " << buffer << std::endl;
    195 
    196   switch ( retval ) {
    197   case Z_OK: std::cout << "successfully compressed" << std::endl; break;
    198   case Z_MEM_ERROR: std::cout << "not enough memory available" << std::endl; break;
    199   case Z_BUF_ERROR: std::cout << "not enough memory available in the buffer" << std::endl; break;
    200   case Z_DATA_ERROR: std::cout << "decompress: data corrupted" << std::endl; break;
    201   }
    202 
    203   GameStateCompressed compressedGamestate;
    204   compressedGamestate.compsize = buffer;
    205   //std::cout << "compressedGamestate.compsize = buffer; " << buffer << std::endl;
    206   compressedGamestate.normsize = size;
    207   //std::cout << "compressedGamestate.normsize = size; " << size << std::endl;
    208   compressedGamestate.id = a->id;
    209   compressedGamestate.data = dest;
    210   compressedGamestate.diffed = a->diffed;
    211 
    212   return compressedGamestate;
    213 }
    214 
    215 void GameStateManager::ackGameState(int clientID, int gamestateID){
    216   ClientInformation *temp = head_->findClient(clientID);
    217   int curid = temp->getID();
    218   // decrease usage of gamestate and save it
    219   deleteUnusedGameState(curid);
    220   //increase gamestateused
    221   ++gameStateUsed.find(gamestateID)->second;
    222   temp->setGamestateID(gamestateID);
    223   /*
    224   GameState *old = clientGameState[clientID];
    225   deleteUnusedGameState(old);
    226   clientGameState[clientID]=idGameState[gamestateID];*/
    227 }
    228 
    229 bool GameStateManager::deleteUnusedGameState(int gamestateID){
    230   int used = --(gameStateUsed.find(gamestateID)->second);
    231   if(id-gamestateID>KEEP_GAMESTATES && used==0){
    232     // delete gamestate
    233     delete gameStateMap.find(gamestateID)->second;
    234     gameStateMap.erase(gamestateID);
    235     return true;
    236   }
    237   return false;
    238 }
    239 
    240 }
    241 
    242 
Note: See TracChangeset for help on using the changeset viewer.