Two things that travel together, because the packaging script carries both. STEAMWORKS 1.65 replaces 1.64. steam_api.dll goes 10.51.08.25 -> 10.87.46.89. Vendored the same way - headers and the win32 redistributable only, examples and other platforms left out - and 1.64 is gone rather than left beside it, since nothing referenced it any more: both include paths, the library path, the DLL the packaging script copies, and the docs that name the folder all moved over. The vendoring rules also gained a line they always needed. The redistributable DLL is caught by the global *.dll rule at the repo root, so it only ever got in by a git add -f, and a fresh checkout could not produce a package without noticing the DLL was missing. It is now re-included by name. OUR OWN APPID, 5108000, replaces Spacewar's 480. steam_appid.txt is what tells the Steam client which game this is when a build is started straight from its folder, which is how every tester runs it. The consequence worth knowing before the next test night: 480 was Valve's public one and every account effectively had it. 5108000 is ours, so the Steam account has to actually have Red Planet on it. An account without it gets the plain TCP fallback - the same quiet symptom as a missing appid file - so the handbook, the environ.ini template, the README and the three-machine test doc all now say to check that first. Nothing in the code hardcodes the number; the file is the whole story. Retail builds launched BY the Steam client need no such file at all. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
118 lines
5.6 KiB
C
118 lines
5.6 KiB
C
//===========================================================================//
|
|
// File: l4steamtransport.h //
|
|
// Project: MUNGA Brick: Steam Network Transport //
|
|
// Contents: NetTransport over ISteamNetworkingSockets (FakeIP) //
|
|
//---------------------------------------------------------------------------//
|
|
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. //
|
|
// PROPRIETARY AND CONFIDENTIAL //
|
|
//===========================================================================//
|
|
|
|
#pragma once
|
|
|
|
#include "..\munga\style.h"
|
|
|
|
//########################################################################
|
|
// SteamNetTransport - the retail wire (l4steamtransport.cpp). Built
|
|
// only under RP412_STEAM (Steamworks SDK vendored at
|
|
// extern\steamworks_sdk_165; steam_api.dll ships beside the exe, but is
|
|
// delay-loaded and optional - see the note further down).
|
|
//
|
|
// Method mapping onto ISteamNetworkingSockets:
|
|
//
|
|
// 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.
|
|
//
|
|
// 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.
|
|
//########################################################################
|
|
|
|
//########################################################################
|
|
// steam_api.dll is DELAY-LOADED (see the DelayLoadDLLs setting in
|
|
// RP_L4.vcxproj), so the game runs on a machine that has never seen
|
|
// Steam - a plain import of a missing DLL kills the process at load time
|
|
// with 0xC0000135, before a window or a single log line.
|
|
//
|
|
// The catch is that delay loading only MOVES the failure: the first call
|
|
// to a delay-loaded function whose DLL cannot be found raises a fatal
|
|
// exception instead. So every path that would reach a Steam symbol has
|
|
// to ask this first. It is declared outside the RP412_STEAM guard, and
|
|
// answers False in a build without the SDK, so callers need no #ifdef.
|
|
//
|
|
// Cheap and idempotent: one LoadLibrary on first call, cached after.
|
|
// Deliberately the same plain-name load the delay-load helper itself
|
|
// does, so a yes here means the helper will succeed too.
|
|
//########################################################################
|
|
Logical
|
|
SteamNetTransport_ClientLibraryPresent();
|
|
|
|
#ifdef RP412_STEAM
|
|
|
|
// 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();
|
|
|
|
// 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();
|
|
|
|
// Our Steam-assigned fake ports (lobby member data): the console
|
|
// channel and the game mesh.
|
|
int
|
|
SteamNetTransport_GetFakeConsolePort();
|
|
int
|
|
SteamNetTransport_GetFakeGamePort();
|
|
|
|
// The engine-side port convention for this session (default 1501;
|
|
// game port is +1). Connect() maps an engine port in a SOCKADDR_IN to
|
|
// the peer's matching Steam fake port.
|
|
void
|
|
SteamNetTransport_SetEnginePorts(int console_port);
|
|
|
|
// The lobby feeds every member's FakeIP + fake ports + SteamID here
|
|
// before anything dials out. The SteamID matters on accept: Steam
|
|
// reports incoming callers under locally-allocated alias addresses,
|
|
// so the transport maps the caller's identity back to the global
|
|
// FakeIP the egg promised. Registering is idempotent per IP.
|
|
void
|
|
SteamNetTransport_RegisterPeer(
|
|
const char *fake_ip,
|
|
int fake_console_port,
|
|
int fake_game_port,
|
|
unsigned __int64 steam_id
|
|
);
|
|
|
|
#endif // RP412_STEAM
|