<?php

class ettvd {
   var $ip       = '';         // ettvd ip
   var $port     = 0;          // ettvd port
   var $password = '';         // guess what?

   var $connection = 0;        // handle returned from fsockopen
   var $connected  = false;    // true if we could connect & authenticate
   var $buffer     = array();  // each array element contains one recieved line

   var $lastcode  = 0;         // last status code recieved from ettvd
   var $lasterror = '';        // last error string from ettvd

   var $start = 0;
   var $time  = 0;

   var $replayers = array();
   var $recorders = array();

   function ettvd($ip, $port, $pass, $connect = false) {
      $this->ip       = $ip;
      $this->port     = intval($port);
      $this->password = $pass;

      if($connect) {
         return $this->init();
      }
   }

   function __destruct() {
      if($this->connected) @fclose($this->connection);
   }

   function addqueue($replayer, $demo) {
      $this->send('addqueue '.intval($replayer).' '.intval($demo));
      if($this->lastcode == 141) {
         return true;
      } else {
         error();
      }
   }

   function autodisconnect($recorder, $disc) {
      $this->send("autodisc $recorder $disc");
      if($this->lastcode == 128) {
         return true;
      } else {
         error();
      }
   }

   function autoreplaynum($replayer, $count) {
      $this->send('autoreplaynum '.intval($replayer).' '.intval($count));
      if($this->lastcode == 118) {
         return true;
      } else {
         error();
      }
   }

   function broadcast($ip, $pass, $ettvpass, $gamename, $autodisconnect, $recmode, $readynum = 4, $slaveslots = 0, $replayerid = false) {
      $rec = $this->connect($ip, $pass, $ettvpass, $slaveslots);
      $this->gamename($rec, $gamename);
      $this->recmode($rec, $recmode);
      if($recmode == 'ready' && $readynum != 4) $this->readynum($rec, $readynum);
      if(!$autodisconnect) $this->autodisconnect($rec, 0);
      if($replayerid) $this->livecast($rec, $replayerid);
      return $rec;
   }

   function connect($ip, $pass, $ettvpass, $slaves = 0) {
      $this->send("connect $ip $pass $ettvpass $slaves");
      if($this->lastcode == 123) {
         $lastline = array_pop($this->buffer);
         list(,$recorderid) = explode(' ', $lastline, 3);
         return intval($recorderid);
      } else {
         error();
      }
   }

   function delqueue($replayer) {
      $this->send('delqueue '.intval($replayer));
      if($this->lastcode == 142) {
         return true;
      } else {
         error();
      }
   }

   function demolist() {
      global $datestyle;
      $demos = array();
      foreach($this->buffer AS $line) {
         list($code, $demoid) = explode(' ', $line, 3);
         if($code == 308 || $code == 314) {
            $demo = array();
            $nfo = explode(' | ', $line);

            $demo['id']   = intval($demoid);
            $demo['name'] = trim($nfo[2]);
            $demo['maps'] = intval($nfo[3]);

            list($date, $time)   = explode('-', trim($nfo[1]));
            list($year, $month, $day) = explode('.', $date);
            list($time, $recid)  = explode('_', $time);
            list($hour, $minute) = explode('.', $time);
            $demo['time'] = mktime($hour, $minute, 0, $month, $day, $year);

            $demo['rec']  = intval($recid);

            $demos[] = $demo;
         }
      }
      return $demos;
   }

   function fetch_demos() {
      $this->send('demolist');
      if($this->lastcode == 109) {
         return $this->demolist();
      } else {
         error();
      }
   }

   function fetch_playlist($replayer) {
      $this->send('listqueue '.intval($replayer));
      if($this->lastcode == 120 || $this->lastcode == 121) {
         return $this->demolist();
      } else {
         error();
      }
   }

