Merge branch 'master' of https://github.com/ZDoom/gzdoom into gzd-master-experimental

This commit is contained in:
nashmuhandes 2024-11-16 13:16:21 +08:00
commit 2e09abc4e8
39 changed files with 279 additions and 91 deletions

View file

@ -132,7 +132,8 @@ enum
PRE_CONACK, // Sent from host to guest to acknowledge PRE_CONNECT receipt
PRE_ALLFULL, // Sent from host to an unwanted guest
PRE_ALLHEREACK, // Sent from guest to host to acknowledge PRE_ALLHEREACK receipt
PRE_GO // Sent from host to guest to continue game startup
PRE_GO, // Sent from host to guest to continue game startup
PRE_IN_PROGRESS, // Sent from host to guest if the game has already started
};
// Set PreGamePacket.fake to this so that the game rejects any pregame packets
@ -269,6 +270,8 @@ void PacketSend (void)
// I_Error ("SendPacket error: %s",strerror(errno));
}
void PreSend(const void* buffer, int bufferlen, const sockaddr_in* to);
void SendConAck(int num_connected, int num_needed);
//
// PacketGet
@ -303,7 +306,7 @@ void PacketGet (void)
GetPlayerName(node).GetChars());
}
doomcom.data[0] = 0x80; // NCMD_EXIT
doomcom.data[0] = NCMD_EXIT;
c = 1;
}
else if (err != WSAEWOULDBLOCK)
@ -341,10 +344,11 @@ void PacketGet (void)
}
else if (c > 0)
{ //The packet is not from any in-game node, so we might as well discard it.
// Don't show the message for disconnect notifications.
if (c != 2 || TransmitBuffer[0] != PRE_FAKE || TransmitBuffer[1] != PRE_DISCONNECT)
if (TransmitBuffer[0] == PRE_FAKE)
{
DPrintf(DMSG_WARNING, "Dropped packet: Unknown host (%s:%d)\n", inet_ntoa(fromaddress.sin_addr), fromaddress.sin_port);
// If it's someone waiting in the lobby, let them know the game already started
uint8_t msg[] = { PRE_FAKE, PRE_IN_PROGRESS };
PreSend(msg, 2, &fromaddress);
}
doomcom.remotenode = -1;
return;
@ -369,7 +373,22 @@ sockaddr_in *PreGet (void *buffer, int bufferlen, bool noabort)
int err = WSAGetLastError();
if (err == WSAEWOULDBLOCK || (noabort && err == WSAECONNRESET))
return NULL; // no packet
I_Error ("PreGet: %s", neterror ());
if (doomcom.consoleplayer == 0)
{
int node = FindNode(&fromaddress);
I_NetMessage("Got unexpected disconnect.");
doomcom.numnodes--;
for (; node < doomcom.numnodes; ++node)
sendaddress[node] = sendaddress[node + 1];
// Let remaining guests know that somebody left.
SendConAck(doomcom.numnodes, doomcom.numplayers);
}
else
{
I_NetError("The host disbanded the game unexpectedly");
}
}
return &fromaddress;
}
@ -499,7 +518,7 @@ void SendAbort (void)
}
}
static void SendConAck (int num_connected, int num_needed)
void SendConAck (int num_connected, int num_needed)
{
PreGamePacket packet;
@ -708,7 +727,7 @@ bool HostGame (int i)
doomcom.numnodes = 1;
I_NetInit ("Waiting for players", numplayers);
I_NetInit ("Hosting game", numplayers);
// Wait for numplayers-1 different connections
if (!I_NetLoop (Host_CheckForConnects, (void *)(intptr_t)numplayers))
@ -783,13 +802,15 @@ bool Guest_ContactHost (void *userdata)
}
else if (packet.Message == PRE_DISCONNECT)
{
doomcom.numnodes = 0;
I_FatalError ("The host cancelled the game.");
I_NetError("The host cancelled the game.");
}
else if (packet.Message == PRE_ALLFULL)
{
doomcom.numnodes = 0;
I_FatalError ("The game is full.");
I_NetError("The game is full.");
}
else if (packet.Message == PRE_IN_PROGRESS)
{
I_NetError("The game was already started.");
}
}
}
@ -850,7 +871,7 @@ bool Guest_WaitForOthers (void *userdata)
return true;
case PRE_DISCONNECT:
I_FatalError ("The host cancelled the game.");
I_NetError("The host cancelled the game.");
break;
}
}
@ -875,6 +896,7 @@ bool JoinGame (int i)
BuildAddress (&sendaddress[1], Args->GetArg(i+1));
sendplayer[1] = 0;
doomcom.numnodes = 2;
doomcom.consoleplayer = -1;
// Let host know we are here
@ -1046,6 +1068,13 @@ void I_NetMessage(const char* text, ...)
#endif
}
void I_NetError(const char* error)
{
doomcom.numnodes = 0;
StartWindow->NetClose();
I_FatalError(error);
}
// todo: later these must be dispatched by the main menu, not the start screen.
void I_NetProgress(int val)
{

View file

@ -7,6 +7,7 @@
int I_InitNetwork (void);
void I_NetCmd (void);
void I_NetMessage(const char*, ...);
void I_NetError(const char* error);
void I_NetProgress(int val);
void I_NetInit(const char* msg, int num);
bool I_NetLoop(bool (*timer_callback)(void*), void* userdata);

View file

@ -83,7 +83,7 @@ FRandom pr_exrandom("EX_Random");
// PUBLIC DATA DEFINITIONS -------------------------------------------------
FRandom M_Random;
FCRandom M_Random;
// Global seed. This is modified predictably to initialize every RNG.
uint32_t rngseed;
@ -126,8 +126,8 @@ CCMD(rngseed)
// PRIVATE DATA DEFINITIONS ------------------------------------------------
FRandom *FRandom::RNGList;
static TDeletingArray<FRandom *> NewRNGs;
FRandom *FRandom::RNGList, *FRandom::CRNGList;
static TDeletingArray<FRandom *> NewRNGs, NewCRNGs;
// CODE --------------------------------------------------------------------
@ -139,14 +139,22 @@ static TDeletingArray<FRandom *> NewRNGs;
//
//==========================================================================
FRandom::FRandom ()
: NameCRC (0)
FRandom::FRandom (bool client)
: NameCRC (0), bClient(client)
{
#ifndef NDEBUG
Name = NULL;
#endif
Next = RNGList;
RNGList = this;
if (bClient)
{
Next = CRNGList;
CRNGList = this;
}
else
{
Next = RNGList;
RNGList = this;
}
Init(0);
}
@ -158,7 +166,7 @@ FRandom::FRandom ()
//
//==========================================================================
FRandom::FRandom (const char *name)
FRandom::FRandom (const char *name, bool client) : bClient(client)
{
NameCRC = CalcCRC32 ((const uint8_t *)name, (unsigned int)strlen (name));
#ifndef NDEBUG
@ -170,7 +178,7 @@ FRandom::FRandom (const char *name)
#endif
// Insert the RNG in the list, sorted by CRC
FRandom **prev = &RNGList, *probe = RNGList;
FRandom **prev = (bClient ? &CRNGList : &RNGList), * probe = (bClient ? CRNGList : RNGList);
while (probe != NULL && probe->NameCRC < NameCRC)
{
@ -205,8 +213,8 @@ FRandom::~FRandom ()
FRandom *last = NULL;
prev = &RNGList;
rng = RNGList;
prev = bClient ? &CRNGList : &RNGList;
rng = bClient ? CRNGList : RNGList;
while (rng != NULL && rng != this)
{
@ -237,6 +245,11 @@ void FRandom::StaticClearRandom ()
{
rng->Init(rngseed);
}
for (FRandom* rng = FRandom::CRNGList; rng != NULL; rng = rng->Next)
{
rng->Init(rngseed);
}
}
//==========================================================================
@ -345,15 +358,15 @@ void FRandom::StaticReadRNGState(FSerializer &arc)
//
//==========================================================================
FRandom *FRandom::StaticFindRNG (const char *name)
FRandom *FRandom::StaticFindRNG (const char *name, bool client)
{
uint32_t NameCRC = CalcCRC32 ((const uint8_t *)name, (unsigned int)strlen (name));
// Use the default RNG if this one happens to have a CRC of 0.
if (NameCRC == 0) return &pr_exrandom;
if (NameCRC == 0) return client ? &M_Random : &pr_exrandom;
// Find the RNG in the list, sorted by CRC
FRandom **prev = &RNGList, *probe = RNGList;
FRandom **prev = (client ? &CRNGList : &RNGList), *probe = (client ? CRNGList : RNGList);
while (probe != NULL && probe->NameCRC < NameCRC)
{
@ -364,14 +377,32 @@ FRandom *FRandom::StaticFindRNG (const char *name)
if (probe == NULL || probe->NameCRC != NameCRC)
{
// A matching RNG doesn't exist yet so create it.
probe = new FRandom(name);
probe = new FRandom(name, client);
// Store the new RNG for destruction when ZDoom quits.
NewRNGs.Push(probe);
if (client)
NewCRNGs.Push(probe);
else
NewRNGs.Push(probe);
}
return probe;
}
void FRandom::SaveRNGState(TArray<FRandom>& backups)
{
for (auto cur = RNGList; cur != nullptr; cur = cur->Next)
backups.Push(*cur);
}
void FRandom::RestoreRNGState(TArray<FRandom>& backups)
{
unsigned int i = 0u;
for (auto cur = RNGList; cur != nullptr; cur = cur->Next)
*cur = backups[i++];
backups.Clear();
}
//==========================================================================
//
// FRandom :: StaticPrintSeeds

View file

@ -44,9 +44,9 @@ class FSerializer;
class FRandom : public SFMTObj
{
public:
FRandom ();
FRandom (const char *name);
~FRandom ();
FRandom() : FRandom(false) {}
FRandom(const char* name) : FRandom(name, false) {}
~FRandom();
int Seed() const
{
@ -170,20 +170,34 @@ public:
static void StaticClearRandom ();
static void StaticReadRNGState (FSerializer &arc);
static void StaticWriteRNGState (FSerializer &file);
static FRandom *StaticFindRNG(const char *name);
static FRandom *StaticFindRNG(const char *name, bool client);
static void SaveRNGState(TArray<FRandom>& backups);
static void RestoreRNGState(TArray<FRandom>& backups);
#ifndef NDEBUG
static void StaticPrintSeeds ();
#endif
protected:
FRandom(bool client);
FRandom(const char* name, bool client);
private:
#ifndef NDEBUG
const char *Name;
#endif
FRandom *Next;
uint32_t NameCRC;
bool bClient;
static FRandom *RNGList;
static FRandom *RNGList, *CRNGList;
};
class FCRandom : public FRandom
{
public:
FCRandom() : FRandom(true) {}
FCRandom(const char* name) : FRandom(name, true) {}
};
extern uint32_t rngseed; // The starting seed (not part of state)
@ -193,6 +207,6 @@ extern bool use_staticrng;
// M_Random can be used for numbers that do not affect gameplay
extern FRandom M_Random;
extern FCRandom M_Random;
#endif

View file

@ -41,6 +41,12 @@ xx(Random2)
xx(RandomPick)
xx(FRandomPick)
xx(SetRandomSeed)
xx(CRandom)
xx(CFRandom)
xx(CRandom2)
xx(CRandomPick)
xx(CFRandomPick)
xx(CSetRandomSeed)
xx(BuiltinRandomSeed)
xx(BuiltinNew)
xx(GetClass)

View file

@ -55,6 +55,7 @@ public:
virtual void NetInit(const char *message, int num_players) {}
virtual void NetProgress(int count) {}
virtual void NetDone() {}
virtual void NetClose() {}
virtual bool NetLoop(bool (*timer_callback)(void *), void *userdata) { return false; }
virtual void AppendStatusLine(const char* status) {}
virtual void LoadingStatus(const char* message, int colors) {}
@ -74,6 +75,7 @@ public:
void NetProgress(int count);
void NetMessage(const char* format, ...); // cover for printf
void NetDone();
void NetClose();
bool NetLoop(bool (*timer_callback)(void*), void* userdata);
protected:
int NetMaxPos, NetCurPos;