mirror of
https://github.com/id-Software/DOOM-3-BFG.git
synced 2024-11-24 21:12:03 +00:00
554 lines
16 KiB
C++
554 lines
16 KiB
C++
/*
|
|
===========================================================================
|
|
|
|
Doom 3 BFG Edition GPL Source Code
|
|
Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company.
|
|
|
|
This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").
|
|
|
|
Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
(at your option) any later version.
|
|
|
|
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with Doom 3 BFG Edition Source Code. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code. If not, please request a copy in writing from id Software at the address below.
|
|
|
|
If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
|
|
|
|
===========================================================================
|
|
*/
|
|
|
|
#include "Precompiled.h"
|
|
#include "globaldata.h"
|
|
#include "doomlib.h"
|
|
#include <assert.h>
|
|
#include "Main.h"
|
|
#include "sys/sys_session.h"
|
|
#include "idlib/Thread.h"
|
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
// Store master volume settings in archived cvars, becausue we want them to apply
|
|
// even if a user isn't signed in.
|
|
// The range is from 0 to 15, which matches the setting in vanilla DOOM.
|
|
idCVar s_volume_sound( "s_volume_sound", "8", CVAR_ARCHIVE | CVAR_INTEGER, "sound volume", 0, 15 );
|
|
idCVar s_volume_midi( "s_volume_midi", "8", CVAR_ARCHIVE | CVAR_INTEGER, "music volume", 0, 15 );
|
|
idCVar m_show_messages( "m_show_messages", "1", CVAR_ARCHIVE | CVAR_INTEGER, "show messages", 0, 1 );
|
|
idCVar m_inDemoMode( "m_inDemoMode", "1", CVAR_INTEGER, "in demo mode", 0, 1 );
|
|
|
|
bool globalNetworking = false;
|
|
bool globalPauseTime = false;
|
|
int PLAYERCOUNT = 1;
|
|
|
|
#ifdef _DEBUG
|
|
bool debugOutput = true;
|
|
#else
|
|
bool debugOutput = false;
|
|
#endif
|
|
|
|
namespace DoomLib
|
|
{
|
|
static const char * Expansion_Names[] = {
|
|
"Ultimate DOOM", "DOOM II: Hell On Earth", "Final DOOM: TNT Evilution", "Final DOOM: Plutonia Experiment", "DOOM II: Master Levels", "DOOM II: No Rest For The Living"
|
|
};
|
|
|
|
static const char* Skill_Names[] = {
|
|
"I'm Too Young To Die!", "Hey, Not Too Rough!", "Hurt Me Plenty!", "Ultra-Violence", "Nightmare"
|
|
};
|
|
|
|
static const char* Filter_Names[] = {
|
|
"#str_friends", "#str_around", "#str_top15"
|
|
};
|
|
|
|
// Game-specific setup values.
|
|
static const char * Doom_MapNames[] = {
|
|
"E1M1: Hangar", "E1M2: Nuclear Plant", "E1M3: Toxin Refinery", "E1M4: Command Control", "E1M5: Phobos Lab", "E1M6: Central Processing", "E1M7: Computer Station", "E1M8: Phobos Anomaly", "E1M9: Military Base",
|
|
"E2M1: Deimos Anomaly", "E2M2: Containment Area", "E2M3: Refinery", "E2M4: Deimos Lab", "E2M5: Command Center", "E2M6: Halls of the Damned", "E2M7: Spawning Vats", "E2M8: Tower of Babel", "E2M9: Fortress of Mystery",
|
|
"E3M1: Hell Keep", "E3M2: Slough of Despair", "E3M3: Pandemonium", "E3M4: House of Pain", "E3M5: Unholy Cathedral", "E3M6: MT. Erebus", "E3M7: Gate to Limbo", "E3M8: DIS", "E3M9: Warrens",
|
|
"E4M1: Hell Beneath", "E4M2: Perfect Hatred", "E4M3: Sever The Wicked", "E4M4: Unruly Evil", "E4M5: They Will Repent", "E4M6: Against Thee Wickedly", "E4M7: And Hell Followed", "E4M8: Unto The Cruel", "E4M9: Fear"
|
|
};
|
|
|
|
static const char * Doom2_MapNames[] = {
|
|
"1: Entryway", "2: Underhalls", "3: The Gantlet", "4: The Focus", "5: The Waste Tunnels", "6: The Crusher", "7: Dead Simple", "8: Tricks and Traps", "9: The Pit", "10: Refueling Base",
|
|
"11: Circle of Death", "12: The Factory", "13: Downtown", "14: The Inmost Dens", "15: Industrial Zone", "16: Suburbs", "17: Tenements", "18: The Courtyard", "19: The Citadel", "20: Gotcha!",
|
|
"21: Nirvana", "22: The Catacombs", "23: Barrels O' Fun", "24: The Chasm", "25: Bloodfalls", "26: The Abandoned Mines", "27: Monster Condo", "28: The Spirit World", "29: The Living End",
|
|
"30: Icon of Sin", "31: IDKFA", "32: Keen"
|
|
};
|
|
|
|
static const char * TNT_MapNames[] = {
|
|
"1: System Control", "2: Human BBQ", "3: Power Control", "4: Wormhole", "5: Hangar", "6: Open Season", "7: Prison", "8: Metal", "9: Stronghold", "10: Redemption", "11: Storage Facility",
|
|
"12: Crater", "13: Nukage Processing", "14: Steel Works", "15: Dead Zone", "16: Deepest Reaches", "17: Processing Area", "18: Mill", "19: Shipping & Respawning", "20: Central Processing",
|
|
"21: Administration Center", "22: Habitat", "23: Lunar Mining Project", "24: Quarry", "25: Baron's Den", "26: Ballistyx", "27: Mount Pain", "28: Heck", "29: River Styx", "30: Last Call", "31: Pharaoh", "32: Caribbean"
|
|
};
|
|
|
|
static const char * Plut_MapNames[] = {
|
|
"1: Congo", "2: Well of Souls", "3: Aztec", "4: Caged", "5: Ghost Town", "6: Baron's Lair", "7: Caughtyard", "8: Realm", "9: Abattoire", "10: Onslaught", "11: Hunted", "12: Speed", "13: The Crypt", "14: Genesis",
|
|
"15: The Twilight", "16: The Omen", "17: Compound", "18: Neurosphere", "19: NME", "20: The Death Domain", "21: Slayer", "22: Impossible Mission", "23: Tombstone", "24: The Final Frontier", "25: The Temple of Darkness",
|
|
"26: Bunker", "27: Anti-Christ", "28: The Sewers", "29: Odyssey of Noises", "30: The Gateway of Hell", "31: Cyberden", "32: Go 2 It"
|
|
};
|
|
|
|
static const char * Mast_MapNames[] = {
|
|
"1: Attack", "2: Canyon","3: The Catwalk", "4: The Combine", "5: The Fistula", "6: The Garrison", "7: Titan Manor", "8: Paradox", "9: Subspace", "10: Subterra", "11: Trapped On Titan", "12: Virgil's Lead", "13: Minos' Judgement",
|
|
"14: Bloodsea Keep", "15: Mephisto's Maosoleum", "16: Nessus", "17: Geryon", "18: Vesperas", "19: Black Tower", "20: The Express Elevator To Hell", "21: Bad Dream"
|
|
};
|
|
|
|
static const char * Nerve_MapNames[] = {
|
|
"1: The Earth Base", "2: The Pain Labs", "3: Canyon of the Dead", "4: Hell Mountain", "5: Vivisection", "6: Inferno of Blood", "7: Baron's Banquet", "8: Tomb of Malevolence", "9: March of Demons"
|
|
};
|
|
|
|
const ExpansionData App_Expansion_Data_Local[] = {
|
|
{ ExpansionData::IWAD, retail, doom, "DOOM", DOOMWADDIR"DOOM.WAD", NULL, "base/textures/DOOMICON.PNG" , Doom_MapNames },
|
|
{ ExpansionData::IWAD, commercial, doom2, "DOOM 2", DOOMWADDIR"DOOM2.WAD", NULL, "base/textures/DOOM2ICON.PNG" , Doom2_MapNames },
|
|
{ ExpansionData::IWAD, commercial, pack_tnt, "FINAL DOOM: TNT EVILUTION", DOOMWADDIR"TNT.WAD", NULL, "base/textures/TNTICON.PNG" , TNT_MapNames },
|
|
{ ExpansionData::IWAD, commercial, pack_plut, "FINAL DOOM: PLUTONIA EXPERIMENT", DOOMWADDIR"PLUTONIA.WAD", NULL, "base/textures/PLUTICON.PNG" , Plut_MapNames },
|
|
{ ExpansionData::PWAD, commercial, pack_master, "DOOM 2: MASTER LEVELS", DOOMWADDIR"DOOM2.WAD", DOOMWADDIR"MASTERLEVELS.WAD", "base/textures/MASTICON.PNG" , Mast_MapNames },
|
|
{ ExpansionData::PWAD, commercial, pack_nerve, "DOOM 2: NO REST FOR THE LIVING", DOOMWADDIR"DOOM2.WAD", DOOMWADDIR"NERVE.WAD", "base/textures/NERVEICON.PNG" , Nerve_MapNames },
|
|
};
|
|
|
|
int classicRemap[K_LAST_KEY];
|
|
|
|
const ExpansionData * GetCurrentExpansion() {
|
|
return &App_Expansion_Data_Local[ DoomLib::expansionSelected ];
|
|
}
|
|
|
|
void SetCurrentExpansion( int expansion ) {
|
|
expansionDirty = true;
|
|
expansionSelected = expansion;
|
|
}
|
|
|
|
void SetIdealExpansion( int expansion ) {
|
|
idealExpansion = expansion;
|
|
}
|
|
|
|
idStr currentMapName;
|
|
idStr currentDifficulty;
|
|
|
|
void SetCurrentMapName( idStr name ) { currentMapName = name; }
|
|
const idStr & GetCurrentMapName() { return currentMapName; }
|
|
void SetCurrentDifficulty( idStr name ) { currentDifficulty = name; }
|
|
const idStr & GetCurrentDifficulty() { return currentDifficulty; }
|
|
|
|
int currentplayer = -1;
|
|
|
|
Globals *globaldata[4];
|
|
|
|
RecvFunc Recv;
|
|
SendFunc Send;
|
|
SendRemoteFunc SendRemote;
|
|
|
|
|
|
bool Active = true;
|
|
DoomInterface Interface;
|
|
|
|
int idealExpansion = 0;
|
|
int expansionSelected = 0;
|
|
bool expansionDirty = true;
|
|
|
|
bool skipToLoad = false;
|
|
char loadGamePath[MAX_PATH];
|
|
|
|
bool skipToNew = false;
|
|
int chosenSkill = 0;
|
|
int chosenEpisode = 1;
|
|
|
|
idMatchParameters matchParms;
|
|
|
|
void * (*Z_Malloc)( int size, int tag, void* user ) = NULL;
|
|
void (*Z_FreeTag)(int lowtag );
|
|
|
|
idArray< idSysMutex, 4 > playerScreenMutexes;
|
|
|
|
void ExitGame() {
|
|
// TODO: If we ever support splitscreen and online,
|
|
// we'll have to call D_QuitNetGame for all local players.
|
|
DoomLib::SetPlayer( 0 );
|
|
D_QuitNetGame();
|
|
|
|
session->QuitMatch();
|
|
}
|
|
|
|
void ShowXToContinue( bool activate ) {
|
|
}
|
|
|
|
/*
|
|
========================
|
|
DoomLib::GetGameSKU
|
|
========================
|
|
*/
|
|
gameSKU_t GetGameSKU() {
|
|
|
|
if ( common->GetCurrentGame() == DOOM_CLASSIC ) {
|
|
return GAME_SKU_DOOM1_BFG;
|
|
} else if ( common->GetCurrentGame() == DOOM2_CLASSIC ) {
|
|
return GAME_SKU_DOOM2_BFG;
|
|
}
|
|
|
|
assert( false && "Invalid basepath" );
|
|
return GAME_SKU_DCC;
|
|
}
|
|
|
|
/*
|
|
========================
|
|
DoomLib::ActivateGame
|
|
========================
|
|
*/
|
|
void ActivateGame() {
|
|
Active = true;
|
|
|
|
// Turn off menu toggler
|
|
int originalPlayer = DoomLib::GetPlayer();
|
|
|
|
for ( int i = 0; i < Interface.GetNumPlayers(); i++ ) {
|
|
DoomLib::SetPlayer(i);
|
|
::g->menuactive = false;
|
|
}
|
|
|
|
globalPauseTime = false;
|
|
|
|
DoomLib::SetPlayer( originalPlayer );
|
|
}
|
|
|
|
/*
|
|
========================
|
|
DoomLib::HandleEndMatch
|
|
========================
|
|
*/
|
|
void HandleEndMatch() {
|
|
if ( session->GetGameLobbyBase().IsHost() ) {
|
|
ShowXToContinue( false );
|
|
session->EndMatch();
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
extern void I_InitGraphics();
|
|
extern void D_DoomMain();
|
|
extern bool D_DoomMainPoll();
|
|
extern void I_InitInput();
|
|
extern void D_RunFrame( bool );
|
|
extern void I_ShutdownSound();
|
|
extern void I_ShutdownMusic();
|
|
extern void I_ShutdownGraphics();
|
|
extern void I_ProcessSoundEvents( void );
|
|
|
|
|
|
void DoomLib::InitGlobals( void *ptr /* = NULL */ )
|
|
{
|
|
if (ptr == NULL)
|
|
ptr = new Globals;
|
|
|
|
globaldata[currentplayer] = static_cast<Globals*>(ptr);
|
|
|
|
memset( globaldata[currentplayer], 0, sizeof(Globals) );
|
|
g = globaldata[currentplayer];
|
|
g->InitGlobals();
|
|
|
|
}
|
|
|
|
void *DoomLib::GetGlobalData( int player ) {
|
|
return globaldata[player];
|
|
}
|
|
|
|
void DoomLib::InitControlRemap() {
|
|
|
|
memset( classicRemap, K_NONE, sizeof( classicRemap ) );
|
|
|
|
classicRemap[K_JOY3] = KEY_TAB ;
|
|
classicRemap[K_JOY4] = K_MINUS;
|
|
classicRemap[K_JOY2] = K_EQUALS;
|
|
classicRemap[K_JOY9] = K_ESCAPE ;
|
|
classicRemap[K_JOY_STICK1_UP] = K_UPARROW ;
|
|
classicRemap[K_JOY_DPAD_UP] = K_UPARROW ;
|
|
classicRemap[K_JOY_STICK1_DOWN] = K_DOWNARROW ;
|
|
classicRemap[K_JOY_DPAD_DOWN] = K_DOWNARROW ;
|
|
classicRemap[K_JOY_STICK1_LEFT] = K_LEFTARROW ;
|
|
classicRemap[K_JOY_DPAD_LEFT] = K_LEFTARROW ;
|
|
classicRemap[K_JOY_STICK1_RIGHT] = K_RIGHTARROW ;
|
|
classicRemap[K_JOY_DPAD_RIGHT] = K_RIGHTARROW ;
|
|
classicRemap[K_JOY1] = K_ENTER;
|
|
|
|
|
|
}
|
|
|
|
keyNum_t DoomLib::RemapControl( keyNum_t key ) {
|
|
|
|
if( classicRemap[ key ] == K_NONE ) {
|
|
return key;
|
|
} else {
|
|
|
|
if( ::g->menuactive && key == K_JOY2 ) {
|
|
return K_BACKSPACE;
|
|
}
|
|
|
|
return (keyNum_t)classicRemap[ key ];
|
|
}
|
|
|
|
}
|
|
|
|
void DoomLib::InitGame( int argc, char** argv )
|
|
{
|
|
::g->myargc = argc;
|
|
::g->myargv = argv;
|
|
|
|
InitControlRemap();
|
|
|
|
|
|
|
|
D_DoomMain();
|
|
}
|
|
|
|
bool DoomLib::Poll()
|
|
{
|
|
return D_DoomMainPoll();
|
|
}
|
|
|
|
bool TryRunTics( idUserCmdMgr * userCmdMgr );
|
|
bool DoomLib::Tic( idUserCmdMgr * userCmdMgr )
|
|
{
|
|
return TryRunTics( userCmdMgr );
|
|
}
|
|
|
|
void D_Wipe();
|
|
void DoomLib::Wipe()
|
|
{
|
|
D_Wipe();
|
|
}
|
|
|
|
void DoomLib::Frame( int realoffset, int buffer )
|
|
{
|
|
::g->realoffset = realoffset;
|
|
|
|
// The render thread needs to read the player's screens[0] array,
|
|
// so updating it needs to be in a critical section.
|
|
// This may seem like a really broad mutex (which it is), and if performance
|
|
// suffers too much, we can try to narrow the scope.
|
|
// Just be careful, because the player's screen data is updated in many different
|
|
// places.
|
|
if ( 0 <= currentplayer && currentplayer <= 4 ) {
|
|
idScopedCriticalSection crit( playerScreenMutexes[currentplayer] );
|
|
|
|
D_RunFrame( true );
|
|
}
|
|
}
|
|
|
|
void DoomLib::Draw()
|
|
{
|
|
R_RenderPlayerView (&::g->players[::g->displayplayer]);
|
|
}
|
|
|
|
angle_t GetViewAngle()
|
|
{
|
|
return g->viewangle;
|
|
}
|
|
|
|
void SetViewAngle( angle_t ang )
|
|
{
|
|
g->viewangle = ang;
|
|
::g->viewxoffset = (finesine[g->viewangle>>ANGLETOFINESHIFT]*::g->realoffset) >> 8;
|
|
::g->viewyoffset = (finecosine[g->viewangle>>ANGLETOFINESHIFT]*::g->realoffset) >> 8;
|
|
|
|
}
|
|
|
|
|
|
void SetViewX( fixed_t x )
|
|
{
|
|
::g->viewx = x;
|
|
}
|
|
|
|
void SetViewY( fixed_t y )
|
|
{
|
|
::g->viewy = y;
|
|
}
|
|
|
|
|
|
fixed_t GetViewX()
|
|
{
|
|
return ::g->viewx + ::g->viewxoffset;
|
|
}
|
|
|
|
fixed_t GetViewY()
|
|
{
|
|
return ::g->viewy + ::g->viewyoffset;
|
|
}
|
|
|
|
void DoomLib::Shutdown() {
|
|
//D_QuitNetGame ();
|
|
I_ShutdownSound();
|
|
I_ShutdownGraphics();
|
|
|
|
W_Shutdown();
|
|
|
|
// De-allocate the zone memory (never happened in original doom, until quit)
|
|
if ( ::g->mainzone ) {
|
|
free( ::g->mainzone );
|
|
}
|
|
|
|
// Delete the globals
|
|
if ( globaldata[currentplayer] ) {
|
|
delete globaldata[currentplayer];
|
|
globaldata[currentplayer] = NULL;
|
|
}
|
|
}
|
|
|
|
// static
|
|
void DoomLib::SetPlayer( int id )
|
|
{
|
|
currentplayer = id;
|
|
|
|
if ( id < 0 || id >= MAX_PLAYERS ) {
|
|
g = NULL;
|
|
}
|
|
else {
|
|
|
|
// Big Fucking hack.
|
|
if( globalNetworking && session->GetGameLobbyBase().GetMatchParms().matchFlags | MATCH_ONLINE ) {
|
|
currentplayer = 0;
|
|
}
|
|
|
|
g = globaldata[currentplayer];
|
|
}
|
|
}
|
|
|
|
void DoomLib::SetNetworking( RecvFunc rf, SendFunc sf, SendRemoteFunc sendRemote )
|
|
{
|
|
Recv = rf;
|
|
Send = sf;
|
|
SendRemote = sendRemote;
|
|
}
|
|
|
|
int DoomLib::GetPlayer()
|
|
{
|
|
return currentplayer;
|
|
}
|
|
|
|
byte DoomLib::BuildSourceDest( int toNode ) {
|
|
byte sourceDest = 0;
|
|
sourceDest |= ::g->consoleplayer << 2;
|
|
sourceDest |= RemoteNodeToPlayerIndex( toNode );
|
|
return sourceDest;
|
|
}
|
|
|
|
void I_Printf(char *error, ...);
|
|
|
|
void DoomLib::GetSourceDest( byte sourceDest, int* source, int* dest ) {
|
|
|
|
int src = (sourceDest & 12) >> 2;
|
|
int dst = sourceDest & 3;
|
|
|
|
*source = PlayerIndexToRemoteNode( src );
|
|
|
|
//I_Printf( "GetSourceDest Current Player(%d) %d --> %d\n", GetPlayer(), src, *source );
|
|
*dest = PlayerIndexToRemoteNode( dst );
|
|
}
|
|
|
|
int nodeMap[4][4] = {
|
|
{0, 1, 2, 3}, //Player 0
|
|
{1, 0, 2, 3}, //Player 1
|
|
{2, 0, 1, 3}, //Player 2
|
|
{3, 0, 1, 2} //Player 3
|
|
};
|
|
|
|
int DoomLib::RemoteNodeToPlayerIndex( int node ) {
|
|
//This needs to be called with the proper doom globals set so this calculation will work properly
|
|
|
|
/*
|
|
int player = ::g->consoleplayer;
|
|
if (player == 2 && node == 2 ) {
|
|
int suck = 0;
|
|
}
|
|
if( node == player ) {
|
|
return 0;
|
|
}
|
|
if( node - player <= 0 ) {
|
|
return node+1;
|
|
}
|
|
return node;*/
|
|
return nodeMap[::g->consoleplayer][node];
|
|
|
|
}
|
|
|
|
int indexMap[4][4] = {
|
|
{0, 1, 2, 3}, //Player 0
|
|
{1, 0, 2, 3}, //Player 1
|
|
{1, 2, 0, 3}, //Player 2
|
|
{1, 2, 3, 0} //Player 3
|
|
};
|
|
|
|
int DoomLib::PlayerIndexToRemoteNode( int index ) {
|
|
/*int player = ::g->consoleplayer;
|
|
if( index == 0 ) {
|
|
return player;
|
|
}
|
|
if( index <= player ) {
|
|
return index-1;
|
|
}
|
|
return index;*/
|
|
return indexMap[::g->consoleplayer][index];
|
|
}
|
|
|
|
void I_Error (char *error, ...);
|
|
extern bool useTech5Packets;
|
|
|
|
void DoomLib::PollNetwork() {
|
|
#if 0
|
|
if ( !useTech5Packets ) {
|
|
|
|
if ( !globalNetworking ) {
|
|
return;
|
|
}
|
|
|
|
int c;
|
|
struct sockaddr fromaddress;
|
|
socklen_t fromlen;
|
|
doomdata_t sw;
|
|
|
|
while(1) {
|
|
int receivedSize = recvfrom( ::g->insocket, &sw, sizeof( doomdata_t ), MSG_DONTWAIT, &fromaddress, &fromlen );
|
|
//c = WSARecvFrom(::g->insocket, &buffer, 1, &num_recieved, &flags, (struct sockaddr*)&fromaddress, &fromlen, 0, 0);
|
|
|
|
if ( receivedSize < 0 )
|
|
{
|
|
int err = sys_net_errno;
|
|
if (err != SYS_NET_EWOULDBLOCK ) {
|
|
I_Error ("GetPacket: %d", err );
|
|
//I_Printf ("GetPacket: %s",strerror(errno));
|
|
}
|
|
return;
|
|
}
|
|
|
|
printf( "RECEIVED PACKET!!\n" );
|
|
|
|
int source;
|
|
int dest;
|
|
GetSourceDest( sw.sourceDest, &source, &dest );
|
|
|
|
//Push the packet onto the network stack to be processed.
|
|
DoomLib::Send( (char*)&sw, receivedSize, NULL, dest );
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void DoomLib::SendNetwork() {
|
|
|
|
if ( !globalNetworking ) {
|
|
return;
|
|
}
|
|
DoomLib::SendRemote();
|
|
}
|
|
|
|
void DoomLib::RunSound() {
|
|
|
|
I_ProcessSoundEvents();
|
|
}
|
|
|