frontport r8667
"Rewrite the stupid file transfer routines. * It will now only send the file to the person that needs it. * Adds abort code to the file routines as well, and also tries to detect when the Host is using a malformed filename to host a map. * Make sure user can't hit the 'ready' button when the map transfer is ongoing. * Get rid of the silly delays (Much faster transfers) NOTE: we are still capped by fps. fixes ticket:1128 fixes ticket:1127 refs ticket:215 (still can't transfer 'map packs')" git-svn-id: https://warzone2100.svn.sourceforge.net/svnroot/warzone2100/trunk@8734 4a71c877-e1ca-e34f-864e-861f7616d084master
parent
87802afa73
commit
38f66c5f9e
|
@ -202,8 +202,6 @@ typedef struct
|
|||
Socket** fds;
|
||||
} SocketSet;
|
||||
|
||||
#define PLAYER_HOST 1
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
// Variables
|
||||
|
||||
|
@ -2309,6 +2307,7 @@ BOOL NETbcast(NETMSG *msg)
|
|||
tcp_socket = NULL;
|
||||
NetPlay.players[NetPlay.hostPlayer].heartbeat = false; // mark host as dead
|
||||
//Game is pretty much over --should just end everything when HOST dies.
|
||||
setLobbyError(ERROR_HOSTDROPPED);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -2720,78 +2719,52 @@ BOOL NETsetupTCPIP(const char *machine)
|
|||
// ////////////////////////////////////////////////////////////////////////
|
||||
// File Transfer programs.
|
||||
/** Send file. It returns % of file sent when 100 it's complete. Call until it returns 100.
|
||||
* @TODO Needs to be rewritten. See issue #215. */
|
||||
* @TODO: more error checking (?) different file types (?)
|
||||
* Maybe should close file handle, and seek each time?
|
||||
*
|
||||
* @NOTE: MAX_FILE_TRANSFER_PACKET is set to 2k per packet since 7*2 = 14K which is pretty
|
||||
* much our limit. Don't screw with that without having a bigger buffer!
|
||||
* NET_BUFFER_SIZE is at 16k. (also remember text chat, plus all the other cruff)
|
||||
*/
|
||||
#define MAX_FILE_TRANSFER_PACKET 2048
|
||||
UBYTE NETsendFile(BOOL newFile, char *fileName, UDWORD player)
|
||||
UBYTE NETsendFile(char *fileName, UDWORD player)
|
||||
{
|
||||
static int32_t currPos;
|
||||
static PHYSFS_sint64 fileSize_64;
|
||||
static PHYSFS_sint32 fileSize_32; // we don't support 64bit nettypes yet.
|
||||
static PHYSFS_file *pFileHandle;
|
||||
int32_t bytesRead;
|
||||
char inBuff[MAX_FILE_TRANSFER_PACKET];
|
||||
int32_t bytesRead = 0;
|
||||
uint8_t sendto = 0;
|
||||
char inBuff[MAX_FILE_TRANSFER_PACKET];
|
||||
|
||||
// We are not the host, so we don't care. (in fact, this would be a error)
|
||||
if(!NetPlay.isHost)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
memset(inBuff, 0x0, sizeof(inBuff));
|
||||
if (newFile)
|
||||
{
|
||||
// open the file.
|
||||
pFileHandle = PHYSFS_openRead(fileName); // check file exists
|
||||
debug(LOG_NET, "Sending [directory: %s] %s to client", PHYSFS_getRealDir(fileName), fileName);
|
||||
if (pFileHandle == NULL)
|
||||
{
|
||||
debug(LOG_ERROR, "Failed to open %s for reading: %s", fileName, PHYSFS_getLastError());
|
||||
return 0; // failed
|
||||
}
|
||||
// get the file's size.
|
||||
fileSize_64 = PHYSFS_fileLength(pFileHandle);
|
||||
fileSize_32 = (int32_t) fileSize_64; // we don't support 64bit int nettypes.
|
||||
currPos = 0;
|
||||
}
|
||||
|
||||
// read some bytes.
|
||||
if (!pFileHandle)
|
||||
{
|
||||
debug(LOG_ERROR, "No filehandle");
|
||||
return 0; // failed
|
||||
}
|
||||
bytesRead = PHYSFS_read(pFileHandle, inBuff,1, MAX_FILE_TRANSFER_PACKET);
|
||||
|
||||
if (player == 0)
|
||||
{ // FIXME: why would you send (map) file to everyone ??
|
||||
// even if they already have it? multiplay.c 1529 & 1550 are both
|
||||
// NETsendFile(true,mapStr,0); & NETsendFile(false,game.map,0);
|
||||
// so we ALWAYS send it, it seems?
|
||||
// NOTE: we send to everyone since there is no way to signal the host
|
||||
// to stop sending the map. Which means that everytime a player joins
|
||||
// that doesn't have the map, it will send to all players again.
|
||||
// We also are limited by fps(!) to the amount of time the loop runs.
|
||||
NETbeginEncode(FILEMSG, NET_ALL_PLAYERS); // send it.
|
||||
}
|
||||
else
|
||||
{
|
||||
bytesRead = PHYSFS_read(NetPlay.players[player].wzFile.pFileHandle, inBuff,1, MAX_FILE_TRANSFER_PACKET);
|
||||
sendto = (uint8_t) player;
|
||||
NETbeginEncode(FILEMSG,sendto);
|
||||
}
|
||||
|
||||
// form a message
|
||||
NETint32_t(&fileSize_32); // total bytes in this file. (we don't support 64bit yet)
|
||||
NETbeginEncode(NET_FILE_PAYLOAD, sendto);
|
||||
NETint32_t(&NetPlay.players[player].wzFile.fileSize_32); // total bytes in this file. (we don't support 64bit yet)
|
||||
NETint32_t(&bytesRead); // bytes in this packet
|
||||
NETint32_t(&currPos); // start byte
|
||||
|
||||
NETint32_t(&NetPlay.players[player].wzFile.currPos); // start byte
|
||||
NETstring(fileName, 256); //256 = max filename size
|
||||
NETbin(inBuff, bytesRead);
|
||||
NETend();
|
||||
|
||||
currPos += bytesRead; // update position!
|
||||
if(currPos == fileSize_64)
|
||||
NetPlay.players[player].wzFile.currPos += bytesRead; // update position!
|
||||
if(NetPlay.players[player].wzFile.currPos == NetPlay.players[player].wzFile.fileSize_32)
|
||||
{
|
||||
PHYSFS_close(pFileHandle);
|
||||
PHYSFS_close(NetPlay.players[player].wzFile.pFileHandle);
|
||||
NetPlay.players[player].wzFile.isSending = false; // we are done sending to this client.
|
||||
NetPlay.players[player].needFile = false;
|
||||
}
|
||||
|
||||
return (currPos * 100) / fileSize_64;
|
||||
return (NetPlay.players[player].wzFile.currPos * 100) / NetPlay.players[player].wzFile.fileSize_32;
|
||||
}
|
||||
|
||||
/* @TODO Needs to be rewritten. See issue #215. */
|
||||
/* @TODO more error checking (?) different file types (?) */
|
||||
// recv file. it returns % of the file so far recvd.
|
||||
UBYTE NETrecvFile(void)
|
||||
{
|
||||
|
@ -2799,18 +2772,17 @@ UBYTE NETrecvFile(void)
|
|||
char fileName[256];
|
||||
char outBuff[MAX_FILE_TRANSFER_PACKET];
|
||||
static PHYSFS_file *pFileHandle;
|
||||
static bool isLoop = false;
|
||||
|
||||
memset(fileName, 0x0, sizeof(fileName));
|
||||
memset(outBuff, 0x0, sizeof(outBuff));
|
||||
|
||||
//read incoming bytes.
|
||||
NETbeginDecode(FILEMSG);
|
||||
NETbeginDecode(NET_FILE_PAYLOAD);
|
||||
NETint32_t(&fileSize); // total bytes in this file.
|
||||
NETint32_t(&bytesRead); // bytes in this packet
|
||||
NETint32_t(&currPos); // start byte
|
||||
|
||||
// read filename
|
||||
NETstring(fileName, 256); // Ugh. 256 = max array size
|
||||
NETstring(fileName, 256); // read filename (only valid on 1st packet)
|
||||
debug(LOG_NET, "Creating new file %s, position is %d", fileName, currPos);
|
||||
|
||||
if (currPos == 0) // first packet!
|
||||
|
@ -2823,21 +2795,38 @@ UBYTE NETrecvFile(void)
|
|||
fsize = PHYSFS_fileLength(fin);
|
||||
if ((int32_t) fsize == fileSize)
|
||||
{
|
||||
// NOTE: we would send a abort message to host, but since we can't,
|
||||
// we won't.
|
||||
#ifdef DEBUG
|
||||
debug(LOG_NET, "We already have the file %s.", fileName);
|
||||
#endif
|
||||
uint32_t reason = ALREADY_HAVE_FILE;
|
||||
debug(LOG_NET, "We already have the file %s! ", fileName);
|
||||
PHYSFS_close(fin);
|
||||
NETend();
|
||||
|
||||
// NOTE: we can't abort out, since the host ALWAYS sends the data until done
|
||||
// PHYSFS_close(fin);
|
||||
// NETend();
|
||||
// return 100;
|
||||
NETbeginEncode(NET_FILE_CANCELLED, NET_HOST_ONLY);
|
||||
NETuint32_t(&selectedPlayer);
|
||||
NETuint32_t(&reason);
|
||||
NETend();
|
||||
if (!isLoop)
|
||||
{
|
||||
isLoop = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t reason = STUCK_IN_FILE_LOOP;
|
||||
|
||||
NETend();
|
||||
// we should never get here, it means, that the game can't detect the level, but we have the file.
|
||||
// so we kick this player out.
|
||||
NETbeginEncode(NET_FILE_CANCELLED, NET_HOST_ONLY);
|
||||
NETuint32_t(&selectedPlayer);
|
||||
NETuint32_t(&reason);
|
||||
NETend();
|
||||
debug(LOG_FATAL, "Something is really wrong with the file's (%s) data, game can't detect it?", fileName);
|
||||
return 100;
|
||||
}
|
||||
}
|
||||
PHYSFS_close(fin);
|
||||
#ifdef DEBUG
|
||||
debug(LOG_NET, "We have the same named file, but different size. Redownloading %s", fileName);
|
||||
#endif
|
||||
|
||||
debug(LOG_NET, "We already have the file %s, but different size %d vs %d. Redownloading", fileName, (int32_t) fsize, fileSize);
|
||||
|
||||
}
|
||||
pFileHandle = PHYSFS_openWrite(fileName); // create a new file.
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#define _netplay_h
|
||||
|
||||
#include "nettypes.h"
|
||||
#include <physfs.h>
|
||||
|
||||
// Lobby Connection errors
|
||||
|
||||
|
@ -40,7 +41,8 @@ typedef enum
|
|||
ERROR_WRONGVERSION,
|
||||
ERROR_WRONGPASSWORD, // NOTE WRONG_PASSWORD results in conflict
|
||||
ERROR_HOSTDROPPED,
|
||||
ERROR_WRONGDATA
|
||||
ERROR_WRONGDATA,
|
||||
ERROR_UNKNOWNFILEISSUE
|
||||
} LOBBY_ERROR_TYPES;
|
||||
|
||||
|
||||
|
@ -92,7 +94,7 @@ typedef enum
|
|||
NET_DROIDDISEMBARK, //43 droid disembarked from a Transporter
|
||||
NET_RESEARCHSTATUS, //44 research state.
|
||||
NET_LASSAT, //45 lassat firing.
|
||||
NET_REQUESTMAP, //46 dont have map, please send it.
|
||||
NET_UNUSED_46, //46 old map request, now unused.
|
||||
NET_AITEXTMSG, //47 chat between AIs
|
||||
NET_TEAMS_ON, //48 locked teams mode
|
||||
NET_BEACONMSG, //49 place beacon
|
||||
|
@ -114,6 +116,12 @@ typedef enum
|
|||
NET_POSITIONREQUEST, //65 position in GUI player list
|
||||
NET_DATA_CHECK, //66 Data integrity check
|
||||
NET_HOST_DROPPED, //67 Host has dropped
|
||||
NET_FUTURE1, //68 future use
|
||||
NET_FUTURE2, //69 "
|
||||
NET_FUTURE3, //70 "
|
||||
NET_FILE_REQUESTED, //71 Player has requested a file (map/mod/?)
|
||||
NET_FILE_CANCELLED, //72 Player cancelled a file request
|
||||
NET_FILE_PAYLOAD, //73 sending file to the player that needs it
|
||||
NUM_GAME_PACKETS // *MUST* be last.
|
||||
} MESSAGE_TYPES;
|
||||
|
||||
|
@ -182,8 +190,29 @@ typedef struct {
|
|||
BOOL status; // If the packet compiled or not (this is _not_ sent!)
|
||||
} NETMSG;
|
||||
|
||||
#define FILEMSG 254 // a file packet
|
||||
typedef struct
|
||||
{
|
||||
PHYSFS_file *pFileHandle; // handle
|
||||
PHYSFS_sint32 fileSize_32; // size
|
||||
int32_t currPos; // current position
|
||||
BOOL isSending; // sending to this player
|
||||
BOOL isCancelled; // player cancelled
|
||||
int32_t filetype; // future use (1=map 2=mod 3=...)
|
||||
} WZFile;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int32_t player; // the client we sent data to
|
||||
int32_t done; // how far done we are (100= finished)
|
||||
int32_t byteCount; // current byte count
|
||||
} wzFileStatus;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
WZ_FILE_OK,
|
||||
ALREADY_HAVE_FILE,
|
||||
STUCK_IN_FILE_LOOP
|
||||
} wzFileEnum;
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
// Player information. Filled when players join, never re-ordered. selectedPlayer global points to
|
||||
// currently controlled player. This array is indexed by GUI slots in pregame.
|
||||
|
@ -201,6 +230,8 @@ typedef struct
|
|||
BOOL ready; ///< player ready to start?
|
||||
uint32_t versionCheckTime; ///< Time when check sent. Uses 0xffffffff for nothing sent yet
|
||||
BOOL playerVersionFlag; ///< We kick on false
|
||||
BOOL needFile; ///< if We need a file sent to us
|
||||
WZFile wzFile; ///< for each player, we keep track of map progress
|
||||
} PLAYER;
|
||||
|
||||
// ////////////////////////////////////////////////////////////////////////
|
||||
|
@ -238,7 +269,7 @@ extern BOOL NETsend(NETMSG *msg, UDWORD player); // send to player
|
|||
extern BOOL NETbcast(NETMSG *msg); // broadcast to everyone
|
||||
extern BOOL NETrecv(uint8_t *type); // recv a message if possible
|
||||
|
||||
extern UBYTE NETsendFile(BOOL newFile, char *fileName, UDWORD player); // send file chunk.
|
||||
extern UBYTE NETsendFile(char *fileName, UDWORD player); // send file chunk.
|
||||
extern UBYTE NETrecvFile(void); // recv file chunk
|
||||
|
||||
extern int NETclose(void); // close current game
|
||||
|
|
25
src/data.c
25
src/data.c
|
@ -152,15 +152,7 @@ UDWORD hashBuffer(uint8_t *pData, uint32_t size)
|
|||
{
|
||||
val = (uint32_t *)(NewData+pt);
|
||||
|
||||
// original:
|
||||
//hashval = SDL_SwapBE32(hashval ^ SDL_SwapBE32((*val))); // I hope this is correct...can't test since no PPC machine
|
||||
// Next time, ask someone who does, or at least get some someone to double-check your math. ;)
|
||||
|
||||
// Here is a solution that makes BE archs binary-compatible with the LE output of the above
|
||||
hashval = SDL_Swap32(hashval ^ SDL_Swap32(*val));
|
||||
|
||||
// Here is the solution that the above was probably intended to do:
|
||||
//hashval ^= (*val); // no endianness enforcement, since it'll be done by whatever handles its output
|
||||
hashval ^= (*val);
|
||||
|
||||
// spams a ton--but useful for debugging.
|
||||
// debug(LOG_NET, "hash %08x pt %08x val is %08x", hashval, pt, *val);
|
||||
|
@ -175,6 +167,8 @@ UDWORD hashBuffer(uint8_t *pData, uint32_t size)
|
|||
return hashval;
|
||||
}
|
||||
|
||||
// create the hash for that data block.
|
||||
// Data should be converted to Network byte order
|
||||
void calcDataHash(uint8_t *pBuffer, uint32_t size, uint32_t index)
|
||||
{
|
||||
if (!bMultiPlayer)
|
||||
|
@ -182,18 +176,9 @@ void calcDataHash(uint8_t *pBuffer, uint32_t size, uint32_t index)
|
|||
return;
|
||||
}
|
||||
|
||||
// create the hash for that data block.
|
||||
DataHash[index] ^= SDL_SwapBE32(hashBuffer(pBuffer, size));
|
||||
|
||||
// Here is the original solution:
|
||||
//DataHash[index] = SDL_SwapBE32(DataHash[index] ^ hashBuffer(pBuffer, size)); // check endian issues?
|
||||
|
||||
// Here is a solution that makes BE archs binary-compatible with the LE output of the above
|
||||
DataHash[index] = SDL_Swap32(DataHash[index] ^ SDL_SwapLE32(hashBuffer(pBuffer, size)));
|
||||
|
||||
// Here is the solution that the above was probably intended to do:
|
||||
//DataHash[index] ^= SDL_SwapBE32(hashBuffer(pBuffer, size));
|
||||
|
||||
debug(LOG_NET, "DataHash[%2u] = %08x\n", index, DataHash[index]);
|
||||
debug(LOG_NET, "DataHash[%2u] = %08x", index, DataHash[index]);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -837,6 +837,11 @@ static void addGames(void)
|
|||
case ERROR_WRONGDATA:
|
||||
txt = _("Wrong data/mod detected by Host.");
|
||||
break;
|
||||
// AFAIK, the only way this can really happy is if the Host's file is named wrong, or a client side error.
|
||||
case ERROR_UNKNOWNFILEISSUE:
|
||||
txt = _("Host couldn't send file?");
|
||||
debug(LOG_POPUP, "Warzone couldn't complete a file request.\n\nPossibly, Host's file is incorrect. Check your logs for more details.");
|
||||
break;
|
||||
case ERROR_WRONGPASSWORD:
|
||||
txt = _("Incorrect Password!");
|
||||
break;
|
||||
|
@ -1577,6 +1582,13 @@ BOOL recvReadyRequest()
|
|||
return false;
|
||||
}
|
||||
|
||||
// do not allow players to select 'ready' if we are sending a map too them!
|
||||
// TODO: make a new icon to show this state?
|
||||
if (NetPlay.players[player].wzFile.isSending)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return changeReadyStatus((UBYTE)player, bReady);
|
||||
}
|
||||
|
||||
|
@ -2695,11 +2707,11 @@ void frontendMultiMessages(void)
|
|||
// Copy the message to the global one used by the new NET API
|
||||
switch(type)
|
||||
{
|
||||
case NET_REQUESTMAP:
|
||||
case NET_FILE_REQUESTED:
|
||||
recvMapFileRequested();
|
||||
break;
|
||||
|
||||
case FILEMSG:
|
||||
case NET_FILE_PAYLOAD:
|
||||
widgSetButtonState(psWScreen, MULTIOP_MAP_BUT, 1); // turn preview button off
|
||||
if (recvMapFileData())
|
||||
{
|
||||
|
@ -2707,6 +2719,34 @@ void frontendMultiMessages(void)
|
|||
}
|
||||
break;
|
||||
|
||||
case NET_FILE_CANCELLED: // host only routine
|
||||
{
|
||||
uint32_t reason;
|
||||
uint32_t victim;
|
||||
|
||||
NETbeginDecode(NET_FILE_CANCELLED);
|
||||
NETuint32_t(&victim);
|
||||
NETuint32_t(&reason);
|
||||
NETend();
|
||||
switch (reason)
|
||||
{
|
||||
case STUCK_IN_FILE_LOOP:
|
||||
debug(LOG_WARNING, "Received file cancel request from player %u, They are stuck in a loop?", victim);
|
||||
kickPlayer(victim, "couldn't upload file for some reason. ", ERROR_UNKNOWNFILEISSUE);
|
||||
NetPlay.players[victim].wzFile.isCancelled = true;
|
||||
NetPlay.players[victim].wzFile.isSending = false;
|
||||
break;
|
||||
|
||||
case ALREADY_HAVE_FILE:
|
||||
default:
|
||||
debug(LOG_WARNING, "Received file cancel request from player %u, They already have the file ?", victim);
|
||||
NetPlay.players[victim].wzFile.isCancelled = true;
|
||||
NetPlay.players[victim].wzFile.isSending = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case NET_OPTIONS: // incoming options file.
|
||||
recvOptions();
|
||||
ingame.localOptionsReceived = true;
|
||||
|
@ -2849,7 +2889,7 @@ void frontendMultiMessages(void)
|
|||
void runMultiOptions(void)
|
||||
{
|
||||
static UDWORD lastrefresh = 0;
|
||||
UDWORD id,value;//,i;
|
||||
UDWORD id, value, i;
|
||||
char sTemp[128];
|
||||
PLAYERSTATS playerStats;
|
||||
W_CONTEXT context;
|
||||
|
@ -2859,11 +2899,14 @@ void runMultiOptions(void)
|
|||
|
||||
frontendMultiMessages();
|
||||
|
||||
// keep sending the map if required.
|
||||
if(bSendingMap)
|
||||
for (i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
// send it for each player that needs it
|
||||
if (NetPlay.players[i].wzFile.isSending)
|
||||
{
|
||||
sendMap();
|
||||
}
|
||||
}
|
||||
|
||||
// update boxes?
|
||||
if (netPlayersUpdated || (NetPlay.isHost && mouseDown(MOUSE_LMB) && gameTime-lastrefresh>500))
|
||||
|
|
|
@ -220,7 +220,7 @@ void recvOptions()
|
|||
|
||||
debug(LOG_NET, "Map was not found, requesting map %s from host.", game.map);
|
||||
// Request the map from the host
|
||||
NETbeginEncode(NET_REQUESTMAP, NET_HOST_ONLY);
|
||||
NETbeginEncode(NET_FILE_REQUESTED, NET_HOST_ONLY);
|
||||
NETuint32_t(&player);
|
||||
NETend();
|
||||
|
||||
|
|
|
@ -80,8 +80,6 @@ UBYTE bDisplayMultiJoiningStatus;
|
|||
MULTIPLAYERGAME game; //info to describe game.
|
||||
MULTIPLAYERINGAME ingame;
|
||||
|
||||
BOOL bSendingMap = false; // map broadcasting.
|
||||
|
||||
char beaconReceiveMsg[MAX_PLAYERS][MAX_CONSOLE_STRING_LENGTH]; //beacon msg for each player
|
||||
char playerName[MAX_PLAYERS][MAX_STR_LENGTH]; //Array to store all player names (humans and AIs)
|
||||
BOOL bPlayerReadyGUI[MAX_PLAYERS] = {false};
|
||||
|
@ -1558,20 +1556,32 @@ BOOL recvDestroyFeature()
|
|||
BOOL recvMapFileRequested()
|
||||
{
|
||||
char mapStr[256],mapName[256],fixedname[256];
|
||||
uint32_t player;
|
||||
|
||||
// another player is requesting the map
|
||||
PHYSFS_sint64 fileSize_64;
|
||||
PHYSFS_file *pFileHandle;
|
||||
|
||||
// We are not the host, so we don't care. (in fact, this would be a error)
|
||||
if(!NetPlay.isHost)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// start sending the map to the other players.
|
||||
if(!bSendingMap)
|
||||
// Check to see who wants the file
|
||||
NETbeginDecode(NET_FILE_REQUESTED);
|
||||
NETuint32_t(&player);
|
||||
NETend();
|
||||
|
||||
if (!NetPlay.players[player].wzFile.isSending)
|
||||
{
|
||||
NetPlay.players[player].needFile = true;
|
||||
NetPlay.players[player].wzFile.isCancelled = false;
|
||||
NetPlay.players[player].wzFile.isSending = true;
|
||||
|
||||
memset(mapStr,0,256);
|
||||
memset(mapName,0,256);
|
||||
memset(fixedname,0,256);
|
||||
bSendingMap = true;
|
||||
|
||||
addConsoleMessage("Map was requested: SENDING MAP!",DEFAULT_JUSTIFY, SYSTEM_MESSAGE);
|
||||
|
||||
sstrcpy(mapName, game.map);
|
||||
|
@ -1592,38 +1602,55 @@ BOOL recvMapFileRequested()
|
|||
snprintf(mapStr, sizeof(mapStr), "%dc-%s.wz", game.maxPlayers, mapName);
|
||||
snprintf(fixedname, sizeof(fixedname), "maps/%s", mapStr); //We know maps are in /maps dir...now. fix for linux -Q
|
||||
sstrcpy(mapStr, fixedname);
|
||||
debug(LOG_NET, "Map was requested. Sending %s", mapStr);
|
||||
// NOTE: should we check if file exsists before trying to send it ?
|
||||
NETsendFile(true,mapStr,0);
|
||||
debug(LOG_NET, "Map was requested. Looking for %s", mapStr);
|
||||
|
||||
// Checking to see if file is available...
|
||||
pFileHandle = PHYSFS_openRead(mapStr);
|
||||
if (pFileHandle == NULL)
|
||||
{
|
||||
debug(LOG_ERROR, "Failed to open %s for reading: %s", mapStr, PHYSFS_getLastError());
|
||||
debug(LOG_FATAL, "You have a map (%s) that can't be located.\n\nMake sure it is in the correct directory and or format!", mapStr);
|
||||
// NOTE: if we get here, then the game is basically over, The host can't send the file for whatever reason...
|
||||
// Which also means, that we can't continue.
|
||||
debug(LOG_NET, "***Host has a file issue, and is being forced to quit!***");
|
||||
NETbeginEncode(NET_HOST_DROPPED, NET_ALL_PLAYERS);
|
||||
NETend();
|
||||
abort();
|
||||
}
|
||||
|
||||
// get the file's size.
|
||||
fileSize_64 = PHYSFS_fileLength(pFileHandle);
|
||||
debug(LOG_NET, "File is valid, sending [directory: %s] %s to client %u", PHYSFS_getRealDir(mapStr), mapStr, player);
|
||||
|
||||
NetPlay.players[player].wzFile.pFileHandle = pFileHandle;
|
||||
NetPlay.players[player].wzFile.fileSize_32 = (int32_t) fileSize_64; //we don't support 64bit int nettypes.
|
||||
NetPlay.players[player].wzFile.currPos = 0;
|
||||
|
||||
NETsendFile(mapStr, player);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// continue sending the map
|
||||
UBYTE sendMap(void)
|
||||
void sendMap(void)
|
||||
{
|
||||
int i = 0;
|
||||
UBYTE done;
|
||||
static UDWORD lastCall;
|
||||
|
||||
|
||||
if(lastCall > gameTime)lastCall= 0;
|
||||
if ( (gameTime - lastCall) <200)
|
||||
for (i = 0; i < MAX_PLAYERS; i++)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
lastCall = gameTime;
|
||||
|
||||
|
||||
done = NETsendFile(false,game.map,0);
|
||||
|
||||
if (NetPlay.players[i].wzFile.isSending)
|
||||
{
|
||||
done = NETsendFile(game.map, i);
|
||||
if (done == 100)
|
||||
{
|
||||
addConsoleMessage("MAP SENT!",DEFAULT_JUSTIFY, SYSTEM_MESSAGE);
|
||||
bSendingMap = false;
|
||||
debug(LOG_NET, "=== File has been sent to player %d ===", i);
|
||||
NetPlay.players[i].wzFile.isSending = false;
|
||||
NetPlay.players[i].needFile = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return done;
|
||||
}
|
||||
|
||||
// Another player is broadcasting a map, recv a chunk. Returns false if not yet done.
|
||||
|
@ -1634,6 +1661,7 @@ BOOL recvMapFileData()
|
|||
{
|
||||
addConsoleMessage("MAP DOWNLOADED!",DEFAULT_JUSTIFY, SYSTEM_MESSAGE);
|
||||
sendTextMessage("MAP DOWNLOADED",true); //send
|
||||
debug(LOG_NET, "=== File has been received. ===");
|
||||
|
||||
// clear out the old level list.
|
||||
levShutDown();
|
||||
|
|
|
@ -147,8 +147,7 @@ extern BOOL sendAIMessage (char *pStr, UDWORD player, UDWORD to); //send AI mes
|
|||
|
||||
extern BOOL turnOffMultiMsg (BOOL bDoit);
|
||||
|
||||
extern UBYTE sendMap (void);
|
||||
|
||||
extern void sendMap(void);
|
||||
extern BOOL multiplayerWinSequence(BOOL firstCall);
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Reference in New Issue