// M_INSPAK.C - Geoff Coovert 8/28/98 // Allows multiplayer messages to get to their destination and // interpreted even if dropped. #ifdef NETWORK #include #include #include #include #include "game.h" #include "modem.h" #include "multi.h" #include "network.h" #include "hudmsg.h" #include "ipx.h" #include "netpkt.h" #include "vers_id.h" //added on 03/05/99 Matt Mueller #include "mono.h" //end addition mekh_packet_stats mekh_acks[MEKH_PACKET_MEM]; //Info for packets that need an ack to come back mekh_ackedpacket_history mekh_packet_history[MEKH_PACKET_MEM]; //Remember last regdpackets we've gotten in case ack is late/dropped //and the packet gets resent, so we can ignore it. fix MEKH_RESEND_DELAY = F1_0; int ackdebugmsg=0; void mekh_send_direct_packet(ubyte *buffer, int len, int plnum) { //edited 03/04/99 Matt Mueller - new DIRECTDATA sending mode, and modem code. if (/*(Players[plnum].connected) && */(plnum!=Player_num)) { // mprintf((0,"mekh_send_direct_packet %i len=%i (%i)\n",buffer[0],len,plnum)); // mprintf((0,"*\n")); if ((Game_mode & GM_SERIAL) || (Game_mode & GM_MODEM)){ mprintf((0,"sending com data, len=%i (%i)\n",len,buffer[0])); com_send_data(buffer, len, 0); //this will be needed for pings and return; //req'd packets and such to work on serial connects. } //edited 03/05/99 Matt Mueller - quick hack for multi_fire.. maybe should have a force_long flag instead? if (Net_D1xPlayer[plnum].iver>=D1X_DIRECTDATA_IVER && buffer[0]!=MULTI_FIRE) //end edit -MM { mprintf((0,"sending DIRECTDATA to %i, len=%i (%i)\n",plnum,len,buffer[0])); // memset(out_buffer, 0, IPX_MAX_DATA_SIZE);//is this really needed? out_buffer[0]=PID_DIRECTDATA; memcpy(&(out_buffer[1]), buffer, len); ipx_send_packet_data( out_buffer, len+1, Netgame.players[plnum].server, Netgame.players[plnum].node, Players[plnum].net_address); } else{ mprintf((0,"sending concat to %i, len=%i (%i)\n",plnum,len,buffer[0])); mekh_prep_concat_send(buffer, len, Netgame.players[plnum].server, Netgame.players[plnum].node, Players[plnum].net_address, Net_D1xPlayer[plnum].shp); } }//else // mprintf((0,"&\n")); //end edit -MM // multi_send_data(buffer, len, 1); } //added 03/04/99 Matt Mueller void mekh_send_direct_broadcast(ubyte *buffer, int len) { int plnum; // mprintf((0,"mekh_send_direct_broadcast %i len=%i\n",buffer[0],len)); if (mekh_insured_packets[buffer[0]]) mekh_send_reg_data_needver(int32_greaterorequal,-1,buffer,len); else for (plnum=0;plnum=ver) mekh_send_direct_packet(buf1,len1,plnum); if (mekh_insured_packets[buf2[0]]) mekh_send_reg_data_needver(int32_lessthan,ver,buf2,len2); else for (plnum=0;plnum -1) { for(i=found;i0; i--) { mekh_acks[i] = mekh_acks[i-1]; //Move up } else mprintf((0,"first ack empty, so using that\n")); mekh_acks[0].packet_type = buf[0]; mekh_acks[0].timestamp = GameTime; memcpy(mekh_acks[0].packet_contents, buf, len); mekh_acks[0].len = len; return tmp; } //end addition -MM //added 03/07/99 Matt Mueller - send regdata to a single player void mekh_send_direct_reg_data(unsigned char *buf, int len,int plnum) { if (Players[plnum].connected && plnum!=Player_num/* && compare(Net_D1xPlayer[i].iver,ver)*/) { int i,tmp; ubyte packet[MAX_MULTI_MESSAGE_LEN+4]; tmp=mekh_prepare_packet(packet,buf,len); for (i=0;i= 0; tmp--) { if ((mekh_packet_history[tmp].player_num == p_info.player_num) && (mekh_packet_history[tmp].timestamp == p_info.timestamp) && (mekh_packet_history[tmp].packet_type == p_info.packet_type)) { mekh_send_ack(p_info); if(ackdebugmsg) hud_message(MSGC_DEBUG, "Ignored AR for %d of %d", (int)p_info.timestamp, p_info.packet_type); return; //We've already gotten this packet, so ack it and abort processing //Ack must have been late or dropped } if (tmp > 0) mekh_packet_history[tmp] = mekh_packet_history[tmp-1]; //Move each history level up } mekh_packet_history[0] = p_info; //Insert the newest at the top if(ackdebugmsg) hud_message(MSGC_MULTI_INFO, "Ackreq for %d of %d from %s(%i)", (int)p_info.timestamp, p_info.packet_type, Players[p_info.player_num].callsign,p_info.player_num); // hud_message(MSGC_MULTI_INFO, "Size should be %d, is %d", message_length[p_info.packet_type], len); //--killed-- memcpy(packet, buf+7, len); //wasteful -MM //Copy the contents of the real message into 'packet' multi_process_data(/*packet*/buf+7, len);//aaaah, much better -MM //end edit -MM //Feed the message to the rest of Descent's incoming protocols mekh_send_ack(p_info); //And toss an ack at the player that sent it. Tada. } //====================================================== //Checks if any acks are waiting, if so, sends the oldest to any players //that haven't acked yet, assuming they're still connected. //====================================================== void mekh_resend_needack() { int tmp, i, pos, len; fix timestamp; ubyte packet[MAX_MULTI_MESSAGE_LEN+4]; pos = -1; for(i=0; irender_type; loc++; out_buffer[loc] = Current_level_num; loc++; create_shortpos((shortpos *)(out_buffer + loc), pl_obj); loc += 9+2*3+2+2*3; // go past shortpos structure *(ushort *)(out_buffer + loc) = len; loc += 2; memcpy(out_buffer + loc, extradata, len); loc += len; } else if (short_packet == 2) { loc = 0; out_buffer[loc] = PID_PDATA_SHORT2; loc++; out_buffer[loc] = MySyncPack.numpackets & 255; loc++; create_shortpos((shortpos *)(out_buffer + loc), pl_obj); loc += 9+2*3+2+2*3; // go past shortpos structure tmpus = len | (Player_num << 12) | (pl_obj->render_type << 15); *(ushort *)(out_buffer + loc) = tmpus; loc += 2; out_buffer[loc] = Current_level_num; loc++; memcpy(out_buffer + loc, extradata, len); loc += len; } else { out_buffer[0] = PID_PDATA; loc++; loc += 3; // skip three for pad byte tmpi = swapint(MySyncPack.numpackets); memcpy(&(out_buffer[loc]), &tmpi, 4); loc += 4; tmpi = swapint((int)pl_obj->pos.x); memcpy(&(out_buffer[loc]), &tmpi, 4); loc += 4; tmpi = swapint((int)pl_obj->pos.y); memcpy(&(out_buffer[loc]), &tmpi, 4); loc += 4; tmpi = swapint((int)pl_obj->pos.z); memcpy(&(out_buffer[loc]), &tmpi, 4); loc += 4; tmpi = swapint((int)pl_obj->orient.rvec.x); memcpy(&(out_buffer[loc]), &tmpi, 4); loc += 4; tmpi = swapint((int)pl_obj->orient.rvec.y); memcpy(&(out_buffer[loc]), &tmpi, 4); loc += 4; tmpi = swapint((int)pl_obj->orient.rvec.z); memcpy(&(out_buffer[loc]), &tmpi, 4); loc += 4; tmpi = swapint((int)pl_obj->orient.uvec.x); memcpy(&(out_buffer[loc]), &tmpi, 4); loc += 4; tmpi = swapint((int)pl_obj->orient.uvec.y); memcpy(&(out_buffer[loc]), &tmpi, 4); loc += 4; tmpi = swapint((int)pl_obj->orient.uvec.z); memcpy(&(out_buffer[loc]), &tmpi, 4); loc += 4; tmpi = swapint((int)pl_obj->orient.fvec.x); memcpy(&(out_buffer[loc]), &tmpi, 4); loc += 4; tmpi = swapint((int)pl_obj->orient.fvec.y); memcpy(&(out_buffer[loc]), &tmpi, 4); loc += 4; tmpi = swapint((int)pl_obj->orient.fvec.z); memcpy(&(out_buffer[loc]), &tmpi, 4); loc += 4; tmpi = swapint((int)pl_obj->mtype.phys_info.velocity.x); memcpy(&(out_buffer[loc]), &tmpi, 4); loc += 4; tmpi = swapint((int)pl_obj->mtype.phys_info.velocity.y); memcpy(&(out_buffer[loc]), &tmpi, 4); loc += 4; tmpi = swapint((int)pl_obj->mtype.phys_info.velocity.z); memcpy(&(out_buffer[loc]), &tmpi, 4); loc += 4; tmpi = swapint((int)pl_obj->mtype.phys_info.rotvel.x); memcpy(&(out_buffer[loc]), &tmpi, 4); loc += 4; tmpi = swapint((int)pl_obj->mtype.phys_info.rotvel.y); memcpy(&(out_buffer[loc]), &tmpi, 4); loc += 4; tmpi = swapint((int)pl_obj->mtype.phys_info.rotvel.z); memcpy(&(out_buffer[loc]), &tmpi, 4); loc += 4; tmps = swapshort(pl_obj->segnum); memcpy(&(out_buffer[loc]), &tmps, 2); loc += 2; tmps = swapshort(len); memcpy(&(out_buffer[loc]), &tmps, 2); loc += 2; out_buffer[loc] = Player_num; loc++; out_buffer[loc] = pl_obj->render_type; loc++; out_buffer[loc] = Current_level_num; loc++; memcpy(&(out_buffer[loc]), extradata, len); loc += len; } ipx_send_packet_data( out_buffer, loc, server, node, address); } #endif