Files
BT412/engine/MUNGA_L4/L4NET.H
T
arcattackandClaude Opus 4.8 7b7d465e5e Initial commit: bt411 -- standalone Windows BattleTech (Tesla 4.10 port)
Clean, self-contained extraction of the BattleTech-specific work from the
reverse-engineering workspace -- engine + game + content + build, with nothing
from Red Planet or the raw archive dumps. Builds green (Win32) and runs the
single-player drive->animate->target->fire->damage->destroy loop out of the box.

Layout:
  engine/   MUNGA + MUNGA_L4 shared 2007 engine, carrying our BT render/loader
            work (bgfload/L4D3D/L4VIDEO: BSL bit-slice decode, LOD/ground/shadow
            models) + image codec; the minimal rp/ headers the audio HAL needs
  game/     reconstructed BT logic + surviving-original BT source + fwd shims
            + WinMain launcher
  content/  full runtime tree (BTL4.RES, VIDEO/, GAUGE/, AUDIO/, eggs, BTDPL.INI)
  docs/     format specs + reconstruction ledgers
  reference/ raw Ghidra pseudocode (recon source-of-truth) + decomp exporter
  tools/    MP console emulator + map/resource scanners

One top-level CMake builds munga_engine lib + bt410_l4 game lib + btl4.exe.
All paths relativized (186 fwd shims + ~437 CMake abs paths -> repo-relative);
DXSDK is the one external, overridable via -DDXSDK. Verified: builds to a
byte-identical 2.27MB exe and runs combat (TARGET DESTROYED, 0 crashes) against
the bundled content.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-05 21:03:40 -05:00

424 lines
11 KiB
C++

