SteamNetTransport: the Steam wire is implemented and live

Steamworks SDK 1.64 vendored at extern/steamworks_sdk_164 (headers +
win32 redistributables only; .gitignore trims the rest). Both projects
build with RP412_STEAM; activation stays behind the RP412STEAM=1
environment switch, so plain desktop runs never touch Steam.

L4STEAMTRANSPORT.cpp implements NetTransport on ISteamNetworkingSockets
with FakeIP: SteamNetTransport_Install brings up SteamAPI, relay
network access, and a two-port FakeIP identity (fake port 0 = console
channel, 1 = game mesh), then swaps the process wire; any failure logs
the reason and the game carries on over TCP. Addressing keeps the
engine untouched: all pods share the -net port convention, eggs carry
fakeip:engineport, and the transport alone translates engine ports to
Steam fake ports via the lobby-fed peer table (RegisterPeer). Connect
mirrors the TCP retry-while-refused loop; Receive normalizes message
lanes back into the stream semantics CheckBuffers expects.

Runtime verified on this box: RP412STEAM=1 under AppID 480 came up as
169.254.59.52 (fake ports 32256/32257); without Steam credentials it
falls back to TCP cleanly; default boot logs no Steam lines at all.
steam_api.dll ships in the dist.

Next: the lobby layer (ISteamMatchmaking member data -> RegisterPeer +
egg build + RPL4CONSOLE marshal), which needs a second account to test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Cyd
2026-07-12 20:34:07 -05:00
co-authored by Claude Fable 5
parent 7315f3488d
commit ff6ec8c56a
61 changed files with 34096 additions and 112 deletions
+651
View File
@@ -0,0 +1,651 @@
#include "mungal4.h"
#pragma hdrstop
#include "l4steamtransport.h"
#ifdef RP412_STEAM
#include "l4nettransport.h"
// The engine builds with /Zp1; Valve's ABI expects default packing.
// Callback structs carry their own pack pragmas, but everything else
// must see the platform default.
#pragma pack(push, 8)
#include "steam/steam_api.h"
#include "steam/isteamnetworkingsockets.h"
#include "steam/isteamnetworkingutils.h"
#include "steam/steamnetworkingfakeip.h"
#pragma pack(pop)
//########################################################################
// SteamNetTransport - see l4steamtransport.h for the design. The
// engine is single threaded and so is this: every entry point pumps
// SteamAPI_RunCallbacks, which is where the status-changed callback
// fires (accepting incoming connections and marking drops).
//########################################################################
namespace
{
enum
{
maxListeners = 4,
maxConnections = 32,
maxPeers = 16,
maxPending = 8,
leftoverSize = 4096
};
struct ListenerRecord
{
HSteamListenSocket handle;
int fakePortIndex;
unsigned short enginePort; // host order
HSteamNetConnection pending[maxPending];
int pendingCount;
};
struct ConnectionRecord
{
HSteamNetConnection handle;
unsigned long remoteIP; // network order
unsigned short remoteEnginePort; // network order
Logical connected;
Logical dead;
char leftover[leftoverSize];
int leftoverCount;
};
struct PeerRecord
{
unsigned long fakeIP; // host order
unsigned short fakeGamePort; // host order
};
Logical gSteamReady = False;
unsigned long gLocalFakeIP = 0; // host order
unsigned short gLocalFakePorts[2] = { 0, 0 };
char gLocalFakeAddressString[32] = "";
// engine ports in the order Listen sees them: [0] console, [1] game
unsigned short gEnginePorts[2] = { 0, 0 };
int gEnginePortCount = 0;
ListenerRecord gListeners[maxListeners];
int gListenerCount = 0;
ConnectionRecord gConnections[maxConnections];
int gConnectionCount = 0;
PeerRecord gPeers[maxPeers];
int gPeerCount = 0;
ListenerRecord *
FindListener(HSteamListenSocket handle)
{
for (int i = 0; i < gListenerCount; ++i)
{
if (gListeners[i].handle == handle)
{
return &gListeners[i];
}
}
return NULL;
}
ConnectionRecord *
FindConnection(HSteamNetConnection handle)
{
for (int i = 0; i < gConnectionCount; ++i)
{
if (gConnections[i].handle == handle)
{
return &gConnections[i];
}
}
return NULL;
}
ConnectionRecord *
AddConnection(
HSteamNetConnection handle,
unsigned long remote_ip_net,
unsigned short remote_engine_port_net
)
{
if (gConnectionCount >= maxConnections)
{
return NULL;
}
ConnectionRecord *record = &gConnections[gConnectionCount++];
memset(record, 0, sizeof(*record));
record->handle = handle;
record->remoteIP = remote_ip_net;
record->remoteEnginePort = remote_engine_port_net;
return record;
}
void
RemoveConnection(HSteamNetConnection handle)
{
for (int i = 0; i < gConnectionCount; ++i)
{
if (gConnections[i].handle == handle)
{
gConnections[i] = gConnections[gConnectionCount - 1];
--gConnectionCount;
return;
}
}
}
unsigned short
LookupPeerFakeGamePort(unsigned long fake_ip_host)
{
for (int i = 0; i < gPeerCount; ++i)
{
if (gPeers[i].fakeIP == fake_ip_host)
{
return gPeers[i].fakeGamePort;
}
}
return 0;
}
//---------------------------------------------------------------
// Status-changed callback (fires inside SteamAPI_RunCallbacks on
// the game thread): accept incoming, queue connected, mark drops
//---------------------------------------------------------------
void __cdecl
OnConnectionStatusChanged(SteamNetConnectionStatusChangedCallback_t *status)
{
switch (status->m_info.m_eState)
{
case k_ESteamNetworkingConnectionState_Connecting:
if (status->m_info.m_hListenSocket != k_HSteamListenSocket_Invalid)
{
// incoming: accept immediately, queue it when Connected
SteamNetworkingSockets()->AcceptConnection(status->m_hConn);
}
break;
case k_ESteamNetworkingConnectionState_Connected:
if (status->m_info.m_hListenSocket != k_HSteamListenSocket_Invalid)
{
ListenerRecord *listener = FindListener(status->m_info.m_hListenSocket);
if (listener != NULL && listener->pendingCount < maxPending)
{
listener->pending[listener->pendingCount++] = status->m_hConn;
}
}
else
{
ConnectionRecord *record = FindConnection(status->m_hConn);
if (record != NULL)
{
record->connected = True;
}
}
break;
case k_ESteamNetworkingConnectionState_ProblemDetectedLocally:
case k_ESteamNetworkingConnectionState_ClosedByPeer:
{
ConnectionRecord *record = FindConnection(status->m_hConn);
if (record != NULL)
{
record->dead = True;
}
}
break;
}
}
//---------------------------------------------------------------
// The transport
//---------------------------------------------------------------
class SteamNetTransport:
public NetTransport
{
public:
Logical
Startup()
{
// Install() already brought Steam up; the network manager
// just confirms the transport is live
return gSteamReady;
}
void
Cleanup()
{
// mission teardown (single-binary race loop): drop the
// wire but keep the Steam API up - the lobby lives on
for (int i = 0; i < gConnectionCount; ++i)
{
SteamNetworkingSockets()->CloseConnection(
gConnections[i].handle, 0, "mission teardown", true);
}
gConnectionCount = 0;
for (int j = 0; j < gListenerCount; ++j)
{
SteamNetworkingSockets()->CloseListenSocket(gListeners[j].handle);
}
gListenerCount = 0;
gEnginePortCount = 0;
}
int
GetLocalAddresses(
unsigned long *addresses,
int max_count
)
{
if (!gSteamReady || max_count < 1)
{
return 0;
}
addresses[0] = htonl(gLocalFakeIP);
return 1;
}
Logical
Resolve(
const char *host_name,
SOCKADDR_IN *address
)
{
memset(address, 0, sizeof(SOCKADDR_IN));
address->sin_family = AF_INET;
SteamNetworkingIPAddr parsed;
if (!parsed.ParseString(host_name))
{
return False;
}
address->sin_addr.S_un.S_addr = htonl(parsed.GetIPv4());
address->sin_port = htons(parsed.m_port); // 0 when absent
return True;
}
Connection
Connect(
const SOCKADDR_IN *remote,
int local_port
)
{
unsigned long remote_fake_ip = ntohl(remote->sin_addr.S_un.S_addr);
unsigned short fake_game_port = LookupPeerFakeGamePort(remote_fake_ip);
if (fake_game_port == 0)
{
DEBUG_STREAM << "SteamNetTransport: no registered peer for "
<< inet_ntoa(remote->sin_addr) << " - lobby did not feed it\n" << std::flush;
return InvalidConnection;
}
DEBUG_STREAM << "SteamNetTransport: connecting to "
<< inet_ntoa(remote->sin_addr) << " (fake port "
<< fake_game_port << ")...\n" << std::flush;
SteamNetworkingConfigValue_t option;
option.SetPtr(
k_ESteamNetworkingConfig_Callback_ConnectionStatusChanged,
(void *) &OnConnectionStatusChanged);
SteamNetworkingIPAddr target;
target.Clear();
target.SetIPv4(remote_fake_ip, fake_game_port);
// mirror the TCP retry-while-refused loop, bounded: the
// egg-ACK ordering means the peer may not be listening yet
DWORD deadline = GetTickCount() + 120 * 1000;
for (;;)
{
HSteamNetConnection handle =
SteamNetworkingSockets()->ConnectByIPAddress(target, 1, &option);
if (handle == k_HSteamNetConnection_Invalid)
{
return InvalidConnection;
}
ConnectionRecord *record =
AddConnection(handle, remote->sin_addr.S_un.S_addr, remote->sin_port);
while (!record->connected && !record->dead &&
(LONG)(GetTickCount() - deadline) < 0)
{
SteamAPI_RunCallbacks();
Sleep(25);
}
if (record->connected)
{
return (Connection) handle;
}
// attempt failed - drop it and retry until the deadline
SteamNetworkingSockets()->CloseConnection(handle, 0, "retry", false);
RemoveConnection(handle);
if ((LONG)(GetTickCount() - deadline) >= 0)
{
DEBUG_STREAM << "SteamNetTransport: connect timed out\n" << std::flush;
return InvalidConnection;
}
Sleep(250);
}
}
Connection
Listen(
int local_port,
int backlog
)
{
if (gListenerCount >= maxListeners)
{
return InvalidConnection;
}
// engine port -> fake port index, in order of appearance:
// the console channel always listens first, the mesh second
int index = -1;
for (int i = 0; i < gEnginePortCount; ++i)
{
if (gEnginePorts[i] == (unsigned short) local_port)
{
index = i;
}
}
if (index < 0)
{
if (gEnginePortCount >= 2)
{
DEBUG_STREAM << "SteamNetTransport: only two fake ports allocated!\n" << std::flush;
return InvalidConnection;
}
index = gEnginePortCount;
gEnginePorts[gEnginePortCount++] = (unsigned short) local_port;
}
DEBUG_STREAM << "SteamNetTransport: listening on engine port "
<< local_port << " (fake port " << gLocalFakePorts[index]
<< ")...\n" << std::flush;
SteamNetworkingConfigValue_t option;
option.SetPtr(
k_ESteamNetworkingConfig_Callback_ConnectionStatusChanged,
(void *) &OnConnectionStatusChanged);
HSteamListenSocket handle =
SteamNetworkingSockets()->CreateListenSocketP2PFakeIP(index, 1, &option);
if (handle == k_HSteamListenSocket_Invalid)
{
return InvalidConnection;
}
ListenerRecord *listener = &gListeners[gListenerCount++];
memset(listener, 0, sizeof(*listener));
listener->handle = handle;
listener->fakePortIndex = index;
listener->enginePort = (unsigned short) local_port;
return (Connection) handle;
}
Connection
Accept(Connection listener_handle)
{
SteamAPI_RunCallbacks();
ListenerRecord *listener = FindListener((HSteamListenSocket) listener_handle);
if (listener == NULL || listener->pendingCount == 0)
{
return InvalidConnection;
}
HSteamNetConnection handle = listener->pending[0];
for (int i = 1; i < listener->pendingCount; ++i)
{
listener->pending[i - 1] = listener->pending[i];
}
--listener->pendingCount;
// the remote engine port is the same engine port we accept
// on: all pods share the -net convention under Steam
unsigned long remote_ip_net = 0;
SteamNetworkingIPAddr remote_fake;
if (SteamNetworkingSockets()->GetRemoteFakeIPForConnection(
handle, &remote_fake) == k_EResultOK)
{
remote_ip_net = htonl(remote_fake.GetIPv4());
}
ConnectionRecord *record = AddConnection(
handle, remote_ip_net, htons(listener->enginePort));
if (record != NULL)
{
record->connected = True;
}
return (Connection) handle;
}
void
Close(Connection connection)
{
ListenerRecord *listener = FindListener((HSteamListenSocket) connection);
if (listener != NULL)
{
SteamNetworkingSockets()->CloseListenSocket(listener->handle);
*listener = gListeners[gListenerCount - 1];
--gListenerCount;
return;
}
SteamNetworkingSockets()->CloseConnection(
(HSteamNetConnection) connection, 0, "closed", true);
RemoveConnection((HSteamNetConnection) connection);
}
int
Send(
Connection connection,
const void *data,
int size
)
{
EResult result = SteamNetworkingSockets()->SendMessageToConnection(
(HSteamNetConnection) connection, data, (uint32) size,
k_nSteamNetworkingSend_Reliable, NULL);
return (result == k_EResultOK) ? size : -1;
}
int
Receive(
Connection connection,
void *buffer,
int size
)
{
SteamAPI_RunCallbacks();
ConnectionRecord *record = FindConnection((HSteamNetConnection) connection);
if (record == NULL)
{
return ReceiveNoData;
}
char *out = (char *) buffer;
int copied = 0;
// leftover bytes from a message that outsized the last call
if (record->leftoverCount > 0)
{
int take = (record->leftoverCount < size) ? record->leftoverCount : size;
memcpy(out, record->leftover, take);
memmove(record->leftover, record->leftover + take,
record->leftoverCount - take);
record->leftoverCount -= take;
out += take;
copied += take;
}
// drain messages while they fit; stash any partial tail
while (copied < size && record->leftoverCount == 0)
{
SteamNetworkingMessage_t *message = NULL;
int count = SteamNetworkingSockets()->ReceiveMessagesOnConnection(
record->handle, &message, 1);
if (count <= 0)
{
break;
}
int room = size - copied;
int take = ((int) message->m_cbSize < room) ? (int) message->m_cbSize : room;
memcpy(out, message->m_pData, take);
out += take;
copied += take;
int rest = (int) message->m_cbSize - take;
if (rest > 0)
{
if (rest > leftoverSize)
{
rest = leftoverSize; // cannot happen: engine packets < 2K
}
memcpy(record->leftover, (const char *) message->m_pData + take, rest);
record->leftoverCount = rest;
}
message->Release();
}
if (copied > 0)
{
return copied;
}
if (record->dead)
{
return ReceiveDisconnected;
}
return ReceiveNoData;
}
Logical
GetRemoteAddress(
Connection connection,
SOCKADDR_IN *address
)
{
memset(address, 0, sizeof(SOCKADDR_IN));
ConnectionRecord *record = FindConnection((HSteamNetConnection) connection);
if (record == NULL || !record->connected)
{
return False;
}
address->sin_family = AF_INET;
address->sin_addr.S_un.S_addr = record->remoteIP;
address->sin_port = record->remoteEnginePort;
return True;
}
};
SteamNetTransport gSteamTransport;
}
//########################################################################
// Install: bring Steam up, get our FakeIP identity, take over the wire
//########################################################################
Logical
SteamNetTransport_Install()
{
if (gSteamReady)
{
return True;
}
if (!SteamAPI_Init())
{
DEBUG_STREAM << "SteamNetTransport: SteamAPI_Init failed "
<< "(Steam not running, or no steam_appid.txt) - staying on TCP\n" << std::flush;
return False;
}
SteamNetworkingUtils()->InitRelayNetworkAccess();
if (!SteamNetworkingSockets()->BeginAsyncRequestFakeIP(2))
{
DEBUG_STREAM << "SteamNetTransport: BeginAsyncRequestFakeIP failed - staying on TCP\n" << std::flush;
return False;
}
// FakeIP allocation is async: pump until it lands (or give up)
SteamNetworkingFakeIPResult_t fake;
memset(&fake, 0, sizeof(fake));
DWORD deadline = GetTickCount() + 20 * 1000;
for (;;)
{
SteamAPI_RunCallbacks();
SteamNetworkingSockets()->GetFakeIP(0, &fake);
if (fake.m_eResult == k_EResultOK)
{
break;
}
if (fake.m_eResult != k_EResultBusy && fake.m_eResult != k_EResultNoMatch)
{
DEBUG_STREAM << "SteamNetTransport: FakeIP allocation failed (EResult "
<< (int) fake.m_eResult << ") - staying on TCP\n" << std::flush;
return False;
}
if ((LONG)(GetTickCount() - deadline) >= 0)
{
DEBUG_STREAM << "SteamNetTransport: FakeIP allocation timed out - staying on TCP\n" << std::flush;
return False;
}
Sleep(50);
}
gLocalFakeIP = fake.m_unIP;
gLocalFakePorts[0] = fake.m_unPorts[0];
gLocalFakePorts[1] = fake.m_unPorts[1];
SteamNetworkingIPAddr mine;
mine.Clear();
mine.SetIPv4(gLocalFakeIP, 0);
mine.ToString(gLocalFakeAddressString, sizeof(gLocalFakeAddressString), false);
DEBUG_STREAM << "SteamNetTransport: up as " << gLocalFakeAddressString
<< " (fake ports " << gLocalFakePorts[0] << " console, "
<< gLocalFakePorts[1] << " game)\n" << std::flush;
gSteamReady = True;
NetTransport_Set(&gSteamTransport);
return True;
}
const char *
SteamNetTransport_GetFakeAddressString()
{
return gLocalFakeAddressString;
}
int
SteamNetTransport_GetFakeGamePort()
{
return gLocalFakePorts[1];
}
void
SteamNetTransport_RegisterPeer(
const char *fake_ip,
int fake_game_port
)
{
if (gPeerCount >= maxPeers)
{
return;
}
SteamNetworkingIPAddr parsed;
if (!parsed.ParseString(fake_ip))
{
return;
}
gPeers[gPeerCount].fakeIP = parsed.GetIPv4();
gPeers[gPeerCount].fakeGamePort = (unsigned short) fake_game_port;
++gPeerCount;
DEBUG_STREAM << "SteamNetTransport: peer registered: " << fake_ip
<< " game port " << fake_game_port << "\n" << std::flush;
}
#endif // RP412_STEAM
+61 -106
View File
@@ -1,7 +1,7 @@
//===========================================================================//
// File: l4steamtransport.h //
// Project: MUNGA Brick: Steam Network Transport (skeleton) //
// Contents: NetTransport over ISteamNetworkingSockets - awaiting the SDK //
// Project: MUNGA Brick: Steam Network Transport //
// Contents: NetTransport over ISteamNetworkingSockets (FakeIP) //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
// PROPRIETARY AND CONFIDENTIAL //
@@ -9,120 +9,75 @@
#pragma once
#include "..\munga\style.h"
//########################################################################
// SteamNetTransport - the retail wire. NOT BUILT YET: everything below
// is guarded by RP412_STEAM, which stays undefined until the Steamworks
// SDK is dropped into the tree (needs a Steamworks partner login to
// download; put it at extern\steamworks and add steam_api.lib +
// steam_api.dll to the link/dist).
// SteamNetTransport - the retail wire (l4steamtransport.cpp). Built
// only under RP412_STEAM (Steamworks SDK vendored at
// extern\steamworks_sdk_164; steam_api.dll ships beside the exe).
//
// Method mapping (see also docs/RP412-FRONTEND-DESIGN.md section 3):
// Method mapping onto ISteamNetworkingSockets:
//
// Startup SteamAPI_Init + ISteamNetworkingUtils::InitRelay
// NetworkAccessAuthorization; then
// BeginAsyncRequestFakeIP so this pod has a fake
// IPv4 identity to put in the [pilots] list.
// Cleanup SteamAPI_Shutdown.
// GetLocalAddresses our allocated FakeIP (the mesh identifies
// "which pilots entry is me" against it, same as
// the LAN build matches its interface list).
// Resolve parse ip[:port] exactly like Winsock - FakeIPs
// ARE IPv4 strings, so egg text stays unchanged.
// Connect ConnectP2PByFakeIP (SDR picks the route, NAT
// traversal and IP privacy come free); block on
// the connection state callback until Connected,
// mirroring the TCP retry-until-accepted loop.
// Listen CreateListenSocketP2PFakeIP(port index); the
// game port / console port pair becomes fake-port
// index 0 / 1.
// Accept poll the connection-request callback queue,
// AcceptConnection, return the HSteamNetConnection
// (it fits the NetTransport::Connection handle).
// Close CloseConnection(reason 0, linger enabled).
// Send SendMessageToConnection with
// k_nSteamNetworkingSend_Reliable: the engine's
// stream framing (NetworkPacketHeader + payload)
// assumes ordered reliable delivery, exactly what
// a reliable Steam message lane provides.
// Receive ReceiveMessagesOnConnection; copy into the
// host's pad buffer, normalize "no messages" to
// ReceiveNoData and connection-closed callbacks
// to ReceiveDisconnected.
// GetRemoteAddress GetConnectionInfo -> m_addrRemote (the FakeIP),
// so the mesh's identity checks keep working on
// SOCKADDR_IN values.
// Install SteamAPI_Init + InitRelayNetworkAccess, then
// BeginAsyncRequestFakeIP(2): fake port 0 is the
// console channel, fake port 1 the game mesh.
// On success installs itself via NetTransport_Set;
// on any failure the process stays on Winsock TCP.
// GetLocalAddresses our FakeIP (the mesh identifies "which [pilots]
// entry is me" against it).
// Resolve SteamNetworkingIPAddr::ParseString - FakeIPs ARE
// IPv4 strings, so egg text stays unchanged.
// Connect ConnectByIPAddress to the peer's FakeIP + fake
// game port (SDR routes it; NAT traversal and IP
// privacy come free); blocks pumping callbacks
// until Connected, retrying like the TCP
// connect-while-refused loop.
// Listen CreateListenSocketP2PFakeIP - first engine port
// seen maps to fake port 0, second to fake port 1.
// Accept connection-request callback AcceptConnections
// queue up; Accept() pops fully-connected ones.
// Send SendMessageToConnection, reliable lane (the
// engine's stream framing assumes ordered
// reliable delivery).
// Receive ReceiveMessagesOnConnection into the caller's
// buffer; normalized to ReceiveNoData /
// ReceiveDisconnected like the Winsock transport.
// GetRemoteAddress GetRemoteFakeIPForConnection, with the fake
// port translated back to the ENGINE port so the
// mesh's SOCKADDR_IN identity checks keep working.
//
// Lobby flow that drives this transport (front-end work, not here):
// the lobby owner collects members' FakeIPs + loadouts via lobby data,
// builds the canonical egg with the ordered [pilots] list of FakeIPs,
// distributes it, and doubles as the console (RPL4CONSOLE marshals the
// mission; StopMissionMessage goes out over the console channel).
//
// Install with NetTransport_Set(new SteamNetTransport) BEFORE the
// network manager constructs (front of WinMain, when -steam / a Steam
// launch is detected).
// Addressing convention under Steam: every pod launches with the same
// -net port (the lobby fixes it), so the egg's [pilots] entries are
// "<fakeip>:<engine game port>" - the engine's self-match and peer
// checks all work on engine ports, and only this transport knows the
// Steam-assigned fake port values. The lobby layer exchanges each
// member's FakeIP + fake game port and feeds RegisterPeer before the
// egg is distributed.
//########################################################################
#ifdef RP412_STEAM
#include "l4nettransport.h"
// Bring Steam up and make this the process transport. False (with the
// reason logged) leaves the Winsock transport in place - callers just
// carry on over TCP.
Logical
SteamNetTransport_Install();
class SteamNetTransport:
public NetTransport
{
public:
SteamNetTransport();
~SteamNetTransport();
// Our FakeIP as a dotted string ("169.254.x.y"), for lobby member data
// and the [pilots] list. Empty until Install succeeds.
const char *
SteamNetTransport_GetFakeAddressString();
Logical
Startup();
void
Cleanup();
// Our Steam-assigned fake game port (lobby member data).
int
SteamNetTransport_GetFakeGamePort();
int
GetLocalAddresses(
unsigned long *addresses,
int max_count
);
Logical
Resolve(
const char *host_name,
SOCKADDR_IN *address
);
Connection
Connect(
const SOCKADDR_IN *remote,
int local_port
);
Connection
Listen(
int local_port,
int backlog
);
Connection
Accept(Connection listener);
void
Close(Connection connection);
int
Send(
Connection connection,
const void *data,
int size
);
int
Receive(
Connection connection,
void *buffer,
int size
);
Logical
GetRemoteAddress(
Connection connection,
SOCKADDR_IN *address
);
};
// The lobby feeds every member's FakeIP + fake game port here before
// StartConnecting runs.
void
SteamNetTransport_RegisterPeer(
const char *fake_ip,
int fake_game_port
);
#endif // RP412_STEAM
+6 -2
View File
@@ -35,7 +35,7 @@
<TargetName>Munga_l4</TargetName>
<!-- Legacy DirectX SDK (June 2010) after the Windows SDK so modern headers/libs win;
only d3dx9 and dxerr actually come from it. -->
<IncludePath>$(IncludePath);$(DXSDK_DIR)Include</IncludePath>
<IncludePath>$(IncludePath);$(DXSDK_DIR)Include;..\extern\steamworks_sdk_164\sdk\public</IncludePath>
<LibraryPath>$(LibraryPath);$(DXSDK_DIR)Lib\x86</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup>
@@ -50,7 +50,9 @@
build always compiled Windows headers at /Zp1, so this keeps those semantics.
_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS: stdext::hash_map, pending
an unordered_map port. -->
<PreprocessorDefinitions>WIN32;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;WINDOWS_IGNORE_PACKING_MISMATCH;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<!-- RP412_STEAM: SteamNetTransport compiles against the vendored Steamworks SDK;
activation stays behind the RP412STEAM env switch at runtime. -->
<PreprocessorDefinitions>WIN32;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;WINDOWS_IGNORE_PACKING_MISMATCH;_SILENCE_STDEXT_HASH_DEPRECATION_WARNINGS;RP412_STEAM;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4996;4244;4267;4305;4018;4138;%(DisableSpecificWarnings)</DisableSpecificWarnings>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
@@ -249,6 +251,7 @@
<ClCompile Include=".\L4MPPR.cpp" />
<ClCompile Include=".\L4NET.CPP" />
<ClCompile Include=".\L4NETTRANSPORT.cpp" />
<ClCompile Include=".\L4STEAMTRANSPORT.cpp" />
<ClCompile Include=".\L4PARTICLES.cpp" />
<ClCompile Include=".\L4MFDVIEW.cpp" />
<ClCompile Include=".\L4PADRIO.cpp" />
@@ -440,6 +443,7 @@
<ClInclude Include=".\L4MPPR.h" />
<ClInclude Include=".\L4NET.H" />
<ClInclude Include=".\L4NETTRANSPORT.h" />
<ClInclude Include=".\L4STEAMTRANSPORT.h" />
<ClInclude Include=".\L4PARTICLES.h" />
<ClInclude Include=".\L4MFDVIEW.h" />
<ClInclude Include=".\L4PADRIO.h" />