Files
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

282 lines
5.4 KiB
C++

#pragma once
#include "receiver.h"
#include "time.h"
#include "hostid.h"
//WinSock support :ADB 01/06/07
#include <Winsock2.h>
#include <Ws2tcpip.h>
class Mission;
class NetworkManager;
class NotationFile;
//
//---------------------------------------------------
// Support types for interest manager
//---------------------------------------------------
//
typedef Enumeration InterestZoneID;
const InterestZoneID NullInterestZoneID = 0;
//~~~~~~~~~~~~~~~~~~~~~~~~~~ NetworkAddress ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
typedef LWord NetworkAddress;
extern const NetworkAddress NullNetworkAddress;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~ NetworkClient ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class NetworkPacket;
class NetworkClient:
public Receiver
{
friend class NetworkManager;
//##########################################################################
// Shared Data support
//
public:
static Derivation *GetClassDerivations();
static SharedData DefaultData;
//##########################################################################
// Construction and destruction support
//
public:
enum ClientID {
NetworkManagerClientID = 0,
EntityManagerClientID = 1,
HostManagerClientID = 2,
InterestManagerClientID = 3,
ApplicationClientID = 4,
ConsoleClientID = 5,
IcomManagerClientID = 6
};
private:
ClientID
clientID;
protected:
NetworkClient(
ClassID class_ID,
SharedData &virtual_data,
ClientID clientID
);
public:
~NetworkClient();
Logical
TestInstance() const;
//##########################################################################
// Message packet receiving
//
public:
virtual void
ReceiveNetworkPacket(
NetworkPacket *packet,
Receiver::Message *packet_message
);
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Network ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#define NETWORKMANAGER_BUFFER_SIZE 1600
class NetworkManager__ReceiveEggFileMessage;
class NetworkManager:
public NetworkClient
{
//##########################################################################
// Shared Data support
//
public:
static Derivation *GetClassDerivations();
static SharedData DefaultData;
public:
typedef Enumeration GameID;
//WinSock support :ADB 01/06/07
//const NetworkAddress&
// GetAddress()
NetworkAddress* GetAddress()
{return addresses;}
NetworkManager(SharedData &shared_data);
~NetworkManager();
void
SetGameID(GameID new_id)
{gameID = new_id;}
virtual void
Send(
Message *what,
ClientID to,
HostID host_id
);
void
Broadcast(
Message *what,
ClientID to
);
virtual void
ExclusiveBroadcast(
Message *what,
ClientID to
);
Logical
RoutePacket();
virtual Logical
ExecuteBackground();
NetworkClient*
GetNetworkClientPointer(ClientID client_id);
virtual void
StartConnecting(Mission *mission);
virtual Logical
Shutdown();
virtual void
Marker(char *) {};
enum NetworkMode
{
ReliableMode,
UnreliableMode
};
virtual void
Mode(NetworkMode) {};
// protected: //GY for test only
virtual Logical
CheckBuffers(NetworkPacket*);
virtual void
RemovePacket(NetworkPacket *packet);
GameID
gameID;
//WinSock support :ADB 01/06/07
//NetworkAddress address;
NetworkAddress* addresses;
int num_addresses;
//struct addrinfo* address;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Message Support
//
public:
//
// Message IDs
//
enum
{
ReceiveEggFileMessageID = NetworkClient::NextMessageID,
NextMessageID
};
//
// Message types
//
typedef NetworkManager__ReceiveEggFileMessage
ReceiveEggFileMessage;
//
// Message table
//
static const HandlerEntry
MessageHandlerEntries[];
//static MessageHandlerSet MessageHandlers;
static MessageHandlerSet& GetMessageHandlers();
void
ReceiveEggFileMessageHandler(ReceiveEggFileMessage* EggMessage);
protected:
char
*eggTempBuffer;
NotationFile
*networkEggNotationFile;
long
eggTempNext;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~ NetworkManager messages ~~~~~~~~~~~~~~~~~~~~~~~~~
// NetworkManager__ReceiveEggFileMessage
// NOTE: this message should be setup as variable length rather than fixing the
// size at 1000, I wasn't sure how to do this and there wasn't anyone around
// to ask at the time so I did it this way temporarily.
//
class NetworkManager__ReceiveEggFileMessage:
public Receiver__Message
{
public:
NetworkManager__ReceiveEggFileMessage(
int sequence_number,
int total_file_length,
char* notation_data,
int length
):
Receiver__Message(
NetworkManager::ReceiveEggFileMessageID,
sizeof(NetworkManager__ReceiveEggFileMessage)
),
sequenceNumber(sequence_number),
notationFileLength(total_file_length),
thisMessageLength(length)
{Mem_Copy(notationData,notation_data,length,sizeof(notationData));}
int
sequenceNumber;
int
notationFileLength;
int
thisMessageLength;
char
notationData[1000];
};
//~~~~~~~~~~~~~~~~~~~~~~~~ NetworkPacketHeader ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class NetworkPacketHeader
{
public:
NetworkClient::ClientID
clientID;
NetworkManager::GameID
gameID;
HostID
fromHost;
Time
timeStamp;
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~ NetworkPacket ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class NetworkPacket:
public NetworkPacketHeader
{
public:
Receiver::Message
messageData;
};
bool operator==(SOCKADDR_IN &address1, SOCKADDR_IN &address2)
{
return (address1.sin_family == address2.sin_family &&
address1.sin_addr.S_un.S_addr == address2.sin_addr.S_un.S_addr &&
address1.sin_port == address2.sin_port);
}