FS2_Open
Open source remastering of the Freespace 2 engine
multimsgs.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (C) Volition, Inc. 1999. All rights reserved.
3  *
4  * All source code herein is the property of Volition, Inc. You may not sell
5  * or otherwise commercially exploit the source or things you created based on the
6  * source.
7  *
8 */
9 
10 
11 
12 
13 #include <limits.h>
14 
15 #include "globalincs/pstypes.h"
16 #include "network/multimsgs.h"
17 #include "network/multiutil.h"
18 #include "network/multiui.h"
19 #include "network/multi.h"
20 #include "globalincs/linklist.h"
22 #include "hud/hudmessage.h"
23 #include "hud/hudsquadmsg.h"
24 #include "freespace2/freespace.h"
25 #include "io/timer.h"
26 #include "mission/missiongoals.h"
27 #include "mission/missionlog.h"
28 #include "mission/missionmessage.h"
29 #include "network/stand_gui.h"
30 #include "gamesnd/gamesnd.h"
31 #include "ship/shiphit.h"
32 #include "render/3d.h"
33 #include "playerman/player.h"
34 #include "debris/debris.h"
37 #include "ship/shipfx.h"
38 #include "popup/popup.h"
39 #include "network/multi_ingame.h"
41 #include "ai/aigoals.h"
42 #include "network/multi_campaign.h"
43 #include "network/multi_team.h"
44 #include "network/multi_respawn.h"
45 #include "network/multi_observer.h"
46 #include "asteroid/asteroid.h"
47 #include "network/multi_pmsg.h"
48 #include "object/object.h"
49 #include "ship/ship.h"
50 #include "weapon/weapon.h"
51 #include "hud/hudreticle.h"
52 #include "network/multi_pause.h"
53 #include "network/multi_endgame.h"
55 #include "network/multi_log.h"
56 #include "weapon/emp.h"
57 #include "network/multi_kick.h"
58 #include "cmdline/cmdline.h"
59 #include "weapon/flak.h"
60 #include "weapon/beam.h"
61 #include "network/multi_rate.h"
62 #include "nebula/neblightning.h"
63 #include "hud/hud.h"
66 #include "network/multi_log.h"
67 #include "object/objectdock.h"
68 #include "cmeasure/cmeasure.h"
69 #include "parse/sexp.h"
70 #include "fs2netd/fs2netd_client.h"
71 #include "network/multi_sexp.h"
72 
73 // #define _MULTI_SUPER_WACKY_COMPRESSION
74 
75 #ifdef _MULTI_SUPER_WACKY_COMPRESSION
76 #define BITS 15
77 #define MAX_CODE ( ( 1 << BITS ) - 1 )
78 #define TABLE_SIZE 35023L
79 #define END_OF_STREAM 256
80 #define BUMP_CODE 257
81 #define FLUSH_CODE 258
82 #define FIRST_CODE 259
83 #define UNUSED -1
84 
85 typedef struct {
86  int code_value;
87  int parent_code;
88  char character;
89 } DICTIONARY;
90 
91 static DICTIONARY dict[TABLE_SIZE];
92 static char decode_stack[TABLE_SIZE];
93 static uint next_code;
94 static int current_code_bits;
95 static uint next_bump_code;
96 
97 typedef struct BitBuf {
98  ubyte mask;
99  int rack;
100  ubyte *data;
101 } BitBuf;
102 
103 void output_bits( BitBuf *bitbuf, uint code, int count )
104 {
105  uint mask;
106 
107  mask = 1L << ( count - 1 );
108  while ( mask != 0) {
109  if ( mask & code )
110  bitbuf->rack |= bitbuf->mask;
111  bitbuf->mask >>= 1;
112  if ( bitbuf->mask == 0 ) {
113  *bitbuf->data++=(ubyte)bitbuf->rack;
114  bitbuf->rack = 0;
115  bitbuf->mask = 0x80;
116  }
117  mask >>= 1;
118  }
119 }
120 
121 uint input_bits( BitBuf *bitbuf, int bit_count )
122 {
123  uint mask;
124  uint return_value;
125 
126  mask = 1L << ( bit_count - 1 );
127  return_value = 0;
128  while ( mask != 0) {
129  if ( bitbuf->mask == 0x80 ) {
130  bitbuf->rack = *bitbuf->data++;
131  if ( bitbuf->rack == EOF )
132  return END_OF_STREAM;
133  }
134  if ( bitbuf->rack & bitbuf->mask )
135  return_value |= mask;
136  mask >>= 1;
137  bitbuf->mask >>= 1;
138  if ( bitbuf->mask == 0 )
139  bitbuf->mask = 0x80;
140  }
141  return( return_value );
142 }
143 
144 
145 static void InitializeDictionary()
146 {
147  uint i;
148 
149  for ( i = 0 ; i < TABLE_SIZE ; i++ )
150  dict[i].code_value = UNUSED;
151 
152  next_code = FIRST_CODE;
153  current_code_bits = 9;
154  next_bump_code = 511;
155 
156 }
157 
158 static uint find_child_node( int parent_code, int child_character )
159 {
160  uint index;
161  int offset;
162 
163  index = ( child_character << ( BITS - 8 ) ) ^ parent_code;
164  if ( index == 0 )
165  offset = 1;
166  else
167  offset = TABLE_SIZE - index;
168  for ( ; ; ) {
169  if ( dict[ index ].code_value == UNUSED )
170  return( (uint) index );
171  if ( dict[ index ].parent_code == parent_code &&
172  dict[ index ].character == (char) child_character )
173  return( index );
174  if ( (int) index >= offset )
175  index -= offset;
176  else
177  index += TABLE_SIZE - offset;
178  }
179 }
180 
181 
182 static uint decode_string( uint count, uint code )
183 {
184  while ( code > 255 ) {
185  decode_stack[ count++ ] = dict[ code ].character;
186  code = dict[ code ].parent_code;
187  }
188  decode_stack[ count++ ] = (char) code;
189  return( count );
190 }
191 
192 int lzw_compress( ubyte *outputbuf, ubyte *inputbuf, int input_size )
193 {
194  BitBuf output;
195  int character;
196  int string_code;
197  uint index;
198  int i;
199 
200  // Init output bit buffer
201  output.rack = 0;
202  output.mask = 0x80;
203  output.data = outputbuf;
204 
205  InitializeDictionary();
206 
207  string_code = *inputbuf++;
208 
209  for ( i=1 ; i<input_size ; i++ ) {
210  character = *inputbuf++;
211  index = find_child_node( string_code, character );
212  if ( dict[ index ].code_value != - 1 )
213  string_code = dict[ index ].code_value;
214  else {
215  dict[ index ].code_value = next_code++;
216  dict[ index ].parent_code = string_code;
217  dict[ index ].character = (char) character;
218  output_bits( &output, (unsigned long) string_code, current_code_bits );
219  string_code = character;
220  if ( next_code > MAX_CODE ) {
221  output_bits( &output, (unsigned long) FLUSH_CODE, current_code_bits );
222  InitializeDictionary();
223  } else if ( next_code > next_bump_code ) {
224  output_bits( &output, (unsigned long) BUMP_CODE, current_code_bits );
225  current_code_bits++;
226  next_bump_code <<= 1;
227  next_bump_code |= 1;
228  }
229  }
230  }
231  output_bits( &output, (unsigned long) string_code, current_code_bits );
232  output_bits( &output, (unsigned long) END_OF_STREAM, current_code_bits);
233 
234  if ( output.mask != 0x80 )
235  *output.data++ = (ubyte)output.rack;
236 
237  return output.data-outputbuf;
238 }
239 
240 
241 int lzw_expand( ubyte *outputbuf, ubyte *inputbuf )
242 {
243  BitBuf input;
244  uint new_code;
245  uint old_code;
246  int character;
247  uint count;
248  uint counter;
249 
250  input.rack = 0;
251  input.mask = 0x80;
252  input.data = inputbuf;
253 
254  counter = 0;
255  for ( ; ; ) {
256  InitializeDictionary();
257  old_code = (uint) input_bits( &input, current_code_bits );
258  if ( old_code == END_OF_STREAM )
259  return counter;
260  character = old_code;
261  outputbuf[counter++] = ( ubyte )old_code;
262  for ( ; ; ) {
263  new_code = (uint) input_bits( &input, current_code_bits );
264  if ( new_code == END_OF_STREAM )
265  return counter;
266  if ( new_code == FLUSH_CODE )
267  break;
268  if ( new_code == BUMP_CODE ) {
269  current_code_bits++;
270  continue;
271  }
272  if ( new_code >= next_code ) {
273  decode_stack[ 0 ] = (char) character;
274  count = decode_string( 1, old_code );
275  } else {
276  count = decode_string( 0, new_code );
277  }
278  character = decode_stack[ count - 1 ];
279  while ( count > 0 )
280  outputbuf[counter++] = ( ubyte )decode_stack[ --count ];
281  dict[ next_code ].parent_code = old_code;
282  dict[ next_code ].character = (char) character;
283  next_code++;
284  old_code = new_code;
285  }
286  }
287 }
288 #endif
289 
290 // process a join request packet add
292 {
293  int packet_size = *size;
294  join_request jr_tmp;
295 
296  memcpy(&jr_tmp, jr, sizeof(join_request));
297 
298  jr_tmp.tracker_id = INTEL_INT(jr->tracker_id);
301 
302  ADD_DATA(jr_tmp);
303 
304  *size = packet_size;
305 }
306 
307 // process a join request packet get
309 {
310  int offset = *size;
311 
312  GET_DATA(*jr);
313 
314  jr->tracker_id = INTEL_INT(jr->tracker_id); //-V570
317 
318  *size = offset;
319 }
320 
322 {
323  int packet_size = *size;
324  net_addr addr_tmp;
325 
326  memcpy(&addr_tmp, addr, sizeof(net_addr));
327 
328  addr_tmp.type = INTEL_INT(addr->type);
329  addr_tmp.port = INTEL_SHORT(addr->port);
330 
331  ADD_DATA(addr_tmp);
332 
333  *size = packet_size;
334 }
335 
337 {
338  int offset = *size;
339 
340  GET_DATA(*addr);
341 
342  addr->type = INTEL_INT(addr->type); //-V570
343  addr->port = INTEL_SHORT(addr->port); //-V570
344 
345  *size = offset;
346 }
347 /*
348 void add_vector_data(ubyte *data, int *size, vec3d vec)
349 {
350  int packet_size = *size;
351 
352  ADD_FLOAT(vec.xyz.x);
353  ADD_FLOAT(vec.xyz.y);
354  ADD_FLOAT(vec.xyz.z);
355 
356  *size = packet_size;
357 }
358 
359 void get_vector_data(ubyte *data, int *size, vec3d vec)
360 {
361  int offset = *size;
362 
363  GET_FLOAT(vec.xyz.x);
364  GET_FLOAT(vec.xyz.y);
365  GET_FLOAT(vec.xyz.z);
366 
367  *size = offset;
368 }
369 */
370 // send the specified data packet to all players
372 {
373  // invalid
374  if((pl == NULL) || (NET_PLAYER_NUM(pl) >= MAX_PLAYERS)){
375  return;
376  }
377 
378  // don't do it for single player
379  if(!(Game_mode & GM_MULTIPLAYER)){
380  return;
381  }
382 
383  // sanity checks
384  if(MULTIPLAYER_CLIENT){
385  // Assert(pl == Net_player);
386  if(pl != Net_player){
387  return;
388  }
389  } else {
390  // Assert(pl != Net_player);
391  if(pl == Net_player){
392  return;
393  }
394  }
395 
396  // If this packet will push the buffer over MAX_PACKET_SIZE, send the current send_buffer
397  if ((pl->s_info.unreliable_buffer_size + len) > MAX_PACKET_SIZE) {
400  }
401 
403 
404  memcpy(pl->s_info.unreliable_buffer + pl->s_info.unreliable_buffer_size, data, len);
406 }
407 
409 {
410  int i;
412 
413  // need to check for i > 1, hmmm... and connected. I don't know.
414  for (i = 0; i < MAX_PLAYERS; i++ ) {
415  if ( !MULTI_CONNECTED(Net_players[i]) || (Net_player == &Net_players[i])){
416  continue;
417  }
418 
419  // maybe ignore a player
420  if((ignore != NULL) && (&Net_players[i] == ignore)){
421  continue;
422  }
423 
424  // ingame joiners not waiting to select a ship doesn't get any packets
426  continue;
427  }
428 
429  // send it
430  multi_io_send(&Net_players[i], data, length);
431  }
432 }
433 
435 {
436  // invalid
437  if((pl == NULL) || (NET_PLAYER_NUM(pl) >= MAX_PLAYERS)){
438  return;
439  }
440 
441  // don't do it for single player
442  if(!(Game_mode & GM_MULTIPLAYER)){
443  return;
444  }
445 
446  // send everything in
447  if (MULTIPLAYER_MASTER) {
449 
450  // add the bytes sent to this player
452  } else {
454  }
456 }
457 
458 // send the data packet to all players via their reliable sockets
460 {
461  // invalid
462  if((pl == NULL) || (NET_PLAYER_NUM(pl) >= MAX_PLAYERS)){
463  return;
464  }
465 
466  // don't do it for single player
467  if(!(Game_mode & GM_MULTIPLAYER)){
468  return;
469  }
470 
471  // sanity checks
472  if(MULTIPLAYER_CLIENT){
473  // Assert(pl == Net_player);
474  if(pl != Net_player){
475  return;
476  }
477  } else {
478  // Assert(pl != Net_player);
479  if(pl == Net_player){
480  return;
481  }
482  }
483 
484  // If this packet will push the buffer over MAX_PACKET_SIZE, send the current send_buffer
485  if ((pl->s_info.reliable_buffer_size + len) > MAX_PACKET_SIZE) {
488  }
489 
491 
492  memcpy(pl->s_info.reliable_buffer + pl->s_info.reliable_buffer_size, data, len);
494 }
495 
497 {
498  int i;
500 
501  // need to check for i > 1, hmmm... and connected. I don't know.
502  for (i = 0; i < MAX_PLAYERS; i++ ) {
503  if ( !MULTI_CONNECTED(Net_players[i]) || (Net_player == &Net_players[i])){
504  continue;
505  }
506 
507  // maybe ignore a player
508  if((ignore != NULL) && (&Net_players[i] == ignore)){
509  continue;
510  }
511 
512  // ingame joiners not waiting to select a ship doesn't get any packets
514  continue;
515  }
516 
517  // send it
518  multi_io_send_reliable(&Net_players[i], data, length);
519  }
520 }
521 
523 {
524  // invalid
525  if((pl == NULL) || (NET_PLAYER_NUM(pl) >= MAX_PLAYERS)){
526  return;
527  }
528 
529  // don't do it for single player
530  if(!(Game_mode & GM_MULTIPLAYER)){
531  return;
532  }
533 
534  // send everything in
535  if(MULTIPLAYER_MASTER) {
537  } else if(Net_player != NULL){
539  }
541 }
542 
543 // send all buffered packets
545 {
546  int idx;
547 
548  // don't do it for single player
549  if(!(Game_mode & GM_MULTIPLAYER)){
550  return;
551  }
552 
553  // server
554  if(MULTIPLAYER_MASTER){
555  for(idx=0; idx<MAX_PLAYERS; idx++){
556  if(MULTI_CONNECTED(Net_players[idx]) && (Net_player != &Net_players[idx])){
557  // force unreliable data
558  if(Net_players[idx].s_info.unreliable_buffer_size > 0){
561  }
562 
563  // force reliable data
564  if(Net_players[idx].s_info.reliable_buffer_size > 0){
567  }
568  }
569  }
570  }
571  // clients
572  else if(Net_player != NULL){
573  // force unreliable data
577  }
578 
579  // force reliable data
583  }
584  }
585 }
586 
587 //*********************************************************************************************************
588 // Game Chat Packet
589 //*********************************************************************************************************
590 /*
591 struct fs2_game_chat_packet
592 {
593  char packet_signature; //0xC3
594  short from_player_id;
595  int server_msg;
596  char mode;
597 
598  // variable record
599  if (mode)
600  short to_player_id;
601  else
602  {
603  int i;
604  char expr[i];
605  }
606  int j;
607  char message[j];
608 
609 }
610 */
611 
612 //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
613 
614 // send a general game chat packet (if msg_mode == MULTI_MSG_TARGET, need to pass in "to", if == MULTI_MSG_EXPR, need to pass in expr)
615 void send_game_chat_packet(net_player *from, const char *msg, int msg_mode, net_player *to, const char *expr, int server_msg)
616 {
618  int packet_size,idx;
619  bool undeliverable = true;
620 
622 
623  // add the id
624  ADD_SHORT(from->player_id);
625 
626  // add the message mode and if in MSG_TARGET mode, add who the target is
627  ADD_INT(server_msg);
628  mode = (ubyte)msg_mode;
629  ADD_DATA(mode);
630  switch(mode){
631  case MULTI_MSG_TARGET:
632  Assert(to != NULL);
633  ADD_SHORT(to->player_id);
634  break;
635  case MULTI_MSG_EXPR:
636  Assert(expr != NULL);
637  ADD_STRING(expr);
638  break;
639  }
640  // add the message itself
641  ADD_STRING( msg );
642 
644  switch(mode){
645  // message all players
646  case MULTI_MSG_ALL:
647  for(idx=0;idx<MAX_PLAYERS;idx++){
648  if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && (&Net_players[idx] != from)){
649  multi_io_send_reliable(&Net_players[idx], data, packet_size);
650  }
651  }
652  break;
653 
654  // message only friendly players
655  case MULTI_MSG_FRIENDLY:
656  for(idx=0;idx<MAX_PLAYERS;idx++){
657  if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && (&Net_players[idx] != from) && (Net_players[idx].p_info.team == from->p_info.team)){
658  multi_io_send_reliable(&Net_players[idx], data, packet_size);
659  }
660  }
661  break;
662 
663  // message only hostile players
664  case MULTI_MSG_HOSTILE:
665  for(idx=0;idx<MAX_PLAYERS;idx++){
666  if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && (&Net_players[idx] != from) && (Net_players[idx].p_info.team != from->p_info.team)){
667  multi_io_send_reliable(&Net_players[idx], data, packet_size);
668  }
669  }
670  break;
671 
672  // message the player's target
673  case MULTI_MSG_TARGET:
674  Assert(to != NULL);
675  if(MULTI_CONNECTED((*to)) && !MULTI_STANDALONE((*to))){
676  multi_io_send_reliable(to, data, packet_size);
677  }
678  break;
679 
680  // message all players who match the expression string
681  case MULTI_MSG_EXPR:
682  Assert(expr != NULL);
683  for(idx=0;idx<MAX_PLAYERS;idx++){
684  if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && (&Net_players[idx] != from) && multi_msg_matches_expr(&Net_players[idx],expr) ){
685  multi_io_send_reliable(&Net_players[idx], data, packet_size);
686  undeliverable = false;
687  }
688  }
689  break;
690  }
691 
692  // if the message can't be delivered, notify the player
693  if (undeliverable) {
694  switch(mode){
695  case MULTI_MSG_EXPR:
696  // if the message came from the server
697  if (from == Net_player) {
698  multi_display_chat_msg ("Unable to send message, player does not exist", 0, 0);
699  }
700  // otherwise send a message back to the player
701  else {
702  send_game_chat_packet(Net_player, "Unable to send message, player does not exist", MULTI_MSG_TARGET, from, NULL, 1);
703  }
704  break;
705  }
706  }
707  }
708  // send to the server, who will take care of routing it
709  else {
710  multi_io_send_reliable(Net_player, data, packet_size);
711  }
712 }
713 
714 //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
715 
716 // process a general game chat packet, if we're the standalone we should rebroadcast
718 {
719  int offset;
720  ubyte mode;
721  int color_index,player_index,to_player_index,should_display,server_msg;
723  char expr[255];
724  short from, to;
725 
726  offset = HEADER_LENGTH;
727 
728  // get the id of the sender
729  GET_SHORT(from);
730 
731  // determine if this is a server message
732  GET_INT(server_msg);
733 
734  // get the mode
735  GET_DATA(mode);
736 
737  // if targeting a specific player, get the address
738  to = -1;
739  switch(mode){
740  case MULTI_MSG_TARGET:
741  GET_SHORT(to);
742  break;
743  case MULTI_MSG_EXPR:
744  GET_STRING(expr);
745  break;
746  }
747  // get the message itself
748  GET_STRING(msg);
749  PACKET_SET_SIZE();
750 
751  // get the index of the sending player
752  color_index = find_player_id(from);
753  player_index = color_index;
754 
755  // if we couldn't find the player - bail
756  if(player_index == -1){
757  nprintf(("Network","Could not find player for processing game chat packet!\n"));
758  return;
759  }
760 
761  should_display = 0;
762 
763  // if we're the server, determine what to do with the packet here
765  // if he's targeting a specific player, find out who it is
766  if(mode == MULTI_MSG_TARGET){
767  to_player_index = find_player_id(to);
768  } else {
769  to_player_index = -1;
770  }
771 
772  // if we couldn't find who sent the message or who should be getting the message, the bail
773  if(((to_player_index == -1) && (mode == MULTI_MSG_TARGET)) || (player_index == -1)){
774  return;
775  }
776 
777  // determine if _I_ should be seeing the text
779  should_display = 1;
780  }
781  // check against myself for several specific cases
782  else {
783  if((mode == MULTI_MSG_ALL) ||
784  ((mode == MULTI_MSG_FRIENDLY) && (Net_player->p_info.team == Net_players[player_index].p_info.team)) ||
785  ((mode == MULTI_MSG_HOSTILE) && (Net_player->p_info.team != Net_players[player_index].p_info.team)) ||
786  ((mode == MULTI_MSG_TARGET) && (MY_NET_PLAYER_NUM == to_player_index)) ||
787  ((mode == MULTI_MSG_EXPR) && multi_msg_matches_expr(Net_player,expr)) ){
788  should_display = 1;
789  }
790  }
791 
792  // if we're the server of a game, we need to rebroadcast to all other players
793  switch(mode){
794  // individual target mission
795  case MULTI_MSG_TARGET:
796  // if I was the inteneded target, or we couldn't find the intended target, don't rebroadcast
797  if(to_player_index != MY_NET_PLAYER_NUM){
798  send_game_chat_packet(&Net_players[player_index], msg, (int)mode, &Net_players[to_player_index], NULL, server_msg);
799  }
800  break;
801  // expression mode
802  case MULTI_MSG_EXPR:
803  send_game_chat_packet(&Net_players[player_index], msg, (int)mode, NULL, expr, server_msg);
804  break;
805  // all other modes
806  default :
807  send_game_chat_packet(&Net_players[player_index], msg, (int)mode, NULL, NULL, server_msg);
808  break;
809  }
810  }
811  // if a client receives this packet, its always ok for him to display it
812  else {
813  should_display = 1;
814  }
815 
816  // if we're not on a standalone
817  if(should_display){
818  if(server_msg == 2){
819  HUD_printf(msg);
820  } else {
821  multi_display_chat_msg(msg, player_index, !server_msg);
822  }
823  }
824 }
825 
826 
827 //*********************************************************************************************************
828 // Hud Message packet
829 //*********************************************************************************************************
830 /*
831 struct fs2_game_chat_packet
832 {
833  char packet_signature; //0xC1 HUD_MSG
834  int msg_size;
835  char msg[msg_size];
836 }
837 */
838 //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
839 
840 // broadcast a hud message to all players
841 void send_hud_msg_to_all( char* msg )
842 {
844  int packet_size;
845 
846  // only the server should be sending this packet
848 
849  ADD_STRING(msg);
850 
851  multi_io_send_to_all( data, packet_size );
852 }
853 
854 //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
855 
856 // process an incoming hud message packet
858 {
859  int offset;
860  char msg_buffer[255];
861 
862  offset = HEADER_LENGTH;
863 
864  GET_STRING(msg_buffer);
865  PACKET_SET_SIZE();
866 
867  // this is the only safe place to do this since only in the mission is the HUD guaranteed to be inited
868  if(Game_mode & GM_IN_MISSION){
869  HUD_printf(msg_buffer);
870  }
871 }
872 
873 
874 //*********************************************************************************************************
875 // Join Packet
876 //*********************************************************************************************************
877 /*
878 struct fs2_game_chat_packet
879 {
880  char packet_signature; //0xC1 HUD_MSG
881  int msg_size;
882  char msg[msg_size];
883 }
884 */
885 //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
886 
887 // send a join packet request to the specified address (should be a server)
889 {
891  int packet_size;
892 
893  // build the header and add the request
894  BUILD_HEADER(JOIN);
895  add_join_request(data, &packet_size, jr);
896 
897  psnet_send(addr, data, packet_size);
898 }
899 
900 //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
901 
902 // process an incoming join request packet
904 {
905  join_request jr;
906  int offset;
907  int ret_code;
908  int host_restr_mode;
909  int team0_avail,team1_avail;
910  char join_string[255];
911  net_addr addr;
912 
913  // only the server of the game should ever receive this packet
915  return;
916 
917  offset = HEADER_LENGTH;
918 
919  // read in the request info
920  memset(&jr,0,sizeof(join_request));
921 
922  get_join_request(data, &offset, &jr);
923 
924  PACKET_SET_SIZE();
925 
926  // fill in the address information of where this came from
927  fill_net_addr(&addr, hinfo->addr, hinfo->port);
928 
929  // determine if we should accept this guy, or return a reason we should reject him
930  // see the DENY_* codes in multi.h
931  ret_code = multi_eval_join_request(&jr,&addr);
932 
933  // evaluate the return code
934  switch(ret_code)
935  {
936  // he should be accepted
937  case -1 :
938  break;
939 
940  // we have to query the host because this is a restricted game
941  case JOIN_QUERY_RESTRICTED :
943  // notify the host of the event
945  }
946 
947  // set the query timestamp
950 
951  // determine what mode we're in
952  host_restr_mode = -1;
953  memset(join_string,0,255);
955  multi_player_ships_available(&team0_avail,&team1_avail);
956 
957  if(team0_avail && team1_avail){
958  host_restr_mode = MULTI_JOIN_RESTR_MODE_4;
959  sprintf(join_string,"Player %s has tried to join. Accept on team 1 or 2 ?",jr.callsign);
960  } else if(team0_avail && !team1_avail){
961  host_restr_mode = MULTI_JOIN_RESTR_MODE_2;
962  sprintf(join_string,"Player %s has tried to join team 0, accept y/n ? ?",jr.callsign);
963  } else if(!team0_avail && team1_avail){
964  host_restr_mode = MULTI_JOIN_RESTR_MODE_3;
965  sprintf(join_string,"Player %s has tried to join team 1, accept y/n ?",jr.callsign);
966  }
967  } else if(Netgame.mode == NG_MODE_RESTRICTED){
968  host_restr_mode = MULTI_JOIN_RESTR_MODE_1;
969  sprintf(join_string,XSTR("Player %s has tried to join, accept y/n ?",715),jr.callsign);
970  }
971  Assert(host_restr_mode != -1);
972 
973  // store the request info
974  memcpy(&Multi_restr_join_request,&jr,sizeof(join_request));
975  memcpy(&Multi_restr_addr,&addr,sizeof(net_addr));
976  Multi_join_restr_mode = host_restr_mode;
977 
978  // if i'm the standalone server, I need to send a query to the host
979  if(Game_mode & GM_STANDALONE_SERVER){
981  } else {
982  HUD_printf(join_string);
983  }
984 
985  // NETLOG
986  ml_printf(NOX("Receive restricted join request from %s"), jr.callsign);
987 
988  return;
989 
990  // he'e being denied for some reason
991  default :
992  // send him the reason he is being denied
993  send_deny_packet(&addr,ret_code);
995  return;
996  }
997 
998  // process the rest of the request
1000 }
1001 
1002 //*********************************************************************************************************
1003 // New Player Packet
1004 //*********************************************************************************************************
1005 /*
1006 struct fs2_new_player_packet
1007 {
1008  char packet_signature; // 0xB4 NOTIFY_NEW_PLAYER
1009  int new_player_num;
1010  net_addr player_addr;
1011  short player_id;
1012  int flags;
1013 
1014  int i;
1015  char callsign[i];
1016 
1017  int j;
1018  char plyr_image_filename[j];
1019 
1020  int k;
1021  char plyr_squad_filename[k];
1022 
1023  int l;
1024  char plyr_pxo_squad_name[l];
1025 }
1026 */
1027 
1028 //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1029 
1030 // send a notification that a new player has joined the game (if target != NULL, broadcast the packet)
1031 void send_new_player_packet(int new_player_num,net_player *target)
1032 {
1034  int packet_size = 0;
1035 
1037 
1038  // add the new player's info
1039  ADD_INT(new_player_num);
1040 // ADD_DATA(Net_players[new_player_num].p_info.addr);
1041  add_net_addr(data, &packet_size, &Net_players[new_player_num].p_info.addr);
1042  ADD_SHORT(Net_players[new_player_num].player_id);
1043  ADD_INT(Net_players[new_player_num].flags);
1044  ADD_STRING(Net_players[new_player_num].m_player->callsign);
1045  ADD_STRING(Net_players[new_player_num].m_player->image_filename);
1046  ADD_STRING(Net_players[new_player_num].m_player->m_squad_filename);
1047  ADD_STRING(Net_players[new_player_num].p_info.pxo_squad_name);
1048 
1049  val = (ubyte)Net_players[new_player_num].p_info.team;
1050  ADD_DATA(val);
1051 
1052  // broadcast the data
1053  if(target != NULL){
1054  multi_io_send_reliable(target, data, packet_size);
1055  } else {
1056  multi_io_send_to_all_reliable(data, packet_size);
1057  }
1058 }
1059 
1060 //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1061 
1062 // process a notification for a new player who has joined the game
1064 {
1065  int already_in_game = 0;
1066  int offset, new_player_num,player_num,new_flags;
1067  net_addr new_addr;
1068  char new_player_name[CALLSIGN_LEN+2] = "";
1069  char new_player_image[MAX_FILENAME_LEN+1] = "";
1070  char new_player_squad[MAX_FILENAME_LEN+1] = "";
1071  char new_player_pxo_squad[LOGIN_LEN+1] = "";
1072  char notify_string[256];
1073  ubyte team;
1074  short new_id;
1075 
1076  offset = HEADER_LENGTH;
1077 
1078  // get the new players information
1079  GET_INT(new_player_num);
1080 // GET_DATA(new_addr);
1081  get_net_addr(data, &offset, &new_addr);
1082  GET_SHORT(new_id);
1083  GET_INT(new_flags);
1084  GET_STRING(new_player_name);
1085  GET_STRING(new_player_image);
1086  GET_STRING(new_player_squad);
1087  GET_STRING(new_player_pxo_squad);
1088  GET_DATA(team);
1089  PACKET_SET_SIZE();
1090 
1091  player_num = multi_find_open_player_slot();
1092  Assert(player_num != -1);
1093 
1094  // note that this new code does not check for duplicate IPs. It merely checks to see if
1095  // the slot referenced by new_player_num is already occupied by a connected player
1096  if(MULTI_CONNECTED(Net_players[new_player_num])){
1097  already_in_game=1;
1098  }
1099 
1100  // if he's not alreayd in the game for one reason or another
1101  if ( !already_in_game ) {
1102  if ( Game_mode & GM_IN_MISSION ){
1103  HUD_sourced_printf(HUD_SOURCE_COMPUTER, XSTR("%s has entered the game\n",716), new_player_name);
1104  }
1105 
1106  // create the player
1107  if(new_flags & NETINFO_FLAG_OBSERVER){
1108  multi_obs_create_player(new_player_num,new_player_name,&new_addr,&Players[player_num]);
1109  Net_players[new_player_num].flags |= new_flags;
1110  } else {
1111  multi_create_player( new_player_num, &Players[player_num],new_player_name, &new_addr, -1, new_id );
1112  Net_players[new_player_num].flags |= new_flags;
1113  }
1114 
1115  // copy in the filename
1116  if(new_player_image[0] != '\0'){
1117  strcpy_s(Net_players[new_player_num].m_player->image_filename, new_player_image);
1118  } else {
1119  strcpy_s(Net_players[new_player_num].m_player->image_filename, "");
1120  }
1121  // copy his pilot squad filename
1122  Net_players[new_player_num].m_player->insignia_texture = -1;
1123  player_set_squad_bitmap(Net_players[new_player_num].m_player, new_player_squad, true);
1124 
1125  // copy in his pxo squad name
1126  strcpy_s(Net_players[new_player_num].p_info.pxo_squad_name, new_player_pxo_squad);
1127 
1128  // since we just created the player, set the last_heard_time here.
1130 
1131  Net_players[new_player_num].p_info.team = team;
1132 
1133  Net_players[new_player_num].player_id = new_id;
1134 
1135  // zero out this players ping
1136  multi_ping_reset(&Net_players[new_player_num].s_info.ping);
1137 
1138  // add a chat message
1139  if(*Net_players[new_player_num].m_player->callsign){
1140  sprintf(notify_string,XSTR("<%s has joined>",717),Net_players[new_player_num].m_player->callsign);
1141  multi_display_chat_msg(notify_string,0,0);
1142  }
1143  }
1144 
1145  // NETLOG
1146  ml_printf(NOX("Received notification of new player %s"), Net_players[new_player_num].m_player->callsign);
1147 
1148  // let the current ui screen know someone joined
1149  switch(gameseq_get_state()){
1151  multi_create_handle_join(&Net_players[new_player_num]);
1152  break;
1154  multi_jw_handle_join(&Net_players[new_player_num]);
1155  break;
1156  }
1157 }
1158 
1159 //*********************************************************************************************************
1160 // Accept Player Data Packet
1161 //*********************************************************************************************************
1162 /*
1163 struct fs2_accept_player_data
1164 {
1165  char packet_signature; //ACCEPT_PLAYER_DATA
1166  ubyte stop;
1167  int player_num;
1168  net_addr plyr_addr;
1169  int player_id;
1170 
1171  int i;
1172  char callsign[i];
1173 
1174  int j;
1175  char plr_image_filename[j];
1176 
1177  int k;
1178  char plr_squad_filename[k]
1179 
1180  int l
1181  char plr_pxo_squadname[l];
1182 
1183  int flags;
1184 
1185  if (is_ingame)
1186  int net_signature;
1187 
1188 
1189 };
1190 */
1191 
1192 //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1193 
1194 #define PLAYER_DATA_SLOP 100
1195 
1196 void send_accept_player_data( net_player *npp, int is_ingame )
1197 {
1198  int packet_size;
1199  int i;
1200  ubyte data[MAX_PACKET_SIZE], stop;
1201 
1203 
1204  // add in the netplayer data for all players
1205  stop = APD_NEXT;
1206  for (i=0; i<MAX_PLAYERS; i++) {
1207  // skip non connected players
1208  if ( !MULTI_CONNECTED(Net_players[i]) ){
1209  continue;
1210  }
1211 
1212  // skip this new player's entry
1213  if ( npp->player_id == Net_players[i].player_id ){
1214  continue;
1215  }
1216 
1217  // add the stop byte
1218  ADD_DATA(stop);
1219 
1220  // add the player's number
1221  ADD_INT(i);
1222 
1223  // add the player's address
1224  // ADD_DATA(Net_players[i].p_info.addr);
1225  add_net_addr(data, &packet_size, &Net_players[i].p_info.addr);
1226 
1227  // add his id#
1228  ADD_SHORT(Net_players[i].player_id);
1229 
1230  // add his callsign
1231  ADD_STRING(Net_players[i].m_player->callsign);
1232 
1233  // add his image filename
1234  ADD_STRING(Net_players[i].m_player->image_filename);
1235 
1236  // add his squad filename
1237  ADD_STRING(Net_players[i].m_player->m_squad_filename);
1238 
1239  // add his PXO squad name
1240  ADD_STRING(Net_players[i].p_info.pxo_squad_name);
1241 
1242  // add his flags
1243  ADD_INT(Net_players[i].flags);
1244 
1245  // add his object's net sig
1246  if ( is_ingame ) {
1247  ADD_USHORT( Objects[Net_players[i].m_player->objnum].net_signature );
1248  }
1249 
1250  if ( (packet_size + PLAYER_DATA_SLOP) > MAX_PACKET_SIZE ) {
1251  stop = APD_END_PACKET;
1252  ADD_DATA(stop);
1253  multi_io_send_reliable( npp, data, packet_size );
1255  stop = APD_NEXT;
1256  }
1257 
1258  }
1259 
1260  // add the stop byte
1261  stop = APD_END_DATA;
1262  ADD_DATA(stop);
1263  multi_io_send_reliable(npp, data, packet_size);
1264 }
1265 
1266 //+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
1267 
1268 // process the player data from the server
1270 {
1271  int offset, player_num, player_slot_num, new_flags;
1272  char name[CALLSIGN_LEN + 1] = "";
1273  char image_name[MAX_FILENAME_LEN + 1] = "";
1274  char squad_name[MAX_FILENAME_LEN + 1] = "";
1275  char pxo_squad_name[LOGIN_LEN+1] = "";
1276  short player_id;
1277  net_addr addr;
1278  ubyte stop;
1279  ushort ig_signature;
1280 
1281  offset = HEADER_LENGTH;
1282 
1283  GET_DATA(stop);
1284  while ( stop == APD_NEXT ) {
1285  player_slot_num = multi_find_open_player_slot();
1286  Assert(player_slot_num != -1);
1287 
1288  // get the player's number
1289  GET_INT(player_num);
1290 
1291  // add the player's address
1292  // GET_DATA(addr);
1293  get_net_addr(data, &offset, &addr);
1294 
1295  // get the player's id#
1296  GET_SHORT(player_id);
1297 
1298  // get his callsign
1299  GET_STRING(name);
1300 
1301  // add his image filename
1302  GET_STRING(image_name);
1303 
1304  // get his squad logo filename
1305  GET_STRING(squad_name);
1306 
1307  // get his PXO squad name
1308  GET_STRING(pxo_squad_name);
1309 
1310  // get his flags
1311  GET_INT(new_flags);
1312 
1313  if (Net_players[player_num].flags & NETINFO_FLAG_OBSERVER) {
1314  if (!multi_obs_create_player(player_num, name, &addr, &Players[player_slot_num])) {
1315  Int3();
1316  }
1317 
1318  } else {
1319  // the error handling here is less than stellar. We should probably put up a popup and go
1320  // back to the main menu. But then again, this should never ever happen!
1321  if ( !multi_create_player(player_num, &Players[player_slot_num],name, &addr, -1, player_id) ) {
1322  Int3();
1323  }
1324  }
1325 
1326  // copy his image filename
1327  strcpy_s(Net_players[player_num].m_player->image_filename, image_name);
1328 
1329  // copy his pilot squad filename
1330  Net_players[player_num].m_player->insignia_texture = -1;
1331  player_set_squad_bitmap(Net_players[player_num].m_player, squad_name, true);
1332 
1333  // copy his pxo squad name
1334  strcpy_s(Net_players[player_num].p_info.pxo_squad_name, pxo_squad_name);
1335 
1336  // set his player id#
1337  Net_players[player_num].player_id = player_id;
1338 
1339  // mark him as being connected
1340  Net_players[player_num].flags |= NETINFO_FLAG_CONNECTED;
1341  Net_players[player_num].flags |= new_flags;
1342 
1343  // set the server pointer
1344  if ( Net_players[player_num].flags & NETINFO_FLAG_AM_MASTER ) {
1345  Netgame.server = &Net_players[player_num];
1347 
1348  // also - always set the server address to be where this data came from, NOT from
1349  // the data in the packet
1350  fill_net_addr(&Net_players[player_num].p_info.addr, hinfo->addr, hinfo->port);
1351  }
1352 
1353  // set the host pointer
1354  if ( Net_players[player_num].flags & NETINFO_FLAG_GAME_HOST ) {
1355  Netgame.host = &Net_players[player_num];
1356  }
1357 
1358  // read in the player's object net signature and store as his objnum for now
1360  GET_USHORT( ig_signature );
1361  Net_players[player_num].m_player->objnum = ig_signature;
1362  }
1363 
1364  // get the stop byte
1365  GET_DATA(stop);
1366  }
1367  PACKET_SET_SIZE();
1368 
1369  if ( stop == APD_END_DATA ) {
1370  // if joining a game automatically, set the connect address to NULl so we don't try and
1371  // do this next time we enter a game
1372  if (Cmdline_connect_addr != NULL) {
1373  Cmdline_connect_addr = NULL;
1374  }
1375 
1376  // send my stats to the server if I'm not in observer mode
1379  }
1380 
1381  // if i'm being accepted as a host, then move into the host setup state
1383  // set my permission bits
1386 
1388  }
1389 
1392 
1393  // since observers can join 1 of 2 ways, only do this if we're not doing an ingame observer join
1396  }
1397  }
1398 
1401  }
1402 
1404  // flag myself as being an ingame joiner
1406 
1407  // move myself into the ingame join mission sync state
1410  }
1411 
1412  // update my options on the server
1414 
1415  // if we're in PXO mode, mark it down in our player struct
1419  }
1420  }
1421 }
1422 
1423 
1424 //*********************************************************************************************************
1425 // Accept Player Packet
1426 //*********************************************************************************************************
1427 /*
1428 struct fs2_accept_packet
1429 {
1430  char packet_signature;
1431  int code;
1432 
1433  if (code & ACCEPT_INGAME)
1434  {
1435  int gm_mis_fname_len;
1436  char mission_filename[gm_mis_fname_len];
1437  unsigned char ingame_joining_team;
1438  if (ingame_joining_team == 1)
1439  unsigned char ingame_join_team;
1440 
1441  }
1442 
1443  int skill_level;
1444  int player_num;
1445  short player_id;
1446  int netgame_type_flags;
1447 
1448 }
1449 */
1450 // send an accept packet to a client in response to a request to join the game
1451 void send_accept_packet(int new_player_num, int code, int ingame_join_team)
1452 {
1453  int packet_size, i;
1455  char notify_string[256];
1456 
1457  // sanity
1458  Assert(new_player_num >= 0);
1459 
1460  // setup his "reliable" socket
1462 
1463  // build the packet header
1464  packet_size = 0;
1465  BUILD_HEADER(ACCEPT);
1466 
1467  // add the accept code
1468  ADD_INT(code);
1469 
1470  // add code specific accept data
1471  if (code & ACCEPT_INGAME) {
1472  // the game filename
1474 
1475  // if he is joining on a specific team, mark it here
1476  if(ingame_join_team != -1){
1477  val = 1;
1478  ADD_DATA(val);
1479  val = (ubyte)ingame_join_team;
1480  ADD_DATA(val);
1481  } else {
1482  val = 0;
1483  ADD_DATA(val);
1484  }
1485  }
1486 
1487  if (code & ACCEPT_OBSERVER) {
1488  Assert(!(code & (ACCEPT_CLIENT | ACCEPT_HOST)));
1489  }
1490 
1491  if (code & ACCEPT_HOST) {
1492  Assert(!(code & (ACCEPT_CLIENT | ACCEPT_OBSERVER | ACCEPT_INGAME)));
1493  }
1494 
1495  if (code & ACCEPT_CLIENT) {
1496  Assert(!(code & (ACCEPT_HOST | ACCEPT_OBSERVER | ACCEPT_INGAME)));
1497  }
1498 
1499  // add the current skill level setting on the host
1500  // sanity check - reset skill level to default before sending if out of range
1501  if (Game_skill_level < 0 || Game_skill_level >= NUM_SKILL_LEVELS) {
1502  Warning(LOCATION, "Trying to send packet containing invalid skill level %i! Valid range 0 to %i. Resetting to default.", Game_skill_level, NUM_SKILL_LEVELS);
1504  }
1506 
1507  // add this guys player num
1508  ADD_INT(new_player_num);
1509 
1510  // add his player id
1511  ADD_SHORT(Net_players[new_player_num].player_id);
1512 
1513  // add netgame type flags
1515 
1516  // actually send the packet
1517  psnet_send(&Net_players[new_player_num].p_info.addr, data, packet_size);
1518 
1519  // if he's not an observer, inform all the other players in the game about him
1520  // inform the other players in the game about this new player
1521  for (i=0; i<MAX_PLAYERS; i++) {
1522  // skip unconnected players as well as this new guy himself
1523  if ( !MULTI_CONNECTED(Net_players[i]) || psnet_same(&Net_players[new_player_num].p_info.addr, &(Net_players[i].p_info.addr)) || (Net_player == &Net_players[i])) {
1524  continue;
1525  }
1526 
1527  // send the new packet
1528  send_new_player_packet(new_player_num,&Net_players[i]);
1529  }
1530 
1531  // add a chat message
1532  if(*Net_players[new_player_num].m_player->callsign){
1533  sprintf(notify_string,XSTR("<%s has joined>",717), Net_players[new_player_num].m_player->callsign);
1534  multi_display_chat_msg(notify_string, 0, 0);
1535  }
1536 
1537  // handle any team vs. team details
1538  if (!(code & ACCEPT_OBSERVER)) {
1539  multi_team_handle_join(&Net_players[new_player_num]);
1540  }
1541 
1542  // NETLOG
1543  if(Net_players[new_player_num].tracker_player_id >= 0){
1544  ml_printf(NOX("Server accepted %s (tracker id %d) as new client"), Net_players[new_player_num].m_player->callsign, Net_players[new_player_num].tracker_player_id);
1545  } else {
1546  ml_printf(NOX("Server accepted %s as new client"), Net_players[new_player_num].m_player->callsign);
1547  }
1548 }
1549 
1550 // process an accept packet from the server
1551 extern int Select_default_ship;
1552 
1554 {
1555  int code, my_player_num, offset;
1556  ubyte val,team = 0;
1557  short player_id;
1558 
1559  // get the accept code
1560  offset = HEADER_LENGTH;
1561 
1562  GET_INT(code);
1563 
1564  // read in the accept code specific data
1565  val = 0;
1566  if (code & ACCEPT_INGAME) {
1567  // the game filename
1569  mprintf(("Got mission filename %s\n", Game_current_mission_filename));
1570  Select_default_ship = 0;
1571 
1572  // determine if I'm being placed on a team
1573  GET_DATA(val);
1574  if(val){
1575  GET_DATA(team);
1576  }
1577  }
1578 
1579  if (code & ACCEPT_OBSERVER) {
1580  Assert(!(code & (ACCEPT_CLIENT | ACCEPT_HOST)));
1581  }
1582 
1583  if (code & ACCEPT_HOST) {
1584  Assert(!(code & (ACCEPT_CLIENT | ACCEPT_OBSERVER | ACCEPT_INGAME)));
1585  }
1586 
1587  if (code & ACCEPT_CLIENT) {
1588  Assert(!(code & (ACCEPT_HOST | ACCEPT_OBSERVER | ACCEPT_INGAME)));
1589  }
1590 
1591  // fill in the netgame server address
1592  fill_net_addr( &Netgame.server_addr, hinfo->addr, hinfo->port );
1593 
1594  // get the skill level setting
1596  if (Game_skill_level < 0 || Game_skill_level >= NUM_SKILL_LEVELS) {
1597  Warning(LOCATION, "Received packet containing invalid skill level %i! Valid range 0 to %i. Resetting to default.", Game_skill_level, NUM_SKILL_LEVELS);
1599  }
1600 
1601  // get my netplayer number
1602  GET_INT(my_player_num);
1603 
1604  // get my id #
1605  GET_SHORT(player_id);
1606 
1607  // get netgame type flags
1609 
1610  // setup the Net_players structure for myself first
1611  Net_player = &Net_players[my_player_num];
1612  Net_player->flags = 0;
1614  Net_player->player_id = player_id;
1616  // stuff_netplayer_info( Net_player, &Psnet_my_addr, Ships[Objects[Player->objnum].instance].ship_info_index, Player );
1619  Net_player->p_info.team = team;
1620 
1621  // determine if I have a CD
1622  if(Multi_has_cd){
1624  }
1625 
1626  // set accept code in netplayer for this guy
1627  if ( code & ACCEPT_INGAME ){
1629  }
1630  if ( code & ACCEPT_OBSERVER ){
1632  }
1633  if ( code & ACCEPT_HOST ){
1635  }
1636  if ( code & ACCEPT_CLIENT ){
1638  }
1639 
1640  // if I have hacked data
1641  if(game_hacked_data()){
1643  }
1644 
1645  // if we're supposed to flush our local data cache, do so now
1648  }
1649 
1651  Net_player->sv_last_pl = -1;
1653  Net_player->cl_last_pl = -1;
1654 
1655  // intiialize endgame stuff
1657 
1658  PACKET_SET_SIZE();
1659 
1660  // make a call to psnet to initialize and try to connect with the server.
1664  }
1665 }
1666 
1667 //*********************************************************************************************************
1668 // Player Leave Packet
1669 //*********************************************************************************************************
1670 /*
1671 struct fs2_leave_game_packet
1672 {
1673  char packet_signature;
1674  char kicked_reason;
1675  short player_id;
1676 
1677 }
1678 */
1679 // send a notice that the player at net_addr is leaving (if target is NULL, the broadcast the packet)
1680 void send_leave_game_packet(short player_id, int kicked_reason, net_player *target)
1681 {
1683  char val;
1684  int packet_size = 0;
1685 
1687 
1688  // add a flag indicating whether he was kicked or not
1689  val = (char)kicked_reason;
1690  ADD_DATA(val);
1691 
1692  if (player_id < 0) {
1694 
1695  // inform the host that we are leaving the game
1697  multi_io_send_to_all_reliable(data, packet_size);
1698  } else {
1699  multi_io_send_reliable(Net_player, data, packet_size);
1700  }
1701  }
1702  // this is the case where to server is tossing a player (or indicating a respawned player has quit or become an observer)
1703  // so he has to tell everyone that this guy left
1704  else {
1705  nprintf(("Network","Sending a leave game packet to all players (server)\n"));
1706 
1707  // a couple of important checks
1708  Assert(player_id != Net_player->player_id);
1710 
1711  // add the id of the guy to be kicked
1712  ADD_SHORT(player_id);
1713 
1714  // broadcast to everyone
1715  if (target == NULL) {
1716  multi_io_send_to_all_reliable(data, packet_size);
1717  } else {
1718  multi_io_send_reliable(target, data, packet_size);
1719  }
1720  }
1721 }
1722 
1723 // process a notification that a player has left the game
1725 {
1726  int offset;
1727  short deader_id;
1728  int player_num;
1729  char kicked_reason;
1730  char str[512];
1731 
1732  offset = HEADER_LENGTH;
1733 
1734  // get whether he was kicked
1735  GET_DATA(kicked_reason);
1736 
1737  // get the address of the guy who is to leave
1738  GET_SHORT(deader_id);
1739  PACKET_SET_SIZE();
1740 
1741  // determine who is dropping and printf out a notification
1742  player_num = find_player_id(deader_id);
1743  if (player_num == -1) {
1744  nprintf(("Network", "Received leave game packet for unknown player, ignoring\n"));
1745  return;
1746 
1747  } else {
1748  nprintf(("Network", "Received a leave game notice for %s\n", Net_players[player_num].m_player->callsign));
1749  }
1750 
1751  // a hook to display that a player was kicked
1752  if (kicked_reason >= 0){
1753  // if it was me that was kicked, leave the game
1754  if((Net_player != NULL) && (Net_player->player_id == deader_id)){
1755  int notify_code;
1756 
1757  switch(kicked_reason){
1758  case KICK_REASON_BAD_XFER:
1759  notify_code = MULTI_END_NOTIFY_KICKED_BAD_XFER;
1760  break;
1761  case KICK_REASON_CANT_XFER:
1762  notify_code = MULTI_END_NOTIFY_KICKED_CANT_XFER;
1763  break;
1766  break;
1767  default:
1768  notify_code = MULTI_END_NOTIFY_KICKED;
1769  break;
1770  }
1771 
1772  multi_quit_game(PROMPT_NONE, notify_code);
1773  return;
1774 
1775  // otherwise indicate someone was kicked
1776  } else {
1777  nprintf(("Network","%s was kicked\n",Net_players[player_num].m_player->callsign));
1778 
1779  // display the result
1780  memset(str, 0, 512);
1781  multi_kick_get_text(&Net_players[player_num], kicked_reason, str);
1782  multi_display_chat_msg(str, player_num, 0);
1783  }
1784  }
1785 
1786  // first of all, if we're the master, we should be rebroadcasting this packet
1788  char msg[255];
1789 
1790  sprintf(msg, XSTR("%s has left the game",719), Net_players[player_num].m_player->callsign );
1791 
1792  if (!(Game_mode & GM_STANDALONE_SERVER)){
1794  }
1795 
1796  send_hud_msg_to_all(msg);
1797  multi_io_send_to_all_reliable(data, offset);
1798  }
1799 
1800  // leave the game if the host and/or master has dropped
1801  /*
1802  if (((Net_players[player_num].flags & NETINFO_FLAG_AM_MASTER) || (Net_players[player_num].flags & NETINFO_FLAG_GAME_HOST)) ) {
1803  nprintf(("Network","Host and/or server has left the game - aborting...\n"));
1804 
1805  // NETLOG
1806  ml_string(NOX("Host and/or server has left the game"));
1807 
1808  // if the host leaves in the debriefing state, we should still wait until the player selects accept before we quit
1809  if (gameseq_get_state() != GS_STATE_DEBRIEF) {
1810  multi_quit_game(PROMPT_NONE, MULTI_END_NOTIFY_SERVER_LEFT);
1811  }
1812 
1813  delete_player(player_num);
1814  } else {
1815  */
1816  delete_player(player_num);
1817 
1818  // OSAPI GUI stuff (if standalone)
1820  // returns true if we should reset the standalone
1821  if (std_remove_player(&Net_players[player_num])) {
1822  nprintf(("Network", "Should reset!!\n"));
1823  return;
1824  }
1825 
1826  // update these gui vals
1829  }
1830 }
1831 
1832 //*********************************************************************************************************
1833 // Game active packet
1834 //*********************************************************************************************************
1835 /*
1836 struct fs2_game_active_packet
1837 {
1838  char packet_signature;
1839  ubyte server_version;
1840  ubyte compat_version;
1841  int len1;
1842  char netgame_name[len1];
1843  int len2;
1844  char netgame_mission_name[len2];
1845  int len3;
1846  char netgame_title[len3];
1847  ubyte num_players;
1848  unsigned short flags;
1849 }
1850 */
1851 // send information about this currently active game to the specified address
1853 {
1854  int packet_size;
1855  ushort flags;
1857 
1858  // build the header and add the data
1860 
1861  // add the server version and compatible version #
1863  ADD_DATA(val);
1865  ADD_DATA(val);
1866 
1870  val = (ubyte)multi_num_players();
1871  ADD_DATA(val);
1872 
1873  // add the proper flags
1874  flags = 0;
1876  flags |= AG_FLAG_PASSWD;
1877  }
1878 
1879  // proper netgame type flags
1881  flags |= AG_FLAG_TEAMS;
1882  } else if(Netgame.type_flags & NG_TYPE_DOGFIGHT){
1883  flags |= AG_FLAG_DOGFIGHT;
1884  } else {
1885  flags |= AG_FLAG_COOP;
1886  }
1887 
1888  // proper netgame state flags
1889  switch(Netgame.game_state){
1890  case NETGAME_STATE_FORMING:
1891  flags |= AG_FLAG_FORMING;
1892  break;
1893 
1897  flags |= AG_FLAG_BRIEFING;
1898  break;
1899 
1901  flags |= AG_FLAG_IN_MISSION;
1902  break;
1903 
1904  case NETGAME_STATE_PAUSED:
1905  flags |= AG_FLAG_PAUSE;
1906  break;
1907 
1908  case NETGAME_STATE_ENDGAME:
1909  case NETGAME_STATE_DEBRIEF:
1910  flags |= AG_FLAG_DEBRIEF;
1911  break;
1912  }
1913 
1914  // if this is a standalone
1915  if(Game_mode & GM_STANDALONE_SERVER){
1916  flags |= AG_FLAG_STANDALONE;
1917  }
1918 
1919  // if we're in campaign mode
1921  flags |= AG_FLAG_CAMPAIGN;
1922  }
1923 
1924  // add the data about the connection speed of the host machine
1927 
1928  ADD_USHORT(flags);
1929 
1930  // send the data
1931  psnet_send(addr, data, packet_size);
1932 }
1933 
1934 // process information about an active game
1936 {
1937  int offset;
1938  ubyte val;
1939  active_game ag;
1940  int modes_compatible = 1;
1941 
1942  fill_net_addr(&ag.server_addr, hinfo->addr, hinfo->port);
1943 
1944  // read this game into a temporary structure
1945  offset = HEADER_LENGTH;
1946 
1947  // get the server version and compatible version
1948  GET_DATA(ag.version);
1949  GET_DATA(ag.comp_version);
1950 
1951  GET_STRING(ag.name);
1953  GET_STRING(ag.title);
1954  GET_DATA(val);
1955  ag.num_players = val;
1956  GET_USHORT(ag.flags);
1957 
1958  PACKET_SET_SIZE();
1959 
1960  if ( (ag.flags & AG_FLAG_TRACKER) && !Multi_options_g.pxo )
1961  modes_compatible = 0;
1962 
1963  if ( !(ag.flags & AG_FLAG_TRACKER) && Multi_options_g.pxo )
1964  modes_compatible = 0;
1965 
1966  // if this is a compatible version, and our modes are compatible, register it
1967  if ( (ag.version == MULTI_FS_SERVER_VERSION) && modes_compatible ) {
1969  }
1970 }
1971 
1972 //*********************************************************************************************************
1973 // Game Update Packet
1974 //*********************************************************************************************************
1975 /*
1976 struct fs2_game_update
1977 {
1978  char packet_signature;
1979  int len1;
1980  char netgame_name[len1];
1981  int len2;
1982  char netgame_mission_name[len2];
1983  int len3;
1984  char netgame_title[len3];
1985  int len4;
1986  char netgame_campaign_name[len4];
1987  int campaign_mode;
1988  int max_players;
1989  int security;
1990  unsigned int respawn;
1991  int flags;
1992  int type_flags;
1993  int version_info;
1994  ubyte debug_flags;
1995 
1996  // !!!!!! this isn't relying on information earlier in the packet!
1997  // receiving seems to always assume it's there!
1998  if(Net_player->flags & NETINFO_FLAG_AM_MASTER){
1999  int game_state;
2000  }
2001 
2002  }
2003 
2004 */
2005 
2006 // send_game_update_packet sends an updated Netgame structure to all players currently connected. The update
2007 // is used to change the current mission, current state, etc.
2009 {
2010  int packet_size;
2011  int idx;
2013 
2014  packet_size = 0;
2016 
2017  // with new mission description field, this becomes way to large
2018  // so we must add every element piece by piece except the
2031 
2032  // only the server should ever send the netgame state (standalone situation)
2035  }
2036 
2037  // if we're the host on a standalone, send to the standalone and let him rebroadcast
2039  if ( pl == NULL ) {
2040  multi_io_send_to_all_reliable(data, packet_size);
2041 
2042  for(idx=0; idx<MAX_PLAYERS; idx++){
2043  if(MULTI_CONNECTED(Net_players[idx]) && (Net_player != &Net_players[idx])){
2044  send_netgame_descript_packet(&Net_players[idx].p_info.addr, 1);
2045  }
2046  }
2047  } else {
2048  multi_io_send_reliable(pl, data, packet_size);
2050  }
2051  } else {
2052  Assert( pl == NULL ); // I don't think that a host in a standalone game would get here.
2053  multi_io_send_reliable(Net_player, data, packet_size);
2054  }
2055 
2056  // host should always send a netgame options update as well
2059  }
2060 }
2061 
2062 // process information about the netgame sent from the server/host
2064 {
2065  int offset;
2066  int ng_state;
2067 
2070 
2071  // read in the netgame information
2072  offset = HEADER_LENGTH;
2078  GET_INT(Netgame.max_players); // ignore on the standalone, who keeps track of this himself
2081 
2082  // be sure not to blast the quitting flag because of the "one frame extra" problem
2083  GET_INT(Netgame.flags);
2087 
2088  // netgame state
2089  GET_INT(ng_state);
2090 
2091  PACKET_SET_SIZE();
2092 
2093  // now compare the passed in game state to our current known state. If it has changed, then maybe
2094  // do something interesting.
2095  // move from the forming or debriefing state to the mission sync state
2096  if ( ng_state == NETGAME_STATE_MISSION_SYNC ){
2097  // if coming from the forming state
2100  // do any special processing for forced state transitions
2102 
2106  }
2107  // if coming from the debriefing state
2108  else if( (Netgame.game_state == NETGAME_STATE_DEBRIEF) ||
2110 
2111  // do any special processing for forced state transitions
2113 
2115 
2119  }
2120  }
2121  // move from mission sync to team select
2122  else if ( ng_state == NETGAME_STATE_BRIEFING ){
2125 
2126  // do any special processing for forced state transitions
2128 
2131  }
2132  }
2133  // move from the debriefing to the create game screen
2134  else if ( ng_state == NETGAME_STATE_FORMING ){
2137  // do any special processing for forced state transitions
2139 
2141 
2142  // move to the proper screen
2145  } else {
2147  }
2148  }
2149  }
2150 
2151  Netgame.game_state = ng_state;
2152 }
2153 
2154 //*********************************************************************************************************
2155 // Game Update Packet
2156 //*********************************************************************************************************
2157 /*
2158 
2159 */
2160 // send a request or a reply for mission description, if code == 0, request, if code == 1, reply
2162 {
2164  int desc_len;
2165  int packet_size = 0;
2166 
2167  // build the header
2169 
2170  val = (ubyte)code;
2171  ADD_DATA(val);
2172 
2173  if(code == 1){
2174  // add as much of the description as we dare
2175  desc_len = strlen(The_mission.mission_desc);
2176  if(desc_len > MAX_PACKET_SIZE - 10){
2177  desc_len = MAX_PACKET_SIZE - 10;
2178  ADD_INT(desc_len);
2179  memcpy(data+packet_size, The_mission.mission_desc, desc_len);
2180  packet_size += desc_len;
2181  } else {
2183  }
2184  }
2185 
2186  Assert(addr != NULL);
2187  if(addr != NULL){
2188  psnet_send(addr, data, packet_size);
2189  }
2190 }
2191 
2192 // process an incoming netgame description packet
2194 {
2195  int offset,state;
2196  ubyte code;
2197  char mission_desc[MISSION_DESC_LENGTH+2];
2198  net_addr addr;
2199 
2200  fill_net_addr(&addr, hinfo->addr, hinfo->port);
2201 
2202  // read this game into a temporary structure
2203  offset = HEADER_LENGTH;
2204  GET_DATA(code);
2205 
2206  // if this is a request for mission description
2207  if(code == 0){
2209  PACKET_SET_SIZE();
2210  return;
2211  }
2212 
2213  // send an update to this guy
2214  send_netgame_descript_packet(&addr, 1);
2215  } else {
2216  memset(mission_desc,0,MISSION_DESC_LENGTH+2);
2217  GET_STRING(mission_desc);
2218 
2219  // only display if we're in the proper state
2220  state = gameseq_get_state();
2221  switch(state){
2225  multi_common_set_text(mission_desc);
2226  break;
2227  }
2228  }
2229 
2230  PACKET_SET_SIZE();
2231 }
2232 
2233 // broadcast a query for active games. TCP will either request from the MT or from the specified list
2235 {
2236  int packet_size;
2237  net_addr addr;
2238  server_item *s_moveup;
2240 
2243  return;
2244  }
2245 
2247 
2248  // go through the server list and query each of those as well
2249  s_moveup = Game_server_head;
2250  if(s_moveup != NULL){
2251  do {
2252  send_server_query(&s_moveup->server_addr);
2253  s_moveup = s_moveup->next;
2254  } while(s_moveup != Game_server_head);
2255  }
2256 
2258 
2259  // send out a broadcast if our options allow us
2261  psnet_broadcast( &addr, data, packet_size);
2262  }
2263 }
2264 
2265 // send an individual query to an address to see if there is an active game
2267 {
2268  int packet_size;
2270 
2271  // build the header and send the data
2273  psnet_send(addr, data, packet_size);
2274 }
2275 
2276 // process a query from a client looking for active freespace games
2278 {
2279  int offset;
2280  net_addr addr;
2281 
2282  offset = HEADER_LENGTH;
2283 
2284  PACKET_SET_SIZE();
2285 
2286  // check to be sure that we don't capture our own broadcast message
2287  fill_net_addr(&addr, hinfo->addr, hinfo->port);
2288  if ( psnet_same( &addr, &Psnet_my_addr) ){
2289  return;
2290  }
2291 
2292  // if I am not a server of a game, don't send a reply!!!
2294  return;
2295  }
2296 
2297  // if the game options are being selected, then ignore the request
2298  // also, if Netgame.max_players == -1, the host has not chosen a mission yet and we should wait
2300  return;
2301  }
2302 
2303  // send information about this active game
2304  send_game_active_packet(&addr);
2305 }
2306 
2307 // sends information about netplayers in the game. if called on the server, broadcasts information about _all_ players
2309 {
2310  int packet_size,idx;
2312 
2314 
2315  // if I'm the server of the game, I should send an update for _all_players in the game
2317  for(idx=0;idx<MAX_PLAYERS;idx++){
2318  // only send info for connected players
2319  if(MULTI_CONNECTED(Net_players[idx])){
2320  // add a stop byte
2321  val = 0x0;
2322  ADD_DATA(val);
2323 
2324  // add the net player's information
2325  ADD_SHORT(Net_players[idx].player_id);
2326  ADD_INT(Net_players[idx].state);
2327  ADD_INT(Net_players[idx].p_info.ship_class);
2328  ADD_INT(Net_players[idx].tracker_player_id);
2329 
2331  val = 1;
2332  } else {
2333  val = 0;
2334  }
2335  ADD_DATA(val);
2336  }
2337  }
2338  // add the final stop byte
2339  val = 0xff;
2340  ADD_DATA(val);
2341 
2342  // broadcast the packet
2343  if(!(Game_mode & GM_IN_MISSION)){
2344  if ( pl == NULL ) {
2345  multi_io_send_to_all_reliable(data, packet_size);
2346  } else {
2347  multi_io_send_reliable(pl, data, packet_size);
2348  }
2349  } else {
2350  if ( pl == NULL ) {
2351  multi_io_send_to_all(data, packet_size);
2352  } else {
2353  multi_io_send(pl, data, packet_size);
2354  }
2355  }
2356  } else {
2357  // add a stop byte
2358  val = 0x0;
2359  ADD_DATA(val);
2360 
2361  // add my current state in the netgame to this packet
2366 
2367  // add if I have a CD or not
2368  if(Multi_has_cd){
2369  val = 1;
2370  } else {
2371  val = 0;
2372  }
2373  ADD_DATA(val);
2374 
2375  // add a final stop byte
2376  val = 0xff;
2377  ADD_DATA(val);
2378 
2379  // send the packet to the server
2380  Assert( pl == NULL ); // shouldn't ever be the case that pl is non-null here.
2381  if(!(Game_mode & GM_IN_MISSION)){
2382  multi_io_send_reliable(Net_player, data, packet_size);
2383  } else {
2384  multi_io_send(Net_player, data, packet_size);
2385  }
2386  }
2387 }
2388 
2389 // process an incoming netplayer state update. if we're the server, we should rebroadcast
2391 {
2392  int offset, player_num;
2393  net_player bogus;
2394  ubyte stop, has_cd;
2395  short player_id;
2396  int new_state;
2397 
2398  offset = HEADER_LENGTH;
2399 
2400  // get the first stop byte
2401  GET_DATA(stop);
2402  player_num = -1;
2403  while(stop != 0xff){
2404  // look the player up
2405  GET_SHORT(player_id);
2406  player_num = find_player_id(player_id);
2407  // if we couldn't find him, read in the bogus data
2408  if((player_num == -1) || (Net_player == &Net_players[player_num])){
2409  GET_INT(bogus.state);
2410  GET_INT(bogus.p_info.ship_class);
2411  GET_INT(bogus.tracker_player_id);
2412 
2413  GET_DATA(has_cd);
2414  }
2415  // otherwise read in the data correctly
2416  else {
2417  GET_INT(new_state);
2418  GET_INT(Net_players[player_num].p_info.ship_class);
2419  GET_INT(Net_players[player_num].tracker_player_id);
2420  GET_DATA(has_cd);
2421  if(has_cd){
2422  Net_players[player_num].flags |= NETINFO_FLAG_HAS_CD;
2423  } else {
2424  Net_players[player_num].flags &= ~(NETINFO_FLAG_HAS_CD);
2425  }
2426 
2427  // if he's changing state to joined, send a team update
2428  if((Net_players[player_num].state == NETPLAYER_STATE_JOINING) && (new_state == NETPLAYER_STATE_JOINED) && (Netgame.type_flags & NG_TYPE_TEAM)){
2430  }
2431 
2432  // set state
2433  Net_players[player_num].state = new_state;
2434  }
2435 
2436  // get the next stop byte
2437  GET_DATA(stop);
2438  }
2439 
2440  PACKET_SET_SIZE();
2441 
2442  // if I'm the host or the server of the game, update everyone else so things are synched up as tightly as possible
2445  }
2446 
2447  // if i'm the standalone and this is an update from the host, maybe change some netgame settings
2448  if((Game_mode & GM_STANDALONE_SERVER) && (player_num != -1) && (Net_players[player_num].flags & NETINFO_FLAG_GAME_HOST)){
2449  switch(Net_players[player_num].state){
2452  break;
2453 
2455  // check for race conditions
2458  }
2459  break;
2460  }
2461  }
2462 }
2463 
2464 #define EXTRA_DEATH_VAPORIZED (1<<0)
2465 #define EXTRA_DEATH_WASHED (1<<1)
2466 // send a packet indicating a ship has been killed
2467 void send_ship_kill_packet( object *objp, object *other_objp, float percent_killed, int self_destruct )
2468 {
2469  int packet_size, model;
2470  ubyte data[MAX_PACKET_SIZE], was_player, extra_death_info, vaporized;
2471  ushort debris_signature;
2472  ubyte sd;
2473  polymodel * pm;
2474 
2475  // only sendable from the master
2477 
2478  // special deaths
2479  vaporized = ( (Ships[objp->instance].flags & SF_VAPORIZE) > 0 );
2480 
2481  extra_death_info = 0;
2482  if ( vaporized ) {
2483  extra_death_info |= EXTRA_DEATH_VAPORIZED;
2484  }
2485 
2486  if ( Ships[objp->instance].wash_killed ) {
2487  extra_death_info |= EXTRA_DEATH_WASHED;
2488  }
2489 
2490  // find out the next network signature that will be used for the debris pieces.
2491  model = Ship_info[Ships[objp->instance].ship_info_index].model_num;
2492  pm = model_get(model);
2493  debris_signature = 0;
2494  if ( pm && !vaporized ) {
2495  debris_signature = multi_get_next_network_signature( MULTI_SIG_DEBRIS );
2497  Ships[objp->instance].debris_net_sig = debris_signature;
2498  }
2499 
2501  ADD_USHORT(objp->net_signature);
2502 
2503  // ships which are initially killed get the rest of the data sent. self destructed ships and
2504  if ( other_objp == NULL ) {
2505  ushort temp;
2506 
2507  temp = 0;
2508  ADD_USHORT(temp);
2509  nprintf(("Network","Don't know other_obj for ship kill packet, sending NULL\n"));
2510  } else {
2511  ADD_USHORT( other_objp->net_signature );
2512  }
2513 
2514  ADD_USHORT( debris_signature );
2515  ADD_FLOAT( percent_killed );
2516  sd = (ubyte)self_destruct;
2517  ADD_DATA(sd);
2518  ADD_DATA( extra_death_info );
2519 
2520  // if the ship who died is a player, then send some extra info, like who killed him, etc.
2521  was_player = 0;
2522  if ( objp->flags & OF_PLAYER_SHIP ) {
2523  int pnum;
2524  char temp;
2525  short temp2;
2526 
2527  pnum = multi_find_player_by_object( objp );
2528  if ( pnum != -1 ) {
2529  was_player = 1;
2530  ADD_DATA( was_player );
2531 
2532  Assert(Net_players[pnum].m_player->killer_objtype < CHAR_MAX);
2533  temp = (char)Net_players[pnum].m_player->killer_objtype;
2534  ADD_DATA( temp );
2535 
2536  Assert(Net_players[pnum].m_player->killer_species < CHAR_MAX);
2537  temp = (char)Net_players[pnum].m_player->killer_species;
2538  ADD_DATA( temp );
2539 
2540  Assert(Net_players[pnum].m_player->killer_weapon_index < SHRT_MAX);
2541  temp2 = (short)Net_players[pnum].m_player->killer_weapon_index;
2542  ADD_SHORT( temp2 );
2543 
2544  ADD_STRING( Net_players[pnum].m_player->killer_parent_name );
2545  } else {
2546  ADD_DATA( was_player );
2547  }
2548  } else {
2549  ADD_DATA( was_player );
2550  }
2551 
2552  // send the packet reliably!!!
2553  multi_io_send_to_all_reliable(data, packet_size);
2554 }
2555 
2556 // process a packet indicating that a ship has been killed
2558 {
2559  int offset;
2560  ushort ship_sig, other_sig, debris_sig;
2561  object *sobjp, *oobjp;
2562  float percent_killed;
2563  ubyte was_player, extra_death_info, sd;
2564  char killer_name[NAME_LENGTH], killer_objtype = OBJ_NONE, killer_species = 0;
2565  short killer_weapon_index = -1;
2566 
2567  offset = HEADER_LENGTH;
2568  GET_USHORT(ship_sig);
2569 
2570  GET_USHORT( other_sig );
2571  GET_USHORT( debris_sig );
2572  GET_FLOAT( percent_killed );
2573  GET_DATA( sd );
2574  GET_DATA( extra_death_info );
2575  GET_DATA( was_player );
2576 
2577 
2578  // pnum is >=0 when the dying ship is a pleyer ship. Get the info about how he died
2579  if ( was_player != 0 ) {
2580  GET_DATA( killer_objtype );
2581  GET_DATA( killer_species );
2582  GET_SHORT( killer_weapon_index );
2583  GET_STRING( killer_name );
2584  }
2585 
2586  PACKET_SET_SIZE();
2587 
2588  sobjp = multi_get_network_object( ship_sig );
2589 
2590  // if I am unable to find the ship object which was killed, I have to bail and rely on getting
2591  // another message from the server that this happened!
2592  if ( sobjp == NULL ) {
2593  nprintf(("Network", "Couldn't find net signature %d for kill packet\n", ship_sig));
2594  return;
2595  }
2596 
2597  // set this ship's hull value to 0
2598  sobjp->hull_strength = 0.0f;
2599 
2600  // maybe set vaporized
2601  if (extra_death_info & EXTRA_DEATH_VAPORIZED) {
2602  Ships[sobjp->instance].flags |= SF_VAPORIZE;
2603  }
2604 
2605  // maybe set wash_killed
2606  if (extra_death_info & EXTRA_DEATH_VAPORIZED) {
2607  Ships[sobjp->instance].wash_killed = 1;
2608  }
2609 
2610  oobjp = multi_get_network_object( other_sig );
2611 
2612  if ( was_player != 0 ) {
2613  int pnum;
2614 
2615  pnum = multi_find_player_by_object( sobjp );
2616  if ( pnum != -1 ) {
2617  Net_players[pnum].m_player->killer_objtype = killer_objtype;
2618  Net_players[pnum].m_player->killer_species = killer_species;
2619  Net_players[pnum].m_player->killer_weapon_index = killer_weapon_index;
2620  strcpy_s( Net_players[pnum].m_player->killer_parent_name, killer_name );
2621  }
2622  }
2623 
2624  // check to see if I need to respawn myself
2625  multi_respawn_check(sobjp);
2626 
2627  // store the debris signature in the arrival distance which will never get used for player ships
2628  Ships[sobjp->instance].debris_net_sig = debris_sig;
2629 
2630  // set this bit so that we don't accidentally start switching targets when we die
2631  if(sobjp == Player_obj){
2633  }
2634 
2635  mprintf(("Network Killing off %s\n", Ships[sobjp->instance].ship_name));
2636 
2637  // do the normal thing when not ingame joining. When ingame joining, simply kill off the ship.
2639  ship_hit_kill( sobjp, oobjp, percent_killed, sd );
2640  } else {
2641  sobjp->flags |= OF_SHOULD_BE_DEAD;
2643  obj_delete( OBJ_INDEX(sobjp) );
2644  }
2645 }
2646 
2647 // send a packet indicating a ship should be created
2648 void send_ship_create_packet( object *objp, int is_support )
2649 {
2650  int packet_size;
2652 
2653  // We will pass the ship to create by name.
2655  ADD_USHORT(objp->net_signature);
2656  ADD_INT( is_support );
2657  if ( is_support ){
2658  ADD_VECTOR( objp->pos );
2659  }
2660 
2661  // broadcast the packet
2662  multi_io_send_to_all_reliable(data, packet_size);
2663 }
2664 
2665 // process a packet indicating a ship should be created
2667 {
2668  int offset, objnum, is_support;
2669  ushort signature;
2670  p_object *objp;
2671  vec3d pos = ZERO_VECTOR;
2672 
2674  offset = HEADER_LENGTH;
2675  GET_USHORT(signature);
2676  GET_INT( is_support );
2677  if ( is_support ){
2678  GET_VECTOR( pos );
2679  }
2680 
2681  PACKET_SET_SIZE();
2682 
2683  // find the name of this ship on ship ship arrival list. if found, pass it to parse_object_create
2684  if ( !is_support ) {
2685  objp = mission_parse_get_arrival_ship( signature );
2686  if ( objp != NULL ) {
2687  objnum = parse_create_object(objp);
2688  } else {
2689  nprintf(("Network", "Ship with sig %d not found on ship arrival list -- not creating!!\n", signature));
2690  }
2691  } else {
2693  if(Arriving_support_ship == NULL){
2694  return;
2695  }
2697  Arriving_support_ship->net_signature = signature;
2699  Assert( objnum != -1 );
2700  if(objnum >= 0){
2702  }
2703  }
2704 }
2705 
2706 // send a packet indicating a wing of ships should be created
2707 void send_wing_create_packet( wing *wingp, int num_to_create, int pre_create_count )
2708 {
2709  int packet_size, index, ship_instance;
2711  ushort signature;
2712  int val;
2713 
2714  // for creating wing -- we just send the index into the wing array of this wing.
2715  // all players load the same mission, and so their array's should all match. We also
2716  // need to send the signature of the first ship that was created. We can find this by
2717  // looking num_to_create places back in the ship_index field in the wing structure.
2718 
2719  index = WING_INDEX(wingp);
2720  ship_instance = wingp->ship_index[wingp->current_count - num_to_create];
2721  signature = Objects[Ships[ship_instance].objnum].net_signature;
2722 
2724  ADD_INT(index);
2725  ADD_INT(num_to_create);
2726  ADD_USHORT(signature);
2727  ADD_INT(pre_create_count);
2728  val = wingp->current_wave - 1;
2729  ADD_INT(val);
2730 
2731  multi_io_send_to_all_reliable(data, packet_size);
2732 }
2733 
2734 // process a packet saying that a wing should be created
2736 {
2737  int offset, index, num_to_create;
2738  ushort signature;
2739  int total_arrived_count, current_wave;
2740 
2741  offset = HEADER_LENGTH;
2742  GET_INT(index);
2743  GET_INT(num_to_create);
2744  GET_USHORT(signature);
2745  GET_INT(total_arrived_count);
2746  GET_INT(current_wave);
2747 
2748  PACKET_SET_SIZE();
2749 
2750  // do a sanity check on the wing to be sure that we are actually working on a valid wing
2751  if ( (index < 0) || (index >= Num_wings) || (Wings[index].num_waves == -1) ) {
2752  nprintf(("Network", "Invalid index %d for wing create packet\n", index));
2753  return;
2754  }
2755  if ( (num_to_create <= 0) || (num_to_create > Wings[index].wave_count) ) {
2756  nprintf(("Network", "Invalid number of ships to create (%d) for wing %s\n", num_to_create, Wings[index].name));
2757  return;
2758  }
2759 
2760  // bash some info
2761  Wings[index].current_count = 0;
2762  Wings[index].total_arrived_count = total_arrived_count;
2763  Wings[index].current_wave = current_wave;
2764 
2765  // set the network signature that was passed. The client should create ships in the same order
2766  // as the server -- so all ships should get the same sigs as assigned by the server. We also
2767  // need to set some timestamps and cues correctly to be sure that these things get created on
2768  // the clients correctly
2770  parse_wing_create_ships( &Wings[index], num_to_create, 1 );
2771 }
2772 
2773 // packet indicating a ship is departing
2774 void send_ship_depart_packet( object *objp, int method )
2775 {
2777  int packet_size;
2778  ushort signature;
2779 
2780  signature = objp->net_signature;
2781 
2783  ADD_USHORT( signature );
2784  ADD_INT( method );
2785 
2786  multi_io_send_to_all_reliable(data, packet_size);
2787 }
2788 
2789 // process a packet indicating a ship is departing
2791 {
2792  int offset;
2793  object *objp;
2794  ushort signature;
2795  int s_method;
2796 
2797  offset = HEADER_LENGTH;
2798  GET_USHORT( signature );
2799  GET_INT(s_method);
2800  PACKET_SET_SIZE();
2801 
2802  // find the object which is departing
2803  objp = multi_get_network_object( signature );
2804  if ( objp == NULL ) {
2805  nprintf(("network", "Couldn't find object with net signature %d to depart\n", signature ));
2806  return;
2807  }
2808 
2809  switch (s_method) {
2810  case SHIP_DEPARTED_BAY:
2811  case SHIP_VANISHED:
2812  if (objp->type == OBJ_SHIP) {
2813  ship_actually_depart(objp->instance, s_method);
2814  }
2815  else {
2816  nprintf(("network", "Can not process ship depart packed. Object with net signature %d is not a ship!\n", signature ));
2817  return;
2818  }
2819  break;
2820 
2821  // assume standard warp out
2822  default:
2823  // start warping him out
2824  shipfx_warpout_start( objp );
2825  }
2826 }
2827 
2828 // packet to tell clients cargo of a ship was revealed to all
2830 {
2832  int packet_size;
2833 
2834  // build the header and add the data
2837 
2838  // server sends to all players
2839  if(MULTIPLAYER_MASTER){
2840  multi_io_send_to_all_reliable(data, packet_size);
2841  }
2842  // clients just send to the server
2843  else {
2844  multi_io_send_reliable(Net_player, data, packet_size);
2845  }
2846 }
2847 
2848 // process a cargo revealed packet
2850 {
2851  int offset;
2852  ushort signature;
2853  object *objp;
2854 
2855  offset = HEADER_LENGTH;
2856  GET_USHORT(signature);
2857  PACKET_SET_SIZE();
2858 
2859  // get a ship pointer and call the ship function to reveal the cargo
2860  objp = multi_get_network_object( signature );
2861  if ( objp == NULL ) {
2862  nprintf(("Network", "Could not find object with net signature %d for cargo revealed\n", signature ));
2863  return;
2864  }
2865 
2866  // Assert( objp->type == OBJ_SHIP );
2867  if((objp->type != OBJ_SHIP) || (objp->instance < 0) || (objp->instance >= MAX_SHIPS)){
2868  return;
2869  }
2870 
2871  // this will take care of re-routing to all other clients
2872  ship_do_cargo_revealed( &Ships[objp->instance], 1);
2873 
2874  // server should rebroadcast
2875  if(MULTIPLAYER_MASTER){
2877  }
2878 }
2879 
2880 // packet to tell clients cargo of a ship was hidden to all
2882 {
2884  int packet_size;
2885 
2886  // build the header and add the data
2889 
2890  // server sends to all players
2891  if(MULTIPLAYER_MASTER){
2892  multi_io_send_to_all_reliable(data, packet_size);
2893  }
2894  // clients just send to the server
2895  else {
2896  multi_io_send_reliable(Net_player, data, packet_size);
2897  }
2898 }
2899 
2900 // process a cargo hidden packet
2902 {
2903  int offset;
2904  ushort signature;
2905  object *objp;
2906 
2907  offset = HEADER_LENGTH;
2908  GET_USHORT(signature);
2909  PACKET_SET_SIZE();
2910 
2911  // get a ship pointer and call the ship function to hide the cargo
2912  objp = multi_get_network_object( signature );
2913  if ( objp == NULL ) {
2914  nprintf(("Network", "Could not find object with net signature %d for cargo hidden\n", signature ));
2915  return;
2916  }
2917 
2918  // Assert( objp->type == OBJ_SHIP );
2919  if((objp->type != OBJ_SHIP) || (objp->instance < 0) || (objp->instance >= MAX_SHIPS)){
2920  return;
2921  }
2922 
2923  // this will take care of re-routing to all other clients
2924  ship_do_cargo_hidden( &Ships[objp->instance], 1);
2925 
2926  // server should rebroadcast
2927  if(MULTIPLAYER_MASTER){
2929  }
2930 }
2931 
2932 // defines used for secondary fire packet
2933 #define SFPF_ALLOW_SWARM (1<<7)
2934 #define SFPF_DUAL_FIRE (1<<6)
2935 #define SFPF_TARGET_LOCKED (1<<5)
2936 
2937 // send a packet indicating a secondary weapon was fired
2938 void send_secondary_fired_packet( ship *shipp, ushort starting_sig, int starting_count, int num_fired, int allow_swarm )
2939 {
2940  int packet_size, net_player_num;
2941  ubyte data[MAX_PACKET_SIZE], sinfo, current_bank;
2942  object *objp;
2943  ushort target_signature;
2944  char t_subsys;
2945  ai_info *aip;
2946 
2947  // Assert ( starting_count < UCHAR_MAX );
2948 
2949  // get the object for this ship. If it is an AI object, send all the info to all player. Otherwise,
2950  // we might send the info to the other player different than the one who fired
2951  objp = &Objects[shipp->objnum];
2952  if ( !(objp->flags & OF_PLAYER_SHIP) ) {
2953  if ( num_fired == 0 ) {
2954  return;
2955  }
2956  }
2957 
2958  aip = &Ai_info[shipp->ai_index];
2959 
2960  current_bank = (ubyte)shipp->weapons.current_secondary_bank;
2961  Assert( (current_bank < MAX_SHIP_SECONDARY_BANKS) );
2962 
2963  // build up the header portion
2965 
2967  ADD_USHORT( starting_sig );
2968 
2969  // add a couple of bits for swarm missiles and dual fire secondary weapons
2970  sinfo = current_bank;
2971 
2972  if ( allow_swarm ){
2973  sinfo |= SFPF_ALLOW_SWARM;
2974  }
2975 
2976  if ( shipp->flags & SF_SECONDARY_DUAL_FIRE ){
2977  sinfo |= SFPF_DUAL_FIRE;
2978  }
2979 
2980  if ( aip->current_target_is_locked ){
2981  sinfo |= SFPF_TARGET_LOCKED;
2982  }
2983 
2984  ADD_DATA( sinfo );
2985 
2986  // add the ship's target and any targeted subsystem
2987  target_signature = 0;
2988  t_subsys = -1;
2989  if ( aip->target_objnum != -1) {
2990  target_signature = Objects[aip->target_objnum].net_signature;
2991  if ( (Objects[aip->target_objnum].type == OBJ_SHIP) && (aip->targeted_subsys != NULL) ) {
2992  int s_index;
2993 
2995  Assert( s_index < CHAR_MAX ); // better be less than this!!!!
2996  t_subsys = (char)s_index;
2997  }
2998 
2999  if ( Objects[aip->target_objnum].type == OBJ_WEAPON ) {
3001  }
3002 
3003  }
3004 
3005  ADD_USHORT( target_signature );
3006  ADD_DATA( t_subsys );
3007 
3008  // just send this packet to everyone, then bail if an AI ship fired.
3009  if ( !(objp->flags & OF_PLAYER_SHIP) ) {
3010  multi_io_send_to_all(data, packet_size);
3011  return;
3012  }
3013 
3014  net_player_num = multi_find_player_by_object( objp );
3015 
3016  if ( net_player_num < 0 ) {
3017  // Pass to higher level code to handle
3018  return;
3019  }
3020 
3021  // getting here means a player fired. Send the current packet to all players except the player
3022  // who fired. If nothing got fired, then don't send to the other players -- we will just send
3023  // a packet to the player who will find out that he didn't fire anything
3024  if ( num_fired > 0 ) {
3025  multi_io_send_to_all_reliable(data, packet_size, &Net_players[net_player_num]);
3026  }
3027 
3028  // if I (the master) fired, then return
3029  if ( Net_players[net_player_num].flags & NETINFO_FLAG_AM_MASTER ){
3030  return;
3031  }
3032 
3033  // now build up the packet to send to the player who actually fired.
3035  ADD_USHORT(starting_sig);
3036  ADD_DATA( sinfo );
3037 
3038  // add the targeting information so that the player's weapons will always home on the correct
3039  // ship
3040  ADD_USHORT( target_signature );
3041  ADD_DATA( t_subsys );
3042 
3043  multi_io_send_reliable(&Net_players[net_player_num], data, packet_size);
3044 }
3045 
3047 void process_secondary_fired_packet(ubyte* data, header* hinfo, int from_player)
3048 {
3049  int offset, allow_swarm, target_objnum_save;
3050  ushort net_signature, starting_sig, target_signature;
3051  ubyte sinfo, current_bank;
3052  object* objp, *target_objp;
3053  ship *shipp;
3054  char t_subsys;
3055  ai_info *aip;
3056  ship_subsys *targeted_subsys_save;
3057 
3058  offset = HEADER_LENGTH; // size of the header
3059 
3060  // if from_player is false, it means that the secondary weapon info in this packet was
3061  // fired by an ai object (or another player). from_player == 1 means tha me (the person
3062  // receiving this packet) fired the secondary weapon
3063  if ( !from_player ) {
3064  GET_USHORT( net_signature );
3065  GET_USHORT( starting_sig );
3066  GET_DATA( sinfo ); // are we firing swarm missiles
3067 
3068  GET_USHORT( target_signature );
3069  GET_DATA( t_subsys );
3070 
3071  PACKET_SET_SIZE();
3072 
3073  // find the object (based on network signatures) for the object that fired
3074  objp = multi_get_network_object( net_signature );
3075  if ( objp == NULL ) {
3076  nprintf(("Network", "Could not find ship for fire secondary packet!"));
3077  return;
3078  }
3079 
3080  // set up the ships current secondary bank and that bank's mode. Below, we will set the timeout
3081  // of the next fire time of this bank to 0 so we can fire right away
3082  shipp = &Ships[objp->instance];
3083 
3084  } else {
3085  GET_USHORT( starting_sig );
3086  GET_DATA( sinfo );
3087 
3088  GET_USHORT( target_signature );
3089  GET_DATA( t_subsys );
3090 
3091  PACKET_SET_SIZE();
3092 
3093  // get the object and ship
3094  objp = Player_obj;
3095  shipp = Player_ship;
3096  }
3097 
3098  // check the allow swarm bit
3099  allow_swarm = 0;
3100  if ( sinfo & SFPF_ALLOW_SWARM ){
3101  allow_swarm = 1;
3102  }
3103 
3104  // set the dual fire properties of the ship
3105  if ( sinfo & SFPF_DUAL_FIRE ){
3106  shipp->flags |= SF_SECONDARY_DUAL_FIRE;
3107  } else {
3108  shipp->flags &= ~SF_SECONDARY_DUAL_FIRE;
3109  }
3110 
3111  // determine whether current target is locked
3112  Assert( shipp->ai_index != -1 );
3113  aip = &Ai_info[shipp->ai_index];
3114  if ( sinfo & SFPF_TARGET_LOCKED ) {
3115  aip->current_target_is_locked = 1;
3116  } else {
3117  aip->current_target_is_locked = 0;
3118  }
3119 
3120  // find out the current bank
3121  current_bank = (ubyte)(sinfo & 0x3);
3122  Assert( (current_bank < MAX_SHIP_SECONDARY_BANKS) );
3123  shipp->weapons.current_secondary_bank = current_bank;
3124 
3125  // make it so we can fire this ship's secondary bank immediately!!!
3127  shipp->weapons.detonate_weapon_time = timestamp(5000); // be sure that we don't detonate a remote weapon before it is time.
3128 
3129  // set this ship's target and subsystem information. We will save and restore target and
3130  // targeted subsystem so that we do not accidentally change targets for this player or
3131  // any AI ships on his system.
3132  target_objnum_save = aip->target_objnum;
3133  targeted_subsys_save = aip->targeted_subsys;
3134 
3135  // reset these variables for accuracy. They will get reassigned at the end of this fuction
3136  aip->target_objnum = -1;
3137  aip->targeted_subsys = NULL;
3138 
3139  target_objp = multi_get_network_object( target_signature );
3140  if ( target_objp != NULL ) {
3141  aip->target_objnum = OBJ_INDEX(target_objp);
3142 
3143  if ( (t_subsys != -1) && (target_objp->type == OBJ_SHIP) ) {
3144  aip->targeted_subsys = ship_get_indexed_subsys( &Ships[target_objp->instance], t_subsys);
3145  }
3146  }
3147 
3148  if ( starting_sig != 0 ){
3150  } else {
3151  shipp->weapons.detonate_weapon_time = timestamp(0); // signature of -1 say detonate remote weapon
3152  }
3153 
3154  ship_fire_secondary( objp, allow_swarm );
3155 
3156  // restore targeted object and targeted subsystem
3157  aip->target_objnum = target_objnum_save;
3158  aip->targeted_subsys = targeted_subsys_save;
3159 }
3160 
3161 // send a packet indicating a countermeasure was fired
3162 void send_countermeasure_fired_packet( object *objp, int cmeasure_count, int rand_val )
3163 {
3165  int packet_size;
3166 
3167  Int3();
3168 
3169  Assert ( cmeasure_count < UCHAR_MAX );
3171  ADD_USHORT( objp->net_signature );
3172  ADD_INT( rand_val );
3173 
3174  multi_io_send_to_all(data, packet_size);
3175 }
3176 
3177 // process a packet indicating a countermeasure was fired
3179 {
3180  int offset, rand_val;
3181  ushort signature;
3182  object *objp;
3183 
3184  Int3();
3185 
3186  offset = HEADER_LENGTH;
3187 
3188  GET_USHORT( signature );
3189  GET_INT( rand_val );
3190  PACKET_SET_SIZE();
3191 
3192  objp = multi_get_network_object( signature );
3193  if ( objp == NULL ) {
3194  nprintf(("network", "Could find object whose countermeasures are being launched!!!\n"));
3195  return;
3196  }
3197  if(objp->type != OBJ_SHIP){
3198  return;
3199  }
3200  // Assert ( objp->type == OBJ_SHIP );
3201 
3202  // make it so ship can fire right away!
3204  if ( objp == Player_obj ){
3205  nprintf(("network", "firing countermeasure from my ship\n"));
3206  }
3207 
3208  ship_launch_countermeasure( objp, rand_val );
3209 }
3210 
3211 // send a packet indicating that a turret has been fired
3212 void send_turret_fired_packet( int ship_objnum, int subsys_index, int weapon_objnum )
3213 {
3214  int packet_size;
3215  ushort pnet_signature;
3216  ubyte data[MAX_PACKET_SIZE], cindex;
3217  object *objp;
3218  ubyte has_sig = 0;
3219  ship_subsys *ssp;
3220  short val;
3221 
3222  // sanity
3223  if((weapon_objnum < 0) || (Objects[weapon_objnum].type != OBJ_WEAPON) || (Objects[weapon_objnum].instance < 0) || (Weapons[Objects[weapon_objnum].instance].weapon_info_index < 0)){
3224  return;
3225  }
3226 
3227  // local setup -- be sure we are actually passing a weapon!!!!
3228  objp = &Objects[weapon_objnum];
3229  Assert ( objp->type == OBJ_WEAPON );
3231  has_sig = 1;
3232  }
3233 
3234  pnet_signature = Objects[ship_objnum].net_signature;
3235 
3236  Assert( subsys_index < UCHAR_MAX );
3237  cindex = (ubyte)subsys_index;
3238 
3239  ssp = ship_get_indexed_subsys( &Ships[Objects[ship_objnum].instance], subsys_index, NULL );
3240  if(ssp == NULL){
3241  return;
3242  }
3243 
3244  // build the fire turret packet.
3246  packet_size += multi_pack_unpack_position(1, data + packet_size, &objp->orient.vec.fvec);
3247  ADD_DATA( has_sig );
3248  ADD_USHORT( pnet_signature );
3249  if(has_sig){
3250  ADD_USHORT( objp->net_signature );
3251  }
3252  ADD_DATA( cindex );
3253  val = (short)ssp->submodel_info_1.angs.h;
3254  ADD_SHORT( val );
3255  val = (short)ssp->submodel_info_2.angs.p;
3256  ADD_SHORT( val );
3257 
3258  multi_io_send_to_all(data, packet_size);
3259 
3260  multi_rate_add(1, "tur", packet_size);
3261 }
3262 
3263 // process a packet indicating a turret has been fired
3265 {
3266  int offset, weapon_objnum, wid = -1;
3267  ushort pnet_signature, wnet_signature;
3268  vec3d pos, temp;
3269  matrix orient;
3270  vec3d o_fvec;
3271  ubyte turret_index;
3272  object *objp;
3273  ship_subsys *ssp;
3274  ubyte has_sig = 0;
3275  ship *shipp;
3276  short pitch, heading;
3277 
3278  // get the data for the turret fired packet
3279  offset = HEADER_LENGTH;
3280  offset += multi_pack_unpack_position(0, data + offset, &o_fvec);
3281  GET_DATA( has_sig );
3282  GET_USHORT( pnet_signature );
3283  if(has_sig){
3284  GET_USHORT( wnet_signature );
3285  } else {
3286  wnet_signature = 0;
3287  }
3288  GET_DATA( turret_index );
3289  GET_SHORT( heading );
3290  GET_SHORT( pitch );
3291  PACKET_SET_SIZE(); // move our counter forward the number of bytes we have read
3292 
3293  // find the object
3294  objp = multi_get_network_object( pnet_signature );
3295  if ( objp == NULL ) {
3296  nprintf(("network", "could find parent object with net signature %d for turret firing\n", pnet_signature));
3297  return;
3298  }
3299 
3300  // if this isn't a ship, do nothing
3301  if ( objp->type != OBJ_SHIP ){
3302  return;
3303  }
3304 
3305  // make an orientation matrix from the o_fvec
3306  vm_vector_2_matrix(&orient, &o_fvec, NULL, NULL);
3307 
3308  // find this turret, and set the position of the turret that just fired to be where it fired. Quite a
3309  // hack, but should be suitable.
3310  shipp = &Ships[objp->instance];
3311  ssp = ship_get_indexed_subsys( shipp, turret_index, NULL );
3312  if(ssp == NULL){
3313  return;
3314  }
3315 
3316  if (ssp->weapons.num_primary_banks > 0) {
3317  wid = ssp->weapons.primary_bank_weapons[0];
3318  } else if (ssp->weapons.num_secondary_banks > 0) {
3319  wid = ssp->weapons.secondary_bank_weapons[0];
3320  }
3321 
3322  if (wid < 0)
3323  return;
3324 
3325  // bash the position and orientation of the turret
3326  ssp->submodel_info_1.angs.h = (float)heading;
3327  ssp->submodel_info_2.angs.p = (float)pitch;
3328 
3329  // get the world position of the weapon
3330  ship_get_global_turret_info(objp, ssp->system_info, &pos, &temp);
3331 
3332  // create the weapon object
3333  if(wnet_signature != 0){
3335  }
3336 
3337  weapon_objnum = weapon_create( &pos, &orient, wid, OBJ_INDEX(objp), -1, 1, 0, 0.0f, ssp);
3338 
3339  if (weapon_objnum != -1) {
3340  wid = Weapons[Objects[weapon_objnum].instance].weapon_info_index;
3341  if ( Weapon_info[wid].launch_snd != -1 ) {
3342  snd_play_3d( &Snds[Weapon_info[wid].launch_snd], &pos, &View_position );
3343  }
3344  }
3345 }
3346 
3347 // send a mission log item packet
3349 {
3350  int packet_size;
3352  ubyte type;
3353  int sindex;
3354  log_entry *entry;
3355 
3357 
3358  // get the data from the log
3359  entry = &log_entries[num];
3360  type = (ubyte)entry->type; // do the type casting thing to save on packet space
3361  sindex = entry->index;
3362 
3364  ADD_DATA(type);
3365  ADD_INT(entry->flags);
3366  ADD_INT(sindex);
3367  ADD_INT(entry->timestamp); // NOTE: this is a long so careful with swapping in 64-bit platforms - taylor
3368  ADD_STRING(entry->pname);
3369  ADD_STRING(entry->sname);
3370 
3371  // broadcast the packet to all players
3372  multi_io_send_to_all_reliable(data, packet_size);
3373 }
3374 
3375 // process a mission log item packet
3377 {
3378  int offset, flags;
3379  int sindex;
3380  ubyte type;
3381  char pname[NAME_LENGTH], sname[NAME_LENGTH];
3382  fix timestamp;
3383 
3385 
3386  offset = HEADER_LENGTH;
3387  GET_DATA(type);
3388  GET_INT(flags);
3389  GET_INT(sindex);
3390  GET_INT(timestamp); // NOTE: this is a long so careful with swapping in 64-bit platforms - taylor
3391  GET_STRING(pname);
3392  GET_STRING(sname);
3393 
3394  PACKET_SET_SIZE();
3395 
3396  mission_log_add_entry_multi( type, pname, sname, sindex, timestamp, flags );
3397 }
3398 
3399 // send a mission message packet
3400 void send_mission_message_packet( int id, char *who_from, int priority, int timing, int source, int builtin_type, int multi_target, int multi_team_filter, int delay)
3401 {
3402  int packet_size;
3403  ubyte data[MAX_PACKET_SIZE], up, us, utime;
3404 
3406  Assert ( (priority >= 0) && (priority < UCHAR_MAX) );
3407  Assert ( (timing >= 0) && (timing < UCHAR_MAX) );
3408 
3409  up = (ubyte) priority;
3410  us = (ubyte) source;
3411  utime = (ubyte)timing;
3412 
3414  ADD_INT(id);
3415  ADD_STRING(who_from);
3416  ADD_DATA(up);
3417  ADD_DATA(utime);
3418  ADD_DATA(us);
3419  ADD_INT(builtin_type);
3420  ADD_INT(multi_team_filter);
3421  ADD_INT(delay);
3422 
3423  if (multi_target == -1){
3424  multi_io_send_to_all_reliable(data, packet_size);
3425  } else {
3426  multi_io_send_reliable(&Net_players[multi_target], data, packet_size);
3427  }
3428 }
3429 
3430 // process a mission message packet
3432 {
3433  int offset, id, builtin_type, delay;
3434  ubyte priority, source, utiming;
3435  char who_from[NAME_LENGTH];
3436  int multi_team_filter;
3437 
3439 
3440  offset = HEADER_LENGTH;
3441  GET_INT(id);
3442  GET_STRING(who_from);
3443  GET_DATA(priority);
3444  GET_DATA(utiming);
3445  GET_DATA(source);
3446  GET_INT(builtin_type);
3447  GET_INT(multi_team_filter);
3448  GET_INT(delay);
3449 
3450  PACKET_SET_SIZE();
3451 
3452  // filter out some builtin ones in TvT
3453  if((builtin_type >= 0) && (Netgame.type_flags & NG_TYPE_TEAM) && (Net_player != NULL) && (Net_player->p_info.team != multi_team_filter)) {
3454  mprintf(("Builtin message of type %d filtered out in process_mission_message_packet()\n", id));
3455  return;
3456  }
3457 
3458  // maybe filter this out
3459  if(!message_filter_multi(id)){
3460  // send the message as if it came from an sexpression
3461  message_queue_message( id, priority, utiming, who_from, source, 0, delay, builtin_type );
3462  }
3463 }
3464 
3465 // just send them a pong back as fast as possible
3467 {
3468  net_addr addr;
3469  int offset;
3470 
3471  offset = HEADER_LENGTH;
3472  PACKET_SET_SIZE();
3473 
3474  // get the address to return the pong to
3475  fill_net_addr(&addr, hinfo->addr, hinfo->port);
3476 
3477  // send the pong
3478  send_pong(&addr);
3479 }
3480 
3481 // right now it just routes the pong through to the standalone gui, which is the only
3482 // system which uses ping and pong right now.
3484 {
3485  net_player *p;
3486  net_addr addr;
3487  int offset,lookup;
3488 
3489  offset = HEADER_LENGTH;
3490 
3491  fill_net_addr(&addr, hinfo->addr, hinfo->port);
3492 
3493  PACKET_SET_SIZE();
3494 
3495  // if we're connected , see who sent us this pong
3497  lookup = find_player_id(hinfo->id);
3498  if(lookup == -1){
3499  return;
3500  }
3501 
3502  p = &Net_players[lookup];
3503 
3504  // evaluate the ping
3505  multi_ping_eval_pong(&Net_players[lookup].s_info.ping);
3506 
3507  // put in calls to any functions which may want to know about the ping times from
3508  // this guy
3511  }
3512 
3513  // mark his socket as still alive (extra precaution)
3515  }
3516  // otherwise, do any special processing
3517  else {
3518  // if we're in the join game state, see if this pong came from a server on our
3519  // list
3522  }
3523  }
3524 }
3525 
3526 // send a ping packet
3528 {
3529  unsigned char data[8];
3530  int packet_size;
3531 
3532  // build the header and send the packet
3533  BUILD_HEADER( PING );
3534  psnet_send(addr, &data[0], packet_size);
3535 }
3536 
3537 // send a pong packet
3539 {
3540  unsigned char data[8];
3541  int packet_size;
3542 
3543  // build the header and send the packet
3544  BUILD_HEADER(PONG);
3545  psnet_send(addr, &data[0], packet_size);
3546 }
3547 
3548 // sent from host to master. give me the list of missions you have.
3549 // this will be used only in a standalone mode
3551 {
3553  int packet_size;
3554 
3555  // build the header and ask for a list of missions or campaigns (depending
3556  // on the 'what' flag).
3558 
3559  multi_io_send_reliable(Net_player, data, packet_size);
3560 }
3561 
3562 // maximum number of bytes that we can send in a mission items packet.
3563 #define MAX_MISSION_ITEMS_BYTES (MAX_PACKET_SIZE - (sizeof(multi_create_info) + 1) )
3564 
3565 // defines used to tell what type of packets are being sent
3566 #define MISSION_LIST_ITEMS 1
3567 #define CAMPAIGN_LIST_ITEMS 2
3568 
3569 // send an individual mission file item
3571 {
3573  int packet_size, i;
3574  ubyte stop, type;
3575 
3576  // build the header
3578 
3579  // send the list of missions and campaigns avilable on the server. Stop when
3580  // reaching a certain maximum
3581  type = MISSION_LIST_ITEMS;
3582  ADD_DATA( type );
3583  for (i = 0; i < (int)Multi_create_mission_list.size(); i++ ) {
3584  stop = 0;
3585  ADD_DATA( stop );
3586 
3590  ADD_DATA( Multi_create_mission_list[i].max_players );
3591  ADD_INT( Multi_create_mission_list[i].respawn );
3592 
3593  // STANDALONE_ONLY
3594  ADD_DATA( Multi_create_mission_list[i].valid_status );
3595 
3596  if ( packet_size > (int)MAX_MISSION_ITEMS_BYTES ) {
3597  stop = 1;
3598  ADD_DATA( stop );
3599  multi_io_send_reliable(pl, data, packet_size);
3601  ADD_DATA( type );
3602  }
3603  }
3604  stop = 1;
3605  ADD_DATA(stop);
3606  multi_io_send_reliable(pl, data, packet_size);
3607 
3608  // send the campaign information
3609  type = CAMPAIGN_LIST_ITEMS;
3611  ADD_DATA( type );
3612  for (i = 0; i < (int)Multi_create_campaign_list.size(); i++ ) {
3613  stop = 0;
3614  ADD_DATA( stop );
3615 
3619  ADD_DATA( Multi_create_campaign_list[i].max_players );
3620 
3621  if ( packet_size > (int)MAX_MISSION_ITEMS_BYTES ) {
3622  stop = 1;
3623  ADD_DATA( stop );
3624  multi_io_send_reliable(pl, data, packet_size);
3626  ADD_DATA( type );
3627  }
3628  }
3629  stop = 1;
3630  ADD_DATA(stop);
3631  multi_io_send_reliable(pl, data, packet_size);
3632 }
3633 
3634 // process a request for a list of missions
3636 {
3637  int player_num,offset;
3638 
3639  offset = HEADER_LENGTH;
3640  PACKET_SET_SIZE();
3641 
3642  // fill in the address information of where this came from
3643  player_num = find_player_id(hinfo->id);
3644  if(player_num == -1){
3645  nprintf(("Network","Could not find player to send mission list items to!\n"));
3646  return;
3647  }
3648 
3649  send_mission_items( &Net_players[player_num] );
3650 }
3651 
3652 // process an individual mission file item
3654 {
3655  int offset, flags;
3656  char filename[MAX_FILENAME_LEN], name[NAME_LENGTH], valid_status;
3657  ubyte stop, type,max_players;
3658  uint respawn;
3659  multi_create_info mcip;
3660 
3662  offset = HEADER_LENGTH;
3663 
3664  GET_DATA( type );
3665  GET_DATA(stop);
3666  while( !stop ) {
3667  GET_STRING( filename );
3668  GET_STRING( name );
3669  GET_INT( flags );
3670  GET_DATA( max_players );
3671 
3672  // missions also have respawns and a crc32 associated with them
3673  if(type == MISSION_LIST_ITEMS){
3674  GET_UINT(respawn);
3675 
3676  // STANDALONE_ONLY
3677  GET_DATA(valid_status);
3678 
3679  strcpy_s(mcip.filename, filename );
3680  strcpy_s(mcip.name, name );
3681  mcip.flags = flags;
3682  mcip.respawn = respawn;
3683  mcip.max_players = max_players;
3684 
3685  // STANDALONE_ONLY
3686  mcip.valid_status = valid_status;
3687 
3688  Multi_create_mission_list.push_back( mcip );
3689  } else if ( type == CAMPAIGN_LIST_ITEMS ) {
3690  strcpy_s(mcip.filename, filename );
3691  strcpy_s(mcip.name, name );
3692  mcip.flags = flags;
3693  mcip.respawn = 0;
3694  mcip.max_players = max_players;
3695 
3696  Multi_create_campaign_list.push_back( mcip );
3697  }
3698 
3699  GET_DATA( stop );
3700  }
3701 
3702  PACKET_SET_SIZE();
3703 
3704  // this will cause whatever list to get resorted (although they should be appearing in order)
3706 }
3707 
3708 // send a request to the server to pause or unpause the game
3710 {
3712  ubyte val;
3713  int packet_size = 0;
3714 
3716 
3717  // build the header
3719  val = (ubyte) pause;
3720 
3721  // add the pause info
3722  ADD_DATA(val);
3723 
3724  // send the request to the server
3725  multi_io_send_reliable(Net_player, data, packet_size);
3726 }
3727 
3728 // process a pause update packet (pause, unpause, etc)
3730 {
3731  int offset;
3732  ubyte val;
3733  int player_index;
3734 
3735  offset = HEADER_LENGTH;
3736 
3737  // get the data
3738  GET_DATA(val);
3739  PACKET_SET_SIZE();
3740 
3741  // get who sent the packet
3742  player_index = find_player_id(hinfo->id);
3743  // if we don't know who sent the packet, don't do anything
3744  if(player_index == -1){
3745  return;
3746  }
3747 
3748  // if we're the server, we should evaluate whether this guy is allowed to send the packet
3749  multi_pause_server_eval_request(&Net_players[player_index],(int)val);
3750 }
3751 
3752 // send a game information update
3754 {
3755  int packet_size;
3756  ubyte data[MAX_PACKET_SIZE], paused;
3757 
3758  // set the paused variable
3759  paused = (ubyte)((Netgame.game_state == NETGAME_STATE_PAUSED)?1:0);
3760 
3762  ADD_INT( Missiontime ); // NOTE: this is a long so careful with swapping in 64-bit platforms - taylor
3763  ADD_DATA( paused );
3764 
3765  multi_io_send_to_all(data, packet_size);
3766 }
3767 
3768 // process a game information update
3770 {
3771  int offset;
3772  fix mission_time;
3773  ubyte paused;
3774 
3775  offset = HEADER_LENGTH;
3776 
3777  // get the mission time -- we should examine our time and the time from the server. If off by some delta
3778  // time, set our time to server time (should take ping time into account!!!)
3779  GET_INT( mission_time ); // NOTE: this is a long so careful with swapping in 64-bit platforms - taylor
3780  GET_DATA( paused );
3781  PACKET_SET_SIZE();
3782 }
3783 
3784 // send an ingame nak packet
3785 void send_ingame_nak(int state, net_player *p)
3786 {
3788  int packet_size;
3789  packet_size = 0;
3791 
3792  ADD_INT(state);
3793 
3794  multi_io_send_reliable(p, data, packet_size);
3795 }
3796 
3797 // process an ingame nak packet
3799 {
3800  int offset,state,pid;
3801 
3802  offset = HEADER_LENGTH;
3803  GET_INT(state);
3804  PACKET_SET_SIZE();
3805 
3806  pid = find_player_id(hinfo->id);
3807  if(pid < 0){
3808  return;
3809  }
3810 
3811  switch(state){
3812  case ACK_FILE_ACCEPTED :
3814  nprintf(("Network","Mission file rejected by server, aborting...\n"));
3816  break;
3817  }
3818 }
3819 
3820 // If the end_mission SEXP has been used tell clients to skip straight to the debrief screen
3822 {
3824  int packet_size;
3825 
3826  packet_size = 0;
3828 
3830  {
3831  // tell everyone to leave the game
3832  multi_io_send_to_all_reliable(data, packet_size);
3833  }
3834 }
3835 
3836 // process a packet indicating that we should jump straight to the debrief screen
3838 {
3839  int offset;
3840 
3841  offset = HEADER_LENGTH;
3842 
3843  PACKET_SET_SIZE();
3844 
3845  ml_string("Receiving force end mission packet");
3846 
3847  // Since only the server sends out these packets it should never receive one
3849 
3852 }
3853 
3854 // send a packet telling players to end the mission
3856 {
3858  int packet_size;
3859 
3860  packet_size = 0;
3862 
3863  // sending to a specific player?
3864  if(pl != NULL){
3866  multi_io_send_reliable(pl, data, packet_size);
3867  return;
3868  }
3869 
3871  // send all player stats here
3873 
3874  // if in dogfight mode, send all dogfight stats as well
3875  ml_string("Before dogfight stats!");
3877  ml_string("Sending dogfight stats!");
3878 
3880  }
3881  ml_string("After dogfight stats!");
3882 
3883  // tell everyone to leave the game
3884  multi_io_send_to_all_reliable(data, packet_size);
3885  } else {
3886  multi_io_send_reliable(Net_player, data, packet_size);
3887  }
3888 }
3889 
3890 // process a packet indicating we should end the current mission
3892 {
3893  int offset;
3894  int player_num;
3895 
3896  offset = HEADER_LENGTH;
3897 
3898  PACKET_SET_SIZE();
3899 
3900  ml_string("Receiving endgame packet");
3901 
3902  // if I'm the server, I should evaluate whether the sender is authorized to end the game
3904  // determine who this came from and make sure he is allowed to end the game
3905  player_num = find_player_id(hinfo->id);
3906  Assert(player_num != -1);
3907  if(player_num < 0){
3908  return;
3909  }
3910 
3911  // if the player is allowed to end the mission
3912  if(!multi_can_end_mission(&Net_players[player_num])){
3913  return;
3914  }
3915 
3916  // act as if we hit alt+j locally
3918  }
3919  // all clients process immediately
3920  else {
3921  // ingame joiners should quit when they receive an endgame packet since the game is over
3924  return;
3925  }
3926 
3927  // do any special processing for being in a state other than the gameplay state
3929 
3930  // make sure we're not already in the debrief state
3933  }
3934  }
3935 }
3936 
3937 // send a position/orientation update for myself (if I'm an observer)
3939 {
3941  int packet_size;
3942  int ret;
3943  ushort target_sig;
3944 
3945  // its possible for the master to be an observer if has run out of respawns. In this case, he doesn't need
3946  // to send any update packets to anyone.
3948  return;
3949  }
3950 
3951  if((Player_obj == NULL) || (Player_obj->type != OBJ_OBSERVER) || (Net_player == NULL) || !(Net_player->flags & NETINFO_FLAG_OBSERVER)){
3952  return;
3953  }
3954 
3955  packet_size = 0;
3956 
3958 
3959  ret = multi_pack_unpack_position( 1, data + packet_size, &Player_obj->pos );
3960  packet_size += ret;
3961  ret = multi_pack_unpack_orient( 1, data + packet_size, &Player_obj->orient );
3962  packet_size += ret;
3963 
3964  // add targeting infomation
3965  if((Player_ai != NULL) && (Player_ai->target_objnum >= 0)){
3967  } else {
3968  target_sig = 0;
3969  }
3970  ADD_USHORT(target_sig);
3971 
3972  multi_io_send(Net_player, data, packet_size);
3973 }
3974 
3975 // process a position/orientation update from an observer
3977 {
3978  int offset,ret;
3979  int obs_num;
3980  vec3d g_vec;
3981  matrix g_mat;
3982  physics_info bogus_pi;
3983  ushort target_sig;
3984  object *target_obj;
3985  offset = HEADER_LENGTH;
3986 
3987  obs_num = find_player_id(hinfo->id);
3988 
3989  memset(&bogus_pi,0,sizeof(physics_info));
3990  ret = multi_pack_unpack_position( 0, data + offset, &g_vec );
3991  offset += ret;
3992  ret = multi_pack_unpack_orient( 0, data + offset, &g_mat );
3993  offset += ret;
3994 
3995  // targeting information
3996  GET_USHORT(target_sig);
3997  PACKET_SET_SIZE();
3998 
3999  if((obs_num < 0) || (Net_players[obs_num].m_player->objnum < 0)){
4000  return;
4001  }
4002 
4003  // set targeting info
4004  if(target_sig == 0){
4005  Net_players[obs_num].s_info.target_objnum = -1;
4006  } else {
4007  target_obj = multi_get_network_object(target_sig);
4008  Net_players[obs_num].s_info.target_objnum = (target_obj == NULL) ? -1 : OBJ_INDEX(target_obj);
4009  }
4010 
4011  Objects[Net_players[obs_num].m_player->objnum].pos = g_vec;
4012  Objects[Net_players[obs_num].m_player->objnum].orient = g_mat;
4013  Net_players[obs_num].s_info.eye_pos = g_vec;
4014  Net_players[obs_num].s_info.eye_orient = g_mat;
4015 }
4016 
4018 {
4020  int packet_size,idx;
4021  ubyte stop;
4022 
4023  packet_size = 0;
4024  stop = 0xff;
4026  for(idx=0;idx<MAX_PLAYERS;idx++){
4028  ADD_DATA(stop);
4029  ADD_SHORT(Net_players[idx].player_id);
4030  ADD_USHORT(Objects[Net_players[idx].m_player->objnum].net_signature);
4031  ADD_INT(Net_players[idx].p_info.ship_class);
4032  ADD_INT(Net_players[idx].p_info.ship_index);
4033  }
4034  }
4035  stop = 0x0;
4036  ADD_DATA(stop);
4037 
4038  // standalone case or not
4040  multi_io_send_to_all_reliable(data, packet_size);
4041  } else {
4042  multi_io_send_reliable(Net_player, data, packet_size);
4043  }
4044 }
4045 
4047 {
4048  int offset;
4049  int player_num,ship_class,ship_index;
4050  ushort net_sig;
4051  object *objp;
4052  ubyte stop;
4053  short player_id;
4054 
4055  offset = HEADER_LENGTH;
4056 
4057  // first untag all of the player ships and make them OF_COULD_BE_PLAYER
4059 
4060  GET_DATA(stop);
4061  while(stop != 0x0){
4062  GET_SHORT(player_id);
4063  GET_USHORT(net_sig);
4064  GET_INT(ship_class);
4065  GET_INT(ship_index);
4066  player_num = find_player_id(player_id);
4067  if(player_num < 0){
4068  nprintf(("Network","Error looking up player for object/slot assignment!!\n"));
4069  } else {
4070  // call the function in multiutil.cpp to set up the player object stuff
4071  // being careful not to muck with the standalone object
4072  if(!((player_num == 0) && (Game_mode & GM_STANDALONE_SERVER))){
4073  objp = multi_get_network_object(net_sig);
4074  if (objp == NULL) {
4075  Error(LOCATION, "Could not retrieve net object for signature %d!\n", net_sig);
4076  }
4077  multi_assign_player_ship( player_num, objp, ship_class );
4078  Net_players[player_num].p_info.ship_index = ship_index;
4079  objp->flags &= ~(OF_COULD_BE_PLAYER);
4080  objp->flags |= OF_PLAYER_SHIP;
4081  }
4082  }
4083  GET_DATA(stop);
4084  }
4085  PACKET_SET_SIZE();
4086 
4087  // standalone should forward the packet and wait for a response
4090  }
4091 
4094 }
4095 
4096 // two functions to deal with ships changing their primary/secondary weapon status. 'what' indicates
4097 // if this change is a primary or secondary change. new_bank is the new current primary/secondary
4098 // bank, link_status is whether primaries are linked or not, or secondaries are dual fire or not
4099 void send_ship_weapon_change( ship *shipp, int what, int new_bank, int link_status )
4100 {
4101  ubyte data[MAX_PACKET_SIZE], utmp;
4102  int packet_size;
4103 
4106  utmp = (ubyte)(what);
4107  ADD_DATA( utmp );
4108  utmp = (ubyte)(new_bank);
4109  ADD_DATA( utmp );
4110  utmp = (ubyte)(link_status);
4111  ADD_DATA( utmp );
4112 
4113  // Removed the above psnet_send() call - it didn't appear to do anything since it was called only from the server anyway - DB
4114  multi_io_send_to_all_reliable(data, packet_size);
4115 }
4116 
4118 {
4119  int offset;
4120  ushort signature;
4121  ubyte what, new_bank, link_status;
4122  object *objp;
4123  ship *shipp;
4124 
4125  offset = HEADER_LENGTH;
4126  GET_USHORT( signature );
4127  GET_DATA( what );
4128  GET_DATA( new_bank );
4129  GET_DATA( link_status );
4130  PACKET_SET_SIZE();
4131 
4132  objp = multi_get_network_object( signature );
4133  if ( objp == NULL ) {
4134  nprintf(("network", "Unable to locate ship with signature %d for weapon state change\n", signature));
4135  return;
4136  }
4137  // Assert( objp->type == OBJ_SHIP );
4138  if(objp->type != OBJ_SHIP){
4139  return;
4140  }
4141 
4142  // if this is my data, do nothing since I already have my own data
4143  if ( objp == Player_obj ){
4144  return;
4145  }
4146 
4147  // now, get the ship and set the new bank and link modes based on the 'what' value
4148  shipp = &Ships[objp->instance];
4149  if ( what == MULTI_PRIMARY_CHANGED ) {
4150  shipp->weapons.current_primary_bank = new_bank;
4151  if ( link_status ){
4152  shipp->flags |= SF_PRIMARY_LINKED;
4153  } else {
4154  shipp->flags &= ~SF_PRIMARY_LINKED;
4155  }
4156  } else {
4157  shipp->weapons.current_secondary_bank = new_bank;
4158  if ( link_status ){
4159  shipp->flags |= SF_SECONDARY_DUAL_FIRE;
4160  } else {
4161  shipp->flags &= ~SF_SECONDARY_DUAL_FIRE;
4162  }
4163  }
4164 }
4165 
4166  // ship status change procedure
4167 // 1.) <client> - Client runs through the normal button_function procedure. Any remaining control bits are implied as being
4168 // server critical.
4169 // 2.) <client> - Client puts this button_info item into his last_buttons array and sends a bunch of SHIP_STATUS packets
4170 // for added redundancy.
4171 // 3.) <server> - Receives the packet. Checks to see if the net_player on his side already has this one defined. If so, it
4172 // ignores as a repeat packet. Otherwise it puts it in the last_buttons array for the net_player
4173 // 4.) <server> - Server applies the command on his side (with multi_apply_ship_status(...) and sends the ack (also a SHIP_STATUS)
4174 // back to the client. Also sends multiple times for redundancy
4175 // 5.) <client> - Receives the packet back. Does a lookup into his last_buttons array. If he finds the match, apply the functions
4176 // and remove the item from the list. If no match is found it means that either he has received an ack, has acted
4177 // on it and removed it, or that it has been "timed out" and replaced by a newer button_info.
4178 
4179 #define SHIP_STATUS_REPEAT 2
4181 {
4182  int idx, temp;
4184  int packet_size = 0;
4185 
4186  if(pl == NULL){
4187  return;
4188  }
4189 
4191  ADD_INT(id);
4192  for(idx=0;idx<NUM_BUTTON_FIELDS;idx++){
4193  temp = bi->status[idx];
4194  ADD_INT(temp);
4195  }
4196 
4197  // server should send reliably (response packet)
4198  if(MULTIPLAYER_MASTER){
4199  multi_io_send_reliable(pl, data, packet_size);
4200  } else {
4201  multi_io_send(pl, data, packet_size);
4202  }
4203 }
4204 
4206 {
4207  int idx;
4208  int offset;
4209  int player_num,unique_id;
4210  button_info bi;
4211  int i_tmp;
4212 
4213  offset = HEADER_LENGTH;
4214 
4215  // zero out the button info structure for good measure
4216  memset(&bi,0,sizeof(button_info));
4217 
4218  // read the button-info
4219  GET_INT(unique_id);
4220 
4221  for(idx=0;idx<NUM_BUTTON_FIELDS;idx++){
4222  GET_INT(i_tmp);
4223  bi.status[idx] = i_tmp;
4224  }
4225 
4226  PACKET_SET_SIZE();
4227 
4228  // this will be handled differently client and server side. Duh.
4229  if(Net_player->flags & NETINFO_FLAG_AM_MASTER){ // SERVER SIDE
4230  // find which net-player has sent us butotn information
4231  player_num = find_player_id(hinfo->id);
4232  Assert(player_num >= 0);
4233  if(player_num < 0){
4234  return;
4235  }
4236 
4237  // don't process critical button information for observers
4238  // its a new button_info for this guy. apply and ack
4239  if(!MULTI_OBSERVER(Net_players[player_num]) && !lookup_ship_status(&Net_players[player_num],unique_id)){
4240  // mark that he's pressed this button
4241  // add_net_button_info(&Net_players[player_num], &bi, unique_id);
4242 
4243  // send a return packet
4244  send_ship_status_packet(&Net_players[player_num], &bi,unique_id);
4245 
4246  // apply the button presses to his ship as normal
4247  multi_apply_ship_status(&Net_players[player_num], &bi, 0);
4248  }
4249  // else ignore it as a repeat from the same guy
4250  } else { // CLIENT SIDE
4251  // this is the return from the server, so we should now apply them locally
4252  // if(lookup_ship_status(Net_player,unique_id,1)){
4254  // }
4255  }
4256 }
4257 
4258 // MWA 4/28/9 -- redid this function since message all fighers was really broken
4259 // for clients. Left all details to this function instead of higher level messaging
4260 // code
4261 void send_player_order_packet(int type, int index, int cmd)
4262 {
4264  ubyte val;
4265  ushort target_signature;
4266  char t_subsys;
4267  int packet_size = 0;
4268 
4270 
4271  val = (ubyte)type;
4272  ADD_DATA(val); // ship order or wing order, or message all fighters
4273 
4274  // if we are not messaging all ships or wings, add the index, which is the shipnum or wingnum
4275  if ( val != SQUAD_MSG_ALL ){
4276  ADD_INT(index); // net signature of target ship
4277  }
4278 
4279  ADD_INT(cmd); // the command itself
4280 
4281  // add target data.
4282  target_signature = 0;
4283  if ( Player_ai->target_objnum != -1 ){
4284  target_signature = Objects[Player_ai->target_objnum].net_signature;
4285  }
4286 
4287  ADD_USHORT( target_signature );
4288 
4289  t_subsys = -1;
4290  if ( (Player_ai->target_objnum != -1) && (Player_ai->targeted_subsys != NULL) ) {
4291  int s_index;
4292 
4294  Assert( s_index < CHAR_MAX ); // better be less than this!!!!
4295  t_subsys = (char)s_index;
4296  }
4297  ADD_DATA(t_subsys);
4298 
4299  multi_io_send_reliable(Net_player, data, packet_size);
4300 }
4301 
4302 // brief explanation :
4303 // in either case (wing or ship command), we need to send in a pseudo-ai object. Basically, both command handler
4304 // functions "normally" (non multiplayer) use a couple of the Player_ai fields. So, we just fill in the ones necessary
4305 // (which we can reconstruct from the packet data), and pass this as the default variable ai_info *local
4306 // Its kind of a hack, but it eliminates the need to go in and screw around with quite a bit of code
4308 {
4309  int offset, player_num, command, index = 0, tobjnum_save;
4310  ushort target_signature;
4311  char t_subsys, type;
4312  object *objp, *target_objp;
4313  ai_info *aip;
4314  ship *shipp;
4315  ship_subsys *tsubsys_save, *targeted_subsys;
4316 
4318 
4319  // packet values - its easier to read all of these in first
4320 
4321  offset = HEADER_LENGTH;
4322 
4323  GET_DATA( type );
4324  if ( type != SQUAD_MSG_ALL ){
4325  GET_INT( index );
4326  }
4327 
4328  GET_INT( command );
4329  GET_USHORT( target_signature );
4330  GET_DATA( t_subsys );
4331 
4332  PACKET_SET_SIZE();
4333 
4334  player_num = find_player_id(hinfo->id);
4335  if(player_num == -1){
4336  nprintf(("Network","Received player order packet from unknown player\n"));
4337  return;
4338  }
4339 
4340  objp = &Objects[Net_players[player_num].m_player->objnum];
4341  if ( objp->type != OBJ_SHIP ) {
4342  nprintf(("Network", "not doing player order because object requestting is not a ship\n"));
4343  return;
4344  }
4345 
4346  // HACK HACK HACK HACK HACK HACK
4347  // if the player has sent a rearm-repair me message, we should bail here after evaluating it, since most likely the rest of
4348  // the data is BOGUS. All people should be able to to these things as well.
4349  if(command == REARM_REPAIR_ME_ITEM){
4350  hud_squadmsg_repair_rearm(0,&Objects[Net_players[player_num].m_player->objnum]);
4351  return;
4352  } else if(command == ABORT_REARM_REPAIR_ITEM){
4353  hud_squadmsg_repair_rearm_abort(0,&Objects[Net_players[player_num].m_player->objnum]);
4354  return;
4355  }
4356 
4357  // if this player is not allowed to do messaging, quit here
4358  if( !multi_can_message(&Net_players[player_num]) ){
4359  nprintf(("Network","Received player order packet from player not allowed to give orders!!\n"));
4360  return;
4361  }
4362 
4363  // check to see if the type of order is a reinforcement call. If so, intercept it, and
4364  // then call them in.
4365  if ( type == SQUAD_MSG_REINFORCEMENT ) {
4366  Assert( (index >= 0) && (index < Num_reinforcements) );
4367  hud_squadmsg_call_reinforcement(index, player_num);
4368  return;
4369  }
4370 
4371  // set the player's ai information here
4372  shipp = &Ships[objp->instance];
4373  aip = &Ai_info[shipp->ai_index];
4374 
4375  // get the target objnum and targeted subsystem. Quick out if we don't have an object to act on.
4376  target_objp = multi_get_network_object( target_signature );
4377  if ( target_objp == NULL ) {
4378  return;
4379  }
4380 
4381  targeted_subsys = NULL;
4382  if ( t_subsys != -1 ) {
4383  Assert( target_objp != NULL );
4384  targeted_subsys = ship_get_indexed_subsys( &Ships[target_objp->instance], t_subsys);
4385  }
4386 
4387  // save and restore the target objnum and targeted subsystem so that we don't mess up other things
4388  // here
4389  tobjnum_save = aip->target_objnum;
4390  tsubsys_save = aip->targeted_subsys;
4391 
4392  if ( target_objp ) {
4393  aip->target_objnum = OBJ_INDEX(target_objp);
4394  } else {
4395  aip->target_objnum = -1;
4396  }
4397 
4398  aip->targeted_subsys = targeted_subsys;
4399 
4400  if ( type == SQUAD_MSG_SHIP ) {
4401  hud_squadmsg_send_ship_command(index, command, 1, SQUADMSG_HISTORY_ADD_ENTRY, player_num);
4402  } else if ( type == SQUAD_MSG_WING ) {
4403  hud_squadmsg_send_wing_command(index, command, 1, SQUADMSG_HISTORY_ADD_ENTRY, player_num);
4404  } else if ( type == SQUAD_MSG_ALL ) {
4405  hud_squadmsg_send_to_all_fighters( command, player_num );
4406  }
4407 
4408  Assert(tobjnum_save != Ships[aip->shipnum].objnum); // make sure not targeting self
4409  aip->target_objnum = tobjnum_save;
4410  aip->targeted_subsys = tsubsys_save;
4411 }
4412 
4413 // FILE SIGNATURE stuff :
4414 // there are 2 cases for file signature sending which are handled very differently
4415 // 1.) Pregame. In this case, the host requires that all clients send a filesig packet (when process_file_sig() is called, it
4416 // posts an ACK_FILE_ACCEPTED packet to ack_evaluate, so he thinks they have acked).
4417 // 2.) Ingame join. In this case, the client sends his filesig packet automatically to the server and the _client_ waits for
4418 // the ack, before continuing to join. It would be way too messy to have the server wait on the clients ack, since he
4419 // would have to keep track of up to potentially 14 other ack handles (ouch).
4420 void send_file_sig_packet(ushort sum_sig,int length_sig)
4421 {
4423  int packet_size = 0;
4424 
4426  ADD_USHORT(sum_sig);
4427  ADD_INT(length_sig);
4428 
4429  multi_io_send_reliable(Net_player, data, packet_size);
4430 }
4431 
4433 {
4434  int offset;
4435  int length_sig;
4436  ushort sum_sig;
4437  offset = HEADER_LENGTH;
4438 
4439  // should only be received on the server-side
4441 
4442  GET_USHORT(sum_sig);
4443  GET_INT(length_sig);
4444  PACKET_SET_SIZE();
4445  server_verify_filesig(hinfo->id, sum_sig, length_sig);
4446 }
4447 
4448 void send_file_sig_request(char *file_name)
4449 {
4451  int packet_size = 0;
4452 
4454  ADD_STRING(file_name);
4455 
4457 
4458  multi_io_send_to_all_reliable(data, packet_size);
4459 }
4460 
4462 {
4463  int offset = HEADER_LENGTH;
4464 
4465  // get the mission name
4467  PACKET_SET_SIZE();
4468 
4469  // set the current mission filename
4471 
4472  // get the checksum
4474 
4475  if(!multi_endgame_ending()){
4476  // reply to the server
4478  }
4479 }
4480 
4481 // functions to deal with subsystems getting whacked
4482 void send_subsystem_destroyed_packet( ship *shipp, int index, vec3d world_hitpos )
4483 {
4485  int packet_size;
4486  ubyte uindex;
4487  vec3d tmp, local_hitpos;
4488  object *objp;
4489 
4490  Assert ( index < UCHAR_MAX );
4491  uindex = (ubyte)(index);
4492 
4493  objp = &Objects[shipp->objnum];
4494 
4495  vm_vec_sub(&tmp, &world_hitpos, &objp->pos );
4496  vm_vec_rotate( &local_hitpos, &tmp, &objp->orient );
4497 
4500  ADD_DATA( uindex );
4501  ADD_VECTOR( local_hitpos );
4502 
4503  multi_io_send_to_all_reliable(data, packet_size);
4504 }
4505 
4507 {
4508  int offset;
4509  ushort signature;
4510  ubyte uindex;
4511  object *objp;
4512  vec3d local_hit_pos, world_hit_pos;
4513 
4514  offset = HEADER_LENGTH;
4515 
4516  GET_USHORT( signature );
4517  GET_DATA( uindex );
4518  GET_VECTOR( local_hit_pos );
4519 
4520  // get the network object. process it if we find it.
4521  objp = multi_get_network_object( signature );
4522  if ( objp != NULL ) {
4523  ship *shipp;
4524  ship_subsys *subsysp;
4525 
4526  // be sure we have a ship!!!
4527  // Assert ( objp->type == OBJ_SHIP );
4528  if(objp->type != OBJ_SHIP){
4529  PACKET_SET_SIZE();
4530  return;
4531  }
4532 
4533  shipp = &Ships[objp->instance];
4534 
4535  // call to get the pointer to the subsystem we should be working on
4536  subsysp = ship_get_indexed_subsys( shipp, (int)uindex );
4537  if (subsysp == NULL) {
4538  nprintf(("Network", "Could not find subsys %d for ship %s to process as being destroyed\n", (int)uindex, shipp->ship_name ));
4539  PACKET_SET_SIZE();
4540  return;
4541  }
4542 
4543  vm_vec_unrotate( &world_hit_pos, &local_hit_pos, &objp->orient );
4544  vm_vec_add2( &world_hit_pos, &objp->pos );
4545 
4546  do_subobj_destroyed_stuff( shipp, subsysp, &world_hit_pos );
4547  if ( objp == Player_obj ) {
4549  }
4550  }
4551 
4552  PACKET_SET_SIZE();
4553 }
4554 
4555 
4556 // packet to tell clients cargo of a ship was revealed to all
4558 {
4559  ubyte data[MAX_PACKET_SIZE], uindex;
4560  int packet_size;
4561 
4562  Assert ( index < UCHAR_MAX );
4563  uindex = (ubyte)(index);
4564 
4565  // build the header and add the data
4568  ADD_DATA( uindex );
4569 
4570  // server sends to all players
4571  if(MULTIPLAYER_MASTER){
4572  multi_io_send_to_all_reliable(data, packet_size);
4573  }
4574  // clients just send to the server
4575  else {
4576  multi_io_send_reliable(Net_player, data, packet_size);
4577  }
4578 }
4579 
4580 // process a subsystem cargo revealed packet
4582 {
4583  int offset;
4584  ushort signature;
4585  ubyte uindex;
4586  object *objp;
4587  ship *shipp;
4588  ship_subsys *subsysp;
4589 
4590  offset = HEADER_LENGTH;
4591  GET_USHORT( signature );
4592  GET_DATA( uindex );
4593  PACKET_SET_SIZE();
4594 
4595  // get a ship pointer and call the ship function to reveal the cargo
4596  objp = multi_get_network_object( signature );
4597  if ( objp == NULL ) {
4598  nprintf(("Network", "Could not find object with net signature %d for cargo revealed\n", signature ));
4599  return;
4600  }
4601 
4602  // Assert( objp->type == OBJ_SHIP );
4603  if((objp->type != OBJ_SHIP) || (objp->instance < 0) || (objp->instance >= MAX_SHIPS)){
4604  return;
4605  }
4606 
4607  shipp = &Ships[objp->instance];
4608 
4609  // call to get the pointer to the subsystem we should be working on
4610  subsysp = ship_get_indexed_subsys( shipp, (int)uindex );
4611  if (subsysp == NULL) {
4612  nprintf(("Network", "Could not find subsys for ship %s for cargo revealed\n", Ships[objp->instance].ship_name ));
4613  return;
4614  }
4615 
4616  // this will take care of re-routing to all other clients
4617  ship_do_cap_subsys_cargo_revealed( shipp, subsysp, 1 );
4618 
4619  // server should rebroadcast
4620  if(MULTIPLAYER_MASTER){
4621  send_subsystem_cargo_revealed_packet(&Ships[objp->instance], (int)uindex);
4622  }
4623 }
4624 
4625 // packet to tell clients cargo of a ship was hidden to all
4627 {
4628  ubyte data[MAX_PACKET_SIZE], uindex;
4629  int packet_size;
4630 
4631  Assert ( index < UCHAR_MAX );
4632  uindex = (ubyte)(index);
4633 
4634  // build the header and add the data
4637  ADD_DATA( uindex );
4638 
4639  // server sends to all players
4640  if(MULTIPLAYER_MASTER){
4641  multi_io_send_to_all_reliable(data, packet_size);
4642  }
4643  // clients just send to the server
4644  else {
4645  multi_io_send_reliable(Net_player, data, packet_size);
4646  }
4647 }
4648 
4649 // process a subsystem cargo hidden packet
4651 {
4652  int offset;
4653  ushort signature;
4654  ubyte uindex;
4655  object *objp;
4656  ship *shipp;
4657  ship_subsys *subsysp;
4658 
4659  offset = HEADER_LENGTH;
4660  GET_USHORT( signature );
4661  GET_DATA( uindex );
4662  PACKET_SET_SIZE();
4663 
4664  // get a ship pointer and call the ship function to reveal the cargo
4665  objp = multi_get_network_object( signature );
4666  if ( objp == NULL ) {
4667  nprintf(("Network", "Could not find object with net signature %d for cargo hidden\n", signature ));
4668  return;
4669  }
4670 
4671  // Assert( objp->type == OBJ_SHIP );
4672  if((objp->type != OBJ_SHIP) || (objp->instance < 0) || (objp->instance >= MAX_SHIPS)){
4673  return;
4674  }
4675 
4676  shipp = &Ships[objp->instance];
4677 
4678  // call to get the pointer to the subsystem we should be working on
4679  subsysp = ship_get_indexed_subsys( shipp, (int)uindex );
4680  if (subsysp == NULL) {
4681  nprintf(("Network", "Could not find subsys for ship %s for cargo hidden\n", Ships[objp->instance].ship_name ));
4682  return;
4683  }
4684 
4685  // this will take care of re-routing to all other clients
4686  ship_do_cap_subsys_cargo_hidden( shipp, subsysp, 1 );
4687 
4688  // server should rebroadcast
4689  if(MULTIPLAYER_MASTER){
4690  send_subsystem_cargo_hidden_packet(&Ships[objp->instance], (int)uindex);
4691  }
4692 }
4693 
4695 {
4697  int packet_size = 0;
4698 
4701 
4702  if(pl == NULL){
4703  multi_io_send_to_all_reliable(data, packet_size);
4704  } else {
4705  multi_io_send_reliable(pl, data, packet_size);
4706  }
4707 }
4708 
4710 {
4711  char str[100];
4712  int offset = HEADER_LENGTH;
4713 
4714  GET_STRING(str);
4715  PACKET_SET_SIZE();
4716 
4719  if(!Multi_mission_loaded){
4720 
4721  // MWA 2/3/98 -- ingame join changes!!!
4722  // everyone can go through the same mission loading path here!!!!
4723  nprintf(("Network","Loading mission..."));
4724 
4725  // notify everyone that I'm loading the mission
4728 
4729  // do the load itself
4730  game_start_mission();
4731 
4732  // ingame joiners need to "untag" all player ships as could_be_players. The ingame joining
4733  // code will remark the correct player ships
4736  }
4737 
4741 
4743  nprintf(("Network","Finished loading mission\n"));
4744  }
4745 }
4746 
4748 {
4750  int packet_size = 0;
4751 
4753 
4755 
4756  // ingame joiners will get special data. We need to tell them about the state of the mission, like paused,
4757  // and possible other things.
4758  if ( pl != NULL ) {
4759  if ( pl->flags & NETINFO_FLAG_INGAME_JOIN ) {
4761  }
4762  }
4763 
4764  // broadcast
4765  if(pl == NULL){
4766  multi_io_send_to_all_reliable(data, packet_size);
4767  }
4768  // send to a specific player
4769  else {
4770  multi_io_send_reliable(pl, data, packet_size);
4771  }
4772 }
4773 
4775 {
4776  int offset = HEADER_LENGTH;
4777  int state;
4778 
4779  state = 0;
4780 
4781  // if I am ingame joining, there should be extra data. For now, this data is the netgame state.
4782  // the game could be paused, so ingame joiner needs to deal with it.
4784  GET_INT( state );
4785  Netgame.game_state = state;
4786  }
4787 
4788  PACKET_SET_SIZE();
4789 
4790  // handle any special processing for being in a weird substate
4792 
4793  // if I'm an ingame joiner, go to the ship select screen, or if I'm an observer, jump right in!
4797  } else {
4801  }
4802  } else {
4803  // start the mission!!
4809  }
4810  }
4811 
4812  // recalc all object pairs now
4813  extern void obj_reset_all_collisions();
4815 
4816  // display some cool text
4817  multi_common_add_text(XSTR("Received mission start\n",720),1);
4818 
4819  // NETLOG
4820  ml_string(NOX("Client received mission start from server - entering mission"));
4821 }
4822 
4823 //XSTR:OFF
4824 
4825 char *repair_text[] = {
4826  "unknown",
4827  "REPAIR_INFO_BEGIN",
4828  "REPAIR_INFO_END",
4829  "REPAIR_INFO_UPDATE",
4830  "REPAIR_INFO_QUEUE",
4831  "REPAIR_INFO_ABORT",
4832  "REPAIR_INFO_BROKEN",
4833  "REPAIR_INFO_WARP_ADD",
4834  "REPAIR_INFO_WARP_REMOVE",
4835  "REPAIR_INFO_ONWAY",
4836  "REPAIR_INFO_KILLED",
4837  "REPAIR_INFO_COMPLETE",
4838 };
4839 
4840 //XSTR:ON
4841 
4842 // the following two routines deal with updating and sending information regarding players
4843 // rearming and repairing during the game. The process function calls the routines to deal with
4844 // setting flags and other interesting things.
4845 void send_repair_info_packet(object *repaired_objp, object *repair_objp, int code )
4846 {
4847  int packet_size = 0;
4848  ushort repaired_signature, repair_signature;
4850  ubyte cd;
4851 
4852  // use the network signature of the destination object if there is one, -1 otherwise.
4853  // client will piece it all together
4854  repaired_signature = repaired_objp->net_signature;
4855 
4856  // the repair ship may be NULL here since it might have been destroyed
4857  repair_signature = 0;
4858  if ( repair_objp ){
4859  repair_signature = repair_objp->net_signature;
4860  }
4861 
4863  cd = (ubyte)code;
4864  ADD_DATA(cd);
4865  ADD_USHORT( repaired_signature );
4866  ADD_USHORT( repair_signature );
4867 
4868  multi_io_send_to_all_reliable(data, packet_size);
4869 
4870  nprintf(("Network", "Repair: %s sent to all players (%s/%s)\n", repair_text[cd], Ships[repaired_objp->instance].ship_name, (repair_objp==NULL)?"<none>":Ships[repair_objp->instance].ship_name));
4871 }
4872 
4874 {
4875  int offset = HEADER_LENGTH;
4876  ushort repaired_signature, repair_signature;
4877  object *repaired_objp, *repair_objp;
4878  ubyte code;
4879 
4880  GET_DATA(code);
4881  GET_USHORT( repaired_signature );
4882  GET_USHORT( repair_signature );
4883  PACKET_SET_SIZE();
4884 
4885  repaired_objp = multi_get_network_object( repaired_signature );
4886  repair_objp = multi_get_network_object( repair_signature );
4887 
4888  nprintf(("Network", "Repair: %s received (%s/%s)\n", repair_text[code], (repaired_objp==NULL)?"<None>":Ships[repaired_objp->instance].ship_name, (repair_objp==NULL)?"<None>":Ships[repair_objp->instance].ship_name));
4889 
4891  return;
4892  }
4893 
4894  if ( repaired_objp == NULL ) {
4895  Int3(); // Sandeep says this is bad bad bad. No ship to repair.
4896  return;
4897  }
4898 
4899  // the hope is to simply call the routine in the ai code to set/unset flags
4900  // based on the code value and everything else should happen..I hope....
4901  if ( (code != REPAIR_INFO_WARP_ADD) && (code != REPAIR_INFO_WARP_REMOVE ) ) {
4902 
4903  ai_do_objects_repairing_stuff( repaired_objp, repair_objp, (int)code );
4904 
4905  // set the dock flags when repair begins. Prevents problem in lagging docking
4906  // packet. Also set any other flags/modes which need to be set to prevent Asserts.
4907  // bleah.
4908  if ( (code == REPAIR_INFO_BEGIN) && (repair_objp != NULL) ) {
4909 // Karajorma removed this in revision 4808 to fix bug 1088. Problem is, if
4910 // this was originally intended to prevent docking problems, will they return?
4911 /*
4912  // find indexes from goal
4913  ai_info *aip = &Ai_info[Ships[repair_objp->instance].ai_index];
4914  Assert(aip->active_goal >= 0);
4915  ai_goal *aigp = &aip->goals[aip->active_goal];
4916  Assert(aigp->flags & AIGF_DOCK_INDEXES_VALID);
4917 
4918  int docker_index = aigp->docker.index;
4919  int dockee_index = aigp->dockee.index;
4920 
4921  ai_do_objects_docked_stuff( repair_objp, docker_index, repaired_objp, dockee_index );
4922 */
4923  Ai_info[Ships[repair_objp->instance].ai_index].mode = AIM_DOCK;
4924  }
4925 
4926  // if the repair is done (either by abort, or ending), mark the repair ship's goal
4927  // as being done.
4928  if ( ((code == REPAIR_INFO_ABORT) || (code == REPAIR_INFO_END)) && repair_objp ){
4929  ai_mission_goal_complete( &Ai_info[Ships[repair_objp->instance].ai_index] );
4930  }
4931  } else {
4932  if ( code == REPAIR_INFO_WARP_ADD ){
4933  mission_bring_in_support_ship( repaired_objp );
4934  } else {
4935  mission_remove_scheduled_repair( repaired_objp );
4936  }
4937  }
4938 }
4939 
4940 // sends information updating clients on certain AI information that clients will
4941 // need to know about to keep HUD information up to date. objp is the object that we
4942 // are updating, and what is the type of stuff that we are updating.
4943 void send_ai_info_update_packet( object *objp, char what, object * other_objp )
4944 {
4945  int packet_size;
4946  ushort other_signature;
4948  ai_info *aip;
4949  ai_goal *aigp = NULL;
4950  ubyte docker_index, dockee_index;
4951 
4952  // Assert( objp->type == OBJ_SHIP );
4953  if(objp->type != OBJ_SHIP){
4954  return;
4955  }
4956  aip = &Ai_info[Ships[objp->instance].ai_index];
4957 
4958  // do an out here
4959  if ( Ships[objp->instance].flags & (SF_DEPARTING | SF_DYING) )
4960  return;
4961 
4962  switch( what ) {
4963 
4964  case AI_UPDATE_DOCK:
4965  case AI_UPDATE_UNDOCK:
4966  Assert (other_objp != NULL);
4967  if (other_objp == NULL) {
4968  return;
4969  }
4970  break;
4971 
4972  default:
4973  Assert (other_objp == NULL);
4974  break;
4975  }
4976 
4978  ADD_USHORT( objp->net_signature );
4979  ADD_DATA( what );
4980 
4981  // depending on the "what" value, we will send different information
4982  // to the clients
4983  switch( what ) {
4984 
4985  case AI_UPDATE_DOCK:
4986  // for docking ships, add the signature of the ship that we are docked with.
4987  Assert( other_objp != NULL );
4988  other_signature = other_objp->net_signature;
4989 
4990  // Goober5000 - this is sort of weird, but it's the best way to do it
4991  docker_index = (ubyte) dock_find_dockpoint_used_by_object(objp, other_objp);
4992  dockee_index = (ubyte) dock_find_dockpoint_used_by_object(other_objp, objp);
4993 
4994  ADD_USHORT( other_signature );
4995  ADD_DATA( docker_index );
4996  ADD_DATA( dockee_index );
4997  break;
4998 
4999  case AI_UPDATE_UNDOCK:
5000  // same for undocking ships
5001  Assert( other_objp != NULL );
5002  other_signature = other_objp->net_signature;
5003  ADD_USHORT( other_signature );
5004 
5005  break;
5006 
5007  case AI_UPDATE_ORDERS: {
5008  int shipnum;
5009 
5010  // for orders, we only need to send a little bit of information here. Be sure that the
5011  // first order for this ship is active
5013  aigp = &aip->goals[aip->active_goal];
5014 
5015  ADD_INT( aigp->ai_mode );
5016  ADD_INT( aigp->ai_submode );
5017 
5018  shipnum = -1;
5019  if ( aigp->target_name != NULL )
5020  shipnum = ship_name_lookup( aigp->target_name );
5021 
5022  // the ship_name member of the goals structure may or may not contain a real shipname. If we don't
5023  // have a valid shipnum, then don't sweat it since it may not really be a ship.
5024  if ( shipnum != -1 ) {
5025  Assert( Ships[shipnum].objnum != -1 );
5026  other_signature = Objects[Ships[shipnum].objnum].net_signature;
5027  } else
5028  other_signature = 0;
5029 
5030  ADD_USHORT( other_signature );
5031 
5032  // for docking, add the dock and dockee index
5033  if ( aigp->ai_mode & (AI_GOAL_DOCK|AI_GOAL_REARM_REPAIR) ) {
5035  Assert( (aigp->docker.index >= 0) && (aigp->docker.index < UCHAR_MAX) );
5036  Assert( (aigp->dockee.index >= 0) && (aigp->dockee.index < UCHAR_MAX) );
5037  docker_index = (ubyte) aigp->docker.index;
5038  dockee_index = (ubyte) aigp->dockee.index;
5039  ADD_DATA( docker_index );
5040  ADD_DATA( dockee_index );
5041  }
5042  break;
5043  }
5044 
5045  default:
5046  Int3();
5047  }
5048 
5049  multi_rate_add(1, "aiu", packet_size);
5050  multi_io_send_to_all_reliable(data, packet_size);
5051 }
5052 
5053 // process an ai_info update packet. Docking/undocking, ai orders, etc. are taken care of here. This
5054 // information is mainly used to keep the clients HUD up to date with the appropriate information.
5056 {
5057  int offset = HEADER_LENGTH;
5058  int mode, submode;
5059  ushort net_signature, other_net_signature;
5060  object *objp, *other_objp;
5061  ai_info *aip;
5062  ai_goal *aigp = NULL;
5063  char code;
5064  ubyte docker_index = 0, dockee_index = 0;
5065 
5066  GET_USHORT( net_signature ); // signature of the object that we are dealing with.
5067  GET_DATA( code ); // code of what we are doing.
5068  objp = multi_get_network_object( net_signature );
5069  if ( !objp )
5070  nprintf(("Network", "Couldn't find object for ai update\n"));
5071 
5072  switch( code ) {
5073  case AI_UPDATE_DOCK:
5074  GET_USHORT( other_net_signature );
5075  GET_DATA( docker_index );
5076  GET_DATA( dockee_index );
5077  other_objp = multi_get_network_object( other_net_signature );
5078  if ( !other_objp )
5079  nprintf(("Network", "Couldn't find other object for ai update on dock\n"));
5080 
5081  // if we don't have an object to work with, break out of loop
5082  if ( !objp || !other_objp || (objp->type != OBJ_SHIP) || (other_objp->type != OBJ_SHIP)){
5083  break;
5084  }
5085 
5086  // don't assign the dock indexes, because they're part of the docking ship's goal code... just dock them
5087  // (and besides, we might be docking initially docked ships and we wouldn't have an active goal)
5088  ai_do_objects_docked_stuff( objp, docker_index, other_objp, dockee_index );
5089  break;
5090 
5091  case AI_UPDATE_UNDOCK:
5092  GET_USHORT( other_net_signature );
5093  other_objp = multi_get_network_object( other_net_signature );
5094 
5095  // if we don't have an object to work with, break out of loop
5096  if ( !objp )
5097  break;
5098 
5099  ai_do_objects_undocked_stuff( objp, other_objp );
5100  break;
5101 
5102  case AI_UPDATE_ORDERS:
5103  GET_INT( mode );
5104  GET_INT( submode );
5105  GET_USHORT( other_net_signature );
5106  if ( mode & (AI_GOAL_DOCK|AI_GOAL_REARM_REPAIR) ) {
5107  GET_DATA(docker_index);
5108  GET_DATA(dockee_index);
5109  }
5110 
5111  // be sure that we have a ship object!!!
5112  if ( !objp || (objp->type != OBJ_SHIP) )
5113  break;
5114 
5115  // set up the information in the first goal element of the object in question
5116  aip = &Ai_info[Ships[objp->instance].ai_index];
5117  aip->active_goal = 0;
5118  aigp = &aip->goals[aip->active_goal];
5119  aigp->ai_mode = mode;
5120  aigp->ai_submode = submode;
5121 
5122  // for docking, add the docker and dockee index to the active goal
5123  if ( mode & (AI_GOAL_DOCK|AI_GOAL_REARM_REPAIR) ) {
5124  aigp->docker.index = docker_index;
5125  aigp->dockee.index = dockee_index;
5126  aigp->flags |= AIGF_DOCK_INDEXES_VALID;
5127  }
5128 
5129  // get a shipname if we can.
5130  other_objp = multi_get_network_object( other_net_signature );
5131  if ( other_objp && (other_objp->type == OBJ_SHIP) ) {
5132  // get a pointer to the shipname in question. Use the ship_name value in the
5133  // ship. We are only using this for HUD display, so I think that using this
5134  // method will be fine.
5135  aigp->target_name = ai_get_goal_target_name(Ships[other_objp->instance].ship_name, &aigp->target_name_index);
5136 
5137  // special case for destroy subsystem -- get the ai_info pointer to our target ship
5138  // so that we can properly set up what subsystem this ship is attacking.
5139  if ( (mode == AI_GOAL_DESTROY_SUBSYSTEM ) && (submode >= 0) )
5140  aip->targeted_subsys = ship_get_indexed_subsys( &Ships[other_objp->instance], submode);
5141  }
5142 
5143  break;
5144 
5145  default:
5146  Int3(); // this Int3() should be temporary
5147  nprintf(("Network", "Invalid code for ai update: %d\n", code));
5148  break;
5149  }
5150  PACKET_SET_SIZE();
5151 }
5152 
5153 // tell the standalone to move into the MISSION_SYNC_STATE
5154 void send_mission_sync_packet(int mode,int start_campaign)
5155 {
5156  ubyte data[MAX_PACKET_SIZE],is_campaign;
5157  int packet_size = 0;
5158 
5160 
5161  // build the header and add the sync mode (pre or post briefing)
5163  ADD_INT(mode);
5164 
5165  // if this is a campaign game
5166  if(mode == MULTI_SYNC_PRE_BRIEFING){
5168  // add a byte indicating campaign mode
5169  is_campaign = 1;
5170  ADD_DATA(is_campaign);
5171 
5172  // add a byte indicating if we should be starting a campaign or continuing it
5173  is_campaign = (ubyte)start_campaign;
5174  ADD_DATA(is_campaign);
5175 
5176  // add the campaign filename
5178  }
5179  // otherwise if this is a single mission
5180  else {
5181  // add a byte indicating single mission mode
5182  is_campaign = 0;
5183  ADD_DATA(is_campaign);
5184 
5185  // add the mission filename
5187  }
5188  }
5189  multi_io_send_reliable(Net_player, data, packet_size);
5190 }
5191 
5192 // move into the MISSION_SYNC state when this is received
5193 // this packet is sent only from a game host to a standalone
5195 {
5196  int mode;
5197  ubyte campaign_flag;
5198  int offset = HEADER_LENGTH;
5199 
5201 
5202  // if this is a team vs team situation, lock the players send a final team update
5206  }
5207 
5208  // get the sync mode (pre or post briefing)
5209  GET_INT(mode);
5210 
5211  if(mode == MULTI_SYNC_PRE_BRIEFING){
5212  // get the flag indicating if this is a single mission or a campaign mode
5213  GET_DATA(campaign_flag);
5214  if(campaign_flag){
5215  // get the flag indicating whether we should be starting a new campaign
5216  GET_DATA(campaign_flag);
5217 
5218  // get the campaign filename
5220 
5221  // either start a new campaign or continue on to the next mission in the current campaign
5222  if(campaign_flag){
5224  } else {
5226  }
5227  } else {
5228  // make sure we remove the campaign mode flag
5230 
5231  // get the single mission filename
5234  }
5235  }
5236  else if (mode == MULTI_SYNC_POST_BRIEFING) {
5237  // process the initial orders now (moved from post_process_mission()in missionparse)
5240  }
5241  PACKET_SET_SIZE();
5242 
5243  // set the correct mode and m ove into the state
5246 }
5247 
5248 // tell a player to merge his mission stats into his alltime stats
5249 void send_store_stats_packet(int accept)
5250 {
5251  ubyte data[10],val;
5252  int packet_size = 0;
5253 
5255 
5256  // add whether we're accepting or tossing
5257  val = (ubyte)accept;
5258  ADD_DATA(val);
5259 
5260  // if I'm the server, send to everyone, else send to the standalone to be rebroadcasted
5262  multi_io_send_to_all_reliable(data, packet_size);
5263  } else {
5264  multi_io_send_reliable(Net_player, data, packet_size);
5265  }
5266 }
5267 
5269 {
5270  int offset = HEADER_LENGTH;
5271  ubyte accept;
5272 
5273  GET_DATA(accept);
5274  PACKET_SET_SIZE();
5275 
5276  // if I'm the standalone, rebroadcast. Otherwise, if I'm a client, merge my mission stats with my alltime stats
5278  // rebroadcast the packet to all others in the game
5279  nprintf(("Network","Standalone received store stats packet - rebroadcasting..\n"));
5280  multi_io_send_to_all_reliable(data, offset);
5281  } else {
5282  if(accept){
5283  // all players should mark the stats as being accepted in the debriefing
5285 
5286 
5287  } else {
5288  // all players should mark the stats as being "tossed" in the debriefing
5290  }
5291  }
5292 }
5293 
5294 void send_debris_update_packet(object *objp,int code)
5295 {
5297  ubyte val;
5298  int packet_size = 0;
5299 
5301  ADD_USHORT(objp->net_signature);
5302  val = (ubyte) code;
5303  ADD_DATA(val);
5304 
5305  // add any extra relevant data
5306  switch(code){
5307  case DEBRIS_UPDATE_UPDATE:
5308  ADD_VECTOR(objp->pos); // add position
5309  ADD_ORIENT(objp->orient); // add orientation
5310  ADD_VECTOR(objp->phys_info.vel); // add velocity
5311  ADD_VECTOR(objp->phys_info.rotvel); // add rotational velocity
5312  break;
5313  }
5314  multi_io_send_to_all(data, packet_size);
5315 }
5316 
5318 {
5319  ushort net_sig;
5320  ubyte code;
5321  object bogus_object;
5322  object *objp;
5323  int offset = HEADER_LENGTH;
5324 
5325  GET_USHORT(net_sig);
5326  GET_DATA(code);
5327 
5328  objp = NULL;
5329  objp = multi_get_network_object(net_sig);
5330  if(objp == NULL){
5331  objp = &bogus_object;
5332  }
5333 
5334  switch((int)code){
5335  // update the object
5336  case DEBRIS_UPDATE_UPDATE:
5337  GET_VECTOR(objp->pos);
5338  GET_ORIENT(objp->orient);
5339  GET_VECTOR(objp->phys_info.vel);
5340  GET_VECTOR(objp->phys_info.rotvel);
5341  break;
5342  // simply remove it (no explosion)
5343  case DEBRIS_UPDATE_REMOVE:
5344  if(objp != &bogus_object){
5345  Assert(objp->type == OBJ_DEBRIS);
5346  obj_delete(OBJ_INDEX(objp));
5347  }
5348  break;
5349  // blow it up
5350  case DEBRIS_UPDATE_NUKE:
5351  if(objp != &bogus_object)
5352  debris_hit(objp,NULL,&objp->pos,1000000.0f);
5353  break;
5354  }
5355 
5356  PACKET_SET_SIZE();
5357 }
5358 
5359 // ALAN begin
5360 void send_wss_request_packet(short player_id, int from_slot, int from_index, int to_slot, int to_index, int wl_ship_slot, int ship_class, int mode, net_player *p)
5361 {
5363 
5364  int packet_size = 0;
5365 
5367 
5368  // add the request information
5369  ADD_SHORT(player_id);
5370  ADD_INT(from_slot);
5371  ADD_INT(from_index);
5372  ADD_INT(to_slot);
5373  ADD_INT(to_index);
5374  ADD_INT(wl_ship_slot); // only used in weapons loadout
5375  ADD_INT(ship_class);
5376  ADD_INT(mode);
5377 
5378  // a standard request
5379  if(p == NULL){
5380  multi_io_send_reliable(Net_player, data, packet_size);
5381  }
5382  // being routed through the standalone to the host of the game
5383  else {
5385  multi_io_send_reliable(p, data, packet_size);
5386  }
5387 }
5388 
5390 {
5391  int offset = HEADER_LENGTH;
5392  int from_slot,from_index;
5393  int to_slot,to_index;
5394  int mode;
5395  int wl_ship_slot,ship_class;
5396  short player_id;
5397  int player_num;
5398 
5399  // determine who this request is from
5400  GET_SHORT(player_id);
5401  player_num = find_player_id(player_id);
5402 
5403  // read in the request data
5404  GET_INT(from_slot);
5405  GET_INT(from_index);
5406  GET_INT(to_slot);
5407  GET_INT(to_index);
5408  GET_INT(wl_ship_slot); // only used in weapons loadout
5409  GET_INT(ship_class); // only used in multi team select
5410  GET_INT(mode);
5411  PACKET_SET_SIZE();
5412 
5413  Assert(player_num != -1);
5414  if(player_num == -1){
5415  return;
5416  }
5417 
5418  // if we're the standalone, we have to route this packet to the host of the game
5420  send_wss_request_packet(player_id, from_slot, from_index, to_slot, to_index, wl_ship_slot, ship_class, mode, Netgame.host);
5421  }
5422  // otherwise we're the host and should process the request
5423  else {
5424  switch(mode){
5425  case WSS_WEAPON_SELECT :
5426  wl_drop(from_slot,from_index,to_slot,to_index,wl_ship_slot,player_num);
5427  break;
5428  case WSS_SHIP_SELECT :
5429  multi_ts_drop(from_slot,from_index,to_slot,to_index,ship_class,player_num);
5430  break;
5431  default:
5432  Int3();
5433  }
5434  }
5435 }
5436 
5437 void send_wss_update_packet(int team_num,ubyte *wss_data,int size)
5438 {
5440  int packet_size = 0;
5441 
5442  Assert(size <= (MAX_PACKET_SIZE - 10));
5443 
5445 
5446  // add the team/pool # this is for
5447  team = (ubyte)team_num;
5448  ADD_DATA(team);
5449 
5450  // add the data block size
5451  ADD_INT(size);
5452 
5453  // add the data itself
5454  memcpy(data + packet_size,wss_data,size);
5455  packet_size += size;
5456 
5457  // if we're also the master of the game (not on a standalone)
5459  multi_io_send_to_all_reliable(data, packet_size);
5460  }
5461  // if we're only the host on the standalone, then send the packet to the standalone to be routed
5462  else {
5463  multi_io_send_reliable(Net_player, data, packet_size);
5464  }
5465 }
5466 
5468 {
5469  ubyte team;
5470  int size,player_index,idx;
5471  int offset = HEADER_LENGTH;
5472 
5473  // get the team/pool #
5474  GET_DATA(team);
5475 
5476  // get the data size
5477  GET_INT(size);
5478 
5479  // if we're the standalone, then we should be routing this data to all the other clients
5481  // read in the data
5482  offset += size;
5483  PACKET_SET_SIZE();
5484 
5485  // determine where this came from
5486  player_index = find_player_id(hinfo->id);
5487  Assert(player_index != -1);
5488  if(player_index < 0){
5489  return;
5490  }
5491 
5492  // route the packet (don't resend it to the host)
5493  for(idx=0;idx<MAX_PLAYERS;idx++){
5494  if(MULTI_CONNECTED(Net_players[idx]) && (&Net_players[idx] != Net_player) && (&Net_players[idx] != &Net_players[player_index]) ){
5495  multi_io_send_reliable(&Net_players[idx], data, offset);
5496  }
5497  }
5498  } else {
5499  // set the proper pool pointers
5500  common_set_team_pointers((int)team);
5501 
5502  // read in the block of data, and apply it to the weapons/ship pools
5503  offset += restore_wss_data(data + offset);
5504  PACKET_SET_SIZE();
5505 
5506  // set the pool pointers back to my own team
5508 
5509  // sync the interface if this was for my own team
5510  if((int)team == Net_player->p_info.team){
5512  }
5513  }
5514 }
5515 // ALAN END
5516 
5517 
5518 // function to send firing information from the client to the server once they reach
5519 // the final sync screen.
5521 {
5523  int packet_size;
5524  ubyte plinked, sdual;
5525 
5527 
5529  plinked = (ubyte)((Player_ship->flags & SF_PRIMARY_LINKED)?1:0);
5530  sdual = (ubyte)((Player_ship->flags & SF_SECONDARY_DUAL_FIRE)?1:0);
5531  ADD_DATA( plinked );
5532  ADD_DATA( sdual );
5533 
5534  multi_io_send_reliable(Net_player, data, packet_size);
5535 }
5536 
5538 {
5539  int offset, player_num;
5540  ubyte plinked, sdual;
5541  ship *shipp;
5542 
5543  // only the master of the game should be dealing with these packets
5545 
5546  offset = HEADER_LENGTH;
5547  GET_DATA( plinked );
5548  GET_DATA( sdual );
5549  PACKET_SET_SIZE();
5550 
5551  player_num = find_player_id(hinfo->id);
5552  if(player_num < 0){
5553  nprintf(("Network","Received firing info packet from unknown player, ignoring\n"));
5554  return;
5555  }
5556 
5557  // get the ship pointer for this player and set the flags accordingly.
5558  shipp = &(Ships[Objects[Net_players[player_num].m_player->objnum].instance]);
5559  if ( plinked )
5560  shipp->flags |= SF_PRIMARY_LINKED;
5561  else
5562  shipp->flags &= ~SF_PRIMARY_LINKED;
5563 
5564  if ( sdual )
5565  shipp->flags |= SF_SECONDARY_DUAL_FIRE;
5566  else
5567  shipp->flags &= ~SF_SECONDARY_DUAL_FIRE;
5568 }
5569 
5570 // packet to deal with changing status of mission goals. used to be sent every so often from server
5571 // to clients, but with addition of reliable sockets, send when complete, invalid, etc.
5572 // goal_num is the index into mission_goals. new_status means failed, success, etc. -1 if not used.
5573 // valid means goal is changing to invalid(0) or valid(1). only applies if new_status == -1
5574 void send_mission_goal_info_packet( int goal_num, int new_status, int valid )
5575 {
5577  int packet_size;
5578 
5580 
5581  ADD_INT(goal_num);
5582  ADD_INT(new_status);
5583  ADD_INT(valid);
5584 
5585  multi_io_send_to_all_reliable(data, packet_size);
5586 }
5587 
5589 {
5590  int offset, goal_num, new_status, valid;
5591 
5592  offset = HEADER_LENGTH;
5593  GET_INT(goal_num);
5594  GET_INT(new_status);
5595  GET_INT(valid);
5596  PACKET_SET_SIZE();
5597 
5598  // if new_status != -1, then this is a change in goal status (i.e. goal failed, or is successful)
5599  if ( new_status != -1 ){
5600  mission_goal_status_change( goal_num, new_status );
5601  } else {
5602  mission_goal_validation_change( goal_num, valid );
5603  }
5604 }
5605 
5607 {
5609  ubyte stop;
5610  int idx;
5611  int packet_size = 0;
5612 
5613  // build the header
5615 
5616  // add all the data for all the players
5617  stop = 0x0;
5618  for(idx=0;idx<MAX_PLAYERS;idx++){
5619  if(MULTI_CONNECTED(Net_players[idx])){
5620  ADD_DATA(stop);
5621  ADD_SHORT(Net_players[idx].player_id);
5622 
5623  // break the p_info structure by member, so we don't overwrite any absolute pointers
5624  // ADD_DATA(Net_players[idx].p_info);
5625  ADD_INT(Net_players[idx].p_info.team);
5626  ADD_INT(Net_players[idx].p_info.ship_index);
5627  ADD_INT(Net_players[idx].p_info.ship_class);
5628  }
5629  }
5630  // add the stop byte
5631  stop = 0xff;
5632  ADD_DATA(stop);
5633 
5634  // either broadcast the data or send to a specific player
5635  if(p == NULL){
5636  multi_io_send_to_all_reliable(data, packet_size);
5637  } else {
5638  multi_io_send_reliable(p, data, packet_size);
5639  }
5640 }
5641 
5643 {
5644  int offset,player_num;
5645  net_player_info bogus,*ptr;
5646  short player_id;
5647  ubyte stop;
5648 
5649  offset = HEADER_LENGTH;
5650 
5651  // read in the data for all the players
5652  GET_DATA(stop);
5653  while(stop != 0xff){
5654  // lookup the player
5655  GET_SHORT(player_id);
5656  player_num = find_player_id(player_id);
5657 
5658  // make sure this is a valid player
5659  if(player_num == -1){
5660  ptr = &bogus;
5661  } else {
5662  ptr = &Net_players[player_num].p_info;
5663  }
5664 
5665  GET_INT(ptr->team);
5666  GET_INT(ptr->ship_index);
5667  GET_INT(ptr->ship_class);
5668 
5669  // next stop byte
5670  GET_DATA(stop);
5671  }
5672  PACKET_SET_SIZE();
5673 
5674  // update the server with my new state
5675  // MWA -- 3/31/98 -- check for in mission instead of state.
5676  //if ( Netgame.game_state == NETGAME_STATE_MISSION_SYNC) {
5677  if( !(Game_mode & GM_IN_MISSION) ) {
5680  }
5681 
5682 
5683  // display some cool text
5684  multi_common_add_text(XSTR("Received player settings packet\n",721),1);
5685 }
5686 
5688 {
5689  ubyte data[10];
5690  int packet_size = 0;
5691 
5692  // build the header and add the rejection code
5693  BUILD_HEADER(DENY);
5694 
5695  ADD_INT(code);
5696 
5697  // send the packet
5698  psnet_send(addr, data, packet_size);
5699 }
5700 
5702 {
5703  int offset,code;
5704 
5705  // get the denial code
5706  offset = HEADER_LENGTH;
5707  GET_INT(code);
5708  PACKET_SET_SIZE();
5709 
5710  // if there is already a dialog active, do nothing - who cares at this point.
5711  if(popup_active()){
5712  return;
5713  }
5714 
5715  // display the appropriate dialog
5716  switch(code){
5717  case JOIN_DENY_JR_STATE :
5718  popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR("You have been rejected because the game is not in an appropriate state to accept",722));
5719  break;
5721  popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR("You have been rejected because this is a Parallax Online game and you are not a registered Parallax Online pilot",723));
5722  break;
5723  case JOIN_DENY_JR_PASSWD :
5724  popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR("You have been rejected because this is a password protected game",724));
5725  break;
5726  case JOIN_DENY_JR_CLOSED :
5727  popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR("You have been rejected because this is a closed game and the mission is in progress",725));
5728  break;
5730  popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR("You have been rejected because the netgame is forming and the host has temporarily closed it",726));
5731  break;
5732  case JOIN_DENY_JR_RANK_HIGH :
5733  popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR("You have been rejected because this is a rank limited game and your rank is too high",727));
5734  break;
5735  case JOIN_DENY_JR_RANK_LOW :
5736  popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR("You have been rejected because this is a rank limited game and your rank is too low",728));
5737  break;
5738  case JOIN_DENY_JR_DUP :
5739  popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR("You have been rejected because there is an identical player already in the game",729));
5740  break;
5741  case JOIN_DENY_JR_FULL :
5742  popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR("You have been rejected because the game is full",730));
5743  break;
5744  case JOIN_DENY_JR_BANNED :
5745  popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR("You have been rejected because you are banned from this server",731));
5746  break;
5747  case JOIN_DENY_JR_NOOBS :
5748  popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR("You have been rejected because this game does not allow observers",732));
5749  break;
5751  popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR("You cannot join at this time since someone else is currently joining. Try again shortly.",733));
5752  break;
5754  popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR("You cannot join this game because you are running an older version of FreeSpace than the server. Exit FreeSpace, and choose the 'Update FreeSpace' button in the FreeSpace launcher to download the latest version of FreeSpace.",734));
5755  break;
5756  case JOIN_DENY_JR_TYPE :
5757  popup(PF_USE_AFFIRMATIVE_ICON,1,POPUP_OK,XSTR("You cannot join a game in progress unless it is a dogfight mission.",1433));
5758  break;
5759  }
5760 
5761  // call this so that the join request timestamp automatically expires when we hear back from the server
5763 }
5764 
5765 // this packet will consist of
5766 // 1.) netplayer ship classes (85 bytes max)
5767 // 2.) ship weapon state data (277 bytes max)
5768 // 3.) player settings et. al. (133 bytes max)
5769 // TOTAL 495 NOTE : keep this in mind when/if adding new data to this packet
5770 void send_post_sync_data_packet(net_player *p, int std_request)
5771 {
5773  char bval;
5774  ship *shipp;
5775  net_player *pl;
5776  ship_obj *so;
5777  ushort sval, ship_ets;
5778  int idx, player_index;
5779  int packet_size = 0;
5780  int ship_count;
5781  short val_short;
5782 
5784 
5785  // some header information for standalone packet routing purposes
5786  val = (ubyte)std_request;
5787  ADD_DATA(val);
5788 
5789  // the standalone has two situations
5790  // 1.) sending a request to the host to distribute this block of data
5791  // 2.) having recevied this block of data from the host, it redistributes it
5792  if((Game_mode & GM_STANDALONE_SERVER) && std_request && (Netgame.host != NULL)){
5793  // case 1, send the request
5794  multi_io_send_reliable(Netgame.host, data, packet_size);
5795  return;
5796  }
5797  // case 2 for the standalone is below (as normal)
5798 
5799  // otherwise build the data now
5800 
5801  // add all deleted ships
5802  val = (ubyte)Multi_ts_num_deleted;
5803  ADD_DATA(val);
5804  for(idx=0;idx<Multi_ts_num_deleted;idx++){
5805  sval = (ushort)Objects[Multi_ts_deleted_objnums[idx]].net_signature;
5806  ADD_USHORT(sval);
5807  }
5808 
5809  // ship count
5810  ship_count = 0;
5811  for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
5812  shipp = &Ships[Objects[so->objnum].instance];
5813 
5814  // don't process non player wing ships
5815  if ( !(shipp->flags & SF_FROM_PLAYER_WING ) )
5816  continue;
5817 
5818  ship_count++;
5819  }
5820 
5821  // # of ships - used multiple times in the packet
5822  val = (ubyte)ship_count;
5823  ADD_DATA(val);
5824 
5825  // add ship class information (85 bytes max)
5826  for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
5827  shipp = &Ships[Objects[so->objnum].instance];
5828 
5829  // don't process non player wing ships
5830  if ( !(shipp->flags & SF_FROM_PLAYER_WING ) )
5831  continue;
5832 
5833  // add the net signature of the object for look up
5834  ADD_USHORT( Objects[so->objnum].net_signature );
5835 
5836  // add the ship info index
5837  val = (ubyte)(shipp->ship_info_index);
5838  ADD_DATA(val);
5839 
5840  // add the ships's team select index
5841  val = (ubyte)shipp->ts_index;
5842  ADD_DATA(val);
5843  }
5844 
5845  // add weapon state information for all starting ships (277 bytes max)
5846  for ( so = GET_FIRST(&Ship_obj_list); so != END_OF_LIST(&Ship_obj_list); so = GET_NEXT(so) ) {
5847  shipp = &Ships[Objects[so->objnum].instance];
5848 
5849  // don't process non player wing ships
5850  if ( !(shipp->flags & SF_FROM_PLAYER_WING ) )
5851  continue;
5852 
5853  // if this is a ship owned by a player, we should mark down his weapons bank/link settings now if we're the server
5854  pl = NULL;
5856  player_index = multi_find_player_by_net_signature(Objects[so->objnum].net_signature);
5857  if(player_index == -1){
5858  pl = NULL;
5859  } else {
5860  pl = &Net_players[player_index];
5861  }
5862  }
5863 
5864  // add the net signature and other weapon information
5865  ADD_USHORT( Objects[so->objnum].net_signature );
5866 
5867  // add number of primary and secondary banks
5868  bval = (char)(shipp->weapons.num_primary_banks);
5869  ADD_DATA(bval);
5870  bval = (char)(shipp->weapons.num_secondary_banks);
5871  ADD_DATA(bval);
5872 
5873  // add weapon bank status
5874  bval = (char)(shipp->weapons.current_primary_bank);
5875  if(pl != NULL){
5876  pl->s_info.cur_primary_bank = bval;
5877  }
5878  // Assert(bval != -1);
5879  ADD_DATA(bval);
5880 
5881  bval = (char)(shipp->weapons.current_secondary_bank);
5882  if(pl != NULL){
5883  pl->s_info.cur_secondary_bank = bval;
5884  }
5885  // Assert(bval != -1);
5886  ADD_DATA(bval);
5887 
5888  // primary weapon info
5889  val = (ubyte)(shipp->weapons.primary_bank_weapons[0]);
5890  ADD_DATA(val);
5891  val = (ubyte)(shipp->weapons.primary_bank_weapons[1]);
5892  ADD_DATA(val);
5893 
5894  // secondary weapon info
5895  val_short = (short)(shipp->weapons.secondary_bank_weapons[0]);
5896  ADD_SHORT(val_short);
5897  val_short = (short)(shipp->weapons.secondary_bank_ammo[0]);
5898  ADD_SHORT(val_short);
5899  val_short = (short)(shipp->weapons.secondary_bank_weapons[1]);
5900  ADD_SHORT(val_short);
5901  val_short = (short)(shipp->weapons.secondary_bank_ammo[1]);
5902  ADD_SHORT(val_short);
5903  val_short = (short)(shipp->weapons.secondary_bank_weapons[2]);
5904  ADD_SHORT(val_short);
5905  val_short = (short)(shipp->weapons.secondary_bank_ammo[2]);
5906  ADD_SHORT(val_short);
5907 
5908  // send primary and secondary weapon link status
5909  val = 0x0;
5910  if(shipp->flags & SF_PRIMARY_LINKED){
5911  if(pl != NULL){
5912  pl->s_info.cur_link_status |= (1<<0);
5913  }
5914  val |= (1<<0);
5915  }
5916  if(shipp->flags & SF_SECONDARY_DUAL_FIRE){
5917  if(pl != NULL){
5918  pl->s_info.cur_link_status |= (1<<1);
5919  }
5920  val |= (1<<1);
5921  }
5922  // if this is a player ship add (1<<2)
5923  if(Objects[shipp->objnum].flags & OF_PLAYER_SHIP){
5924  val |= (1<<2);
5925  }
5926  ADD_DATA(val);
5927 
5928  // add a ship ets value
5929  ship_ets = 0x0000;
5930  // shield ets
5931  ship_ets |= ((ushort)shipp->shield_recharge_index << 8);
5932  // weapon ets
5933  ship_ets |= ((ushort)shipp->weapon_recharge_index << 4);
5934  // engine ets
5935  ship_ets |= ((ushort)shipp->engine_recharge_index);
5936  ADD_USHORT(ship_ets);
5937 
5938  }
5939 
5940  // 2 cases, if I'm the host on a standalone, I should be sending this to the standalone only
5941  // or if I'm the server as well as the host, I should be sending this to all players
5944  // broadcast
5945  if(p == NULL){
5946  multi_io_send_to_all_reliable(data, packet_size);
5947  }
5948  // send to a specific player
5949  else {
5950  multi_io_send_reliable(p, data, packet_size);
5951  }
5952  } else {
5953  multi_io_send_reliable(Net_player, data, packet_size);
5954  }
5955  }
5956  // standalone mode
5957  else {
5958  // broadcast
5959  if(p == NULL){
5960  multi_io_send_to_all_reliable(data, packet_size);
5961  }
5962  // send to a specific player
5963  else {
5964  multi_io_send_reliable(p, data, packet_size);
5965  }
5966  }
5967 }
5968 
5970 {
5971  ubyte val, sinfo_index, ts_index;
5972  char b;
5973  ushort net_sig, ship_ets, sval;
5974  ship *shipp;
5975  object *objp;
5976  int idx;
5977  int offset = HEADER_LENGTH;
5978  int ship_count;
5979  short val_short;
5980 
5981  // packet routing information
5982  GET_DATA(val);
5983 
5984  // if I'm the host on a standalone, this is going to be a request to send the data to the standalone to be routed
5986  PACKET_SET_SIZE();
5987 
5988  // at this point we want to delete all necessary ships, change all necessary ship classes, and set all weapons up
5990 
5991  // send to the standalone through my socket
5993  return;
5994  }
5995 
5996  // process player
5997 
5998  // add all deleted ships
5999  GET_DATA(val);
6000  Multi_ts_num_deleted = (int)val;
6001  for(idx=0;idx<Multi_ts_num_deleted;idx++){
6002  // get the ship's objnum
6003  GET_USHORT(sval);
6004  objp = NULL;
6005  objp = multi_get_network_object(sval);
6006  if(objp != NULL){
6007  // delete the ship appropriately
6008  // mark the object as having been deleted
6010 
6011  // delete the ship
6015  } else {
6016  Multi_ts_num_deleted--;
6017  nprintf(("Network","Couldn't find object by net signature for ship delete in post sync data packet\n"));
6018  }
6019  }
6020 
6021  // ship count
6022  GET_DATA(val);
6023  ship_count = val;
6024 
6025  // process ship class information
6026  for(idx=0; idx<ship_count; idx++){
6027  // get the object's net signature
6028  GET_USHORT(net_sig);
6029  GET_DATA(sinfo_index);
6030  GET_DATA(ts_index);
6031 
6032  // attempt to get the object
6033  objp = multi_get_network_object(net_sig);
6034 
6035  // make sure we found a ship
6036  Assertion(objp != NULL, "idx: %d, ship_count: %d, sinfo_index: %u, ts_index: %u, net_sig: %u",
6037  idx, ship_count, sinfo_index, ts_index, net_sig);
6038  Assertion(objp->type == OBJ_SHIP, "type: %d, idx: %d, ship_count: %d, sinfo_index: %u, ts_index: %u, net_sig: %u",
6039  objp->type, idx, ship_count, sinfo_index, ts_index, net_sig);
6040 
6041  // set the ship to be the right class
6042  change_ship_type(objp->instance,(int)sinfo_index);
6043 
6044  // set the ship's team select index
6045  Ships[objp->instance].ts_index = (int)ts_index;
6046  }
6047 
6048  // process ship weapon state info
6049  for(idx=0; idx<ship_count; idx++){
6050  // get the object's net signature
6051  GET_USHORT(net_sig);
6052 
6053  // attempt to get the object
6054  objp = multi_get_network_object(net_sig);
6055 
6056  // make sure we found a ship
6057  Assert((objp != NULL) && (objp->type == OBJ_SHIP));
6058 
6059  // get a pointer to the ship
6060  shipp = &Ships[objp->instance];
6061 
6062  // get number of primary and secondary banks;
6063  GET_DATA(b);
6064  Assert( b != -1 );
6065  shipp->weapons.num_primary_banks = (int)b;
6066 
6067  GET_DATA(b);
6068  Assert( b != -1 );
6069  shipp->weapons.num_secondary_banks = (int)b;
6070 
6071  // get bank selection info
6072  GET_DATA(b);
6073  if ( b == -1 ){
6074  b = 0;
6075  }
6076  shipp->weapons.current_primary_bank = (int)b;
6077 
6078  GET_DATA(b);
6079  if ( b == -1 ){
6080  b = 0;
6081  }
6082  shipp->weapons.current_secondary_bank = (int)b;
6083 
6084  // primary weapon info
6085  GET_DATA(val);
6086  shipp->weapons.primary_bank_weapons[0] = (int)val;
6087 
6088  GET_DATA(val);
6089  shipp->weapons.primary_bank_weapons[1] = (int)val;
6090 
6091  // secondary weapon info
6092  GET_SHORT(val_short);
6093  shipp->weapons.secondary_bank_weapons[0] = (int)val_short;
6094  GET_SHORT(val_short);
6095  shipp->weapons.secondary_bank_ammo[0] = (int)val_short;
6096 
6097  GET_SHORT(val_short);
6098  shipp->weapons.secondary_bank_weapons[1] = (int)val_short;
6099  GET_SHORT(val_short);
6100  shipp->weapons.secondary_bank_ammo[1] = (int)val_short;
6101 
6102  GET_SHORT(val_short);
6103  shipp->weapons.secondary_bank_weapons[2] = (int)val_short;
6104  GET_SHORT(val_short);
6105  shipp->weapons.secondary_bank_ammo[2] = (int)val_short;
6106 
6107  // other flags
6108  val = 0x0;
6109  GET_DATA(val);
6110 
6111  if(val & (1<<0)){
6112  shipp->flags |= SF_PRIMARY_LINKED;
6113  }
6114  if(val & (1<<1)){
6115  shipp->flags |= SF_SECONDARY_DUAL_FIRE;
6116  }
6117  Objects[shipp->objnum].flags &= ~(OF_PLAYER_SHIP);
6118  Objects[shipp->objnum].flags &= ~(OF_COULD_BE_PLAYER);
6119  if(val & (1<<2)){
6120  Objects[shipp->objnum].flags |= OF_PLAYER_SHIP;
6121  } else {
6123  }
6124 
6125  // get ship ets
6126  GET_USHORT(ship_ets);
6127  // shield ets
6128  shipp->shield_recharge_index = ((ship_ets & 0x0f00) >> 8);
6129  // weapon ets
6130  shipp->weapon_recharge_index = ((ship_ets & 0x00f0) >> 4);
6131  // engine ets
6132  shipp->engine_recharge_index = (ship_ets & 0x000f);
6133  }
6134  PACKET_SET_SIZE();
6135 
6136  // ack the server
6139 
6140  // the standalone server will receive this packet from the host of the game, to be applied locally and
6141  // also to be rebroadcast.
6143  // update player ets settings
6144  for(idx=0;idx<MAX_PLAYERS;idx++){
6145  if(MULTI_CONNECTED(Net_players[idx]) && !MULTI_STANDALONE(Net_players[idx]) && !MULTI_PERM_OBSERVER(Net_players[idx]) && (Net_players[idx].m_player->objnum != -1)){
6147  }
6148  }
6149 
6151  }
6152 }
6153 
6154 void send_wss_slots_data_packet(int team_num,int final,net_player *p,int std_request)
6155 {
6157  short val_short;
6158  int idx,i;
6159  int packet_size = 0;
6160 
6161  // build the header
6163 
6164  // some header information for standalone packet routing purposes
6165  val = (ubyte)std_request;
6166  ADD_DATA(val);
6167 
6168  // add the team #
6169  val = (ubyte)team_num;
6170  ADD_DATA(val);
6171 
6172  // add whether this is the final packet or not
6173  val = (ubyte)final;
6174  ADD_DATA(val);
6175 
6176  // the standalone has two situations
6177  // 1.) sending a request to the host to distribute this block of data
6178  // 2.) having recevied this block of data from the host, it redistributes it
6179  if((Game_mode & GM_STANDALONE_SERVER) && std_request){
6180  // case 1, send the request
6181  multi_io_send_reliable(Netgame.host, data, packet_size);
6182  return;
6183  }
6184  // case 2 for the standalone is below (as normal)
6185 
6186  // add all the slots
6187  for(idx=0;idx<MULTI_TS_NUM_SHIP_SLOTS;idx++){
6188  // add the ship class
6189  val = (ubyte)Wss_slots_teams[team_num][idx].ship_class;
6190  ADD_DATA(val);
6191 
6192  // add the weapons
6193  for(i = 0;i<MAX_SHIP_WEAPONS;i++){
6194  val_short = (short)Wss_slots_teams[team_num][idx].wep[i];
6195  ADD_SHORT(val_short);
6196  }
6197 
6198  // add the weapon counts
6199  for(i = 0;i<MAX_SHIP_WEAPONS;i++){
6200  val_short = (short)Wss_slots_teams[team_num][idx].wep_count[i];
6201  ADD_SHORT(val_short);
6202  }
6203  }
6204 
6205  // 2 cases, if I'm the host on a standalone, I should be sending this to the standalone only
6206  // or if I'm the server as well as the host, I should be sending this to all players
6209  // broadcast
6210  if(p == NULL){
6211  multi_io_send_to_all_reliable(data, packet_size);
6212  }
6213  // send to a specific player
6214  else {
6215  multi_io_send_reliable(p, data, packet_size);
6216  }
6217  } else {
6218  multi_io_send_reliable(Net_player, data, packet_size);
6219  }
6220  }
6221  // standalone mode
6222  else {
6223  // broadcast
6224  if(p == NULL){
6225  multi_io_send_to_all_reliable(data, packet_size);
6226  }
6227  // send to a specific player
6228  else {
6229  multi_io_send_reliable(p, data, packet_size);
6230  }
6231  }
6232 }
6233 
6235 {
6236  ubyte val,team_num,final;
6237  int idx,i;
6238  int offset = HEADER_LENGTH;
6239  short val_short;
6240 
6241  // packet routing information
6242  GET_DATA(val);
6243 
6244  // get team data
6245  GET_DATA(team_num);
6246 
6247  // get whether this is the final packet or not
6248  GET_DATA(final);
6249 
6250  // if I'm the host on a standalone, this is going to be a request to send the data to the standalone to be routed
6252  PACKET_SET_SIZE();
6253 
6254  // send to the standalone through my socket
6255  send_wss_slots_data_packet((int)team_num,(int)final,Net_player);
6256  return;
6257  }
6258 
6259  // read in all the slot data
6260  for(idx=0;idx<MULTI_TS_NUM_SHIP_SLOTS;idx++){
6261  memset(&Wss_slots_teams[team_num][idx],0,sizeof(wss_unit));
6262 
6263  // get the ship class
6264  GET_DATA(val);
6265  Wss_slots_teams[team_num][idx].ship_class = (int)val;
6266 
6267  // get the weapons
6268  for(i = 0;i<MAX_SHIP_WEAPONS;i++){
6269  GET_SHORT(val_short);
6270  Wss_slots_teams[team_num][idx].wep[i] = (int)val_short;
6271  }
6272 
6273  // get the weapon counts
6274  for(i = 0;i<MAX_SHIP_WEAPONS;i++){
6275  GET_SHORT(val_short);
6276  Wss_slots_teams[team_num][idx].wep_count[i] = (int)val_short;
6277  }
6278  }
6279  PACKET_SET_SIZE();
6280 
6281  // update my netplayer state if this is the final packet
6282  if(final){
6285  }
6286 
6287  // the standalone server will receive this packet from the host of the game, to be applied locally and
6288  // also to be rebroadcast.
6290  send_wss_slots_data_packet((int)team_num,(int)final,NULL,0);
6291  } else {
6292  // add some mission sync text
6293  multi_common_add_text(XSTR("Weapon slots packet\n",735),1);
6294  }
6295 }
6296 
6297 #define OBJ_VISIBILITY_DOT 0.6f
6298 
6299 // send and receive packets for shield explosion information
6300 void send_shield_explosion_packet( int objnum, int tri_num, vec3d hit_pos )
6301 {
6302  int packet_size, i;
6303  ubyte data[MAX_PACKET_SIZE], utri_num;
6304 
6305  Int3();
6306  // Assert(!(Netgame.debug_flags & NETD_FLAG_CLIENT_NODAMAGE));
6307 
6308  Assert( tri_num < UCHAR_MAX );
6309  utri_num = (ubyte)tri_num;
6310 
6311  // for each player, determine if this object is behind the player -- if so, don't
6312  // send the packet.
6313  for ( i = 0; i < MAX_PLAYERS; i++ ) {
6314  if ( MULTI_CONNECTED(Net_players[i]) && (&Net_players[i] != Net_player) ) {
6315  float dot;
6316  vec3d eye_to_obj_vec, diff, eye_pos;
6318 
6319  eye_pos = Net_players[i].s_info.eye_pos;
6320  eye_orient = Net_players[i].s_info.eye_orient;
6321 
6322  // check for same vectors
6323  vm_vec_sub(&diff, &Objects[objnum].pos, &eye_pos);
6324  if ( vm_vec_mag_quick(&diff) < 0.01 ){
6325  continue;
6326  }
6327 
6328  vm_vec_normalized_dir(&eye_to_obj_vec, &Objects[objnum].pos, &eye_pos);
6329  dot = vm_vec_dot(&eye_orient.vec.fvec, &eye_to_obj_vec);
6330 
6331  if ( dot < OBJ_VISIBILITY_DOT ){
6332  continue;
6333  }
6334 
6336 
6337  ADD_USHORT( Objects[objnum].net_signature );
6338  ADD_DATA(utri_num);
6339 
6340  multi_io_send(&Net_players[i], data, packet_size);
6341  }
6342  }
6343 }
6344 
6345 void add_shield_point_multi(int objnum, int tri_num, vec3d *hit_pos);
6346 
6348 {
6349  int offset;
6350  ushort signature;
6351  ubyte utri_num;
6352  object *objp;
6353 
6354  // get the shield hit data
6355  offset = HEADER_LENGTH;
6356  GET_USHORT(signature);
6357  GET_DATA(utri_num);
6358  //GET_DATA(hit_pos);
6359  PACKET_SET_SIZE();
6360 
6361  // find the object with this signature. If found, then do a shield explosion
6362  objp = multi_get_network_object( signature );
6363  if ( objp ) {
6364  polymodel *pm;
6365  shield_info *shieldp;
6366  shield_tri stri;
6367  vec3d hit_pos;
6368  int i;
6369 
6370  // given the tri num, find the local position which is the average of the
6371  // three vertices of the triangle affected. Use this average point as the hit
6372  // point
6373  // Assert( objp->type == OBJ_SHIP );
6374  if(objp->type != OBJ_SHIP){
6375  return;
6376  }
6377 
6378  pm = model_get(Ship_info[Ships[objp->instance].ship_info_index].model_num);
6379  shieldp = &pm->shield;
6380  Assert( utri_num < shieldp->ntris );
6381  stri = shieldp->tris[utri_num];
6382  vm_vec_zero(&hit_pos);
6383  for ( i = 0; i < 3; i++ ) {
6384  vm_vec_add2( &hit_pos, &(shieldp->verts[stri.verts[i]].pos) );
6385  }
6386  vm_vec_scale( &hit_pos, 1.0f/3.0f );
6387  add_shield_point_multi( OBJ_INDEX(objp), utri_num, &hit_pos );
6388  }
6389 }
6390 
6391 void send_player_stats_block_packet(net_player *pl, int stats_code, net_player *target, short offset)
6392 {
6393  scoring_struct *sc;
6395  int idx;
6396  int packet_size = 0;
6397 
6398  ushort u_tmp;
6399  int i_tmp;
6400 
6401  sc = &pl->m_player->stats;
6402 
6403  // build the header
6405 
6406  // add the player id
6407  ADD_SHORT(pl->player_id);
6408 
6409  // add the byte indicating whether these stats are all-time or not
6410  val = (ubyte)stats_code;
6411  ADD_DATA(val);
6412 
6413  // kill information - alltime
6414  switch(stats_code){
6415  case STATS_ALLTIME:
6416  // alltime kills
6417 
6418  idx = 0;
6419  while(idx<MAX_SHIP_CLASSES)
6420  {
6421  send_player_stats_block_packet(pl, STATS_ALLTIME_KILLS, target, (short)idx);
6422  idx += MAX_SHIPS_PER_PACKET;
6423  }
6424 
6425  Assert( (Num_medals >= 0) && (Num_medals < USHRT_MAX) );
6427 
6428  // medal information
6429  for(idx=0;idx<Num_medals;idx++){
6430  i_tmp = sc->medal_counts[idx];
6431  ADD_INT(i_tmp);
6432  }
6433 
6434  ADD_INT(sc->score);
6435  ADD_INT(sc->rank);
6436  ADD_INT(sc->assists);
6437  ADD_INT(sc->kill_count);
6438  ADD_INT(sc->kill_count_ok);
6439  ADD_UINT(sc->p_shots_fired);
6440  ADD_UINT(sc->s_shots_fired);
6441  ADD_UINT(sc->p_shots_hit);
6442  ADD_UINT(sc->s_shots_hit);
6445  ADD_INT(sc->bonehead_kills);
6446 
6447  ADD_UINT(sc->missions_flown);
6448  ADD_UINT(sc->flight_time);
6449  ADD_INT(sc->last_flown); // should be 32-bit value - taylor
6450  ADD_INT(sc->last_backup); // should be 32-bit value - taylor
6451  break;
6452 
6453  case STATS_MISSION:
6454  // mission OKkills
6455 
6456  idx = 0;
6457  while(idx<MAX_SHIP_CLASSES)
6458  {
6460  idx += MAX_SHIPS_PER_PACKET;
6461  }
6462 
6463  ADD_INT(sc->m_score);
6464  ADD_INT(sc->m_assists);
6465  ADD_INT(sc->m_kill_count);
6466  ADD_INT(sc->m_kill_count_ok);
6467  ADD_UINT(sc->mp_shots_fired);
6468  ADD_UINT(sc->ms_shots_fired);
6469  ADD_UINT(sc->mp_shots_hit);
6470  ADD_UINT(sc->ms_shots_hit);
6474  ADD_INT(sc->m_player_deaths);
6475  ADD_INT(sc->m_medal_earned);
6476  break;
6477 
6478  case STATS_MISSION_KILLS:
6479  ADD_INT(sc->m_kill_count);
6480  ADD_INT(sc->m_kill_count_ok);
6481  ADD_INT(sc->m_assists);
6482  break;
6483 
6484  case STATS_DOGFIGHT_KILLS:
6485  for(idx=0; idx<MAX_PLAYERS; idx++){
6486  u_tmp = (ushort)sc->m_dogfight_kills[idx];
6487  ADD_USHORT(u_tmp);
6488  }
6489  ADD_INT(sc->m_kill_count);
6490  ADD_INT(sc->m_kill_count_ok);
6491  ADD_INT(sc->m_assists);
6492  break;
6493 
6495  ADD_SHORT(offset);
6496  for (idx=offset; idx<MAX_SHIP_CLASSES && idx<offset+MAX_SHIPS_PER_PACKET; idx++)
6497  {
6498  ADD_INT(sc->m_okKills[idx]);
6499  }
6500  break;
6501 
6502  case STATS_ALLTIME_KILLS:
6503  ADD_SHORT(offset);
6504  for (idx=offset; idx<MAX_SHIP_CLASSES && idx<offset+MAX_SHIPS_PER_PACKET; idx++)
6505  {
6506  ADD_INT(sc->kills[idx]);
6507  }
6508  break;
6509  }
6510 
6511  Assert(packet_size < MAX_PACKET_SIZE);
6512 
6513  // if we're a client, always send the data to the server
6515  multi_io_send_reliable(Net_player, data, packet_size);
6516  }
6517  // otherwise do server specific stuff
6518  else {
6519  // send to a specific target
6520  if(target != NULL){
6521  multi_io_send_reliable(target, data, packet_size);
6522  }
6523  // otherwise, send to everyone
6524  else {
6525  multi_io_send_to_all_reliable(data, packet_size);
6526  }
6527  }
6528 }
6529 
6531 {
6532  ubyte val;
6533  int player_num,idx;
6534  scoring_struct *sc,bogus;
6535  short player_id;
6536  int offset = HEADER_LENGTH;
6537  ushort u_tmp, num_medals;
6538  int i_tmp;
6539 
6540  // nprintf(("Network","----------++++++++++********RECEIVED STATS***********+++++++++----------\n"));
6541 
6542  // get the player who these stats are for
6543  GET_SHORT(player_id);
6544  player_num = find_player_id(player_id);
6545  if (player_num == -1) {
6546  nprintf(("Network", "Couldn't find player for stats update!\n"));
6547  ml_string("Couldn't find player for stats update!\n");
6548 
6549  sc = &bogus;
6550  Int3();
6551  } else {
6552  sc = &Net_players[player_num].m_player->stats;
6553  }
6554 
6555  // get the stats code
6556  GET_DATA(val);
6557  switch(val){
6558  short si_offset;
6559 
6560  case STATS_ALLTIME_KILLS:
6561  GET_SHORT(si_offset);
6562  for (idx = si_offset; idx<MAX_SHIP_CLASSES && idx<si_offset+MAX_SHIPS_PER_PACKET; idx++)
6563  {
6564  GET_INT(i_tmp);
6565  sc->kills[idx] = i_tmp;
6566  }
6567  break;
6568 
6570  GET_SHORT(si_offset);
6571  for (idx = si_offset; idx<MAX_SHIP_CLASSES && idx<si_offset+MAX_SHIPS_PER_PACKET; idx++)
6572  {
6573  GET_INT(i_tmp);
6574  sc->m_okKills[idx] = i_tmp;
6575  }
6576  break;
6577 
6578  case STATS_ALLTIME:
6579  ml_string("Received STATS_ALLTIME\n");
6580 
6581  // read in the stats
6582  GET_USHORT( num_medals );
6583 
6584  for (idx=0; (idx < Num_medals) && (idx < num_medals); idx++) {
6585  GET_INT(i_tmp);
6586  sc->medal_counts[idx] = i_tmp;
6587  }
6588 
6589  GET_INT(sc->score);
6590  GET_INT(sc->rank);
6591  GET_INT(sc->assists);
6592  GET_INT(sc->kill_count);
6593  GET_INT(sc->kill_count_ok);
6594  GET_UINT(sc->p_shots_fired);
6595  GET_UINT(sc->s_shots_fired);
6596  GET_UINT(sc->p_shots_hit);
6597  GET_UINT(sc->s_shots_hit);
6600  GET_INT(sc->bonehead_kills);
6601 
6602  GET_UINT(sc->missions_flown);
6603  GET_UINT(sc->flight_time);
6604  GET_INT(sc->last_flown); // should be 32-bit value - taylor
6605  GET_INT(sc->last_backup); // should be 32-bit value - taylor
6606  break;
6607 
6608  case STATS_MISSION:
6609  ml_string("Received STATS_MISSION\n");
6610 
6611  GET_INT(sc->m_score);
6612  GET_INT(sc->m_assists);
6613  GET_INT(sc->m_kill_count);
6614  GET_INT(sc->m_kill_count_ok);
6615  GET_UINT(sc->mp_shots_fired);
6616  GET_UINT(sc->ms_shots_fired);
6617  GET_UINT(sc->mp_shots_hit);
6618  GET_UINT(sc->ms_shots_hit);
6622  GET_INT(sc->m_player_deaths);
6623  GET_INT(sc->m_medal_earned);
6624  break;
6625 
6626  case STATS_MISSION_KILLS:
6627  ml_string("Received STATS_MISSION_KILLS\n");
6628 
6629  GET_INT(sc->m_kill_count);
6630  GET_INT(sc->m_kill_count_ok);
6631  GET_INT(sc->m_assists);
6632  break;
6633 
6634  case STATS_DOGFIGHT_KILLS:
6635  ml_string("Received STATS_DOGFIGHT_KILLS\n");
6636  if(player_num >= 0){
6637  ml_printf("Dogfight stats for %s", Net_players[player_num].m_player->callsign);
6638  }
6639  for(idx=0; idx<MAX_PLAYERS; idx++){
6640  GET_USHORT(u_tmp);
6641  sc->m_dogfight_kills[idx] = u_tmp;
6642  if(player_num >= 0){
6643  ml_printf("%d", Net_players[player_num].m_player->stats.m_dogfight_kills[idx]);
6644  }
6645  }
6646  GET_INT(sc->m_kill_count);
6647  GET_INT(sc->m_kill_count_ok);
6648  GET_INT(sc->m_assists);
6649  break;
6650  }
6651  PACKET_SET_SIZE();
6652 
6653  // if I'm the server of the game, I should always rebroadcast these stats
6654  if ((Net_player->flags & NETINFO_FLAG_AM_MASTER) && (sc != &bogus)) {
6655  // make sure these are alltime stats
6656  Assert(val == STATS_ALLTIME || val == STATS_ALLTIME_KILLS);
6657 
6658  multi_broadcast_stats(val);
6659  }
6660 }
6661 
6662 // called to create asteroid stuff
6663 void send_asteroid_create( object *new_objp, object *parent_objp, int asteroid_type, vec3d *relvec )
6664 {
6665  int packet_size;
6667  ubyte packet_type, atype;
6668  vec3d vec;
6669 
6670  vm_vec_zero(&vec);
6671  if (relvec != NULL )
6672  vec = *relvec;
6673 
6675  packet_type = ASTEROID_CREATE;
6676 
6677  Assert( asteroid_type < UCHAR_MAX );
6678  atype = (ubyte)asteroid_type;
6679 
6680  ADD_DATA( packet_type );
6681  ADD_USHORT( parent_objp->net_signature );
6682  ADD_USHORT( new_objp->net_signature );
6683  ADD_DATA( atype );
6684  ADD_VECTOR( vec );
6685 
6686  multi_io_send_to_all(data, packet_size);
6687 }
6688 
6689 void send_asteroid_throw( object *objp )
6690 {
6691  int packet_size;
6692  ubyte data[MAX_PACKET_SIZE], packet_type;
6693 
6695 
6696  // this packet type is an asteroid throw
6697  packet_type = ASTEROID_THROW;
6698  ADD_DATA( packet_type );
6699  ADD_USHORT( objp->net_signature );
6700  ADD_VECTOR( objp->pos );
6701  ADD_VECTOR( objp->phys_info.vel );
6702 
6703  multi_io_send_to_all(data, packet_size);
6704 }
6705 
6706 void send_asteroid_hit( object *objp, object *other_objp, vec3d *hitpos, float damage )
6707 {
6708  int packet_size;
6709  ubyte data[MAX_PACKET_SIZE], packet_type;
6710  vec3d vec;
6711 
6712  vm_vec_zero(&vec);
6713  if ( hitpos != NULL )
6714  vec = *hitpos;
6715 
6716  // build up an asteroid hit packet
6718  packet_type = ASTEROID_HIT;
6719  ADD_DATA( packet_type );
6720  ADD_USHORT( objp->net_signature );
6721 
6722  if(other_objp == NULL){
6723  ushort invalid_sig = 0xffff;
6724  ADD_USHORT(invalid_sig);
6725  } else {
6726  ADD_USHORT( other_objp->net_signature );
6727  }
6728  ADD_VECTOR( vec );
6729  ADD_FLOAT( damage );
6730 
6731  multi_io_send_to_all(data, packet_size);
6732 }
6733 
6735 {
6736  int offset;
6737  ubyte packet_type;
6738 
6739  offset = HEADER_LENGTH;
6740  GET_DATA( packet_type );
6741 
6742  // based on the packet type, do something interesting with an asteroid!
6743  switch( packet_type ) {
6744 
6745  case ASTEROID_CREATE: {
6746  ushort psignature, signature;
6747  ubyte atype;
6748  vec3d relvec;
6749  object *parent_objp;
6750 
6751  GET_USHORT( psignature );
6752  GET_USHORT( signature );
6753  GET_DATA( atype );
6754  GET_VECTOR( relvec );
6755 
6756  // after getting the values, set the next network signature, and call the create sub function
6758  parent_objp = multi_get_network_object( psignature );
6759  if ( parent_objp ) {
6760  asteroid_sub_create( parent_objp, atype, &relvec );
6761  } else {
6762  nprintf(("Network", "Couldn't create asteroid because parent wasn't found!!!\n"));
6763  }
6764 
6765 
6766  break;
6767  }
6768 
6769  // asteroid throw packet -- asteroid has wrapped bounds
6770  case ASTEROID_THROW: {
6771  ushort signature;
6772  vec3d pos, vel;
6773  object *objp;
6774 
6775  GET_USHORT( signature );
6776  GET_VECTOR( pos );
6777  GET_VECTOR( vel );
6778  objp = multi_get_network_object( signature );
6779  if ( !objp ) {
6780  nprintf(("Network", "Couldn't throw asteroid because couldn't find it\n"));
6781  break;
6782  }
6783  objp->pos = pos;
6784  objp->phys_info.vel = vel;
6785  objp->phys_info.desired_vel = vel;
6786  break;
6787  }
6788 
6789  case ASTEROID_HIT: {
6790  ushort signature, osignature;
6791  object *objp, *other_objp;
6792  vec3d hitpos;
6793  float damage;
6794 
6795  GET_USHORT( signature );
6796  GET_USHORT( osignature );
6797  GET_VECTOR( hitpos );
6798  GET_FLOAT( damage );
6799 
6800  objp = multi_get_network_object( signature );
6801  if(osignature == 0xffff){
6802  other_objp = NULL;
6803  } else {
6804  other_objp = multi_get_network_object( osignature );
6805  }
6806  if ( !objp ) {
6807  nprintf(("Network", "Cannot hit asteroid because signature isn't found\n"));
6808  break;
6809  }
6810 
6811  if ( IS_VEC_NULL(&hitpos) ){
6812  asteroid_hit( objp, other_objp, NULL, damage );
6813  } else {
6814  asteroid_hit( objp, other_objp, &hitpos, damage );
6815  }
6816 
6817  // if we know the other object is a weapon, then do a weapon hit to kill the weapon
6818  if ( other_objp && (other_objp->type == OBJ_WEAPON) ){
6819  weapon_hit( other_objp, objp, &hitpos );
6820  }
6821  break;
6822  }
6823 
6824  default:
6825  Int3();
6826  break;
6827  }
6828 
6829  PACKET_SET_SIZE();
6830 }
6831 
6832 void send_host_restr_packet(char *callsign,int code,int mode)
6833 {
6835  int packet_size = 0;
6836 
6837  // build the header and add the opcode
6839  val = (ubyte)code;
6840  ADD_DATA(val);
6841  val = (ubyte)mode;
6842  ADD_DATA(val);
6843 
6844  // add the callsign
6845  ADD_STRING(callsign);
6846 
6847  // if I'm the standalone server, I should be sending this to the game host
6848  if((Game_mode & GM_STANDALONE_SERVER) && (Netgame.host != NULL)){
6849  multi_io_send_reliable(Netgame.host, data, packet_size);
6850  }
6851  // otherwise if I'm the host, I should be sending a reply back to the standalone server
6852  else {
6854  multi_io_send_reliable(Net_player, data, packet_size);
6855  }
6856 }
6857 
6859 {
6860  char callsign[255];
6861  ubyte code,mode;
6862  int offset = HEADER_LENGTH;
6863 
6864  // get the opcode and the callsign
6865  GET_DATA(code);
6866  GET_DATA(mode);
6867  GET_STRING(callsign);
6868  PACKET_SET_SIZE();
6869 
6870  // do code specific operations
6871  switch(code)
6872  {
6873  // query to the host from standalone
6874  case 0:
6876 
6877  // set the join mode
6879 
6880  // set the timestamp
6882 
6883  // notify the host of the event
6885  HUD_printf(XSTR("Player %s has tried to join - allow (y/n) ?",736),callsign);
6886  break;
6887 
6888  // affirmative reply from the host to the standalone
6889  case 1:
6891 
6892  // let the player join if the timestamp has not already elapsed on the server
6893  if(Multi_restr_query_timestamp != -1){
6895  }
6896  break;
6897 
6898  // negative reply
6899  case 2 :
6900  Assert(Game_mode & GM_STANDALONE_SERVER);
6903  break;
6904  }
6905 }
6906 
6907 void send_netgame_end_error_packet(int notify_code,int err_code)
6908 {
6909  ubyte data[10];
6910  char code;
6911  int packet_size = 0;
6912 
6913  // only the server should ever be here - although this might change if for some reason the host wants to end the game
6915 
6916  // build the header and add the notification and error codes
6918  code = (char)notify_code;
6919  ADD_DATA(code);
6920  code = (char)err_code;
6921  ADD_DATA(code);
6922 
6923  // send the packet
6924  multi_io_send_to_all_reliable(data, packet_size);
6925 }
6926 
6928 {
6929  int offset = HEADER_LENGTH;
6930  char notify_code,error_code;
6931 
6932  // get the error and notification codes
6933  GET_DATA(notify_code);
6934  GET_DATA(error_code);
6935  PACKET_SET_SIZE();
6936 
6937  // quit the game
6938  multi_quit_game(PROMPT_NONE,notify_code,error_code);
6939 }
6940 
6941 // sends info that a countermeasure succeeded.
6943 {
6944  int pnum, packet_size;
6946 
6947  pnum = multi_find_player_by_object( &Objects[objnum] );
6948  if ( pnum == -1 ) {
6949  nprintf(("Network", "Coulnd't find player for countermeasure success packet\n"));
6950  return;
6951  }
6952 
6954  multi_io_send(&Net_players[pnum], data, packet_size);
6955 }
6956 
6957 // start the flashing of my hud gauge
6959 {
6960  int offset;
6961 
6962  offset = HEADER_LENGTH;
6963  PACKET_SET_SIZE();
6964 
6965  //Do this instead so there's less repeat code
6966  //Player_obj is necessary...infinitely recursive function calls != FTW
6968  /*hud_start_text_flash(XSTR("Evaded", 1430), 800);
6969  snd_play(&Snds[SND_MISSILE_EVADED_POPUP]);*/
6970 }
6971 
6972 #define UPDATE_IS_PAUSED (1<<0)
6973 #define UPDATE_HULL_INFO (1<<1)
6974 
6976 {
6978  int packet_size = 0;
6979 
6980  // build the header
6982 
6983  val = 0;
6984 
6985  // add the pause status
6986  if ( Multi_pause_status ) {
6987  val |= UPDATE_IS_PAUSED;
6988  } else if ( (Game_mode & GM_IN_MISSION) && !(pl->flags & NETINFO_FLAG_INGAME_JOIN) && !(NETPLAYER_IS_OBSERVER(pl)) && !(NETPLAYER_IS_DEAD(pl)) && (Objects[pl->m_player->objnum].type == OBJ_SHIP) ) {
6989  val |= UPDATE_HULL_INFO;
6990  Assert( Player_ship ); // I"d better have one of these!!!!
6991  }
6992 
6993  ADD_DATA(val);
6994 
6995  // if paused, add the net address of the guy who paused
6996  if(val & UPDATE_IS_PAUSED){
6997  Assert(Multi_pause_pauser != NULL);
6999  }
7000 
7001  // when not paused, send hull/shield/subsystem updates to all clients (except for ingame joiners)
7002  if ( val & UPDATE_HULL_INFO ) {
7003  object *objp;
7004  ubyte percent, ns, threats, n_quadrants;
7005  ship_info *sip;
7006  ship *shipp;
7007  ship_subsys *subsysp;
7008  int i;
7009 
7010  // get the object for the player
7011  Assert( pl->m_player->objnum != -1 );
7012 
7013  objp = &Objects[pl->m_player->objnum];
7014 
7015  Assert ( objp->type == OBJ_SHIP );
7016  shipp = &Ships[objp->instance];
7017  sip = &Ship_info[shipp->ship_info_index];
7018 
7019  // hull strength and shield mesh information are floats (as a percentage). Pass the integer
7020  // percentage value since that should be close enough
7021  percent = (ubyte) ((get_hull_pct(objp) * 100.0f) + 0.5f);
7022  if ( (percent == 0) && (get_hull_pct(objp) > 0.0f) ) {
7023  percent = 1;
7024  }
7025  ADD_DATA( percent );
7026 
7027  n_quadrants = (ubyte)objp->n_quadrants;
7028  ADD_DATA( n_quadrants );
7029  for (i = 0; i < n_quadrants; i++ ) {
7030  percent = (ubyte)(objp->shield_quadrant[i] / get_max_shield_quad(objp) * 100.0f);
7031 
7032  ADD_DATA( percent );
7033  }
7034 
7035  // add the data for the subsystem hits. We can assume that the lists will be the same side of
7036  // both machines. Added as percent since that number <= 100
7037 
7038  // also write out the number of subsystems. We do this because the client might not know
7039  // about the object he is getting data for. (i.e. he killed the object already).
7040  ns = (ubyte)sip->n_subsystems;
7041  ADD_DATA( ns );
7042 
7043  // now the subsystems.
7044  for ( subsysp = GET_FIRST(&shipp->subsys_list); subsysp != END_OF_LIST(&shipp->subsys_list); subsysp = GET_NEXT(subsysp) ) {
7045  percent = (ubyte)(subsysp->current_hits / subsysp->max_hits * 100.0f);
7046  ADD_DATA( percent );
7047  }
7048 
7049  // compute the threats for this player. Only compute the threats if this player is actually
7050  // playing (i.e. he has a ship)
7052  threats = (ubyte)pl->m_player->threat_flags;
7053  ADD_DATA( threats );
7054 
7055  // add his energy level for guns
7056  ADD_FLOAT(shipp->weapon_energy);
7057 
7058  // add his secondary bank ammo
7060  for(i=0; i<shipp->weapons.num_secondary_banks; i++){
7061  ADD_INT(shipp->weapons.secondary_bank_ammo[i]);
7062  }
7063  }
7064 
7065  // add pl
7066  ADD_INT(pl->sv_last_pl);
7067 
7068  // send the packet reliably to the player
7069  multi_io_send(pl, data, packet_size);
7070 }
7071 
7073 {
7074  ubyte val;
7075  short pauser;
7076  int player_index;
7077  int is_paused, have_hull_info;
7078  int ammo_count;
7079  int ammo[10];
7080  float weapon_energy;
7081  int offset = HEADER_LENGTH;
7082 
7083  // get the header byte containing useful information
7084  GET_DATA(val);
7085 
7086  is_paused = (val & UPDATE_IS_PAUSED)?1:0;
7087  have_hull_info = (val & UPDATE_HULL_INFO)?1:0;
7088 
7089  // if we are paused, get who paused
7090  if(is_paused){
7091  GET_SHORT(pauser);
7092  player_index = find_player_id(pauser);
7093  if(player_index != -1){
7094  Multi_pause_pauser = &Net_players[player_index];
7095  } else {
7096  Multi_pause_pauser = NULL;
7097  }
7098  }
7099 
7100  // if we have hull information, then read it in.
7101  if ( have_hull_info ) {
7102  float fl_val;
7103  ship_info *sip;
7104  ship *shipp;
7105  ubyte hull_percent, n_quadrants, n_subsystems, subsystem_percent[MAX_MODEL_SUBSYSTEMS], threats;
7106  SCP_vector<ubyte> shield_percent;
7107  ubyte ub_tmp;
7108  ship_subsys *subsysp;
7109  object *objp;
7110  int i;
7111 
7112  // hull strength and shield mesh information are floats (as a percentage). Pass the integer
7113  // percentage value since that should be close enough
7114  GET_DATA( hull_percent );
7115 
7116  GET_DATA( n_quadrants );
7117  shield_percent.resize(n_quadrants);
7118  for (i = 0; i < n_quadrants; i++ ){
7119  GET_DATA(ub_tmp);
7120  shield_percent[i] = ub_tmp;
7121  }
7122 
7123  // get the data for the subsystems
7124  GET_DATA( n_subsystems );
7125  for ( i = 0; i < n_subsystems; i++ ){
7126  GET_DATA(ub_tmp);
7127  subsystem_percent[i] = ub_tmp;
7128  }
7129 
7130  GET_DATA( threats );
7131 
7132  // add his energy level for guns
7133  GET_FLOAT(weapon_energy);
7134 
7135  // add his secondary bank ammo
7136  GET_INT(ammo_count);
7137  for(i=0; i<ammo_count; i++){
7138  GET_INT(ammo[i]);
7139  }
7140 
7141  // assign the above information to my ship, assuming that I can find it! Ingame joiners might get this
7142  // packet because of delay between reliable packet acknowledging my ingame ship and the start of these
7143  // UDP client update packets. Only read this info if I have a ship.
7144  if ( !(Net_player->flags & NETINFO_FLAG_INGAME_JOIN) && (Player_ship != NULL) && (Player_obj != NULL) && (Net_player != NULL)) {
7145  shipp = Player_ship;
7146  objp = Player_obj;
7147  sip = &Ship_info[shipp->ship_info_index];
7148 
7149  fl_val = hull_percent * shipp->ship_max_hull_strength / 100.0f;
7150  objp->hull_strength = fl_val;
7151 
7152  for ( i = 0; i < n_quadrants; i++ ) {
7153  if (i < objp->n_quadrants) {
7154  fl_val = (shield_percent[i] * get_max_shield_quad(objp) / 100.0f);
7155  objp->shield_quadrant[i] = fl_val;
7156  }
7157  }
7158 
7159  // for sanity, be sure that the number of susbystems that I read in matches the player. If not,
7160  // then don't read these in.
7161  if ( n_subsystems == sip->n_subsystems ) {
7162 
7163  n_subsystems = 0; // reuse this variable
7164  for ( subsysp = GET_FIRST(&shipp->subsys_list); subsysp != END_OF_LIST(&shipp->subsys_list); subsysp = GET_NEXT(subsysp) ) {
7165  int subsys_type;
7166 
7167  fl_val = subsystem_percent[n_subsystems] * subsysp->max_hits / 100.0f;
7168  subsysp->current_hits = fl_val;
7169 
7170  // add the value just generated (it was zero'ed above) into the array of generic system types
7171  subsys_type = subsysp->system_info->type; // this is the generic type of subsystem
7172  Assert ( subsys_type < SUBSYSTEM_MAX );
7173  if (!(subsysp->flags & SSF_NO_AGGREGATE)) {
7174  shipp->subsys_info[subsys_type].aggregate_current_hits += fl_val;
7175  }
7176  n_subsystems++;
7177  }
7178  }
7179  ship_recalc_subsys_strength( shipp );
7180 
7181  shipp->weapon_energy = weapon_energy;
7182  for(i=0; i<ammo_count; i++){
7183  shipp->weapons.secondary_bank_ammo[i] = ammo[i];
7184  }
7185 
7186  // update my threat flags.
7187  // temporarily commented out until tested.
7188  Net_player->m_player->threat_flags = threats;
7189  }
7190  }
7191 
7192  // get pl
7193  int pl;
7194  GET_INT(pl);
7195  if(Net_player != NULL){
7196  Net_player->cl_last_pl = pl;
7197  }
7198 
7199  PACKET_SET_SIZE();
7200  // note, if we're already paused or unpaused, calling these will have no effect, so it is safe to do so
7202  if( is_paused ) {
7204  } else {
7206  }
7207  }
7208 }
7209 
7211 {
7212  ubyte data[20];
7213  char val;
7214  int packet_size = 0;
7215 
7216  // build the header and add the time
7218  val = (char)time;
7219  ADD_DATA(val);
7220 
7221  // if we're the server, we should broadcast to everyone
7223  multi_io_send_to_all_reliable(data, packet_size);
7224  }
7225  // otherwise we'de better be a host sending to the standalone
7226  else {
7228  multi_io_send_reliable(Net_player, data, packet_size);
7229  }
7230 }
7231 
7233 {
7234  int offset = HEADER_LENGTH;
7235  char time;
7236 
7237  // get the time
7238  GET_DATA(time);
7239  PACKET_SET_SIZE();
7240 
7241  // if we're not in the post sync data screen, ignore it
7243  return;
7244  }
7245 
7246  // if we're the standalone, this should be a -1 telling us to start the countdown
7248  Assert((int)time == -1);
7249 
7250  // start the countdown
7252  }
7253  // otherwise if we're clients, just bash the countdown
7254  else {
7255  Multi_sync_countdown = (int)time;
7256  }
7257 }
7258 
7259 // packets for debriefing information
7260 void send_debrief_info( int stage_count[], int *stages[] )
7261 {
7263  int packet_size, i, j;
7264  int i_tmp;
7265 
7267 
7268  // add the data for the teams
7269  for ( i = 0; i < Num_teams; i++ ) {
7270  int count;
7271 
7272  count = stage_count[i];
7273  ADD_INT( count );
7274  for ( j = 0; j < count; j++ ) {
7275  i_tmp = stages[i][j];
7276  ADD_INT( i_tmp );
7277  }
7278  }
7279 
7280  multi_io_send_to_all_reliable(data, packet_size);
7281 }
7282 
7283 // process a debrief info packet from the server
7285 {
7286  int offset, i, j;
7287  int stage_counts[MAX_TVT_TEAMS], active_stages[MAX_TVT_TEAMS][MAX_DEBRIEF_STAGES], *stages[MAX_TVT_TEAMS];
7288  int i_tmp;
7289 
7290  offset = HEADER_LENGTH;
7291  for ( i = 0; i < Num_teams; i++ ) {
7292  int count;
7293 
7294  GET_INT( count );
7295  stage_counts[i] = count;
7296  stages[i] = active_stages[i];
7297  for ( j = 0; j < count; j++ ) {
7298  GET_INT(i_tmp);
7299  active_stages[i][j] = i_tmp;
7300  }
7301  }
7302  PACKET_SET_SIZE();
7303 
7304  // now that we have the stage data for the debriefing stages, call debrief function with the
7305  // data so that clients can now see the debriefing stuff. Do it only for my team.
7306  Assert( (Net_player->p_info.team >= 0) && (Net_player->p_info.team < Num_teams) );
7308 }
7309 
7310 // sends homing information to all clients. We only need signature and num_missiles (because of hornets).
7311 // sends homing_object and homing_subsystem to all clients.
7312 void send_homing_weapon_info( int weapon_num )
7313 {
7315  char t_subsys;
7316  int packet_size;
7317  object *homing_object;
7318  ushort homing_signature;
7319  weapon *wp;
7320 
7321  wp = &Weapons[weapon_num];
7322 
7323  // be sure that this weapon object is a homing object.
7325  return;
7326 
7327  // default the subsystem
7328  t_subsys = -1;
7329 
7330  // get the homing signature. If this weapon isn't homing on anything, then sent 0 as the
7331  // homing signature.
7332  homing_signature = 0;
7333  homing_object = wp->homing_object;
7334  if ( homing_object != &obj_used_list ) {
7335  homing_signature = homing_object->net_signature;
7336 
7337  // get the subsystem index.
7338  if ( (homing_object->type == OBJ_SHIP) && (wp->homing_subsys != NULL) ) {
7339  int s_index;
7340 
7341  s_index = ship_get_index_from_subsys( wp->homing_subsys, OBJ_INDEX(homing_object), 1 );
7342  Assert( s_index < CHAR_MAX ); // better be less than this!!!!
7343  t_subsys = (char)s_index;
7344  }
7345  }
7346 
7349  ADD_USHORT( homing_signature );
7350  ADD_DATA( t_subsys );
7351 
7352  multi_io_send_to_all(data, packet_size);
7353 }
7354 
7355 // process a homing weapon info change packet. multiple_missiles parameter specifies is this
7356 // packet contains information for multiple weapons (like hornets).
7358 {
7359  int offset;
7360  ushort weapon_signature, homing_signature;
7361  char h_subsys;
7362  object *homing_object, *weapon_objp;
7363  weapon *wp;
7364 
7365  offset = HEADER_LENGTH;
7366 
7367  // get the data for the packet
7368  GET_USHORT( weapon_signature );
7369  GET_USHORT( homing_signature );
7370  GET_DATA( h_subsys );
7371  PACKET_SET_SIZE();
7372 
7373  // deal with changing this weapons homing information
7374  weapon_objp = multi_get_network_object( weapon_signature );
7375  if ( weapon_objp == NULL ) {
7376  nprintf(("Network", "Couldn't find weapon object for homing update -- skipping update\n"));
7377  return;
7378  }
7379  Assert( weapon_objp->type == OBJ_WEAPON );
7380  wp = &Weapons[weapon_objp->instance];
7381 
7382  // be sure that we can find these weapons and
7383  homing_object = multi_get_network_object( homing_signature );
7384  if ( homing_object == NULL ) {
7385  nprintf(("Network", "Couldn't find homing object for homing update\n"));
7386  return;
7387  }
7388 
7389  if ( homing_object->type == OBJ_WEAPON ) {
7391 
7392  // Assert( (flags & WIF_BOMB) || (flags & WIF_CMEASURE) );
7393 
7394  if ( !((flags & WIF_BOMB) || (flags & WIF_CMEASURE)) ) {
7395  nprintf(("Network", "Homing object is invalid for homing update\n"));
7396  return;
7397  }
7398  }
7399 
7400  wp->homing_object = homing_object;
7401  wp->homing_subsys = NULL;
7402  wp->target_num = OBJ_INDEX(homing_object);
7403  wp->target_sig = homing_object->signature;
7404  if ( h_subsys != -1 ) {
7405  Assert( homing_object->type == OBJ_SHIP );
7406  wp->homing_subsys = ship_get_indexed_subsys( &Ships[homing_object->instance], h_subsys);
7407  }
7408 
7409  if ( homing_object->type == OBJ_SHIP ) {
7410  nprintf(("Network", "Updating homing information for weapon -- homing on %s\n", Ships[homing_object->instance].ship_name));
7411  }
7412 }
7413 
7414 void send_emp_effect(ushort net_sig, float intensity, float time)
7415 {
7416  ubyte data[25];
7417  int packet_size;
7418 
7420 
7421  // build the packet and add the opcode
7423  ADD_USHORT(net_sig);
7424  ADD_FLOAT(intensity);
7425  ADD_FLOAT(time);
7426 
7427  // send it to the player
7428  multi_io_send_to_all(data, packet_size);
7429 }
7430 
7432 {
7433  float intensity, time;
7434  ushort net_sig;
7435  object *objp;
7436  int offset = HEADER_LENGTH;
7437 
7438  // read in the EMP effect data
7439  GET_USHORT(net_sig);
7440  GET_FLOAT(intensity);
7441  GET_FLOAT(time);
7442  PACKET_SET_SIZE();
7443 
7444  // try and find the object
7445  objp = multi_get_network_object(net_sig);
7446  if((objp != NULL) && (objp->type == OBJ_SHIP)){
7447  // if i'm not an observer and I have a valid ship, play the EMP effect
7448  if(!(Net_player->flags & NETINFO_FLAG_OBSERVER) && (Player_obj != NULL) && (Player_obj->type == OBJ_SHIP) && (Player_obj == objp)){
7449  emp_start_local(intensity, time);
7450  }
7451 
7452  // start the effect for the ship itself
7453  emp_start_ship(objp, intensity, time);
7454  }
7455 }
7456 
7457 // tells whether or not reinforcements are available
7459 {
7460  ubyte data[25];
7461  int packet_size;
7462 
7464  ADD_INT( rnum );
7465  multi_io_send_to_all_reliable(data, packet_size);
7466 }
7467 
7469 {
7470  int offset;
7471  int rnum;
7472 
7473  offset = HEADER_LENGTH;
7474  GET_INT( rnum );
7475  PACKET_SET_SIZE();
7476 
7477  // sanity check for a valid reinforcement number
7478  if ( (rnum >= 0) && (rnum < Num_reinforcements) ) {
7480  }
7481 }
7482 
7483 void send_change_iff_packet(ushort net_signature, int new_team)
7484 {
7486  int packet_size = 0;
7487 
7488  if(Net_player == NULL){
7489  return;
7490  }
7492  return;
7493  }
7494 
7495  // build the packet and add the data
7497  ADD_USHORT(net_signature);
7498  ADD_INT(new_team);
7499 
7500  // send to all players
7501  multi_io_send_to_all_reliable(data, packet_size);
7502 }
7503 
7505 {
7506  int offset = HEADER_LENGTH;
7507  ushort net_signature;
7508  int new_team;
7509  object *objp;
7510 
7511  // get the data
7512  GET_USHORT(net_signature);
7513  GET_INT(new_team);
7514  PACKET_SET_SIZE();
7515 
7516  // lookup the object
7517  objp = multi_get_network_object(net_signature);
7518  if((objp != NULL) && (objp->type == OBJ_SHIP) && (objp->instance >=0)){
7519  Ships[objp->instance].team = new_team;
7520  }
7521 }
7522 
7523 void send_change_iff_color_packet(ushort net_signature, int observer_team, int observed_team, int alternate_iff_color)
7524 {
7526  int packet_size = 0;
7527 
7528  if(Net_player == NULL){
7529  return;
7530  }
7532  return;
7533  }
7534 
7535  // build the packet and add the data
7537  ADD_USHORT(net_signature);
7538  ADD_INT(observer_team);
7539  ADD_INT(observed_team);
7540  ADD_INT(alternate_iff_color);
7541 
7542  // send to all players
7543  multi_io_send_to_all_reliable(data, packet_size);
7544 }
7545 
7547 {
7548  int offset = HEADER_LENGTH;
7549  ushort net_signature;
7550  int observer_team, observed_team, alternate_iff_color;
7551  object *objp;
7552 
7553  // get the data
7554  GET_USHORT(net_signature);
7555  GET_INT(observer_team);
7556  GET_INT(observed_team);
7557  GET_INT(alternate_iff_color);
7558  PACKET_SET_SIZE();
7559 
7560  // lookup the object
7561  objp = multi_get_network_object(net_signature);
7562  if((objp != NULL) && (objp->type == OBJ_SHIP) && (objp->instance >=0))
7563  {
7564  Ships[objp->instance].ship_iff_color[observer_team][observed_team] = alternate_iff_color;
7565  }
7566 }
7567 
7568 void send_change_ai_class_packet(ushort net_signature, char *subsystem, int new_ai_class)
7569 {
7571  int packet_size = 0;
7572 
7573  if(Net_player == NULL){
7574  return;
7575  }
7577  return;
7578  }
7579 
7580  // build the packet and add the data
7582  ADD_USHORT(net_signature);
7583  if (subsystem)
7584  ADD_STRING(subsystem);
7585  else
7587  ADD_INT(new_ai_class);
7588 
7589  // send to all players
7590  multi_io_send_to_all_reliable(data, packet_size);
7591 }
7592 
7594 {
7595  int offset = HEADER_LENGTH;
7596  ushort net_signature;
7597  int new_ai_class;
7598  char subsys_buf[255];
7599  object *objp;
7600 
7601  // get the data
7602  GET_USHORT(net_signature);
7603  GET_STRING(subsys_buf);
7604  GET_INT(new_ai_class);
7605  PACKET_SET_SIZE();
7606 
7607  // lookup the object
7608  objp = multi_get_network_object(net_signature);
7609  if((objp != NULL) && (objp->type == OBJ_SHIP) && (objp->instance >=0))
7610  {
7611  // no subsystem?
7612  if (!strcmp(subsys_buf, NO_SUBSYS_STRING))
7613  {
7614  ship_set_new_ai_class(objp->instance, new_ai_class);
7615  }
7616  // subsystem
7617  else
7618  {
7619  ship_subsystem_set_new_ai_class(objp->instance, subsys_buf, new_ai_class);
7620  }
7621  }
7622 }
7623 
7625 {
7626  int packet_size, objnum;
7627  ubyte data[MAX_PACKET_SIZE]; // ubanks_fired, current_bank;
7628  object *objp;
7629  int np_index;
7630  net_player *ignore = NULL;
7631 
7632  // get an object pointer for this ship.
7633  objnum = shipp->objnum;
7634  objp = &Objects[objnum];
7635 
7636  // if i'm a multiplayer client, I should never send primary fired packets for anyone except me
7637  if(MULTIPLAYER_CLIENT && (Player_obj != objp)){
7638  return;
7639  }
7640 
7641  // just in case nothing got fired
7642  if(banks_fired <= 0){
7643  return;
7644  }
7645 
7646  // ubanks_fired = (ubyte)banks_fired;
7647  // current_bank = (ubyte)shipp->weapons.current_primary_bank;
7648  // Assert( current_bank <= 3 );
7649 
7650  // insert the current primary bank into this byte
7651  // ubanks_fired |= (current_bank << CURRENT_BANK_BIT);
7652 
7653  // append the SF_PRIMARY_LINKED flag on the top nibble of the banks_fired
7654  // if ( shipp->flags & SF_PRIMARY_LINKED ){
7655  // ubanks_fired |= (1<<7);
7656  // }
7657 
7658  if(MULTIPLAYER_MASTER){
7660  if((np_index >= 0) && (np_index < MAX_PLAYERS)){
7661  ignore = &Net_players[np_index];
7662  }
7663  }
7664 
7665  // build up the standard weapon fired packet. This packet will get sent to all players if an AI
7666  // ship fired the primary weapons. If a player fired the weapon, then this packet will get sent
7667  // to every player but the guy who actullly fired the weapon. This method is used to help keep client
7668  // and server in sync w.r.t. weapon energy for player ship
7670  ADD_USHORT(objp->net_signature);
7671  // ADD_DATA(ubanks_fired);
7672 
7673  // if I'm a server, broadcast to all players
7674  if(MULTIPLAYER_MASTER){
7675  multi_io_send_to_all(data, packet_size, ignore);
7676 
7677  // TEST CODE
7678  multi_rate_add(1, "wfi", packet_size);
7679  }
7680  // otherwise just send to the server
7681  else {
7682  multi_io_send(Net_player, data, packet_size);
7683  }
7684 }
7685 
7687 {
7688  int offset; // linked;
7689  // ubyte banks_fired, current_bank;
7690  object* objp;
7691  ship *shipp;
7692  ushort shooter_sig;
7693 
7694  // read all packet info
7695  offset = HEADER_LENGTH;
7696  GET_USHORT(shooter_sig);
7697  // GET_DATA(banks_fired);
7698  PACKET_SET_SIZE();
7699 
7700  // find the object this fired packet is operating on
7701  objp = multi_get_network_object( shooter_sig );
7702  if ( objp == NULL ) {
7703  nprintf(("Network", "Could not find ship for fire primary packet NEW!"));
7704  return;
7705  }
7706  // if this object is not actually a valid ship, don't do anything
7707  if(objp->type != OBJ_SHIP){
7708  return;
7709  }
7710  // Juke - also check (objp->instance >= MAX_SHIPS)
7711  if(objp->instance < 0 || objp->instance >= MAX_SHIPS){
7712  return;
7713  }
7714  shipp = &Ships[objp->instance];
7715 
7716  // get the link status of the primary banks
7717  // linked = 0;
7718  // if ( banks_fired & (1<<7) ) {
7719  // linked = 1;
7720  // banks_fired ^= (1<<7);
7721  // }
7722 
7723  // get the current primary bank
7724  // current_bank = (ubyte)(banks_fired >> CURRENT_BANK_BIT);
7725  // current_bank &= 0x3;
7726  // Assert( (current_bank >= 0) && (current_bank < MAX_SHIP_PRIMARY_BANKS) );
7727  // shipp->weapons.current_primary_bank = current_bank;
7728 
7729  // strip off all remaining bits and just keep which banks were actually fired.
7730  // banks_fired &= 0x3;
7731 
7732  // set the link status of the ship if not the player. If it is the player, we will do sanity checking
7733  // only (for now).
7734  // if ( !linked ){
7735 // shipp->flags &= ~SF_PRIMARY_LINKED;
7736  // } else {
7737  // shipp->flags |= SF_PRIMARY_LINKED;
7738  // }
7739 
7740  // if we're in client firing mode, ignore ones for myself
7741  if((Player_obj != NULL) && (Player_obj == objp)){
7742  return;
7743  }
7744 
7745  ship_fire_primary( objp, 0, 1 );
7746 
7747  // Karajorma - It's still a hack but at least this way it only affects AI ships
7748  if (!(objp->flags & OF_PLAYER_SHIP))
7749  {
7750  // Juke - this is the hackiest hack, but hopefully it will fix stream weapon
7751  // notifications generated by AI ships.
7752  uint flags = shipp->flags & SF_TRIGGER_DOWN;
7753 
7754  shipp->flags |= SF_TRIGGER_DOWN;
7755  ship_fire_primary( objp, 1, 1 );
7756  shipp->flags &= flags | ~SF_TRIGGER_DOWN;
7757  }
7758 }
7759 
7760 void send_NEW_countermeasure_fired_packet(object *objp, int cmeasure_count, int rand_val)
7761 {
7763  int packet_size;
7764  int np_index;
7765  net_player *ignore = NULL;
7766 
7767  // if i'm a multiplayer client, I should never send primary fired packets for anyone except me
7768  if(MULTIPLAYER_CLIENT && (Player_obj != objp)){
7769  return;
7770  }
7771 
7772  Assert ( cmeasure_count < UCHAR_MAX );
7774  ADD_USHORT( objp->net_signature );
7775  ADD_INT( rand_val );
7776 
7777  nprintf(("Network","Sending NEW countermeasure packet!\n"));
7778 
7779  // determine if its a player
7780  if(MULTIPLAYER_MASTER){
7782  if((np_index >= 0) && (np_index < MAX_PLAYERS)){
7783  ignore = &Net_players[np_index];
7784  }
7785  }
7786 
7787  // if I'm the server, send to all players
7788  if(MULTIPLAYER_MASTER){
7789  multi_io_send_to_all(data, packet_size, ignore);
7790  }
7791  // otherwise send to the server
7792  else {
7793  multi_io_send(Net_player, data, packet_size);
7794  }
7795 }
7796 
7798 {
7799  int offset;
7800  ushort signature;
7801  int rand_val;
7802  object *objp;
7803 
7804  offset = HEADER_LENGTH;
7805  GET_USHORT( signature );
7806  GET_INT( rand_val );
7807  PACKET_SET_SIZE();
7808 
7809  objp = multi_get_network_object( signature );
7810  if ( objp == NULL ) {
7811  nprintf(("network", "Could find object whose countermeasures are being launched!!!\n"));
7812  return;
7813  }
7814  if(objp->type != OBJ_SHIP){
7815  return;
7816  }
7817 
7818  // if we're in client firing mode, ignore ones for myself
7819  if((Player_obj != NULL) && (Player_obj == objp)){
7820  return;
7821  }
7822 
7823  if ( (rand_val >= NPERM_SIG_MIN) && (rand_val <= NPERM_SIG_MAX) ) {
7825  }
7826 
7827  // make it so ship can fire right away!
7829  if ( objp == Player_obj ){
7830  nprintf(("network", "firing countermeasure from my ship\n"));
7831  }
7832  ship_launch_countermeasure( objp, rand_val );
7833 }
7834 
7835 void send_beam_fired_packet(object *shooter, ship_subsys *turret, object *target, int beam_info_index, beam_info *override, int bfi_flags, int bank_point)
7836 {
7838  int packet_size = 0;
7839  short u_beam_info;
7840  char subsys_index;
7841  beam_info b_info;
7842  ushort target_sig;
7843 
7844  // only the server should ever be doing this
7846 
7847  // setup outgoing data
7848  Assert(shooter != NULL);
7849  Assert(turret != NULL);
7850  Assert(override != NULL);
7851  if((shooter == NULL) || (turret == NULL) || (override == NULL)){
7852  return;
7853  }
7854 
7855  if (!(bfi_flags & BFIF_IS_FIGHTER_BEAM)) {
7856  Assert(target != NULL);
7857  if (target == NULL) {
7858  return;
7859  }
7860  }
7861 
7862  target_sig = (target) ? target->net_signature : 0;
7863 
7864  u_beam_info = (short)beam_info_index;
7865 
7866  if (bfi_flags & BFIF_IS_FIGHTER_BEAM) {
7867  Assert( (bank_point >= 0) && (bank_point < UCHAR_MAX) );
7868  subsys_index = (char)bank_point;
7869  } else {
7870  subsys_index = (char)ship_get_index_from_subsys(turret, OBJ_INDEX(shooter), 1);
7871  }
7872 
7873  Assert(subsys_index >= 0);
7874  if (subsys_index < 0) {
7875  return;
7876  }
7877 
7878  // swap the beam_info override info into little endian byte order
7879  b_info.dir_a.xyz.x = INTEL_FLOAT(&override->dir_a.xyz.x);
7880  b_info.dir_a.xyz.y = INTEL_FLOAT(&override->dir_a.xyz.y);
7881  b_info.dir_a.xyz.z = INTEL_FLOAT(&override->dir_a.xyz.z);
7882 
7883  b_info.dir_b.xyz.x = INTEL_FLOAT(&override->dir_b.xyz.x);
7884  b_info.dir_b.xyz.y = INTEL_FLOAT(&override->dir_b.xyz.y);
7885  b_info.dir_b.xyz.z = INTEL_FLOAT(&override->dir_b.xyz.z);
7886 
7887  b_info.delta_ang = INTEL_FLOAT(&override->delta_ang);
7888  b_info.shot_count = override->shot_count;
7889 
7890  for (int i = 0; i < b_info.shot_count; i++) {
7891  b_info.shot_aim[i] = INTEL_FLOAT(&override->shot_aim[i]);
7892  }
7893 
7894  // build the header
7896  ADD_USHORT(shooter->net_signature);
7897  ADD_DATA(subsys_index);
7898  ADD_USHORT(target_sig);
7899  ADD_SHORT(u_beam_info);
7900  ADD_DATA(b_info); // FIXME: This is still wrong, we shouldn't be sending an entire struct over the wire - taylor
7901 // ADD_DATA(bfi_flags); // this breaks the protocol but is here in case we decided to do that in the future - taylor
7902 // ADD_DATA(target_pos); // ditto - Goober5000
7903 
7904  // send to all clients
7905  multi_io_send_to_all_reliable(data, packet_size);
7906 }
7907 
7909 {
7910  int i, offset;
7911  ushort shooter_sig, target_sig;
7912  char subsys_index;
7913  short u_beam_info;
7914  beam_info b_info;
7915  beam_fire_info fire_info;
7916 // ubyte fighter_beam = 0;
7917 
7918  // only clients should ever get this
7920 
7921  // read in packet data
7922  offset = HEADER_LENGTH;
7923  GET_USHORT(shooter_sig);
7924  GET_DATA(subsys_index);
7925  GET_USHORT(target_sig);
7926  GET_SHORT(u_beam_info);
7927  GET_DATA(b_info); // FIXME: This is still wrong, we shouldn't be sending an entire struct over the wire - taylor
7928 // GET_DATA(fighter_beam); // this breaks the protocol but is here in case we decided to do that in the future - taylor
7929  PACKET_SET_SIZE();
7930 
7931  // swap the beam_info override info into native byte order
7932  b_info.dir_a.xyz.x = INTEL_FLOAT(&b_info.dir_a.xyz.x);
7933  b_info.dir_a.xyz.y = INTEL_FLOAT(&b_info.dir_a.xyz.y);
7934  b_info.dir_a.xyz.z = INTEL_FLOAT(&b_info.dir_a.xyz.z);
7935 
7936  b_info.dir_b.xyz.x = INTEL_FLOAT(&b_info.dir_b.xyz.x);
7937  b_info.dir_b.xyz.y = INTEL_FLOAT(&b_info.dir_b.xyz.y);
7938  b_info.dir_b.xyz.z = INTEL_FLOAT(&b_info.dir_b.xyz.z);
7939 
7940  b_info.delta_ang = INTEL_FLOAT(&b_info.delta_ang);
7941 
7942  for (i = 0; i < b_info.shot_count; i++) {
7943  b_info.shot_aim[i] = INTEL_FLOAT(&b_info.shot_aim[i]);
7944  }
7945 
7946  memset(&fire_info, 0, sizeof(beam_fire_info));
7947 
7948  // lookup all relevant data
7949  fire_info.beam_info_index = (int)u_beam_info;
7950  fire_info.shooter = NULL;
7951  fire_info.target = NULL;
7952  fire_info.turret = NULL;
7953  fire_info.target_subsys = NULL;
7954  fire_info.beam_info_override = NULL;
7955  fire_info.shooter = multi_get_network_object(shooter_sig);
7956  fire_info.target = multi_get_network_object(target_sig);
7957  fire_info.beam_info_override = &b_info;
7958  fire_info.accuracy = 1.0f;
7959 
7960  if((fire_info.shooter == NULL) || (fire_info.shooter->type != OBJ_SHIP) || (fire_info.shooter->instance < 0) || (fire_info.shooter->instance >= MAX_SHIPS)){
7961  nprintf(("Network", "Couldn't get shooter info for BEAM weapon!\n"));
7962  return;
7963  }
7964 
7965  ship *shipp = &Ships[fire_info.shooter->instance];
7966 
7967  // this check is a little convoluted but should cover all bases until we decide to just break the protocol
7968  if ( Ship_info[shipp->ship_info_index].flags & (SIF_FIGHTER | SIF_BOMBER) ) {
7969  // make sure the beam is a primary weapon and not attached to a turret or something
7970  for (i = 0; i < shipp->weapons.num_primary_banks; i++) {
7971  if ( shipp->weapons.primary_bank_weapons[i] == fire_info.beam_info_index ) {
7972  fire_info.bfi_flags |= BFIF_IS_FIGHTER_BEAM;
7973  }
7974  }
7975  }
7976 
7977  if ( !(fire_info.bfi_flags & BFIF_IS_FIGHTER_BEAM) && (fire_info.target == NULL) ) {
7978  nprintf(("Network", "Couldn't get target info for BEAM weapon!\n"));
7979  return;
7980  }
7981 
7982  if (fire_info.bfi_flags & BFIF_IS_FIGHTER_BEAM) {
7983  polymodel *pm = model_get( Ship_info[shipp->ship_info_index].model_num );
7984  float field_of_fire = Weapon_info[fire_info.beam_info_index].field_of_fire;
7985 
7986  int bank = (ubyte)subsys_index % 10;
7987  int point = (ubyte)subsys_index / 10;
7988 
7989  fire_info.targeting_laser_offset = pm->gun_banks[bank].pnt[point];
7990 
7991  shipp->beam_sys_info.turret_norm.xyz.x = 0.0f;
7992  shipp->beam_sys_info.turret_norm.xyz.y = 0.0f;
7993  shipp->beam_sys_info.turret_norm.xyz.z = 1.0f;
7994  shipp->beam_sys_info.model_num = Ship_info[shipp->ship_info_index].model_num;
7995  shipp->beam_sys_info.turret_gun_sobj = pm->detail[0];
7997  shipp->beam_sys_info.turret_fov = cosf((field_of_fire != 0.0f) ? field_of_fire : 180);
7998  shipp->beam_sys_info.pnt = fire_info.targeting_laser_offset;
8000 
8005 
8006  fire_info.turret = &shipp->fighter_beam_turret_data;
8007  fire_info.bank = bank;
8008  } else {
8009  fire_info.turret = ship_get_indexed_subsys(shipp, (int)subsys_index);
8010 
8011  if (fire_info.turret == NULL) {
8012  nprintf(("Network", "Couldn't get turret for BEAM weapon!\n"));
8013  return;
8014  }
8015  }
8016 
8017  // fire da beam
8018  beam_fire(&fire_info);
8019 }
8020 
8021 void send_sw_query_packet(ubyte code, char *txt)
8022 {
8024  int packet_size = 0;
8025 
8026  // build the packet and add the code
8028  ADD_DATA(code);
8029  if((code == SW_STD_START) || (code == SW_STD_BAD)){
8030  ADD_STRING(txt);
8031  }
8032 
8033  // if I'm the host, send to standalone
8034  if(MULTIPLAYER_HOST){
8036  Assert(code == SW_STD_START);
8037  multi_io_send_reliable(Net_player, data, packet_size);
8038  }
8039  // otherwise standalone sends back to host
8040  else {
8042  Assert(code != SW_STD_START);
8043  Assert(Netgame.host != NULL);
8044  if(Netgame.host != NULL){
8045  multi_io_send_reliable(Netgame.host, data, packet_size);
8046  }
8047  }
8048 }
8049 
8051 {
8052 }
8053 
8055 {
8057  ushort u_event = (ushort)event;
8058  int packet_size = 0;
8059 
8060  // build the header and add the event
8062  ADD_USHORT(u_event);
8063  ADD_INT(Mission_events[event].flags);
8064  ADD_INT(Mission_events[event].formula);
8065  ADD_INT(Mission_events[event].result);
8066  ADD_INT(Mission_events[event].count);
8067 
8068  // send to all players
8069  multi_io_send_to_all_reliable(data, packet_size);
8070 }
8071 
8073 {
8074  int offset = HEADER_LENGTH;
8075  int store_flags;
8076  ushort u_event;
8077 
8078  // get the data
8079  GET_USHORT(u_event);
8080  store_flags = Mission_events[u_event].flags;
8081  GET_INT(Mission_events[u_event].flags);
8082  GET_INT(Mission_events[u_event].formula);
8083  GET_INT(Mission_events[u_event].result);
8084  GET_INT(Mission_events[u_event].count);
8085  PACKET_SET_SIZE();
8086 
8087  // went from non directive special to directive special
8088  if(!(store_flags & MEF_DIRECTIVE_SPECIAL) && (Mission_events[u_event].flags & MEF_DIRECTIVE_SPECIAL)){
8090  }
8091  // if we went directive special to non directive special
8092  else if((store_flags & MEF_DIRECTIVE_SPECIAL) && !(Mission_events[u_event].flags & MEF_DIRECTIVE_SPECIAL)){
8094  }
8095 }
8096 
8097 void send_weapon_or_ammo_changed_packet (int ship_index, int bank_type, int bank_number, int ammo_left, int rearm_limit, int new_weapon_index)
8098 {
8100  int packet_size = 0;
8101 
8102  if(Net_player == NULL){
8103  return;
8104  }
8106  return;
8107  }
8108 
8109  // build the packet and add the data
8111  ADD_INT(ship_index);
8112  ADD_INT(bank_type);
8113  ADD_INT(bank_number);
8114  ADD_INT(ammo_left);
8115  ADD_INT(rearm_limit);
8116  ADD_INT(new_weapon_index);
8117 
8118  //Send it to the player whose weapons have changes
8119  multi_io_send_to_all_reliable(data, packet_size);
8120 }
8121 
8123 {
8124  int offset = HEADER_LENGTH;
8125  int ship_index, bank_type, bank_number, ammo_left, rearm_limit, new_weapon_index;
8126  ship *shipp;
8127 
8128  // get the data
8129  GET_INT(ship_index);
8130  GET_INT(bank_type);
8131  GET_INT(bank_number);
8132  GET_INT(ammo_left);
8133  GET_INT(rearm_limit);
8134  GET_INT(new_weapon_index);
8135  PACKET_SET_SIZE();
8136 
8137  // Now set the ships values up.
8138 
8139  //Primary weapons
8140  if (bank_type == 0)
8141  {
8142  // don't swap weapons
8143  if (new_weapon_index < 0)
8144  {
8145  set_primary_ammo(ship_index, bank_number, ammo_left, rearm_limit);
8146  }
8147  else
8148  {
8149  Assert (new_weapon_index < MAX_WEAPON_TYPES);
8150  shipp = &Ships[ship_index];
8151  shipp->weapons.primary_bank_weapons[bank_number] = new_weapon_index;
8152  set_primary_ammo(Player_obj->instance, bank_number, ammo_left, rearm_limit);
8153  }
8154  }
8155  // Secondary weapons
8156  else if (bank_type == 1)
8157  {
8158  // don't swap weapons
8159  if (new_weapon_index < 0)
8160  {
8161  set_secondary_ammo(ship_index, bank_number, ammo_left, rearm_limit);
8162  }
8163  else
8164  {
8165  Assert (new_weapon_index < MAX_WEAPON_TYPES);
8166  shipp = &Ships[ship_index];
8167  shipp->weapons.secondary_bank_weapons[bank_number] = new_weapon_index;
8168  set_secondary_ammo(Player_obj->instance, bank_number, ammo_left, rearm_limit);
8169  }
8170  }
8171  else
8172  {
8173  nprintf(("network", "weapon_or_ammo_changed_packet recived for tertiary or other unsupported type\n"));
8174  return;
8175  }
8176 }
8177 
8178 // Karajorma - Sends a packet to all clients telling them that a SEXP variable has changed its value
8179 void send_variable_update_packet(int variable_index, char *value)
8180 {
8182  int packet_size = 0;
8183 
8184  if(Net_player == NULL){
8185  return;
8186  }
8188  return;
8189  }
8190 
8191  // build the packet and add the data
8193  ADD_INT(variable_index);
8194  ADD_STRING(value);
8195 
8196  if (MULTIPLAYER_MASTER) {
8197  // send to all players
8198  multi_io_send_to_all_reliable(data, packet_size);
8199  }
8200  else {
8201  multi_io_send_reliable(Net_player, data, packet_size);
8202  }
8203 }
8204 
8206 {
8207  int offset = HEADER_LENGTH;
8208  char value[TOKEN_LENGTH];
8209  int variable_index;
8210 
8211  // get the data
8212  GET_INT(variable_index);
8213  GET_STRING(value);
8214  PACKET_SET_SIZE();
8215 
8216  // set the sexp_variable
8217  if ( (variable_index >= 0) && (variable_index < sexp_variable_count()) )
8218  {
8219  strcpy_s(Sexp_variables[variable_index].text, value);
8220  }
8221 
8222  // send the packet on to all clients.
8223  if (MULTIPLAYER_MASTER) {
8224  send_variable_update_packet(variable_index, Sexp_variables[variable_index].text);
8225  }
8226 }
8227 
8228 // weapon detonate packet
8230 {
8232  int packet_size = 0;
8233 
8234  // sanity checks
8236  if(!MULTIPLAYER_MASTER){
8237  return;
8238  }
8239  Assert(objp != NULL);
8240  if(objp == NULL){
8241  return;
8242  }
8243 
8244  // build the header and add the data
8246  ADD_USHORT(objp->net_signature);
8247 
8248  // send to all players
8249  multi_io_send_to_all(data, packet_size);
8250 }
8251 
8253 {
8254  ushort net_sig;
8255  int offset = HEADER_LENGTH;
8256  object *objp = NULL;
8257 
8258  // get the weapon signature
8259  GET_USHORT(net_sig);
8260  PACKET_SET_SIZE();
8261 
8262  // lookup the weapon
8263  objp = multi_get_network_object(net_sig);
8264  if((objp != NULL) && (objp->type == OBJ_WEAPON) && (objp->instance >= 0)){
8265  weapon_detonate(objp);
8266  }
8267 }
8268 
8269 // flak fired packet
8270 void send_flak_fired_packet(int ship_objnum, int subsys_index, int weapon_objnum, float flak_range)
8271 {
8272  int packet_size;
8273  ushort pnet_signature;
8274  ubyte data[MAX_PACKET_SIZE], cindex;
8275  object *objp;
8276  ship_subsys *ssp;
8277  short val;
8278 
8279  // sanity
8280  if((weapon_objnum < 0) || (Objects[weapon_objnum].type != OBJ_WEAPON) || (Objects[weapon_objnum].instance < 0) || (Weapons[Objects[weapon_objnum].instance].weapon_info_index < 0)){
8281  return;
8282  }
8283 
8284  // local setup -- be sure we are actually passing a weapon!!!!
8285  objp = &Objects[weapon_objnum];
8286  Assert ( objp->type == OBJ_WEAPON );
8287  pnet_signature = Objects[ship_objnum].net_signature;
8288 
8289  Assert( subsys_index < UCHAR_MAX );
8290  cindex = (ubyte)subsys_index;
8291 
8292  ssp = ship_get_indexed_subsys( &Ships[Objects[ship_objnum].instance], subsys_index, NULL );
8293  if(ssp == NULL){
8294  return;
8295  }
8296 
8297  // build the fire turret packet.
8299  packet_size += multi_pack_unpack_position(1, data + packet_size, &objp->orient.vec.fvec);
8300  ADD_USHORT( pnet_signature );
8301  ADD_DATA( cindex );
8302  val = (short)ssp->submodel_info_1.angs.h;
8303  ADD_SHORT( val );
8304  val = (short)ssp->submodel_info_2.angs.p;
8305  ADD_SHORT( val );
8306  ADD_FLOAT( flak_range );
8307 
8308  multi_io_send_to_all(data, packet_size);
8309 
8310  multi_rate_add(1, "flk", packet_size);
8311 }
8312 
8314 {
8315  int offset, weapon_objnum, wid = -1;
8316  ushort pnet_signature;
8317  vec3d pos, dir;
8318  matrix orient;
8319  vec3d o_fvec;
8320  ubyte turret_index;
8321  object *objp;
8322  ship_subsys *ssp;
8323  ship *shipp;
8324  short pitch, heading;
8325  float flak_range;
8326 
8327  // get the data for the turret fired packet
8328  offset = HEADER_LENGTH;
8329  offset += multi_pack_unpack_position(0, data + offset, &o_fvec);
8330  GET_USHORT( pnet_signature );
8331  GET_DATA( turret_index );
8332  GET_SHORT( heading );
8333  GET_SHORT( pitch );
8334  GET_FLOAT( flak_range );
8335  PACKET_SET_SIZE(); // move our counter forward the number of bytes we have read
8336 
8337  // find the object
8338  objp = multi_get_network_object( pnet_signature );
8339  if ( objp == NULL ) {
8340  nprintf(("network", "could find parent object with net signature %d for flak firing\n", pnet_signature));
8341  return;
8342  }
8343 
8344  // if this isn't a ship, do nothing
8345  if ( objp->type != OBJ_SHIP ){
8346  return;
8347  }
8348 
8349  // make an orientation matrix from the o_fvec
8350  vm_vector_2_matrix(&orient, &o_fvec, NULL, NULL);
8351 
8352  // find this turret, and set the position of the turret that just fired to be where it fired. Quite a
8353  // hack, but should be suitable.
8354  shipp = &Ships[objp->instance];
8355  ssp = ship_get_indexed_subsys( shipp, turret_index, NULL );
8356  if(ssp == NULL){
8357  return;
8358  }
8359 
8360  if (ssp->weapons.num_primary_banks > 0) {
8361  wid = ssp->weapons.primary_bank_weapons[0];
8362  } else if (ssp->weapons.num_secondary_banks > 0) {
8363  wid = ssp->weapons.secondary_bank_weapons[0];
8364  }
8365 
8366  if((wid < 0) || !(Weapon_info[wid].wi_flags & WIF_FLAK)){
8367  return;
8368  }
8369 
8370  // bash the position and orientation of the turret
8371  ssp->submodel_info_1.angs.h = (float)heading;
8372  ssp->submodel_info_2.angs.p = (float)pitch;
8373 
8374  // get the world position of the weapon
8375  ship_get_global_turret_info(objp, ssp->system_info, &pos, &dir);
8376 
8377  // create the weapon object
8378  weapon_objnum = weapon_create( &pos, &orient, wid, OBJ_INDEX(objp), -1, 1, 0, 0.0f, ssp);
8379  if (weapon_objnum != -1) {
8380  wid = Weapons[Objects[weapon_objnum].instance].weapon_info_index;
8381  if ( Weapon_info[wid].launch_snd != -1 ) {
8382  snd_play_3d( &Snds[Weapon_info[wid].launch_snd], &pos, &View_position );
8383  }
8384 
8385  // create a muzzle flash from a flak gun based upon firing position and weapon type
8386  flak_muzzle_flash(&pos, &dir, &objp->phys_info, wid);
8387 
8388  // set its range explicitly - make it long enough so that it's guaranteed to still exist when the server tells us it blew up
8389  flak_set_range(&Objects[weapon_objnum], (float)flak_range);
8390  }
8391 }
8392 
8393 #define ADD_NORM_VEC(d) do { Assert((packet_size + 3) < MAX_PACKET_SIZE); char vnorm[3] = { (char)(d.x * 127.0f), (char)(d.y * 127.0f), (char)(d.z * 127.0f) }; memcpy(data + packet_size, vnorm, 3); packet_size += 3; } while(0);
8394 #define GET_NORM_VEC(d) do { char vnorm[3]; memcpy(vnorm, data+offset, 3); d.x = (float)vnorm[0] / 127.0f; d.y = (float)vnorm[1] / 127.0f; d.z = (float)vnorm[2] / 127.0f; } while(0);
8395 
8396 // player pain packet
8397 void send_player_pain_packet(net_player *pl, int weapon_info_index, float damage, vec3d *force, vec3d *hitpos, int quadrant_num)
8398 {
8400  short windex;
8401  ushort udamage;
8402  int packet_size = 0;
8403 
8405  if(!MULTIPLAYER_MASTER){
8406  return;
8407  }
8408  Assert(pl != NULL);
8409  if(pl == NULL){
8410  return;
8411  }
8412 
8413  // build the packet and add the code
8415  windex = (short)weapon_info_index;
8416  ADD_SHORT(windex);
8417  udamage = (ushort)damage;
8418  ADD_USHORT(udamage);
8419  ADD_VECTOR((*force));
8420  ADD_VECTOR((*hitpos));
8421  ADD_INT(quadrant_num);
8422 
8423  // send to the player
8424  multi_io_send(pl, data, packet_size);
8425 
8426  multi_rate_add(1, "pai", packet_size);
8427 }
8428 
8430 {
8431  int offset;
8432  short windex = 0;
8433  ushort udamage;
8434  vec3d force;
8435  vec3d local_hit_pos;
8436  weapon_info *wip;
8437  int quadrant_num;
8438 
8439  // get the data for the pain packet
8440  offset = HEADER_LENGTH;
8441  GET_SHORT(windex);
8442  GET_USHORT(udamage);
8443  GET_VECTOR(force);
8444  GET_VECTOR(local_hit_pos);
8445  GET_INT(quadrant_num);
8446  PACKET_SET_SIZE();
8447 
8448  // mprintf(("PAIN!\n"));
8449 
8450  // get weapon info pointer
8451  Assert((windex < Num_weapon_types) && (Weapon_info[windex].subtype == WP_LASER));
8452  if(! ((windex < Num_weapon_types) && (Weapon_info[windex].subtype == WP_LASER)) ){
8453  return;
8454  }
8455  wip = &Weapon_info[windex];
8456 
8457  // play the weapon hit sound
8458  Assert(Player_obj != NULL);
8459  if(Player_obj == NULL){
8460  return;
8461  }
8462 
8463  //Assume the weapon is armed -WMC
8465 
8466  // we need to do 3 things here. player pain (game flash), weapon hit sound, ship_apply_whack()
8467  ship_hit_pain((float)udamage, quadrant_num);
8468 
8469  // apply the whack
8470  ship_apply_whack(&force, &local_hit_pos, Player_obj);
8471 }
8472 
8473 // lightning packet
8474 void send_lightning_packet(int bolt_type_internal, vec3d *start, vec3d *strike)
8475 {
8477  char val;
8478  int packet_size = 0;
8479 
8480  // build the header and add the data
8482  val = (char)bolt_type_internal;
8483  ADD_DATA(val);
8484  ADD_VECTOR((*start));
8485  ADD_VECTOR((*strike));
8486 
8487  // send to everyone unreliable for now
8488  multi_io_send_to_all(data, packet_size);
8489 }
8490 
8492 {
8493  int offset;
8494  char bolt_type_internal;
8495  vec3d start, strike;
8496 
8497  // read the data
8498  offset = HEADER_LENGTH;
8499  GET_DATA(bolt_type_internal);
8500  GET_VECTOR(start);
8501  GET_VECTOR(strike);
8502  PACKET_SET_SIZE();
8503 
8504  // invalid bolt?
8505  if(bolt_type_internal < 0){
8506  return;
8507  }
8508 
8509  // fire it up
8510  nebl_bolt(bolt_type_internal, &start, &strike);
8511 }
8512 
8514 {
8515  // only clients should ever be doing this
8516  if(pl == NULL){
8517  return;
8518  }
8519 
8521  int packet_size = 0;
8523  ADD_INT(pl->cl_bytes_recvd);
8524 
8525  // send to the server
8526  multi_io_send_reliable(pl, data, packet_size);
8527 }
8528 
8530 {
8531  int bytes;
8532  int pid;
8533  net_player *pl = NULL;
8534  int offset = HEADER_LENGTH;
8535 
8536  GET_INT(bytes);
8537  PACKET_SET_SIZE();
8538 
8539  // not server?
8540  if(Net_player == NULL){
8541  return;
8542  }
8543  if(!MULTIPLAYER_MASTER){
8544  return;
8545  }
8546 
8547  // make sure we know what player sent this
8548  pid = find_player_id(hinfo->id);
8549  if((pid < 0) || (pid >= MAX_PLAYERS)){
8550  return;
8551  }
8552  pl = &Net_players[pid];
8553 
8554  // compute his pl
8555  pl->cl_bytes_recvd = bytes;
8556  if(bytes < 0){
8557  return;
8558  }
8559  pl->sv_last_pl = (int)(100.0f * (1.0f - ((float)pl->cl_bytes_recvd / (float)pl->sv_bytes_sent)));
8560 
8561  // reset bytes sent
8562  pl->sv_bytes_sent = 0;
8563 }
8564 
8565 // host transfer
8566 void send_host_captain_change_packet(short player_id, int captain_change)
8567 {
8569  int packet_size = 0;
8570 
8571  // build the packet
8573  ADD_SHORT(player_id);
8574  ADD_INT(captain_change);
8575 
8576  // send to all
8577  multi_io_send_to_all_reliable(data, packet_size);
8578 }
8579 
8581 {
8582  int offset = HEADER_LENGTH;
8583  int idx, found_player, captain_change;
8584  short player_id;
8585 
8586  // get the player id
8587  GET_SHORT(player_id);
8588  GET_INT(captain_change);
8589  PACKET_SET_SIZE();
8590 
8591  // captain change
8592  if(captain_change){
8593  // flag the new guy
8594  for(idx=0; idx<MAX_PLAYERS; idx++){
8595  if(MULTI_CONNECTED(Net_players[idx]) && (Net_players[idx].player_id == player_id)){
8596  HUD_printf("%s is the new captain of team %d", Net_players[idx].m_player->callsign, Net_players[idx].p_info.team + 1);
8597  break;
8598  }
8599  }
8600  } else {
8601  // unflag all old players
8602  for(idx=0; idx<MAX_PLAYERS; idx++){
8604  }
8605 
8606  // flag the new guy
8607  found_player = 0;
8608  for(idx=0; idx<MAX_PLAYERS; idx++){
8609  if(MULTI_CONNECTED(Net_players[idx]) && (Net_players[idx].player_id == player_id)){
8611 
8612  // spew to the HUD config
8613  if(Net_players[idx].m_player != NULL){
8614  HUD_printf("%s is the new game host", Net_players[idx].m_player->callsign);
8615  }
8616 
8617  found_player = 1;
8618  break;
8619  }
8620  }
8621 
8622  // doh
8623  if(!found_player){
8625  }
8626  }
8627 }
8628 
8630 {
8632  int packet_size = 0;
8633 
8634  // bogus
8635  if(Net_player == NULL){
8636  return;
8637  }
8638 
8639  // if i'm the server, I shouldn't be here
8642  return;
8643  }
8644 
8645  // only if this is valid
8647  return;
8648  }
8649 
8650  // bogus object?
8651  if((Player_ship == NULL) || (Player_obj == NULL)){
8652  return;
8653  }
8654 
8655  // self destruct
8658 
8659  // send to the server
8660  multi_io_send_reliable(Net_player, data, packet_size);
8661 }
8662 
8664 {
8665  int offset = HEADER_LENGTH;
8666  ushort net_sig;
8667  int np_index;
8668 
8669  // get the net signature
8670  GET_USHORT(net_sig);
8671  PACKET_SET_SIZE();
8672 
8673  // get the player
8674  np_index = find_player_id(hinfo->id);
8675  if(np_index < 0){
8676  return;
8677  }
8678  if(MULTI_OBSERVER(Net_players[np_index])){
8679  return;
8680  }
8681  if(Net_players[np_index].m_player == NULL){
8682  return;
8683  }
8684  if((Net_players[np_index].m_player->objnum < 0) || (Net_players[np_index].m_player->objnum >= MAX_OBJECTS)){
8685  return;
8686  }
8687  if(Objects[Net_players[np_index].m_player->objnum].net_signature != net_sig){
8688  return;
8689  }
8690  if(Objects[Net_players[np_index].m_player->objnum].type != OBJ_SHIP){
8691  return;
8692  }
8693  if((Objects[Net_players[np_index].m_player->objnum].instance < 0) || (Objects[Net_players[np_index].m_player->objnum].instance >= MAX_SHIPS)){
8694  return;
8695  }
8696 
8697  // do eet
8698  ship_self_destruct(&Objects[Net_players[np_index].m_player->objnum]);
8699 }
8700 
8701 void send_sexp_packet(ubyte *sexp_packet, int num_ubytes)
8702 {
8704  int packet_size = 0;
8705  int i;
8706  ushort val;
8707 
8709  // must have a bare minimum of OP, COUNT and TERMINATOR
8710  if (num_ubytes < 9) {
8711  Warning(LOCATION, "Invalid call to send_sexp_packet. Not enough data included!");
8712  return;
8713  }
8714 
8715  BUILD_HEADER(SEXP);
8716 
8717  val = (ushort)num_ubytes;
8718  ADD_USHORT(val);
8719 
8720  for (i =0; i < num_ubytes; i++) {
8721  Assert (packet_size < MAX_PACKET_SIZE);
8722  data[packet_size] = sexp_packet[i];
8723  packet_size++;
8724  }
8725 
8726  // send to all
8727  multi_io_send_to_all_reliable(data, packet_size);
8728 }
8729 
8731 {
8732  int offset = HEADER_LENGTH;
8733  int i;
8734  ushort num_ubytes;
8735  ubyte received_packet[MAX_PACKET_SIZE];
8736 
8737  // get the number of bytes of data in the packet
8738  GET_USHORT(num_ubytes);
8739 
8740  for (i=0; i < num_ubytes; i++) {
8741  GET_DATA(received_packet[i]);
8742  }
8743 
8744  PACKET_SET_SIZE();
8745 
8746  sexp_packet_received(received_packet, num_ubytes);
8747 }
void asteroid_sub_create(object *parent_objp, int asteroid_type, vec3d *relvec)
Definition: asteroid.cpp:405
#define NETINFO_FLAG_WARPING_OUT
Definition: multi.h:618
#define GM_DEAD_DIED
Definition: systemvars.h:20
void ship_wing_cleanup(int shipnum, wing *wingp)
Definition: ship.cpp:7640
void send_change_ai_class_packet(ushort net_signature, char *subsystem, int new_ai_class)
Definition: multimsgs.cpp:7568
void send_variable_update_packet(int variable_index, char *value)
Definition: multimsgs.cpp:8179
void message_queue_message(int message_num, int priority, int timing, char *who_from, int source, int group, int delay, int builtin_type)
char * Cmdline_connect_addr
Definition: cmdline.cpp:263
int target_num
Definition: weapon.h:172
GLuint64EXT * result
Definition: Glext.h:10775
void send_shield_explosion_packet(int objnum, int tri_num, vec3d hit_pos)
Definition: multimsgs.cpp:6300
uint respawn
Definition: multi.h:507
#define SHIP_VANISHED
Definition: ship.h:1622
#define MAX_FILENAME_LEN
Definition: pstypes.h:324
#define TRANSFER_HOST
Definition: multi.h:220
#define REARM_REPAIR_ME_ITEM
Definition: hudsquadmsg.h:49
#define SQUAD_MSG_REINFORCEMENT
Definition: multi.h:359
void send_turret_fired_packet(int ship_objnum, int subsys_index, int weapon_objnum)
Definition: multimsgs.cpp:3212
int timestamp(int delta_ms)
Definition: timer.cpp:226
#define NETINFO_FLAG_ACCEPT_INGAME
Definition: multi.h:614
#define GAME_INFO
Definition: multi.h:218
wing Wings[MAX_WINGS]
Definition: ship.cpp:128
#define MULTIPLAYER_CLIENT
Definition: multi.h:132
#define SUBSYSTEM_DESTROYED
Definition: multi.h:170
#define MY_NET_PLAYER_NUM
Definition: multi.h:127
#define NET_TCP
Definition: psnet2.h:29
#define NETGAME_STATE_DEBRIEF
Definition: multi.h:669
void obj_set_flags(object *obj, uint new_flags)
Definition: object.cpp:1000
int i
Definition: multi_pxo.cpp:466
float get_max_shield_quad(object *objp)
Definition: object.cpp:260
fix Missiontime
Definition: systemvars.cpp:19
int kill_count_ok
Definition: scoring.h:90
ubyte wash_killed
Definition: ship.h:548
int Multi_sync_countdown
Definition: multiui.cpp:7352
float p
Definition: pstypes.h:111
int Select_default_ship
#define GET_DATA(d)
Definition: multimsgs.h:47
char * repair_text[]
Definition: multimsgs.cpp:4825
#define WIF_CMEASURE
Definition: weapon.h:51
model_subsystem * system_info
Definition: ship.h:314
void send_beam_fired_packet(object *shooter, ship_subsys *turret, object *target, int beam_info_index, beam_info *override, int bfi_flags, int bank_point)
Definition: multimsgs.cpp:7835
#define NETPLAYER_STATE_HOST_SETUP
Definition: multi.h:694
weapon Weapons[MAX_WEAPONS]
Definition: weapons.cpp:78
int primary_bank_weapons[MAX_SHIP_PRIMARY_BANKS]
Definition: ship.h:103
#define NETPLAYER_STATE_IN_MISSION
Definition: multi.h:686
void hud_gauge_popup_start(int gauge_index, int time)
Start a gauge to pop-up.
Definition: hud.cpp:3036
union ai_goal::@1 dockee
#define SUBSYS_CARGO_HIDDEN
Definition: multi.h:267
void process_ship_create_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:2666
void ai_mission_goal_complete(ai_info *aip)
Definition: aigoals.cpp:360
#define AG_FLAG_FORMING
Definition: multi.h:524
#define UPDATE_HULL_INFO
Definition: multimsgs.cpp:6973
vec3d turret_norm
Definition: model.h:186
#define MULTI_END_NOTIFY_KICKED_INGAME_ENDED
Definition: multi_endgame.h:40
void multi_debrief_stats_accept()
Definition: multiui.cpp:8897
void send_server_query(net_addr *addr)
Definition: multimsgs.cpp:2266
int cmeasure_fire_stamp
Definition: ship.h:654
int ts_index
Definition: ship.h:704
ai_info * Player_ai
Definition: ai.cpp:24
int team
Definition: ship.h:606
int multi_msg_matches_expr(net_player *np, const char *expr)
Definition: multi_pmsg.cpp:318
void sexp_packet_received(ubyte *received_packet, int num_ubytes)
Definition: multi_sexp.cpp:461
GLbitfield stages
Definition: Glext.h:7177
void process_ai_info_update_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:5055
int ship_class
Definition: multi.h:451
#define AG_FLAG_PAUSE
Definition: multi.h:527
float vm_vec_mag_quick(const vec3d *v)
Definition: vecmat.cpp:371
int flags
Definition: player.h:104
int kills[MAX_SHIP_CLASSES]
Definition: scoring.h:87
void player_set_squad_bitmap(player *p, char *fname, bool ismulti)
int beam_info_index
Definition: beam.h:57
void mission_parse_support_arrived(int objnum)
int Multi_mission_loaded
Definition: multi.cpp:98
vec3d View_position
Definition: 3dsetup.cpp:20
int num_primary_banks
Definition: ship.h:99
object * homing_object
Definition: weapon.h:177
int objnum
Definition: ship.h:537
int Game_mode
Definition: systemvars.cpp:24
int std_is_host_passwd()
vec3d rotvel
Definition: physics.h:78
#define NETPLAYER_UPDATE
Definition: multi.h:257
char name[MAX_GAMENAME_LEN+1]
Definition: multi.h:548
void process_ship_kill_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:2557
void send_sw_query_packet(ubyte code, char *txt)
Definition: multimsgs.cpp:8021
net_addr server_addr
Definition: multi.h:552
#define SHIP_STATUS_CHANGE
Definition: multi.h:203
int multi_pack_unpack_orient(int write, ubyte *data, matrix *orient)
Definition: multiutil.cpp:3677
#define NETGAME_STATE_PAUSED
Definition: multi.h:668
#define MULTI_MSG_FRIENDLY
Definition: multi_pmsg.h:28
void add_join_request(ubyte *data, int *size, join_request *jr)
Definition: multimsgs.cpp:291
void process_ping_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:3466
char Game_current_mission_filename[MAX_FILENAME_LEN]
Definition: fredstubs.cpp:26
void send_store_stats_packet(int accept)
Definition: multimsgs.cpp:5249
polymodel * model_get(int model_num)
Definition: modelread.cpp:3134
weapon_info Weapon_info[MAX_WEAPON_TYPES]
Definition: weapons.cpp:79
ship_weapon weapons
Definition: ship.h:658
int killer_species
Definition: player.h:181
GLuint counter
Definition: Glext.h:10587
#define JOIN_DENY_JR_NOOBS
Definition: multi.h:295
void send_reinforcement_avail(int rnum)
Definition: multimsgs.cpp:7458
net_player * Net_player
Definition: multi.cpp:94
#define PLAYER_ORDER_PACKET
Definition: multi.h:204
SCP_vector< game_snd > Snds
Definition: gamesnd.cpp:19
object * target
Definition: beam.h:62
int Multi_pause_status
Definition: multi_pause.cpp:38
void send_NEW_countermeasure_fired_packet(object *objp, int cmeasure_count, int rand_val)
Definition: multimsgs.cpp:7760
#define NETPLAYER_STATE_MISSION_LOADED
Definition: multi.h:679
#define AG_FLAG_IN_MISSION
Definition: multi.h:528
int turret_gun_sobj
Definition: model.h:193
void process_change_iff_color_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:7546
submodel_instance_info submodel_info_1
Definition: ship.h:368
void send_self_destruct_packet()
Definition: multimsgs.cpp:8629
void multi_ingame_observer_finish()
void send_ship_create_packet(object *objp, int is_support)
Definition: multimsgs.cpp:2648
GLsizei const GLfloat * value
Definition: Glext.h:5646
#define PACKET_SET_SIZE()
Definition: multimsgs.h:57
int Multi_ts_num_deleted
#define MULTI_SIG_DEBRIS
Definition: multiutil.h:35
vec3d desired_vel
Definition: physics.h:70
Definition: weapon.h:163
GLuint index
Definition: Glext.h:5608
void multi_ts_create_wings()
void process_observer_update_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:3976
#define AI_GOAL_DOCK
Definition: aigoals.h:30
ushort multi_get_next_network_signature(int what_kind)
Definition: multiutil.cpp:168
int multi_eval_join_request(join_request *jr, net_addr *addr)
Definition: multiutil.cpp:1946
int active_goal
Definition: ai.h:413
int weapon_create(vec3d *pos, matrix *orient, int weapon_type, int parent_obj, int group_id=-1, int is_locked=0, int is_spawned=0, float fof_cooldown=0.0f, ship_subsys *src_turret=NULL)
Definition: weapons.cpp:5246
physics_info phys_info
Definition: object.h:157
#define JOIN_DENY_JR_TRACKER_INVAL
Definition: multi.h:286
player * m_player
Definition: multi.h:459
int index
Definition: missionlog.h:53
void multi_untag_player_ships()
Definition: multiutil.cpp:1404
int security
Definition: multi.h:499
#define NETPLAYER_STATE_MISSION_LOADING
Definition: multi.h:678
#define EXTRA_DEATH_VAPORIZED
Definition: multimsgs.cpp:2464
void obj_reset_all_collisions()
Definition: object.cpp:1985
#define MAX_SHIPS
Definition: globals.h:37
int flags
Definition: missionlog.h:49
int flags
Definition: ship.h:88
int Multi_restr_query_timestamp
Definition: multi.cpp:135
#define MULTI_SIG_SHIP
Definition: multiutil.h:32
#define PLAYER_DATA_SLOP
Definition: multimsgs.cpp:1194
int mode
Definition: multi.h:494
ship_subsys fighter_beam_turret_data
Definition: ship.h:743
#define MULTI_PRIMARY_CHANGED
Definition: multimsgs.h:60
void hud_squadmsg_call_reinforcement(int reinforcement_num, int player_num)
#define SQUADMSG_HISTORY_ADD_ENTRY
Definition: hudsquadmsg.h:156
#define NETGAME_STATE_BRIEFING
Definition: multi.h:665
void ship_hit_pain(float damage, int quadrant)
Definition: shiphit.cpp:2562
ubyte max_players
Definition: multiui.h:41
#define COUNTDOWN
Definition: multi.h:261
#define NO_SUBSYS_STRING
Definition: multi.h:270
void multi_options_update_local()
int ship_iff_color[MAX_IFFS][MAX_IFFS]
Definition: ship.h:793
float max_hits
Definition: ship.h:320
void send_netplayer_update_packet(net_player *pl)
Definition: multimsgs.cpp:2308
void psnet_mark_received(PSNET_SOCKET_RELIABLE socket)
Definition: psnet2.cpp:2174
void ship_add_exited_ship(ship *sp, int reason)
Definition: ship.cpp:5298
void process_game_chat_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:717
#define ADD_DATA(d)
Definition: multimsgs.h:37
#define MULTI_STANDALONE(np)
Definition: multi.h:139
#define MULTI_SYNC_PRE_BRIEFING
Definition: multiui.h:138
int next_secondary_fire_stamp[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:115
int gameseq_get_state(void)
Definition: fredstubs.cpp:60
int insignia_texture
Definition: player.h:195
void _cdecl void void _cdecl void _cdecl Warning(char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
void multi_io_send(net_player *pl, ubyte *data, int len)
Definition: multimsgs.cpp:371
Assert(pm!=NULL)
int target_objnum
Definition: ai.h:339
#define AG_FLAG_DEBRIEF
Definition: multi.h:526
#define NETPLAYER_STATE_SLOT_ACK
Definition: multi.h:685
void add_net_addr(ubyte *data, int *size, net_addr *addr)
Definition: multimsgs.cpp:321
int multi_obs_create_player(int player_num, char *name, net_addr *addr, player *pl)
int ai_submode
Definition: ai.h:137
int detail[MAX_MODEL_DETAIL_LEVELS]
Definition: model.h:738
void send_secondary_fired_packet(ship *shipp, ushort starting_sig, int starting_count, int num_fired, int allow_swarm)
Definition: multimsgs.cpp:2938
int bfi_flags
Definition: beam.h:71
int detonate_weapon_time
Definition: ship.h:147
void process_countdown_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:7232
Definition: pstypes.h:88
submodel_instance_info submodel_info_2
Definition: ship.h:369
#define ADD_STRING(s)
Definition: multimsgs.h:43
#define mprintf(args)
Definition: pstypes.h:238
void process_variable_update_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:8205
int ai_index
Definition: ship.h:538
void process_homing_weapon_info(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:7357
ship_weapon weapons
Definition: ship.h:362
#define NETINFO_FLAG_OBSERVER
Definition: multi.h:605
float delta_ang
Definition: beam.h:45
int hud_squadmsg_send_wing_command(int wingnum, int command, int send_message, int update_history, int player_num)
void multi_io_send_to_all_reliable(ubyte *data, int length, net_player *ignore)
Definition: multimsgs.cpp:496
ushort net_signature
Definition: object.h:163
w_bank * gun_banks
Definition: model.h:772
int ship_fire_primary(object *obj, int stream_weapons, int force)
Definition: ship.cpp:10760
void process_turret_fired_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:3264
#define NUM_SKILL_LEVELS
Definition: systemvars.h:150
#define STATS_MISSION
Definition: multi.h:367
int weapon_recharge_index
Definition: ship.h:638
void process_force_end_mission_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:3837
void process_mission_request_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:3635
#define AG_FLAG_DOGFIGHT
Definition: multi.h:523
void server_verify_filesig(short player_id, ushort sum_sig, int length_sig)
Definition: multiutil.cpp:1324
#define ACCEPT_HOST
Definition: multi.h:326
unsigned int mp_shots_fired
Definition: scoring.h:117
int verts[3]
Definition: model.h:552
void process_repair_info_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:4873
void send_cargo_hidden_packet(ship *shipp)
Definition: multimsgs.cpp:2881
#define LOGIN_LEN
Definition: multi.h:85
void process_flak_fired_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:8313
void process_subsystem_cargo_hidden_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:4650
void process_mission_message_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:3431
void send_subsystem_cargo_revealed_packet(ship *shipp, int index)
Definition: multimsgs.cpp:4557
ship_subsys * turret
Definition: beam.h:60
unsigned int mp_bonehead_hits
Definition: scoring.h:121
struct vec3d::@225::@227 xyz
int m_bonehead_kills
Definition: scoring.h:123
CButton * team
#define KICK_REASON_BAD_XFER
Definition: multi_kick.h:24
void multi_io_send_reliable(net_player *pl, ubyte *data, int len)
Definition: multimsgs.cpp:459
ship_subsys * target_subsys
Definition: beam.h:63
int message_filter_multi(int id)
#define NETPLAYER_IS_OBSERVER(player)
Definition: multi.h:626
void process_debris_update_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:5317
int find_player_id(short player_id)
Definition: multiutil.cpp:465
void mission_goal_validation_change(int goal_num, int valid)
#define NETPLAYER_STATE_JOINING
Definition: multi.h:676
void ml_string(const char *string, int add_time)
Definition: multi_log.cpp:131
#define JUMP_INTO_GAME
Definition: multi.h:164
GLclampf f
Definition: Glext.h:7097
_fs_time_t last_flown
Definition: scoring.h:103
#define INTEL_SHORT(x)
Definition: pstypes.h:389
#define MAX_OBJECTS
Definition: globals.h:83
#define CHANGE_IFF_COLOR
Definition: multi.h:275
#define MULTI_END_NOTIFY_EARLY_END
Definition: multi_endgame.h:36
#define PLAYER_FLAGS_HAS_PLAYED_PXO
Definition: player.h:49
void send_asteroid_throw(object *objp)
Definition: multimsgs.cpp:6689
int psnet_rel_send(PSNET_SOCKET_RELIABLE socketid, ubyte *data, int length, int np_index)
Definition: psnet2.cpp:1075
int target_name_index
Definition: ai.h:144
#define DENY
Definition: multi.h:214
server_item * next
Definition: multi.h:560
void ship_do_cargo_revealed(ship *shipp, int from_network)
Definition: ship.cpp:16138
void send_file_sig_request(char *file_name)
Definition: multimsgs.cpp:4448
int kill_count
Definition: scoring.h:89
void send_ship_kill_packet(object *objp, object *other_objp, float percent_killed, int self_destruct)
Definition: multimsgs.cpp:2467
#define SEF_PLAYER_DELETED
Definition: ship.h:849
#define ASTEROID_CREATE
Definition: multi.h:351
void send_NEW_primary_fired_packet(ship *shipp, int banks_fired)
Definition: multimsgs.cpp:7624
ai_info Ai_info[MAX_AI_INFO]
Definition: ai.cpp:23
vec3d * vm_vec_rotate(vec3d *dest, const vec3d *src, const matrix *m)
Definition: vecmat.cpp:933
void process_countermeasure_success_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:6958
#define Assertion(expr, msg,...)
Definition: clang.h:41
#define INVALID_SOCKET
Definition: psnet2.h:53
#define CAMPAIGN_LIST_ITEMS
Definition: multimsgs.cpp:3567
int dock_find_dockpoint_used_by_object(object *objp, object *other_objp)
Definition: objectdock.cpp:116
void process_wing_create_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:2735
void process_host_captain_change_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:8580
object obj_used_list
Definition: object.cpp:53
#define GAME_CHAT
Definition: multi.h:228
int Multi_has_cd
Definition: multi.cpp:112
void send_game_active_packet(net_addr *addr)
Definition: multimsgs.cpp:1852
char mission_name[NAME_LENGTH+1]
Definition: multi.h:549
#define FILE_SIG_INFO
Definition: multi.h:160
#define MEF_DIRECTIVE_SPECIAL
Definition: missiongoals.h:83
Definition: ship.h:1516
int current_primary_bank
Definition: ship.h:106
#define NETPLAYER_STATE_JOINED
Definition: multi.h:677
#define AG_FLAG_BRIEFING
Definition: multi.h:525
int restore_wss_data(ubyte *block)
ship_subsys * targeted_subsys
Definition: ai.h:472
#define NETGAME_STATE_STD_HOST_SETUP
Definition: multi.h:672
GLenum mode
Definition: Glext.h:5794
void mission_log_add_entry_multi(int type, char *pname, char *sname, int index, fix timestamp, int flags)
Definition: missionlog.cpp:393
unsigned int ms_bonehead_hits
Definition: scoring.h:122
net_player * Multi_pause_pauser
Definition: multi_pause.cpp:41
int n_quadrants
Definition: object.h:158
sexp_variable Sexp_variables[MAX_SEXP_VARIABLES]
Definition: sexp.cpp:846
float shot_aim[MAX_BEAM_SHOTS]
Definition: beam.h:47
void send_join_packet(net_addr *addr, join_request *jr)
Definition: multimsgs.cpp:888
#define MULTI_JOIN_RESTR_MODE_2
Definition: multi.h:781
ship_subsys * homing_subsys
Definition: weapon.h:178
#define NETPLAYER_STATE_SETTINGS_ACK
Definition: multi.h:695
Definition: ai.h:329
void ship_do_cap_subsys_cargo_revealed(ship *shipp, ship_subsys *subsys, int from_network)
Definition: ship.cpp:16161
shield_vertex * verts
Definition: model.h:569
void send_netgame_update_packet(net_player *pl)
Definition: multimsgs.cpp:2008
float weapon_energy
Definition: ship.h:640
void process_sexp_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:8730
#define FIRING_INFO
Definition: multi.h:156
uint flags
Definition: ship.h:644
int ship_fire_secondary(object *obj, int allow_swarm)
Definition: ship.cpp:11799
#define LIGHTNING_PACKET
Definition: multi.h:251
#define NETPLAYER_PAIN
Definition: multi.h:180
#define GET_ORIENT(d)
Definition: multimsgs.h:54
hull_check orient
Definition: lua.cpp:5049
int flags
Definition: multi.h:463
#define OF_PLAYER_SHIP
Definition: object.h:109
int tracker_id
Definition: multi.h:576
#define MISSION_LIST_ITEMS
Definition: multimsgs.cpp:3566
ubyte addr[6]
Definition: psnet2.h:41
object * objp
Definition: lua.cpp:3105
void send_repair_info_packet(object *repaired_objp, object *repair_objp, int code)
Definition: multimsgs.cpp:4845
unsigned int s_shots_fired
Definition: scoring.h:92
log_entry log_entries[MAX_LOG_ENTRIES]
Definition: missionlog.cpp:69
#define OBJ_OBSERVER
Definition: object.h:43
int current_secondary_bank
Definition: ship.h:107
GLsizeiptr size
Definition: Glext.h:5496
int subtype
Definition: weapon.h:326
#define Int3()
Definition: pstypes.h:292
void send_hud_msg_to_all(char *msg)
Definition: multimsgs.cpp:841
void multi_handle_sudden_mission_end()
Definition: multiutil.cpp:2135
void process_store_stats_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:5268
ushort net_signature
Definition: missionparse.h:413
void HUD_sourced_printf(int source, const char *format,...)
Definition: hudmessage.cpp:571
void multi_io_send_to_all(ubyte *data, int length, net_player *ignore)
Definition: multimsgs.cpp:408
#define SHIP_CREATE
Definition: multi.h:243
#define AI_GOAL_NONE
Definition: ai.h:194
ship * shipp
Definition: lua.cpp:9162
void send_mission_message_packet(int id, char *who_from, int priority, int timing, int source, int builtin_type, int multi_target, int multi_team_filter, int delay)
Definition: multimsgs.cpp:3400
void multi_team_host_lock_all()
Definition: multi_team.cpp:530
void process_NEW_primary_fired_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:7686
vec3d pos
Definition: object.h:152
void multi_debrief_stats_toss()
Definition: multiui.cpp:8919
int packet_size
Definition: multi_sexp.cpp:41
ship_subsys_info subsys_info[SUBSYSTEM_MAX]
Definition: ship.h:632
void ship_apply_whack(vec3d *force, vec3d *hit_pos, object *objp)
Definition: shiphit.cpp:1740
void process_debrief_info(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:7284
#define AI_UPDATE_DOCK
Definition: multi.h:342
multi_local_options player_options
Definition: multi.h:577
vec3d turret_firing_point[MAX_TFP]
Definition: model.h:192
void ship_get_global_turret_info(object *objp, model_subsystem *tp, vec3d *gpos, vec3d *gvec)
Definition: aiturret.cpp:1303
void multi_create_handle_join(net_player *pl)
Definition: multiui.cpp:5058
#define IS_VEC_NULL(v)
Definition: vecmat.h:28
void nebl_bolt(size_t type, vec3d *start, vec3d *strike)
int game_state
Definition: multi.h:498
unsigned int mp_shots_hit
Definition: scoring.h:119
int psnet_same(net_addr *a1, net_addr *a2)
Definition: psnet2.cpp:785
#define SQUAD_MSG_ALL
Definition: multi.h:358
#define SECONDARY_FIRED_PLR
Definition: multi.h:200
#define MULTI_JOIN_RESTR_MODE_4
Definition: multi.h:783
vec3d pnt[MAX_SLOTS]
Definition: model.h:434
#define GAME_ACTIVE
Definition: multi.h:254
int signature
Definition: object.h:145
#define MULTI_JOIN_RESTR_MODE_1
Definition: multi.h:780
#define GET_VECTOR(d)
Definition: multimsgs.h:55
void process_new_player_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:1063
GLenum type
Definition: Gl.h:1492
void std_update_player_ping(net_player *p)
#define HUD_DAMAGE_GAUGE
Definition: hudgauges.h:44
void send_host_restr_packet(char *callsign, int code, int mode)
Definition: multimsgs.cpp:6832
void send_cargo_revealed_packet(ship *shipp)
Definition: multimsgs.cpp:2829
int Multi_sync_mode
Definition: multiui.cpp:7348
void multi_handle_end_mission_request()
Definition: multiutil.cpp:2218
void ai_do_objects_docked_stuff(object *docker, int docker_point, object *dockee, int dockee_point, bool update_clients=true)
Definition: aicode.cpp:3008
int wep_count[MAX_SHIP_WEAPONS]
void ship_actually_depart(int shipnum, int method)
Definition: ship.cpp:7748
#define GET_FLOAT(d)
Definition: multimsgs.h:52
void debris_hit(object *debris_obj, object *other_obj, vec3d *hitpos, float damage)
Definition: debris.cpp:751
void multi_ping_reset(ping_struct *ps)
Definition: multi_ping.cpp:41
int weapon_info_index
Definition: weapon.h:164
void process_netgame_update_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:2063
#define MULTI_END_ERROR_HOST_LEFT
Definition: multi_endgame.h:51
#define ADD_INT(d)
Definition: multimsgs.h:40
HWND DWORD code
Definition: vddraw.h:425
reinforcements Reinforcements[MAX_REINFORCEMENTS]
Definition: ship.cpp:165
#define SHIP_DESTROYED
Definition: ship.h:1623
#define MISSION_GOAL_INFO
Definition: multi.h:178
#define AI_ACTIVE_GOAL_DYNAMIC
Definition: ai.h:196
int version_info
Definition: multi.h:492
int objnum
Definition: ship.h:1483
ship_subsys subsys_list
Definition: ship.h:630
void send_emp_effect(ushort net_sig, float intensity, float time)
Definition: multimsgs.cpp:7414
void process_host_restr_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:6858
int multi_endgame_ending()
void send_ping(net_addr *addr)
Definition: multimsgs.cpp:3527
int type
Definition: missionlog.h:48
void process_NEW_countermeasure_fired_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:7797
player Players[MAX_PLAYERS]
int tracker_player_id
Definition: multi.h:461
void std_connect_set_host_connect_status()
int mission_remove_scheduled_repair(object *objp)
void process_shield_explosion_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:6347
void send_netplayer_load_packet(net_player *pl)
Definition: multimsgs.cpp:4694
unsigned int ms_shots_fired
Definition: scoring.h:118
void send_event_update_packet(int event)
Definition: multimsgs.cpp:8054
int m_kill_count_ok
Definition: scoring.h:115
#define SIF_BOMBER
Definition: ship.h:886
void process_beam_fired_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:7908
void process_secondary_fired_packet(ubyte *data, header *hinfo, int from_player)
process a packet indicating a secondary weapon was fired
Definition: multimsgs.cpp:3047
void send_mission_goal_info_packet(int goal_num, int new_status, int valid)
Definition: multimsgs.cpp:5574
#define MAX_PACKET_SIZE
Definition: psnet2.h:34
typedef int(SCP_EXT_CALLCONV *SCPDLL_PFVERSION)(SCPDLL_Version *)
#define MAX_SHIP_SECONDARY_BANKS
Definition: globals.h:63
unsigned int missions_flown
Definition: scoring.h:101
int instance
Definition: object.h:150
void send_ai_info_update_packet(object *objp, char what, object *other_objp)
Definition: multimsgs.cpp:4943
void process_pong_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:3483
int multi_num_players()
Definition: multiutil.cpp:1799
void process_game_active_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:1935
void multi_display_chat_msg(const char *msg, int player_index, int add_id)
Definition: multiutil.cpp:2895
#define JOIN_DENY_JR_INGAME_JOIN
Definition: multi.h:296
#define WIF_FLAK
Definition: weapon.h:75
void send_bytes_recvd_packet(net_player *pl)
Definition: multimsgs.cpp:8513
matrix * vm_vector_2_matrix(matrix *m, const vec3d *fvec, const vec3d *uvec, const vec3d *rvec)
Definition: vecmat.cpp:850
ubyte shot_count
Definition: beam.h:46
GLintptr offset
Definition: Glext.h:5497
int game_hacked_data()
Definition: fredstubs.cpp:208
void process_hud_message(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:857
void send_asteroid_hit(object *objp, object *other_objp, vec3d *hitpos, float damage)
Definition: multimsgs.cpp:6706
p_object * mission_parse_get_arrival_ship(const char *name)
Returns the parse object on the ship arrival list associated with the given name. ...
void vm_vec_add2(vec3d *dest, const vec3d *src)
Definition: vecmat.cpp:178
net_player_info p_info
Definition: multi.h:473
int m_okKills[MAX_SHIP_CLASSES]
Definition: scoring.h:113
GLenum GLenum GLenum input
Definition: Glext.h:8502
int type_flags
Definition: multi.h:493
void flak_muzzle_flash(vec3d *pos, vec3d *dir, physics_info *pip, int turret_weapon_class)
Definition: flak.cpp:120
ship_subsys * ship_get_indexed_subsys(ship *sp, int index, vec3d *attacker_pos)
Definition: ship.cpp:13340
void mission_parse_fixup_players()
#define SHIP_DEPART
Definition: multi.h:230
int flags
Definition: ship.h:322
void multi_join_reset_join_stamp()
Definition: multiui.cpp:1983
char pname[NAME_LENGTH]
Definition: missionlog.h:51
void mission_goal_status_change(int goal_num, int new_status)
#define MAX_SHIP_WEAPONS
Definition: globals.h:64
struct matrix::@228::@230 vec
#define NETINFO_FLAG_AM_MASTER
Definition: multi.h:599
ubyte reliable_buffer[MAX_PACKET_SIZE]
Definition: multi.h:442
unsigned int uint
Definition: pstypes.h:64
void send_debrief_event()
Definition: multiutil.cpp:4159
#define HUD_SOURCE_COMPUTER
Definition: hudmessage.h:21
int subtype
Definition: lua.cpp:9763
void ml_printf(const char *format,...)
Definition: multi_log.cpp:112
GLenum pname
Definition: Gl.h:1517
float ship_max_hull_strength
Definition: ship.h:597
#define MISSION_SYNC_DATA
Definition: multi.h:171
void vm_vec_scale(vec3d *dest, float s)
Definition: vecmat.cpp:248
#define SQUAD_MSG_WING
Definition: multi.h:357
void process_lightning_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:8491
#define ADD_FLOAT(d)
Definition: multimsgs.h:42
#define JOIN_DENY_JR_FULL
Definition: multi.h:292
int state
Definition: multi.h:464
void process_netplayer_load_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:4709
void process_event_update_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:8072
#define MULTI_FS_SERVER_COMPATIBLE_VERSION
Definition: multi.h:67
#define nprintf(args)
Definition: pstypes.h:239
#define MAX_SHIPS_PER_PACKET
Definition: multi.h:374
#define GM_MULTIPLAYER
Definition: systemvars.h:18
void send_client_update_packet(net_player *pl)
Definition: multimsgs.cpp:6975
#define ASTEROID_HIT
Definition: multi.h:353
PSNET_SOCKET_RELIABLE reliable_socket
Definition: multi.h:465
void process_reinforcement_avail(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:7468
#define BUILD_HEADER(t)
Definition: multimsgs.h:36
#define NETINFO_FLAG_HAS_CD
Definition: multi.h:619
char name[MAX_GAMENAME_LEN+1]
Definition: multi.h:487
void multi_flush_multidata_cache()
Definition: multiutil.cpp:2778
void send_game_chat_packet(net_player *from, const char *msg, int msg_mode, net_player *to, const char *expr, int server_msg)
Definition: multimsgs.cpp:615
void send_countdown_packet(int time)
Definition: multimsgs.cpp:7210
#define SHIP_DEPARTED_BAY
Definition: ship.h:1625
unsigned int p_shots_fired
Definition: scoring.h:91
#define MAX_SHIP_CLASSES
Definition: globals.h:48
int objnum
Definition: weapon.h:165
int unreliable_buffer_size
Definition: multi.h:441
fix last_heard_time
Definition: multi.h:470
void emp_start_local(float intensity, float time)
Definition: emp.cpp:375
float get_hull_pct(object *objp)
Definition: object.cpp:271
void multi_flush_mission_stuff()
Definition: multiutil.cpp:2787
#define WSS_WEAPON_SELECT
Definition: multi.h:321
#define DEFAULT_GAME_PORT
Definition: psnet2.h:36
char * filename
#define STORE_MISSION_STATS
Definition: multi.h:172
int ship_get_index_from_subsys(ship_subsys *ssp, int objnum, int error_bypass)
Definition: ship.cpp:13390
#define ADD_UINT(d)
Definition: multimsgs.h:41
int wingnum
Definition: ship.h:623
netgame_info Netgame
Definition: multi.cpp:97
#define HOMING_WEAPON_UPDATE
Definition: multi.h:208
int num_secondary_banks
Definition: ship.h:100
#define NUM_BUTTON_FIELDS
Definition: keycontrol.h:18
ai_goal goals[MAX_AI_GOALS]
Definition: ai.h:412
#define ACCEPT_PLAYER_DATA
Definition: multi.h:222
#define OBJ_WEAPON
Definition: object.h:33
void mission_event_set_directive_special(int event)
int snd_play_3d(game_snd *gs, vec3d *source_pos, vec3d *listen_pos, float radius, vec3d *source_vel, int looping, float vol_scale, int priority, vec3d *sound_fvec, float range_factor, int force, bool is_ambient)
Definition: sound.cpp:594
void multi_team_send_update()
Definition: multi_team.cpp:696
void send_accept_packet(int new_player_num, int code, int ingame_join_team)
Definition: multimsgs.cpp:1451
int mode
Definition: ai.h:336
mission_event Mission_events[MAX_MISSION_EVENTS]
#define MISSION_END
Definition: multi.h:233
int disruption_timestamp
Definition: ship.h:371
int shipnum
Definition: ai.h:331
char name[NAME_LENGTH]
Definition: multiui.h:38
#define MULTIPLAYER_HOST
Definition: multi.h:131
void process_endgame_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:3891
#define WP_LASER
Definition: weapon.h:27
#define MAX_WEAPON_TYPES
Definition: globals.h:73
#define MULTI_SIG_NON_PERMANENT
Definition: multiutil.h:34
void send_change_iff_packet(ushort net_signature, int new_team)
Definition: multimsgs.cpp:7483
void weapon_hit(object *weapon_obj, object *other_obj, vec3d *hitpos, int quadrant=-1)
Definition: weapons.cpp:6253
void send_player_order_packet(int type, int index, int cmd)
Definition: multimsgs.cpp:4261
void multi_broadcast_stats(int stats_code)
Definition: multiutil.cpp:1419
#define COUNTERMEASURE_FIRED
Definition: multi.h:201
float hull_strength
Definition: object.h:160
Definition: beam.h:43
#define OBJ_DEBRIS
Definition: object.h:37
#define SUBSYS_CARGO_REVEALED
Definition: multi.h:182
#define MULTI_FS_SERVER_VERSION
Definition: multi.h:65
#define MP_CAMPAIGN
Definition: multi.h:98
#define MAX_MODEL_SUBSYSTEMS
Definition: model.h:103
sprintf(buf,"(%f,%f,%f)", v3->xyz.x, v3->xyz.y, v3->xyz.z)
void hud_squadmsg_send_to_all_fighters(int command, int player_num)
#define NG_TYPE_TEAM
Definition: multi.h:650
int ai_mode
Definition: ai.h:136
net_player * host
Definition: multi.h:504
void send_netgame_end_error_packet(int notify_code, int err_code)
Definition: multimsgs.cpp:6907
char filename[MAX_FILENAME_LEN]
Definition: multiui.h:37
#define WSS_REQUEST_PACKET
Definition: multi.h:175
int multi_pack_unpack_position(int write, ubyte *data, vec3d *pos)
Definition: multiutil.cpp:3586
void set_primary_ammo(int ship_index, int requested_bank, int requested_ammo, int rearm_limit, bool update)
Definition: sexp.cpp:15983
int n_subsystems
Definition: ship.h:1270
#define NETINFO_FLAG_MISSION_OK
Definition: multi.h:608
void process_countermeasure_fired_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:3178
void process_ship_status_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:4205
#define RF_IS_AVAILABLE
Definition: ship.h:80
void process_weapon_or_ammo_changed_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:8122
#define NETGAME_END_ERROR
Definition: multi.h:248
#define MULTI_OBSERVER(np)
Definition: multi.h:140
int model_num
Definition: model.h:176
void set_secondary_ammo(int ship_index, int requested_bank, int requested_ammo, int rearm_limit, bool update)
Definition: sexp.cpp:16131
#define NETINFO_FLAG_INGAME_JOIN
Definition: multi.h:604
#define FIRE_TURRET_WEAPON
Definition: multi.h:202
shield_info shield
Definition: model.h:778
#define PRIMARY_FIRED_NEW
Definition: multi.h:195
#define FLAK_FIRED
Definition: multi.h:209
void process_multi_pause_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:3729
#define OBJ_VISIBILITY_DOT
Definition: multimsgs.cpp:6297
void ai_do_objects_repairing_stuff(object *repaired_obj, object *repair_obj, int how)
Definition: aicode.cpp:10186
#define HUD_SOURCE_HIDDEN
Definition: hudmessage.h:23
model_subsystem beam_sys_info
Definition: ship.h:744
void send_subsystem_destroyed_packet(ship *shipp, int index, vec3d world_hitpos)
Definition: multimsgs.cpp:4482
ushort flags
Definition: multi.h:553
int threat_flags
Definition: player.h:189
int psnet_send(net_addr *who_to, void *data, int len, int np_index)
Definition: psnet2.cpp:793
#define AG_FLAG_STANDALONE
Definition: multi.h:530
int snd_play(game_snd *gs, float pan, float vol_scale, int priority, bool is_voice_msg)
Definition: sound.cpp:517
int engine_recharge_index
Definition: ship.h:639
#define SF_PRIMARY_LINKED
Definition: ship.h:458
int Num_wings
Definition: ship.cpp:120
void fill_net_addr(net_addr *addr, ubyte *address, ushort port)
Definition: multiutil.cpp:1049
int secondary_bank_weapons[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:104
int Num_teams
char * target_name
Definition: ai.h:143
net_player_server_info s_info
Definition: multi.h:472
ubyte version
Definition: multi.h:554
#define NETGAME_STATE_MISSION_SYNC
Definition: multi.h:670
#define JOIN_DENY_JR_BAD_VERSION
Definition: multi.h:297
float vm_vec_normalized_dir(vec3d *dest, const vec3d *end, const vec3d *start)
Definition: vecmat.cpp:591
int Multi_connection_speed
Definition: multi.cpp:113
void ai_post_process_mission()
Definition: aigoals.cpp:159
#define REPAIR_INFO_WARP_ADD
Definition: multi.h:308
#define MAX_PLAYERS
Definition: pstypes.h:32
#define STATS_MISSION_KILLS
Definition: multi.h:369
short player_id
Definition: multi.h:460
void send_ship_weapon_change(ship *shipp, int what, int new_bank, int link_status)
Definition: multimsgs.cpp:4099
net_addr server_addr
Definition: multi.h:562
int current_count
Definition: ship.h:1530
void send_player_settings_packet(net_player *p)
Definition: multimsgs.cpp:5606
void send_wss_update_packet(int team_num, ubyte *wss_data, int size)
Definition: multimsgs.cpp:5437
float aggregate_current_hits
Definition: ship.h:419
matrix eye_orient
Definition: fredrender.cpp:112
#define NETINFO_FLAG_HAXOR
Definition: multi.h:624
void send_jump_into_mission_packet(net_player *pl)
Definition: multimsgs.cpp:4747
#define ACCEPT_CLIENT
Definition: multi.h:328
char mission_name[NAME_LENGTH+1]
Definition: multi.h:488
SCP_vector< int > medal_counts
Definition: scoring.h:85
#define OF_COULD_BE_PLAYER
Definition: object.h:112
#define ADD_SHORT(d)
Definition: multimsgs.h:38
void common_set_team_pointers(int team)
#define NETINFO_FLAG_GAME_HOST
Definition: multi.h:603
#define MISSION_DESC_LENGTH
Definition: globals.h:28
#define FORCE_MISSION_END
Definition: multi.h:238
void process_game_query(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:2277
void send_mission_sync_packet(int mode, int start_campaign)
Definition: multimsgs.cpp:5154
float current_hits
Definition: ship.h:319
#define KICK_REASON_CANT_XFER
Definition: multi_kick.h:25
void do_subobj_destroyed_stuff(ship *ship_p, ship_subsys *subsys, vec3d *hitpos, bool no_explosion)
Definition: shiphit.cpp:108
#define EVENT_UPDATE
Definition: multi.h:197
ubyte debug_flags
Definition: multi.h:516
void send_sexp_packet(ubyte *sexp_packet, int num_ubytes)
Definition: multimsgs.cpp:8701
Definition: ship.h:534
void send_multi_pause_packet(int pause)
Definition: multimsgs.cpp:3709
GLenum GLuint id
Definition: Glext.h:5156
void process_subsystem_destroyed_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:4506
#define NG_MODE_PASSWORD
Definition: multi.h:632
void ship_cleanup(int shipnum, int cleanup_mode)
Definition: ship.cpp:7786
int multi_find_open_player_slot()
Definition: multiutil.cpp:647
void process_netplayer_update_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:2390
vec3d eye_pos
Definition: fredrender.cpp:103
char sname[NAME_LENGTH]
Definition: missionlog.h:52
#define AG_FLAG_COOP
Definition: multi.h:521
void send_mission_items(net_player *pl)
Definition: multimsgs.cpp:3570
void hud_squadmsg_repair_rearm_abort(int toggle_state, object *obj)
void multi_respawn_check(object *objp)
short port
Definition: multi.h:389
int save_flags
Definition: player.h:105
#define MULTI_END_NOTIFY_FILE_REJECTED
Definition: multi_endgame.h:35
#define NETPLAYER_IS_DEAD(player)
Definition: multi.h:627
void process_cargo_hidden_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:2901
void process_wss_request_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:5389
int beam_fire(beam_fire_info *fire_info)
Definition: beam.cpp:281
#define CARGO_REVEALED
Definition: multi.h:167
int killer_objtype
Definition: player.h:180
#define NETINFO_FLAG_ACCEPT_HOST
Definition: multi.h:615
void flak_set_range(object *objp, float range)
Definition: flak.cpp:142
int turret_num_firing_points
Definition: model.h:191
int idx
Definition: multiui.cpp:761
int m_dogfight_kills[MAX_PLAYERS]
Definition: scoring.h:126
int secondary_bank_ammo[MAX_SHIP_SECONDARY_BANKS]
Definition: ship.h:134
#define REPAIR_INFO_END
Definition: multi.h:303
char campaign_name[NAME_LENGTH+1]
Definition: multi.h:490
beam_info * beam_info_override
Definition: beam.h:67
void ship_set_new_ai_class(int ship_num, int new_ai_class)
Definition: ship.cpp:17362
#define CARGO_HIDDEN
Definition: multi.h:266
void multi_io_send_reliable_force(net_player *pl)
Definition: multimsgs.cpp:522
void ship_recalc_subsys_strength(ship *shipp)
Definition: ship.cpp:6020
void process_player_settings_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:5642
vec3d * vm_vec_unrotate(vec3d *dest, const vec3d *src, const matrix *m)
Definition: vecmat.cpp:959
void multi_io_send_force(net_player *pl)
Definition: multimsgs.cpp:434
void multi_sync_start_countdown()
Definition: multiui.cpp:8463
void process_client_update_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:7072
void send_observer_update_packet()
Definition: multimsgs.cpp:3938
object Objects[MAX_OBJECTS]
Definition: object.cpp:62
void process_firing_info_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:5537
long fix
Definition: pstypes.h:54
#define AIM_DOCK
Definition: ai.h:174
unsigned char ubyte
Definition: pstypes.h:62
void multi_warpout_all_players()
Definition: multiutil.cpp:2143
int wi_flags
Definition: weapon.h:384
char title[NAME_LENGTH+1]
Definition: multi.h:489
vec3d targeting_laser_offset
Definition: beam.h:59
int sexp_variable_count()
Definition: sexp.cpp:29490
ushort Multi_current_file_checksum
Definition: multi.cpp:150
#define vm_vec_zero(v)
Definition: vecmat.h:37
int multi_rate_add(int np_index, char *type, int size)
#define MULTI_MSG_ALL
Definition: multi_pmsg.h:27
#define MULTI_JOIN_RESTR_MODE_3
Definition: multi.h:782
net_addr addr
Definition: multi.h:453
void send_wss_slots_data_packet(int team_num, int final, net_player *p, int std_request)
Definition: multimsgs.cpp:6154
#define AG_FLAG_TEAMS
Definition: multi.h:522
void mission_event_unset_directive_special(int event)
const char * XSTR(const char *str, int index)
Definition: localize.cpp:851
void multi_kick_get_text(net_player *pl, int reason, char *str)
Definition: multi_kick.cpp:165
void send_force_end_mission_packet()
Definition: multimsgs.cpp:3821
void multi_assign_player_ship(int net_player_num, object *objp, int ship_class)
Definition: multiutil.cpp:681
#define DEBRIS_UPDATE_NUKE
Definition: multi.h:317
#define ZERO_VECTOR
Definition: vecmat.h:60
#define MAX_MISSION_ITEMS_BYTES
Definition: multimsgs.cpp:3563
int objnum
Definition: player.h:124
int cl_last_pl
Definition: multi.h:482
#define OBJ_INDEX(objp)
Definition: object.h:235
#define INGAME_NAK
Definition: multi.h:234
#define CHANGE_IFF
Definition: multi.h:264
#define NETINFO_FLAG_LIMBO
Definition: multi.h:607
ship * Player_ship
Definition: ship.cpp:124
#define GM_IN_MISSION
Definition: systemvars.h:23
#define MULTI_MSG_HOSTILE
Definition: multi_pmsg.h:29
#define DEBRIS_UPDATE_REMOVE
Definition: multi.h:316
int Multi_tracker_id
Definition: multi.cpp:146
#define LOAD_MISSION_NOW
Definition: multi.h:162
void send_debris_update_packet(object *objp, int code)
Definition: multimsgs.cpp:5294
void process_sw_query_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:8050
matrix orient
Definition: object.h:153
#define JOIN_DENY_JR_PASSWD
Definition: multi.h:287
#define NETINFO_FLAG_ACCEPT_CLIENT
Definition: multi.h:617
#define VARIABLE_UPDATE
Definition: multi.h:272
void get_join_request(ubyte *data, int *size, join_request *jr)
Definition: multimsgs.cpp:308
ubyte num_players
Definition: multi.h:551
#define NOX(s)
Definition: pstypes.h:473
vec3d pos
Definition: model.h:560
char * ai_get_goal_target_name(const char *name, int *index)
Definition: ai.cpp:85
#define EMP_EFFECT
Definition: multi.h:263
GLuint start
Definition: Gl.h:1502
void process_self_destruct_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:8663
void process_ship_weapon_change(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:4117
void multi_ts_drop(int from_type, int from_index, int to_type, int to_index, int ship_class, int player_index)
#define WIF_BOMB
Definition: weapon.h:63
vec3d vec
Definition: lua.cpp:2173
#define OBJ_SHIP
Definition: object.h:32
void multi_team_handle_join(net_player *pl)
Definition: multi_team.cpp:438
void _cdecl void void _cdecl Error(const char *filename, int line, SCP_FORMAT_STRING const char *format,...) SCP_FORMAT_STRING_ARGS(3
int target_sig
Definition: weapon.h:173
#define GM_STANDALONE_SERVER
Definition: systemvars.h:27
#define JOIN_DENY_JR_RANK_LOW
Definition: multi.h:290
void send_countermeasure_success_packet(int objnum)
Definition: multimsgs.cpp:6942
#define MISSION_MESSAGE
Definition: multi.h:229
void broadcast_game_query()
Definition: multimsgs.cpp:2234
#define NPERM_SIG_MAX
Definition: multi.h:748
#define MULTI_END_NOTIFY_NONE
Definition: multi_endgame.h:32
void process_change_ai_class_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:7593
GLbitfield flags
Definition: Glext.h:6722
#define AG_FLAG_TRACKER
Definition: multi.h:532
#define APD_END_DATA
Definition: multi.h:333
int Num_weapon_types
Definition: weapons.cpp:105
#define SECONDARY_FIRED_AI
Definition: multi.h:199
void process_mission_sync_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:5194
#define HOST_RESTR_QUERY
Definition: multi.h:191
void stuff_netplayer_info(net_player *nplayer, net_addr *addr, int ship_class, player *pplayer)
Definition: multiutil.cpp:664
#define WSS_UPDATE_PACKET
Definition: multi.h:176
#define NETGAME_STATE_IN_MISSION
Definition: multi.h:666
#define INTEL_INT(x)
Definition: pstypes.h:388
#define ADD_USHORT(d)
Definition: multimsgs.h:39
GLuint const GLchar * name
Definition: Glext.h:5608
#define INTEL_FLOAT(x)
Definition: pstypes.h:391
#define MISSION_ITEM
Definition: multi.h:217
char valid_status
Definition: multiui.h:42
#define NETINFO_FLAG_CONNECTED
Definition: multi.h:598
#define PROMPT_NONE
Definition: multi_endgame.h:26
void multi_options_local_load(multi_local_options *options, net_player *pxo_pl)
void process_mission_item_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:3653
void multi_server_update_player_weapons(net_player *pl, ship *shipp)
Definition: multiutil.cpp:2737
GLuint GLfloat * val
Definition: Glext.h:6741
int psnet_broadcast(net_addr *who_to, void *data, int len)
Definition: psnet2.cpp:897
void cmeasure_maybe_alert_success(object *objp)
If this is a player countermeasure, let the player know they evaded a missile.
Definition: cmeasure.cpp:84
#define SHIP_WSTATE_CHANGE
Definition: multi.h:174
net_addr server_addr
Definition: multi.h:503
void vm_vec_sub(vec3d *dest, const vec3d *src0, const vec3d *src1)
Definition: vecmat.cpp:168
#define SW_STD_START
Definition: multi.h:362
#define JOIN_DENY_JR_STATE
Definition: multi.h:285
int hud_squadmsg_send_ship_command(int shipnum, int command, int send_message, int update_history, int player_num)
vec3d vel
Definition: physics.h:77
int lookup_ship_status(net_player *p, int unique_id, int remove)
Definition: multiutil.cpp:1156
p_object * Arriving_support_ship
#define TOKEN_LENGTH
Definition: globals.h:41
int Multi_ts_deleted_objnums[MULTI_TS_MAX_TVT_TEAMS *MULTI_TS_NUM_SHIP_SLOTS]
#define NPERM_SIG_MIN
Definition: multi.h:747
#define SW_STD_QUERY
Definition: multi.h:224
brief stage change fail
Definition: gamesnd.h:302
#define SFPF_ALLOW_SWARM
Definition: multimsgs.cpp:2933
#define SF_VAPORIZE
Definition: ship.h:470
#define ASTEROID_THROW
Definition: multi.h:352
#define MULTI_SIG_ASTEROID
Definition: multiutil.h:33
void get_net_addr(ubyte *data, int *size, net_addr *addr)
Definition: multimsgs.cpp:336
int multi_quit_game(int prompt, int notify_code, int err_code, int wsa_error)
GLboolean GLboolean GLboolean b
Definition: Glext.h:5781
void send_weapon_or_ammo_changed_packet(int ship_index, int bank_type, int bank_number, int ammo_left, int rearm_limit, int new_weapon_index)
Definition: multimsgs.cpp:8097
#define WEAPON_DET
Definition: multi.h:240
ship Ships[MAX_SHIPS]
Definition: ship.cpp:122
void send_game_info_packet()
Definition: multimsgs.cpp:3753
void process_netgame_end_error_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:6927
#define POST_SYNC_DATA
Definition: multi.h:184
void send_netplayer_slot_packet()
Definition: multimsgs.cpp:4017
#define SF_DEPARTING
Definition: ship.h:475
#define PLAYER_STATS
Definition: multi.h:187
#define MULTI_PERM_OBSERVER(np)
Definition: multi.h:142
void process_subsystem_cargo_revealed_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:4581
#define SFPF_TARGET_LOCKED
Definition: multimsgs.cpp:2935
void send_ship_depart_packet(object *objp, int method)
Definition: multimsgs.cpp:2774
#define SFPF_DUAL_FIRE
Definition: multimsgs.cpp:2934
#define SQUAD_MSG_SHIP
Definition: multi.h:356
SCP_vector< multi_create_info > Multi_create_campaign_list
Definition: multiui.cpp:3327
#define EXTRA_DEATH_WASHED
Definition: multimsgs.cpp:2465
void send_host_captain_change_packet(short player_id, int captain_change)
Definition: multimsgs.cpp:8566
void send_flak_fired_packet(int ship_objnum, int subsys_index, int weapon_objnum, float flak_range)
Definition: multimsgs.cpp:8270
int total_arrived_count
Definition: ship.h:1528
typedef float(SCP_EXT_CALLCONV *SCPTRACKIR_PFFLOATVOID)()
unsigned int flight_time
Definition: scoring.h:102
GLuint GLuint num
Definition: Glext.h:9089
#define WING_INDEX(wingp)
Definition: ship.h:1601
join_request Multi_restr_join_request
Definition: multi.cpp:136
void multi_create_setup_list_data(int mode)
Definition: multiui.cpp:3448
vec3d dir_b
Definition: beam.h:44
SCP_vector< multi_create_info > Multi_create_mission_list
Definition: multiui.cpp:3326
void multi_pause_server_eval_request(net_player *pl, int pause)
void send_wing_create_packet(wing *wingp, int num_to_create, int pre_create_count)
Definition: multimsgs.cpp:2707
void send_netgame_descript_packet(net_addr *addr, int code)
Definition: multimsgs.cpp:2161
void process_leave_game_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:1724
int game_start_mission()
Definition: fredstubs.cpp:179
void obj_delete(int objnum)
Definition: object.cpp:522
void multi_options_update_netgame()
void process_bytes_recvd_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:8529
#define MULTI_MSG_EXPR
Definition: multi_pmsg.h:31
void multi_process_valid_join_request(join_request *jr, net_addr *who_from, int ingame_join_team)
Definition: multiutil.cpp:2416
#define CALLSIGN_LEN
Definition: globals.h:31
vec3d pnt
Definition: model.h:178
int ship_launch_countermeasure(object *objp, int rand_val)
Definition: ship.cpp:10421
void multi_pause_unpause()
#define UPDATE_IS_PAUSED
Definition: multimsgs.cpp:6972
#define NETPLAYER_SLOTS_P
Definition: multi.h:155
int Multi_join_restr_mode
Definition: multi.cpp:138
#define BFIF_IS_FIGHTER_BEAM
Definition: beam.h:50
#define REPAIR_INFO_ABORT
Definition: multi.h:306
fix timestamp
Definition: missionlog.h:50
float turret_fov
Definition: model.h:188
int campaign_mode
Definition: multi.h:509
int turret_next_fire_pos
Definition: ship.h:339
int m_medal_earned
Definition: scoring.h:107
void process_post_sync_data_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:5969
int wl_drop(int from_bank, int from_list, int to_bank, int to_list, int ship_slot, int player_index, bool dont_play_sound)
void process_game_info_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:3769
vec3d dir_a
Definition: beam.h:44
ubyte unreliable_buffer[MAX_PACKET_SIZE]
Definition: multi.h:440
#define STATS_MISSION_CLASS_KILLS
Definition: multi.h:371
void weapon_hit_do_sound(object *hit_obj, weapon_info *wip, vec3d *hitpos, bool is_armed)
Definition: weapons.cpp:5834
#define NAME_LENGTH
Definition: globals.h:15
#define SF_SECONDARY_DUAL_FIRE
Definition: ship.h:459
int wep[MAX_SHIP_WEAPONS]
#define AIGF_DOCK_INDEXES_VALID
Definition: ai.h:114
void multi_endgame_init()
#define NG_MODE_RESTRICTED
Definition: multi.h:633
int num_debris_objects
Definition: model.h:741
#define MULTI_MSG_MAX_TEXT_LEN
Definition: multi_pmsg.h:34
#define WP_MISSILE
Definition: weapon.h:28
void process_wss_update_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:5467
void process_player_order_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:4307
#define AI_INFO_UPDATE
Definition: multi.h:205
#define REINFORCEMENT_AVAIL
Definition: multi.h:250
void multi_join_eval_pong(net_addr *addr, fix pong_time)
Definition: multiui.cpp:1562
#define SSF_NO_AGGREGATE
Definition: ship.h:294
void process_ship_depart_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:2790
void delete_player(int player_num, int kicked_reason)
Definition: multiutil.cpp:862
void mission_bring_in_support_ship(object *requester_objp)
#define MULTI_CONNECTED(np)
Definition: multi.h:136
#define MULTI_END_NOTIFY_KICKED_CANT_XFER
Definition: multi_endgame.h:39
#define ADD_VECTOR(d)
Definition: multimsgs.h:45
#define LEAVE_GAME
Definition: multi.h:227
#define ACCEPT
Definition: multi.h:213
int std_remove_player(net_player *p)
#define SHIP_KILL
Definition: multi.h:241
fix timer_get_fixed_seconds()
Definition: timer.cpp:116
void hud_squadmsg_repair_rearm(int toggle_state, object *objp)
player * Player
#define GET_USHORT(d)
Definition: multimsgs.h:49
#define OBSERVER_UPDATE
Definition: multi.h:235
void process_asteroid_info(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:6734
void send_ingame_nak(int state, net_player *p)
Definition: multimsgs.cpp:3785
void send_ship_status_packet(net_player *pl, button_info *bi, int id)
Definition: multimsgs.cpp:4180
#define ADD_ORIENT(d)
Definition: multimsgs.h:44
void send_player_stats_block_packet(net_player *pl, int stats_code, net_player *target, short offset)
Definition: multimsgs.cpp:6391
GLenum target
Definition: Glext.h:6872
#define MULTI_TS_NUM_SHIP_SLOTS
#define MULTI_SYNC_INGAME
Definition: multiui.h:140
uint type
Definition: psnet2.h:39
void multi_handle_state_special()
Definition: multiutil.cpp:2253
Definition: multi.h:385
#define MULTI_SYNC_POST_BRIEFING
Definition: multiui.h:139
#define MULTI_END_NOTIFY_KICKED_BAD_XFER
Definition: multi_endgame.h:38
void process_deny_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:5701
#define SW_STD_BAD
Definition: multi.h:364
void process_ingame_nak(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:3798
int current_wave
Definition: ship.h:1522
unsigned short ushort
Definition: pstypes.h:63
#define NETINFO_FLAG_RESPAWNING
Definition: multi.h:609
void psnet_rel_connect_to_server(PSNET_SOCKET *socket, net_addr *server_addr)
Definition: psnet2.cpp:1593
void multi_pause_pause()
#define STATS_ALLTIME
Definition: multi.h:368
unsigned int p_shots_hit
Definition: scoring.h:94
#define GET_UINT(d)
Definition: multimsgs.h:51
#define ACCEPT_INGAME
Definition: multi.h:325
void process_netplayer_slot_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:4046
#define STATS_ALLTIME_KILLS
Definition: multi.h:372
void ship_do_cargo_hidden(ship *shipp, int from_network)
Definition: ship.cpp:16190
int status[NUM_BUTTON_FIELDS]
Definition: keycontrol.h:30
void ship_hit_kill(object *ship_objp, object *other_obj, float percent_killed, int self_destruct)
Definition: shiphit.cpp:1542
ship_obj Ship_obj_list
Definition: ship.cpp:162
object * shooter
Definition: beam.h:58
#define JOIN_DENY_JR_TEMP_CLOSED
Definition: multi.h:293
#define NETGAME_STATE_HOST_SETUP
Definition: multi.h:673
int ship_info_index
Definition: ship.h:539
#define NETPLAYER_STATE_WSS_ACK
Definition: multi.h:698
void send_countermeasure_fired_packet(object *objp, int cmeasure_count, int rand_val)
Definition: multimsgs.cpp:3162
GLfloat GLfloat p
Definition: Glext.h:8373
int HEADER_LENGTH
Definition: multi.cpp:106
unsigned int p_bonehead_hits
Definition: scoring.h:97
void send_pong(net_addr *addr)
Definition: multimsgs.cpp:3538
#define MULTIPLAYER_MASTER
Definition: multi.h:130
#define DEBRIEF_INFO
Definition: multi.h:262
#define SELF_DESTRUCT
Definition: multi.h:210
struct _cl_event * event
Definition: Glext.h:7296
#define BYTES_SENT
Definition: multi.h:252
SCP_vector< ship_info > Ship_info
Definition: ship.cpp:164
#define LOCATION
Definition: pstypes.h:245
#define NETPLAYER_STATE_POST_DATA_ACK
Definition: multi.h:697
void ai_do_objects_undocked_stuff(object *docker, object *dockee)
Definition: aicode.cpp:3054
#define NETPLAYER_STATE_INGAME_SHIP_SELECT
Definition: multi.h:690
#define MULTI_PAUSE_REQUEST
Definition: multi.h:219
#define SIF_FIGHTER
Definition: ship.h:885
void fs2netd_send_game_request()
GLenum GLsizei GLenum GLenum const GLvoid * data
Definition: Gl.h:1509
int bank
Definition: beam.h:69
void multi_player_ships_available(int *team_0, int *team_1)
Definition: multiutil.cpp:2711
void send_accept_player_data(net_player *npp, int is_ingame)
Definition: multimsgs.cpp:1196
#define WIF_HOMING
Definition: weapon.h:129
#define CHANGE_AI_CLASS
Definition: multi.h:269
int Multi_current_file_length
Definition: multi.cpp:151
#define MLO_FLAG_LOCAL_BROADCAST
ubyte addr[6]
Definition: multi.h:388
SCP_vector< float > shield_quadrant
Definition: object.h:159
#define APD_NEXT
Definition: multi.h:331
int multi_create_player(int net_player_num, player *pl, const char *name, net_addr *addr, int ship_class, short id)
Definition: multiutil.cpp:728
#define OF_SHOULD_BE_DEAD
Definition: object.h:106
union ai_goal::@0 docker
char mission_desc[MISSION_DESC_LENGTH]
Definition: missionparse.h:137
short id
Definition: multi.h:390
void process_emp_effect(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:7431
void shipfx_warpout_start(object *objp)
Definition: shipfx.cpp:794
hull_check pos
Definition: lua.cpp:5050
#define DEBRIS_UPDATE_UPDATE
Definition: multi.h:315
void multi_campaign_start(char *filename)
Definition: missionlog.h:47
int Game_skill_level
Definition: fredstubs.cpp:170
char callsign[CALLSIGN_LEN+1]
Definition: multi.h:571
void send_weapon_detonate_packet(object *objp)
Definition: multimsgs.cpp:8229
#define MULTI_MSG_TARGET
Definition: multi_pmsg.h:30
#define PONG
Definition: multi.h:245
wss_unit Wss_slots_teams[MAX_TVT_TEAMS][MAX_WSS_SLOTS]
object * multi_get_network_object(ushort net_signature)
Definition: multiutil.cpp:220
#define MAX_TVT_TEAMS
Definition: globals.h:57
void change_ship_type(int n, int ship_type, int by_sexp)
Definition: ship.cpp:9983
float vm_vec_dot(const vec3d *v0, const vec3d *v1)
Definition: vecmat.cpp:312
void process_accept_player_data(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:1269
#define MULTI_END_NOTIFY_KICKED
Definition: multi_endgame.h:33
GLenum GLuint GLenum GLsizei length
Definition: Glext.h:5156
float accuracy
Definition: beam.h:61
void send_asteroid_create(object *new_objp, object *parent_objp, int asteroid_type, vec3d *relvec)
Definition: multimsgs.cpp:6663
void asteroid_hit(object *pasteroid_obj, object *other_obj, vec3d *hitpos, float damage)
Definition: asteroid.cpp:1368
void process_change_iff_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:7504
#define STATS_DOGFIGHT_KILLS
Definition: multi.h:370
active_game * multi_update_active_games(active_game *ag)
Definition: multiutil.cpp:1649
void multi_get_mission_checksum(const char *filename)
Definition: multiutil.cpp:2921
GLint GLsizei count
Definition: Gl.h:1491
GLsizei GLsizei GLchar * source
Definition: Glext.h:5625
void send_homing_weapon_info(int weapon_num)
Definition: multimsgs.cpp:7312
#define NETGAME_STATE_ENDGAME
Definition: multi.h:671
#define WEAPON_OR_AMMO_CHANGED
Definition: multi.h:273
void send_mission_log_packet(int num)
Definition: multimsgs.cpp:3348
int game_get_default_skill_level()
Definition: fredstubs.cpp:190
void multi_apply_ship_status(net_player *p, button_info *bi, int locally)
Definition: multiutil.cpp:1212
#define UPDATE_DESCRIPT
Definition: multi.h:260
GLenum GLsizei len
Definition: Glext.h:6283
void ship_self_destruct(object *objp)
Definition: shiphit.cpp:1697
object * Player_obj
Definition: object.cpp:56
int killer_weapon_index
Definition: player.h:182
int ship_index
Definition: multi.h:450
#define GET_SHORT(d)
Definition: multimsgs.h:48
#define ACK_FILE_ACCEPTED
Definition: multi.h:281
void send_debrief_info(int stage_count[], int *stages[])
Definition: multimsgs.cpp:7260
ushort debris_net_sig
Definition: ship.h:800
int Num_reinforcements
Definition: ship.cpp:121
Definition: ai.h:134
void multi_jw_handle_join(net_player *pl)
Definition: multiui.cpp:7167
#define AI_GOAL_REARM_REPAIR
Definition: aigoals.h:49
#define SF_DYING
Definition: ship.h:447
int temp
Definition: lua.cpp:4996
void send_change_iff_color_packet(ushort net_signature, int observer_team, int observed_team, int alternate_iff_color)
Definition: multimsgs.cpp:7523
int ship_index[MAX_SHIPS_PER_WING]
Definition: ship.h:1531
void add_shield_point_multi(int objnum, int tri_num, vec3d *hit_pos)
Definition: shield.cpp:802
#define GAME_UPDATE
Definition: multi.h:256
net_addr Psnet_my_addr
Definition: psnet2.cpp:52
polymodel * pm
Definition: lua.cpp:1598
int m_player_deaths
Definition: scoring.h:124
#define KICK_REASON_INGAME_ENDED
Definition: multi_kick.h:26
void multi_campaign_next_mission()
void multi_set_network_signature(ushort signature, int what_kind)
Definition: multiutil.cpp:198
void HUD_printf(const char *format,...)
Definition: hudmessage.cpp:527
void process_weapon_detonate_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:8252
#define APD_END_PACKET
Definition: multi.h:332
#define MISSION_LOG_ENTRY
Definition: multi.h:259
#define AG_FLAG_CONNECTION_BIT
Definition: multi.h:539
#define GET_INT(d)
Definition: multimsgs.h:50
#define WSS_SLOTS_DATA
Definition: multi.h:186
#define REPAIR_INFO_BEGIN
Definition: multi.h:302
#define JOIN_DENY_JR_BANNED
Definition: multi.h:294
#define OBJ_NONE
Definition: object.h:31
int ship_name_lookup(const char *name, int inc_players)
Definition: ship.cpp:12900
void ship_do_cap_subsys_cargo_hidden(ship *shipp, ship_subsys *subsys, int from_network)
Definition: ship.cpp:16210
server_item * Game_server_head
Definition: multi.cpp:118
void process_accept_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:1553
int parse_wing_create_ships(wing *wingp, int num_to_create, int force, int specific_instance)
Tries to create a wing of ships.
int multi_can_message(net_player *p)
Definition: multiutil.cpp:1848
void hud_update_reticle(player *pp)
Definition: hudreticle.cpp:960
void process_player_pain_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:8429
#define ABORT_REARM_REPAIR_ITEM
Definition: hudsquadmsg.h:50
int std_connect_set_connect_count()
uint flags
Definition: object.h:151
void process_jump_into_mission_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:4774
#define SUBSYSTEM_MAX
Definition: model.h:64
#define BEAM_FIRED
Definition: multi.h:223
void gamesnd_play_iface(int n)
Definition: gamesnd.cpp:260
void process_cargo_revealed_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:2849
mission The_mission
int bonehead_kills
Definition: scoring.h:99
#define NETINFO_FLAG_ACCEPT_OBSERVER
Definition: multi.h:616
#define JOIN_DENY_JR_RANK_HIGH
Definition: multi.h:289
#define PLAYER_SETTINGS
Definition: multi.h:185
#define AI_GOAL_DESTROY_SUBSYSTEM
Definition: aigoals.h:34
void process_wss_slots_data_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:6234
#define NOTIFY_NEW_PLAYER
Definition: multi.h:215
int cl_bytes_recvd
Definition: multi.h:481
void multi_io_send_buffered_packets()
Definition: multimsgs.cpp:544
#define SF_TRIGGER_DOWN
Definition: ship.h:462
net_addr Multi_restr_addr
Definition: multi.cpp:137
float h
Definition: pstypes.h:111
#define AG_FLAG_PASSWD
Definition: multi.h:529
void multi_ping_eval_pong(ping_struct *ps)
Definition: multi_ping.cpp:57
void emp_start_ship(object *ship_objp, float intensity, float time)
Definition: emp.cpp:264
void multi_ts_sync_interface()
#define PING
Definition: multi.h:244
#define ACCEPT_OBSERVER
Definition: multi.h:327
void send_wss_request_packet(short player_id, int from_slot, int from_index, int to_slot, int to_index, int wl_ship_slot, int ship_class, int mode, net_player *p)
Definition: multimsgs.cpp:5360
GLenum const GLvoid * addr
Definition: Glext.h:9092
char type
Definition: object.h:146
#define NETGAME_STATE_FORMING
Definition: multi.h:664
void send_leave_game_packet(short player_id, int kicked_reason, net_player *target)
Definition: multimsgs.cpp:1680
void process_mission_goal_info_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:5588
void process_player_stats_block_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:6530
#define INGAME_JOIN_FLAG_PICK_SHIP
Definition: multi_ingame.h:74
void multi_common_add_text(const char *str, int auto_scroll)
Definition: multiui.cpp:167
void process_join_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:903
#define HUD_MSG
Definition: multi.h:226
#define SF_FROM_PLAYER_WING
Definition: ship.h:457
int multi_find_player_by_object(object *objp)
Definition: multiutil.cpp:500
#define wp(p)
Definition: modelsinc.h:69
int parse_create_object(p_object *pobjp)
#define MULTI_IS_TRACKER_GAME
Definition: multi.h:146
#define WSS_SHIP_SELECT
Definition: multi.h:322
int m_kill_count
Definition: scoring.h:114
char title[NAME_LENGTH+1]
Definition: multi.h:550
#define WING_CREATE
Definition: multi.h:242
int Num_medals
Definition: medals.cpp:30
net_player Net_players[MAX_PLAYERS]
Definition: multi.cpp:93
void multi_common_set_text(const char *str, int auto_scroll)
Definition: multiui.cpp:148
int sv_bytes_sent
Definition: multi.h:477
short port
Definition: psnet2.h:42
int sv_last_pl
Definition: multi.h:478
int max_players
Definition: multi.h:497
int index
Definition: ai.h:154
#define MISSION_REQUEST
Definition: multi.h:216
unsigned int ms_shots_hit
Definition: scoring.h:120
void gameseq_post_event(int event)
GLenum GLint GLuint mask
Definition: Glext.h:5605
#define MLO_FLAG_FLUSH_CACHE
#define GET_STRING(s)
Definition: multimsgs.h:53
#define JOIN
Definition: multi.h:212
int shield_recharge_index
Definition: ship.h:637
#define AG_FLAG_CAMPAIGN
Definition: multi.h:531
#define GM_CAMPAIGN_MODE
Definition: systemvars.h:29
unsigned int s_shots_hit
Definition: scoring.h:95
#define JOIN_DENY_JR_CLOSED
Definition: multi.h:288
void process_file_sig_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:4432
#define MULTI_QUERY_RESTR_STAMP
Definition: multi.h:779
net_player * server
Definition: multi.h:505
#define COUNTERMEASURE_NEW
Definition: multi.h:196
sound to indicate voice is about to start
Definition: gamesnd.h:132
shield_tri * tris
Definition: model.h:570
void weapon_detonate(object *objp)
Definition: weapons.cpp:6450
#define CLIENT_REPAIR_INFO
Definition: multi.h:166
void send_firing_info_packet()
Definition: multimsgs.cpp:5520
multi_global_options Multi_options_g
int flags
Definition: ai.h:139
int flags
Definition: multi.h:495
#define AI_UPDATE_ORDERS
Definition: multi.h:344
char ship_name[NAME_LENGTH]
Definition: ship.h:604
#define JOIN_DENY_JR_TYPE
Definition: multi.h:299
void debrief_set_multi_clients(int stage_count, int active_stages[])
unsigned int s_bonehead_hits
Definition: scoring.h:98
void send_post_sync_data_packet(net_player *p, int std_request)
Definition: multimsgs.cpp:5770
void process_file_sig_request(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:4461
#define JOIN_DENY_JR_DUP
Definition: multi.h:291
int multi_find_player_by_net_signature(ushort net_signature)
Definition: multiutil.cpp:537
void send_lightning_packet(int bolt_type_internal, vec3d *start, vec3d *strike)
Definition: multimsgs.cpp:8474
#define NETPLAYER_STATE_STD_HOST_SETUP
Definition: multi.h:693
#define JOIN_QUERY_RESTRICTED
Definition: multi.h:298
void send_mission_list_request(int what)
Definition: multimsgs.cpp:3550
#define NET_PLAYER_NUM(np)
Definition: multi.h:126
void send_deny_packet(net_addr *addr, int code)
Definition: multimsgs.cpp:5687
_fs_time_t last_backup
Definition: scoring.h:104
#define DEBRIS_UPDATE
Definition: multi.h:173
multi_local_options options
Definition: multi.h:452
#define COUNTERMEASURE_SUCCESS
Definition: multi.h:249
void send_subsystem_cargo_hidden_packet(ship *shipp, int index)
Definition: multimsgs.cpp:4626
void process_netgame_descript_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:2193
int current_target_is_locked
Definition: ai.h:490
void send_endgame_packet(net_player *pl)
Definition: multimsgs.cpp:3855
void send_player_pain_packet(net_player *pl, int weapon_info_index, float damage, vec3d *force, vec3d *hitpos, int quadrant_num)
Definition: multimsgs.cpp:8397
#define MAX_DEBRIEF_STAGES
#define NG_TYPE_DOGFIGHT
Definition: multi.h:651
#define REPAIR_INFO_WARP_REMOVE
Definition: multi.h:309
scoring_struct stats
Definition: player.h:127
void process_mission_log_packet(ubyte *data, header *hinfo)
Definition: multimsgs.cpp:3376
#define AI_UPDATE_UNDOCK
Definition: multi.h:343
ubyte comp_version
Definition: multi.h:554
void send_new_player_packet(int new_player_num, net_player *target)
Definition: multimsgs.cpp:1031
#define MULTI_END_ERROR_CONNECT_FAIL
Definition: multi_endgame.h:45
#define SEXP
Definition: multi.h:274
#define strcpy_s(...)
Definition: safe_strings.h:67
void ship_subsystem_set_new_ai_class(int ship_num, char *subsystem, int new_ai_class)
Definition: ship.cpp:17380
#define GAME_QUERY
Definition: multi.h:255
#define ASTEROID_INFO
Definition: multi.h:179
vec3d pos
Definition: missionparse.h:349
#define SHIELD_EXPLOSION
Definition: multi.h:168
float field_of_fire
Definition: weapon.h:494
#define FILE_SIG_REQUEST
Definition: multi.h:163
void send_file_sig_packet(ushort sum_sig, int length_sig)
Definition: multimsgs.cpp:4420
#define NG_FLAG_INGAME_JOINING
Definition: multi.h:640
#define CLIENT_UPDATE
Definition: multi.h:193
int multi_can_end_mission(net_player *p)
Definition: multiutil.cpp:1897