   function fetch_replayers() {
      $this->replayers = array();
      $this->send('replist');
      foreach($this->buffer AS $line) {
         list($code, $proc) = explode(' ', $line, 3);
         if($code == 323) {
            $server = array();
            $nfo = explode(' | ', $line);

            $server['procid']      = intval($proc);
            $server['num']         = intval($nfo[1]);
            $server['path']        = trim($nfo[2]);
            $server['demo']        = trim($nfo[3]);
            $server['ip']          = trim($nfo[4]);
            $server['inc']         = intval($nfo[5]);
            $server['mapcount']    = intval($nfo[6]) + 1;
            $server['gameid']      = intval($nfo[7]);
            $server['warmup']      = (intval($nfo[8])) ? 'Yes' : 'No';
            $server['round']       = intval($nfo[9]);
            $server['viewers']     = intval($nfo[10]);
            $server['islive']      = intval($nfo[11]);
            $server['slots']       = intval($nfo[12]);
            $server['privslots']   = intval($nfo[13]);
            $server['config']      = intval($nfo[14]);
            $server['pissed']      = intval($nfo[15]);
            $server['autoreplay']  = intval($nfo[16]);
            $server['replaydelay'] = intval($nfo[17]);
            $server['repeatqueue'] = intval($nfo[18]);

            $this->replayers[$server['num']] = $server;
         }
      }
      return $this->replayers;
   }

   function fetch_recorders() {
      $this->recorders = array();
      $this->send('reclist');
      foreach($this->buffer AS $line) {
         list($code, $proc) = explode(' ', $line, 3);
         if($code == 322) {
            $server = array();
            $nfo = explode(' | ', $line);

            $server['procid']       = intval($proc);
            $server['num']          = intval($nfo[1]);
            $server['master']       = trim($nfo[2]);
            $server['gamename']     = trim($nfo[3]);
            $server['mapcount']     = intval(trim($nfo[5])) + 1;
            $server['recmode']      = trim($nfo[6]);
            $server['gameid']       = intval($nfo[7]);
            $server['warmup']       = intval($nfo[8]);
            $server['round']        = intval($nfo[9]);
            $server['recstatus']    = trim($nfo[10]);
            $server['connected']    = intval($nfo[11]);
            $server['players']      = intval($nfo[12]);
            $server['readyplayers'] = intval($nfo[13]);
            $server['startcount']   = intval($nfo[14]);
            $server['pissed']       = intval($nfo[15]);
            $server['autodisc']     = intval($nfo[16]);
            $server['readynum']     = intval($nfo[17]);

            if($nfo[4]) {
               $reps = explode(',', $nfo[4]);
               foreach($reps AS $rep) {
                  $rep = intval($rep);
                  if(isset($this->replayers[$rep])) {
                     $server['broadcaster'][$rep] =& $this->replayers[$rep];
                  } else {
                     $server['broadcaster'][$rep] = array();
                  }
               }
            } else {
               $server['broadcaster'] = array();
            }

            $this->recorders[$server['num']] = $server;
         }
      }
   }

   function fetch_servers() {
      $this->fetch_replayers();
      $this->fetch_recorders();
   }

   function fetch_viewerlist($repid) {
      $this->send('viewerlist '.intval($repid));
      if($this->lastcode == 401) {
         return false;
      } elseif($this->lastcode == 109) {
         $viewers = array();
         foreach($this->buffer AS $line) {
            list($code, $pid) = explode(' ', $line, 3);
            if($code == 313) {
               $nfo = explode(' | ', $line);
               $user = array();
               $user['pid']     = intval($pid);
               $user['nick']    = fixetcolors(trim($nfo[1]));
               $user['ip']      = trim($nfo[2]);
               $user['uid']     = intval($nfo[3]);
               $user['visits']  = intval($nfo[4]);

               $viewers[] = $user;
            }
         }
      }
      return $viewers;
   }

   function find_replayer($port) {
      $this->send('replist');
      foreach($this->buffer AS $line) {
         list($code) = explode(' ', $line, 2);
         if($code == 323) {
            list(,$replayerid,,,$ip) = explode(' | ', $line, 6);
            list(,$repport) = explode(':', $ip);
            if($repport != $port) continue;
            return intval($replayerid);
         }
      }
      return false;
   }

   function gamename($id, $name = 'no name given') {
      $this->send("gamename $id $name");
      if($this->lastcode == 105) {
         return true;
      } else {
         error();
      }
   }

   function hopserver($recorder, $ip, $serverpass, $ettvpass) {
      $this->send("hopserver $recorder $ip $serverpass $ettvpass");
      if($this->lastcode == 123) {
         return true;
      } else {
         error();
      }
   }

