Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
mmorpgclient.cpp
Go to the documentation of this file.
1 #include "command.h"
2 #include "mmorpgclient.h"
3 #include "SDL/SDL.h"
4 #include "SDL_thread.h"
5 #include "vegastrike.h"
6 #include "vs_globals.h"
7 
8 //#ifdef WIN32
9 //#include <winsock.h> // For socket(), connect(), send(), and recv()
10 //typedef int socklen_t;
11 //#else
12 //#include <sys/types.h> // For data types
13 //#include <sys/socket.h> // For socket(), connect(), send(), and recv()
14 //#include <netdb.h> // For gethostbyname()
15 //#include <arpa/inet.h> // For inet_addr()
16 //#include <unistd.h> // For close()
17 //#include <netinet/in.h> // For sockaddr_in
18 //#endif
19 #include "networking/inet.h"
20 
21 //This is created in command.cpp with single like (search for mmoc)
22 //If you wish to disable this module, just comment out that single line in command.cpp,
23 //and don't compile this .cpp file.
24 
26 {
27  //{{{
28  status = false; //used to let the thread exit
29  binmode = false;
30  POSmode = false;
31  INET_startup();
32  //add the connectto to the players command interp.
33  cmd = new Functor< mmoc > ( this, &mmoc::connectTo );
34  CommandInterpretor->addCommand( cmd, "connectto" );
35  //{{{
36  //add commands here to be parsed from network input.
37  //some notes:
38  //just make them like normal, and the word "FOO" will be the "tag" that triggers it.
39  //eg: the server sends <FOO>args</FOO>, the input routines will parse it to:
40  //FOO , and try sending it through the LOCAL command processor (NOT the main one used for the player console).
41 
42  //now some notes more to myself
43  //The users console at the highest level (in the main ship rendering routines) will need to gather data from the mmoc console to render it there.
44  //and never call mmoc::renderconsole. I'll need to make a mutex'd function for this.
45  //}}}
46 } //}}}
47 void mmoc::connectTo( const char *address_in, const char *port_in )
48 {
49  //{{{
50 //sockaddr_in m_addr;
51  char *address = (char*) address_in;
52  char *port = (char*) port_in;
53  if (address == NULL) {
54  CommandInterpretor->conoutf( "Need a host at least, a host and port at most!" );
55  return;
56  }
57  if (port == NULL)
58  port = "5555";
59  std::string test;
60  test.append( address );
61  if (test.compare( "default" ) == 0) {
62  address = "ant.infice.com";
63  port = "5555";
64  }
65  if ( ( socket = INET_ConnectTo( address, atoi( port ) ) ) < 0 ) {
66  CommandInterpretor->conoutf( "Error connecting. Specify another host or verify the status if your network connection." );
67  return;
68  }
69 //hostent *server; // Resolve name
70 //if ((server = gethostbyname(address)) == NULL) {
71 //CommandInterpretor->conoutf("Error, couldn't find host");
72  //strerror() will not work for gethostbyname() and hstrerror()
73  //is supposedly obsolete
74 //return;
75 //}
76 
77 //bzero((char *) &m_addr, sizeof(m_addr));
78 //m_addr.sin_family = AF_INET;
79 //bcopy((char *)server->h_addr,
80 //(char *)&m_addr.sin_addr.s_addr,
81 //server->h_length);
82 //m_addr.sin_port = htons(atoi(port));
83 //int status = 0;
84 
85 //if ( (status = ::connect(socket,reinterpret_cast<sockaddr *>(&m_addr),sizeof(m_addr))) < 0) {
86 //CommandInterpretor->conoutf("Couldn't Connect\n");
87 //return;
88 //}
89  std::string hellomsg;
90  hellomsg.append( "Vegastrike-user" );
91  send( hellomsg );
92  cl = new Functor< mmoc > ( this, &mmoc::close );
93  CommandInterpretor->addCommand( cl, "disconnect" );
94 
95  csay = new Functor< mmoc > ( this, &mmoc::send );
97 
98  createThread();
99 } //}}}
100 bool mmoc::getStatus( int in )
101 {
102  //{{{
103 //if in = 0, return status, else toggle status.
104  SDL_mutex *m = SDL_CreateMutex();
105  SDL_mutexP( m );
106  if (in != 0)
107  status = !status;
108  bool returner = status;
109  SDL_mutexV( m );
110  SDL_DestroyMutex( m );
111  return returner;
112 } //}}}
113 void mmoc::ParseRemoteInput( char *buf )
114 {
115  //{{{ Main parser
116 //add binary modes here.
117  if (buf != NULL)
118  start.append( buf );
119  size_t teststart;
120  if ( ( teststart = start.find( "\n" ) ) < std::string::npos ) {
121  //we have a full string and are ready to process
122  if (teststart < start.size()-2) {
123  for (unsigned int soda = teststart+1; soda < start.size(); soda++)
124  tempstr += start[soda];
125  while (start.size() > teststart) {
126  std::string::iterator iter = start.end();
127  iter--;
128  start.erase( iter ); //pop goes the weasle
129  }
130  }
131  } else {
132 //return;
133  }
134  unsigned int end = start.size();
135  std::string hackedup;
136  bool open = false, ignore2close = false;
137  unsigned int fopend = 0;
138  unsigned int counter;
139  //parse commands to be executed <FOO=BAR>
140  for (counter = 0; counter < end; counter++) {
141  if (open) {
142  if (start[counter] == '=') {hackedup.append( "\" " ); } else if (start[counter] == '>') {
143  open = false;
144  start.replace( fopend, (counter+1)-fopend, "" );
145  unsigned int offset = (counter+1)-fopend;
146  counter = counter-offset;
147  commandI::execute( &hackedup, true, socket );
148  hackedup.erase();
149  end = start.size();
150  } else {
151  hackedup += start[counter];
152  }
153  } else if (start[counter] == '<') {
154  open = true;
155  fopend = counter;
156  hackedup.append( "\"" );
157  }
158  }
159  //optimize by moving this above.
160  unsigned int ender = start.size();
161  for (counter = 0; counter < ender; counter++) //remove \r's
162  if (start[counter] == '\r') {
163  start.replace( counter, 1, "" );
164  counter = counter-2;
165  ender = start.size();
166  }
167  CommandInterpretor->conoutf( start ); //print what's left to the console
168 
169  start.erase();
170  if (tempstr.size() > 0) {
171  start.append( tempstr );
172  tempstr.erase();
173  }
174  {
175  size_t asdf;
176  while ( ( asdf = start.find( "\n" ) ) < std::string::npos )
177  ParseRemoteInput( NULL );
178 //if(start.size() > 0 ) {
179 //start.append("\n\r");
180 //ParseRemoteInput(NULL);
181 //}
182  }
183 } //}}}
184 class POSpack
185 {
186 public:
187  int playernum; //who's position is this
188  double x, y, z; //the position
189 };
191 {
192  //{{{
193  const int MAXBUF = 1000;
194  char buffer[MAXBUF+1];
195  bool stat;
196  while ( ( stat = getStatus( 0 ) ) == true ) {
197  bzero( buffer, MAXBUF );
198  if (!binmode) {
199  if (::INET_Recv( socket, buffer, sizeof (buffer)-1 ) <= 0) {
200  getStatus( 1 ); //1 toggles status, 0 reads status
201  return false;
202  } else {
203  ParseRemoteInput( buffer );
204  }
205  }
206  if (binmode) {
207  if (POSmode) {
208  //if Position mode
209  POSpack position;
210  if (::INET_Read( socket, reinterpret_cast< char* > (&position), sizeof (POSpack) ) <= 0) {
211  //I believe INET_Read will keep looping until size is filled
212  getStatus( 1 ); //toggle status
213  return false;
214  }
215  ParseMovement( position );
216  POSmode = false;
217  }
218  //other bin modes
219  binmode = false; //done
220  }
221  }
222  /*---Clean up---*/
223  return stat;
224 } //}}}
226 {
227  //{{{
228  ::SDL_CreateThread( startThread, reinterpret_cast< void* > (this) );
229 } //}}}
230 void mmoc::send( char *buffer, int size )
231 {
232  //{{{
233  ::INET_Write( socket, size, buffer ); //or write(socket, buffer, size) for windwos?
234 } //}}}
235 void mmoc::send( std::string &instring )
236 {
237  //{{{
238  unsigned int x = instring.find( "send " );
239  if (x == 0) instring.replace( 0, 5, "" );
240  instring.append( "\r\n" );
241  send( (char*) instring.c_str(), instring.size() );
242 } //}}}
243 void mmoc::negotiate( std::vector< std::string* > *d )
244 {
245  std::vector< std::string* >::iterator iter = d->begin();
246  iter++;
247  if ( iter >= d->end() ) return; //nothing to negotiate
248  if ( ( *(iter) )->compare( "P" ) ) {
249  binarysize = sizeof (POSpack);
250  //check the next iterator for a number (X), if there is one
251  //set it up to loop in the listenThread() to read X Position packets
252  binmode = true;
253  POSmode = true;
254  std::string ack;
255  ack.append( "ap" ); //ack position, tell the server to send it
256  send( ack );
257  }
258 }
260 {
261  //.....
262 }
263 int startThread( void *mmoc2use )
264 {
265  //{{{
266  mmoc *looper = reinterpret_cast< mmoc* > (mmoc2use);
267  if ( !looper->getStatus( 0 ) ) looper->getStatus( 1 );
268  CommandInterpretor->conoutf( "Connected." );
269  while ( looper->listenThread() )
270  ;
271  ::close( looper->getSocket() );
272  CommandInterpretor->remCommand( looper->csay );
273  CommandInterpretor->remCommand( looper->cl );
274  CommandInterpretor->conoutf( "Closed" );
275  if ( looper->getStatus( 0 ) ) looper->getStatus( 1 );
276  return 0;
277 } //}}}
279 {
280  if ( getStatus( 0 ) )
281  getStatus( 1 );
282 }
283 void mmoc::conoutf( std::string &in, int x, int y, int z )
284 {
285  CommandInterpretor->conoutf( in, x, y, z );
286 }
287 /*
288  * Local variables:
289  * tab-width: 4
290  * c-basic-offset: 4
291  * End:
292  * vim600: sw=4 ts=4 fdm=marker
293  * vim<600: sw=4 ts=4
294  */
295