//===========================================================================//
// File: l4net.hh //
// Project: MUNGA Brick: Network Manager //
// Contents: Interface specification for network brick //
//---------------------------------------------------------------------------//
// Date Who Modification //
// -------- --- ---------------------------------------------------------- //
// 03/02/95 GAC Initial coding. //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// PROPRIETARY AND CONFIDENTIAL //
//===========================================================================//
#pragma once
#include "l4host.h"
#include "..\munga\network.h"
#include "..\munga\hostmgr.h"
//WinSock support :ADB 01/06/07
//#include "..\munga\netnub.h"
#define NETNUB_TCP_OPEN 3 // Opens a TCP stream to another computer
#define NETNUB_TCP_LISTEN 4 // Queue's a TCP listen that we can accept a connection on
#define MULTIPLE_SEND_PACKET_MAX 10
#define MAX_RECEIVE_DATA_SIZE 1600
#include <Winsock2.h>
#include <Ws2tcpip.h>
class NotationFile;
class L4NetworkManager__ReceiveEggFileMessage;
class L4NetworkManager__AcknowledgeEggFileMessage;
class L4NetworkManager__HostConnectedMessage;
class L4NetworkManager__HostDisconnectedMessage;
class NetNub
{
friend int
Netnub_Open_File(
const char* filename,
int access,
unsigned int model
);
friend int
Netnub_Write_File(
int handle,
void *buffer,
size_t length
);
friend int
Netnub_Close_File(int handle);
public:
//WinSock support :ADB 01/06/07
//static void SendCommand();
};
//extern Netcom_Ptr
// Net_Common_Ptr;
//~~~~~~~~~~~~~~~~~~~~~ MessageQueue__SendRequest ~~~~~~~~~~~~~~~~~~~~~~~~~~
class MessageQueue__SendRequest:
public Plug
{
friend class HostMessageBuffer__MessageQueue;
friend class L4NetworkManager__MessageBuffer;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private methods
//
private:
MessageQueue__SendRequest(
NetworkClient::ClientID client_ID,
Receiver::Message *message
);
~MessageQueue__SendRequest();
Logical
TestInstance() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private data
//
private:
NetworkClient::ClientID
clientID;
Receiver::Message
*messageToSend;
};
//~~~~~~~~~~~~~~~~~~~ HostMessageBuffer__MessageQueue ~~~~~~~~~~~~~~~~~~~~~~
class HostMessageBuffer__MessageQueue:
public Node
{
friend class L4NetworkManager__MessageBuffer;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private methods
//
private:
HostMessageBuffer__MessageQueue(HostID host_ID);
~HostMessageBuffer__MessageQueue();
Logical
TestInstance() const;
void
AddSendRequest(
NetworkClient::ClientID client_ID,
Receiver::Message *message
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private data
//
private:
HostID
hostID;
typedef MessageQueue__SendRequest
SendRequest;
ChainOf<SendRequest*>
sendRequestSocket;
};
//~~~~~~~~~~~~~~~~~~ L4NetworkManager__MessageBuffer ~~~~~~~~~~~~~~~~~~~~~~~
class L4NetworkManager__MessageBuffer:
public Node
{
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Public methods
//
public:
L4NetworkManager__MessageBuffer(L4NetworkManager *network_manager);
~L4NetworkManager__MessageBuffer();
Logical
TestInstance() const;
Logical
IsEmpty();
void
AddSendRequest(
HostID host_ID,
NetworkClient::ClientID client_ID,
Receiver::Message *message
);
void
AttemptToSend();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private data
//
private:
L4NetworkManager
*networkManager;
typedef HostMessageBuffer__MessageQueue
MessageQueue;
TableOf<MessageQueue*, HostID>
messageQueueSocket;
IteratorPosition
currentQueueIndex;
CollectionSize
bufferSize;
#ifdef LAB_ONLY
CollectionSize
messageCount,
maxBufferSize;
#endif
};
inline Logical
L4NetworkManager__MessageBuffer::IsEmpty()
{
Check(this);
return (bufferSize == 0);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~ l4Network manager~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class L4NetworkManager: public NetworkManager
{
friend class L4NetworkManager__MessageBuffer;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Constructor, Destructor, Testing
//
public:
L4NetworkManager();
~L4NetworkManager();
static Logical TestClass();
Logical TestInstance() const;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Network message methods
//
public:
void Send(
Message *what,
ClientID to,
HostID host_ID);
void ExclusiveBroadcast(
Message *what,
ClientID to);
void StartConnecting(Mission *mission);
Logical Shutdown();
Logical CheckBuffers(NetworkPacket *packet);
void RemovePacket(NetworkPacket *packet);
Logical ExecuteBackground();
void Marker(char *marker_text);
void Mode(NetworkMode myMode);
void CreateConsoleHost();
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Network maintenance support
//
public:
int netPlayerCount;
enum NetworkState
{
NormalState,
ConsoleOnly
};
enum NetworkStartupMode
{
SlaveMode,
MasterMode
};
bool CheckSocket(SOCKET socket, SOCKADDR_IN *remoteEndpoint);
bool ResolveAddress(CString host_name, SOCKADDR_IN *address);
//WinSock support :ADB 01/06/07
NetworkAddress* GetMyAddress();
//WinSock support :ADB 01/06/07
SOCKET OpenConnection(
int connection_type, // NETNUB_TCP_LISTEN or NETNUB_TCP_OPEN
int local_port,
int remote_port,
int internet_address);
void CloseConnection(SOCKET socket_ptr); // socket address from netnub (to close)
Logical GetNextMungaPacket(
NetworkPacket *network_packet,
HostManager::RemoteHostIterator* all_iterator);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Shared Data support
//
public:
static Derivation *GetClassDerivations();
static SharedData DefaultData;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Message Support
//
public:
//
// Message IDs
//
enum
{
AcknowledgeEggFileMessageID = NetworkManager::NextMessageID,
HostConnectedMessageID,
HostDisconnectedMessageID,
NextMessageID
};
//
// Message types
//
typedef L4NetworkManager__AcknowledgeEggFileMessage
AcknowledgeEggFileMessage;
typedef L4NetworkManager__HostConnectedMessage
HostConnectedMessage;
typedef L4NetworkManager__HostDisconnectedMessage
HostDisconnectedMessage;
//
// Message table
//
static const HandlerEntry MessageHandlerEntries[];
//static MessageHandlerSet MessageHandlers;
static MessageHandlerSet& GetMessageHandlers();
void ReceiveEggFileMessageHandler(
ReceiveEggFileMessage *EggMessage);
void AcknowledgeEggFileMessageHandler(
AcknowledgeEggFileMessage *AcknowledgeEgg);
void HostConnectedMessageHandler(
HostConnectedMessage *HostConnected);
void HostDisconnectedMessageHandler(
HostDisconnectedMessage *ConsoleDisconnect);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private methods
//
private:
typedef ChainOf<L4Host*>
DroppedMessageHostSocket;
typedef ChainIteratorOf<L4Host*>
DroppedMessageHostIterator;
Logical
SendMessageToNetnub(
Message *message,
ClientID client_ID,
HostID host_ID
);
void
SendBatchedMessageToNetnub(
Message *message,
ClientID client,
DroppedMessageHostSocket *dropped_message_host_socket
);
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Private Data
//
private:
int
numberOfMungaHostsConnected,
numberOfConsoleHostsConnected,
remoteHostCount;
NetworkStartupMode networkStartupMode;
Logical eggAcknowledged;
NetworkState currentNetworkState;
L4Host *myConsoleHost;
HostID nextOpenHostID;
IteratorPosition lastHostIteratorPosition;
typedef L4NetworkManager__MessageBuffer
MessageBuffer;
MessageBuffer
messageBuffer;
//WinSock Support
WSADATA* wsaData;
//hostent* thisHost;
addrinfo* thisHost;
SOCKET gameListenerSocket;
SOCKET consoleListenerSocket;
};
//~~~~~~~~~~~~~~~~~~~~~~ L4NetworkManager inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// L4NetworkManager__AcknowledgeEggFileMessage
// This message is sent back to the console to acknowledge receipt of the
// egg, it indicates this computer has established all it's connections and
// the console can procede with the next host
//
class L4NetworkManager__AcknowledgeEggFileMessage:
public NetworkManager::Message
{
public:
L4NetworkManager__AcknowledgeEggFileMessage():
NetworkManager::Message(
L4NetworkManager::AcknowledgeEggFileMessageID,
sizeof(L4NetworkManager__AcknowledgeEggFileMessage)
){}
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// L4NetworkManager__HostConnectedMessage
// This message is generated internally by CheckBuffers and indicates that
// a host has connected up to us. This is an INTERNAL message only and is
// not ment to be sent on the network.
class L4NetworkManager__HostConnectedMessage :
public NetworkManager::Message
{
public:
L4NetworkManager__HostConnectedMessage(HostID host_id, const SOCKADDR_IN &network_address, unsigned long stream_pointer) :
NetworkManager::Message(L4NetworkManager::HostConnectedMessageID, sizeof(L4NetworkManager__HostConnectedMessage)),
hostID(host_id),
networkAddress(network_address),
streamPointer(stream_pointer)
{
}
HostID hostID;
SOCKADDR_IN networkAddress;
unsigned long streamPointer;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// L4NetworkManager__HostDisconnectedMessage
// The console is expected to send us this message if it disconnects from us
// for any reason. This allows the local host to setup the internal state
// so the game will auto start even if the console can't stay connected to us
// for some reason (for example, the console simulator in the game code can't
// connect to more than one host at once).
// !!! CheckBuffers should poll the connection state of all the streams and
// generate this message automatically whenever a host drops off the net.
// !!! HACK At the moment this message is always treated as if it came from
// the console host, so it should only be sent down the console stream.
//
class L4NetworkManager__HostDisconnectedMessage :
public NetworkManager::Message
{
public:
L4NetworkManager__HostDisconnectedMessage(HostID host_id, unsigned long stream_pointer) :
NetworkManager::Message(L4NetworkManager::HostDisconnectedMessageID, sizeof(L4NetworkManager__HostDisconnectedMessage)),
hostID(host_id),
streamPointer(stream_pointer)
{
}
HostID hostID;
unsigned long streamPointer;
};