   function init() {
      if(!$fp = @fsockopen($this->ip, $this->port, $errno, $errstr, 15)) {
         error("Error Connecting to the ETTVd Daemon ($errno):<br />$errstr");
      } else {
         $this->connection = $fp;
         $this->errno  = 0;
         $this->errstr = '';

         $this->send($this->password);
         if($this->lastcode == 111) {
            $this->connected = true;
            return true;
         }
      }
      error("Error Connecting to the ETTVd Daemon:<br />Wrong password given OR ip not on the trusted list.");
   }

   function dellive($recorder, $replayer) {
      $this->send('dellive '.$recorder.' '.$replayer);
      if($this->lastcode == 126) {
         return true;
      } else {
         error();
      }
   }

   function killproc($procid) {
      $this->send("killproc $procid");
      if($this->lastcode == 176) {
         return true;
      } else {
         error();
      }
   }

   function livecast($recorder, $replayer) {
      $recorder = intval($recorder);
      $replayers = array();
      if(is_string($replayer)) {
         $replayers[] = $replayer;
      } else {
         $replayers = $replayer;
      }
      if(is_array($replayers)) {
         foreach($replayers AS $replayer) {
            $this->send("livecast $recorder ".intval($replayer));
            if($this->lastcode != 106) {
               error();
            }
         }
      } else {
         return false;
      }
      return true;
   }

   function newdemo($recorder, $matchname, $recmode = 'ready', $autodisconnect = 1) {
      if($this->stoprecord($recorder)) {
         if($this->gamename($recorder, $matchname)) {
            if($this->recmode($recorder, $recmode)) {
               if($this->autodisconnect($recorder, $autodisconnect)) {
                  return true;
               }
            }
         }
      }
   }

   function playgame($replayer, $demo) {
      $this->send('playgame '.intval($replayer).' '.intval($demo));
      if($this->lastcode == 117) {
         return true;
      } else {
         error();
      }
   }

   function read() {
      $this->buffer = array();
      while(1) {
         $in = fgets($this->connection, 512);
         list($code) = explode(' ', $in, 2);
         if(($code < 200) OR ($code > 399)) {
            $this->buffer[] = trim($in);
            break;
         } else {
            $this->buffer[] = trim($in);
         }
      }
      $this->lastcode = $code;
      $this->time += microtime_float() - $this->start;
   }

   function readynum($recorder, $num) {
      $this->send("readynum $recorder $num");
      if($this->lastcode == 129) {
         return true;
      } else {
         error();
      }
   }

   function recmode($recorder, $recmode) {
      $this->send("recordmode $recorder $recmode");
      if($this->lastcode == 104) {
         return true;
      } else {
         error();
      }
   }

   function reload_demolist() {
      $this->send('reloaddemos');
      if($this->lastcode == 107) {
         return true;
      } else {
         error();
      }
   }

   function repeatqueue($replayer, $mode) {
      $this->send('repeatqueue '.intval($replayer).' '.intval($mode));
      if($this->lastcode == 143) {
         return true;
      } else {
         error();
      }
   }

   function send($str) {
      $this->start = microtime_float();
      fputs($this->connection, "$str\n");
      $this->read();
   }

   function spawn_replayer($slots, $port, $privslots, $demo, $config) {
      $send = 'broadcast ';
      if(!empty($slots)) {
         $send .= intval($slots);
         if(!empty($port)) {
            $send .= ' '.intval($port);
            if(!empty($privslots)) {
               $send .= ' '.intval($privslots);
               if(!empty($demo)) {
                  $send .= ' '.intval($demo);
                  if(!empty($config)) {
                     $send .= ' '.$config;
                  }
               }
            }
         }
         $this->send($send);
         if($this->lastcode == 124) {
            $lastline = array_pop($this->buffer); array_push($this->buffer, $lastline);
            list(,$id) = explode(' ', $lastline, 3);
            return intval($id);
         } else {
            error();
         }
      }
      return false;
   }

   function stoprecord($recorder) {
      $this->send('stoprecord '.$recorder);
      if($this->lastcode == 103) {
         return true;
      } else {
         error();
      }
   }
}

?>