mirror of
https://github.com/scp-fs2open/fs2open.github.com.git
synced 2026-11-07 18:31:26 -10:00
Some streamlining and constifying of the readyroom popup list and associated functions. Followup to #5462.
421 lines
12 KiB
C++
421 lines
12 KiB
C++
/*
|
|
* Copyright (C) Volition, Inc. 1999. All rights reserved.
|
|
*
|
|
* All source code herein is the property of Volition, Inc. You may not sell
|
|
* or otherwise commercially exploit the source or things you created based on the
|
|
* source.
|
|
*
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include <ctime>
|
|
#include <cctype>
|
|
|
|
#include "network/multi.h"
|
|
#include "network/multi_data.h"
|
|
#include "network/multi_xfer.h"
|
|
#include "network/multiutil.h"
|
|
#include "playerman/player.h"
|
|
#include "cfile/cfile.h"
|
|
#include "globalincs/systemvars.h"
|
|
|
|
|
|
|
|
// -------------------------------------------------------------------------
|
|
// MULTI DATA DEFINES/VARS
|
|
//
|
|
|
|
#define MAX_MULTI_DATA 40
|
|
|
|
// player data struct
|
|
typedef struct np_data {
|
|
ushort player_id; // id of the player who sent the file
|
|
char filename[MAX_FILENAME_LEN+1]; // filename
|
|
ubyte status[MAX_PLAYERS]; // status for all players (0 == don't have it, 1 == have or sending, 2 == i sent it originally)
|
|
ubyte used; // in use or not
|
|
} np_data;
|
|
|
|
np_data Multi_data[MAX_MULTI_DATA];
|
|
|
|
// this doesn't travel off platform to don't _fs_time_t it
|
|
time_t Multi_data_time = 0;
|
|
|
|
|
|
// -------------------------------------------------------------------------
|
|
// MULTI DATA FORWARD DECLARATIONS
|
|
//
|
|
|
|
// is the given filename for a "multi data" file (pcx, wav, etc)
|
|
int multi_data_is_data(char *filename);
|
|
|
|
// get a free np_data slot
|
|
int multi_data_get_free();
|
|
|
|
// server side - add a new file
|
|
int multi_data_add_new(char *filename, int player_index);
|
|
|
|
// maybe try and reload player squad logo bitmaps
|
|
void multi_data_maybe_reload();
|
|
|
|
|
|
// -------------------------------------------------------------------------
|
|
// MULTI DATA FUNCTIONS
|
|
//
|
|
|
|
// reset the data xfer system
|
|
void multi_data_reset()
|
|
{
|
|
int idx;
|
|
|
|
// clear out all used bits
|
|
for(idx=0; idx<MAX_MULTI_DATA; idx++){
|
|
Multi_data[idx].used = 0;
|
|
}
|
|
}
|
|
|
|
// handle a player join (clear out lists of files, etc)
|
|
void multi_data_handle_join(int player_index)
|
|
{
|
|
int idx;
|
|
|
|
// clear out his status for all files
|
|
for(idx=0;idx<MAX_MULTI_DATA;idx++){
|
|
Multi_data[idx].status[player_index] = 0;
|
|
}
|
|
}
|
|
|
|
// handle a player drop (essentially the same as multi_data_handle_join)
|
|
void multi_data_handle_drop(int player_index)
|
|
{
|
|
int idx;
|
|
|
|
// mark all files he sent as being unused
|
|
for(idx=0;idx<MAX_MULTI_DATA;idx++){
|
|
if(Multi_data[idx].player_id == Net_players[player_index].player_id){
|
|
Multi_data[idx].used = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
// do all sync related data stuff (server-side only)
|
|
void multi_data_do()
|
|
{
|
|
int idx, p_idx;
|
|
|
|
// only do this once a second
|
|
if((time(NULL) - Multi_data_time) < 1){
|
|
return;
|
|
}
|
|
|
|
// maybe try and reload player squad logo bitmaps
|
|
multi_data_maybe_reload();
|
|
|
|
// reset the time
|
|
Multi_data_time = time(NULL);
|
|
|
|
// if I'm the server
|
|
if(Net_player && (Net_player->flags & NETINFO_FLAG_AM_MASTER)){
|
|
// for all valid files
|
|
for(idx=0; idx<MAX_MULTI_DATA; idx++){
|
|
// a valid file that isn't currently xferring (ie, anything we've got completely on our hard drive)
|
|
if(Multi_data[idx].used && (multi_xfer_lookup(Multi_data[idx].filename) < 0)){
|
|
// send it to all players who need it
|
|
for(p_idx=0; p_idx<MAX_PLAYERS; p_idx++){
|
|
// if he doesn't have it
|
|
if ( (Net_player != &Net_players[p_idx]) && MULTI_CONNECTED(Net_players[p_idx]) && (Net_players[p_idx].reliable_socket != PSNET_INVALID_SOCKET) && (Multi_data[idx].status[p_idx] == 0) ) {
|
|
// queue up the file to send to him, or at least try to
|
|
if(multi_xfer_send_file(Net_players[p_idx].reliable_socket, Multi_data[idx].filename, CF_TYPE_ANY, MULTI_XFER_FLAG_AUTODESTROY | MULTI_XFER_FLAG_QUEUE) < 0){
|
|
nprintf(("Network", "Failed to send data file! Trying again later...\n"));
|
|
} else {
|
|
// mark his status
|
|
Multi_data[idx].status[p_idx] = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// handle an incoming xfer request from the xfer system
|
|
void multi_data_handle_incoming(int handle)
|
|
{
|
|
int player_index = -1;
|
|
PSNET_SOCKET_RELIABLE sock;
|
|
char *fname;
|
|
|
|
// get the player who is sending us this file
|
|
sock = multi_xfer_get_sock(handle);
|
|
player_index = find_player_socket(sock);
|
|
|
|
// get the filename of the file
|
|
fname = multi_xfer_get_filename(handle);
|
|
if(fname == NULL){
|
|
nprintf(("Network", "Could not get file xfer filename! wacky...!\n"));
|
|
|
|
// kill the stream
|
|
multi_xfer_xor_flags(handle, MULTI_XFER_FLAG_REJECT);
|
|
return;
|
|
}
|
|
|
|
// if this is not a valid data file
|
|
if(!multi_data_is_data(fname)){
|
|
nprintf(("Network", "Not accepting xfer request because its not a valid data file!\n"));
|
|
|
|
// kill the stream
|
|
multi_xfer_xor_flags(handle, MULTI_XFER_FLAG_REJECT);
|
|
return;
|
|
}
|
|
|
|
// if we already have a copy of this file, abort the xfer
|
|
// Does file exist in \multidata?
|
|
if (cf_exists(fname, CF_TYPE_MULTI_CACHE)) {
|
|
nprintf(("Network", "Not accepting file xfer because a duplicate exists!\n"));
|
|
|
|
// kill the stream
|
|
multi_xfer_xor_flags(handle, MULTI_XFER_FLAG_REJECT);
|
|
|
|
// if we're the server, we still need to add it to the list though
|
|
if((Net_player->flags & NETINFO_FLAG_AM_MASTER) && (player_index >= 0)){
|
|
multi_data_add_new(fname, player_index);
|
|
}
|
|
return;
|
|
}
|
|
|
|
// if I'm the server of the game, do stuff a little differently
|
|
if(Net_player->flags & NETINFO_FLAG_AM_MASTER){
|
|
if(player_index == -1){
|
|
nprintf(("Network", "Could not find player for incoming player data stream!\n"));
|
|
|
|
// kill the stream
|
|
multi_xfer_xor_flags(handle, MULTI_XFER_FLAG_REJECT);
|
|
return;
|
|
}
|
|
|
|
// attempt to add the file
|
|
if(!multi_data_add_new(fname, player_index)){
|
|
// kill the stream
|
|
multi_xfer_xor_flags(handle, MULTI_XFER_FLAG_REJECT);
|
|
return;
|
|
} else {
|
|
// force the file to go into the multi cache directory
|
|
multi_xfer_handle_force_dir(handle, CF_TYPE_MULTI_CACHE);
|
|
|
|
// mark it as autodestroy
|
|
multi_xfer_xor_flags(handle, MULTI_XFER_FLAG_AUTODESTROY);
|
|
}
|
|
}
|
|
// if i'm a client, this is an incoming file from the server
|
|
else {
|
|
// if i'm not accepting pilot pics, abort
|
|
if(!(Net_player->p_info.options.flags & MLO_FLAG_ACCEPT_PIX)){
|
|
nprintf(("Network", "Client not accepting files because we don't want 'em!\n"));
|
|
|
|
// kill the stream
|
|
multi_xfer_xor_flags(handle, MULTI_XFER_FLAG_REJECT);
|
|
return;
|
|
}
|
|
|
|
// set the xfer handle to autodestroy itself since we don't really want to have to manage all incoming pics
|
|
multi_xfer_xor_flags(handle, MULTI_XFER_FLAG_AUTODESTROY);
|
|
|
|
// force the file to go into the multi cache directory
|
|
multi_xfer_handle_force_dir(handle, CF_TYPE_MULTI_CACHE);
|
|
|
|
// begin receiving the file
|
|
nprintf(("Network", "Client receiving xfer handle %d\n",handle));
|
|
}
|
|
}
|
|
|
|
// send all my files as necessary
|
|
void multi_data_send_my_junk()
|
|
{
|
|
int bmap, w, h;
|
|
int ok_to_send = 1;
|
|
|
|
// pilot pic --------------------------------------------------------------
|
|
|
|
// verify that my pilot pic is valid
|
|
if(strlen(Net_player->m_player->image_filename)){
|
|
bmap = bm_load(Net_player->m_player->image_filename);
|
|
if(bmap == -1){
|
|
ok_to_send = 0;
|
|
}
|
|
|
|
// verify image dimensions
|
|
if(ok_to_send){
|
|
w = -1;
|
|
h = -1;
|
|
bm_get_info(bmap,&w,&h);
|
|
|
|
// release the bitmap
|
|
bm_release(bmap);
|
|
bmap = -1;
|
|
|
|
// if the dimensions are invalid, kill the filename
|
|
if((w != PLAYER_PILOT_PIC_W) || (h != PLAYER_PILOT_PIC_H)){
|
|
ok_to_send = 0;
|
|
}
|
|
}
|
|
} else {
|
|
ok_to_send = 0;
|
|
}
|
|
|
|
if(ok_to_send){
|
|
auto with_ext = cf_add_ext(Net_player->m_player->image_filename, NOX(".pcx"));
|
|
if(with_ext != NULL){
|
|
strcpy_s(Net_player->m_player->image_filename, with_ext);
|
|
}
|
|
|
|
// host should put his own pic file in the list now
|
|
if((Net_player->flags & NETINFO_FLAG_AM_MASTER) && !(Game_mode & GM_STANDALONE_SERVER) && (Net_player->m_player->image_filename[0] != '\0')){
|
|
multi_data_add_new(Net_player->m_player->image_filename, MY_NET_PLAYER_NUM);
|
|
}
|
|
// otherwise clients should just queue up a send
|
|
else {
|
|
// add a file extension if necessary
|
|
multi_xfer_send_file(Net_player->reliable_socket, Net_player->m_player->image_filename, CF_TYPE_ANY, MULTI_XFER_FLAG_AUTODESTROY | MULTI_XFER_FLAG_QUEUE);
|
|
}
|
|
}
|
|
|
|
|
|
// squad logo --------------------------------------------------------------
|
|
|
|
// verify that my pilot pic is valid
|
|
ok_to_send = 1;
|
|
if(strlen(Net_player->m_player->m_squad_filename)){
|
|
bmap = bm_load(Net_player->m_player->m_squad_filename);
|
|
if(bmap == -1){
|
|
ok_to_send = 0;
|
|
}
|
|
|
|
if(ok_to_send){
|
|
// verify image dimensions
|
|
w = -1;
|
|
h = -1;
|
|
bm_get_info(bmap,&w,&h);
|
|
|
|
// release the bitmap
|
|
bm_release(bmap);
|
|
bmap = -1;
|
|
|
|
// if the dimensions are invalid, kill the filename
|
|
if((w != PLAYER_SQUAD_PIC_W) || (h != PLAYER_SQUAD_PIC_H)){
|
|
ok_to_send = 0;
|
|
}
|
|
}
|
|
} else {
|
|
ok_to_send = 0;
|
|
}
|
|
|
|
if(ok_to_send){
|
|
auto with_ext = cf_add_ext(Net_player->m_player->m_squad_filename, NOX(".pcx"));
|
|
if(with_ext != NULL){
|
|
strcpy_s(Net_player->m_player->m_squad_filename,with_ext);
|
|
}
|
|
|
|
// host should put his own pic file in the list now
|
|
if((Net_player->flags & NETINFO_FLAG_AM_MASTER) && !(Game_mode & GM_STANDALONE_SERVER) && (Net_player->m_player->m_squad_filename[0] != '\0')){
|
|
multi_data_add_new(Net_player->m_player->m_squad_filename, MY_NET_PLAYER_NUM);
|
|
}
|
|
// otherwise clients should just queue up a send
|
|
else {
|
|
// add a file extension if necessary
|
|
multi_xfer_send_file(Net_player->reliable_socket, Net_player->m_player->m_squad_filename, CF_TYPE_ANY, MULTI_XFER_FLAG_AUTODESTROY | MULTI_XFER_FLAG_QUEUE);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
// -------------------------------------------------------------------------
|
|
// MULTI DATA FORWARD DECLARATIONS
|
|
//
|
|
|
|
// is the give file xfer handle for a "multi data" file (pcx, wav, etc)
|
|
int multi_data_is_data(char *filename)
|
|
{
|
|
Assert(filename != NULL);
|
|
|
|
// some kind of error
|
|
if(filename == NULL){
|
|
return 0;
|
|
}
|
|
|
|
// convert to lowercase
|
|
SCP_tolower(filename);
|
|
|
|
// check to see if the extension is .pcx
|
|
if(strstr(filename, NOX(".pcx"))){
|
|
return 1;
|
|
}
|
|
|
|
// not a data file
|
|
return 0;
|
|
}
|
|
|
|
// get a free np_data slot
|
|
int multi_data_get_free()
|
|
{
|
|
int idx;
|
|
|
|
// find a free slot
|
|
for(idx=0; idx<MAX_MULTI_DATA; idx++){
|
|
if(!Multi_data[idx].used){
|
|
return idx;
|
|
}
|
|
}
|
|
|
|
// couldn't find one
|
|
return -1;
|
|
}
|
|
|
|
// server side - add a new file. return 1 on success
|
|
int multi_data_add_new(char *filename, int player_index)
|
|
{
|
|
int slot;
|
|
|
|
// try and get a free slot
|
|
slot = multi_data_get_free();
|
|
if(slot < 0){
|
|
nprintf(("Network", "Could not get free np_data slot! yikes!\n"));
|
|
return 0;
|
|
}
|
|
|
|
// if the netgame isn't flagged as accepting data files
|
|
if(!(Netgame.options.flags & MSO_FLAG_ACCEPT_PIX)){
|
|
nprintf(("Network", "Server not accepting pilot pic because we don't want 'em!\n"));
|
|
return 0;
|
|
}
|
|
|
|
// assign the data
|
|
memset(&Multi_data[slot], 0, sizeof(np_data)); // clear the slot out
|
|
strcpy_s(Multi_data[slot].filename, filename); // copy the filename
|
|
Multi_data[slot].used = 1; // set it as being in use
|
|
Multi_data[slot].player_id = Net_players[player_index].player_id; // player id of who's sending the file
|
|
Multi_data[slot].status[player_index] = 2; // mark his status appropriately
|
|
|
|
// success
|
|
return 1;
|
|
}
|
|
|
|
// maybe try and reload player squad logo bitmaps
|
|
void multi_data_maybe_reload()
|
|
{
|
|
int idx;
|
|
|
|
// go through all connected and try to reload their images if necessary
|
|
for(idx=0; idx<MAX_PLAYERS; idx++){
|
|
if(MULTI_CONNECTED(Net_players[idx]) && strlen(Net_players[idx].m_player->m_squad_filename) && (Net_players[idx].m_player->insignia_texture == -1)){
|
|
Net_players[idx].m_player->insignia_texture = bm_load_duplicate(Net_players[idx].m_player->m_squad_filename);
|
|
|
|
// if the bitmap loaded properly, lock it as a transparent texture
|
|
if(Net_players[idx].m_player->insignia_texture != -1){
|
|
bm_lock(Net_players[idx].m_player->insignia_texture, 16, BMP_TEX_XPARENT);
|
|
bm_unlock(Net_players[idx].m_player->insignia_texture);
|
|
}
|
|
}
|
|
}
|
|
}
|