Skip to content

Commit fa89cf9

Browse files
committed
Add modern Steam networking APIs
1 parent ec30f70 commit fa89cf9

14 files changed

Lines changed: 509 additions & 12 deletions

‎README.md‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -239,6 +239,10 @@ call results, so keep pumping callbacks with `steam.runCallbacks()` or
239239
`{ data, steamIdRemote, messageSize }`. The requested read size is capped to
240240
avoid unbounded native allocation.
241241

242+
`networking.sockets` and `networking.messages` expose Steam's modern P2P APIs;
243+
see [Modern P2P networking](docs/api/networking-modern.md). They are separate
244+
from the legacy `networking` namespace so existing applications remain stable.
245+
242246
`cloud`:
243247

244248
- `cloud.saveTextToFile(fileName, content)`

‎docs/api/README.md‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ promise completion, callback delivery, and convenience helpers.
2424
| `friends` | [Friends and presence](friends.md) | [ISteamFriends](https://partner.steamgames.com/doc/api/ISteamFriends) |
2525
| `matchmaking` | [Lobbies](matchmaking.md) | [ISteamMatchmaking](https://partner.steamgames.com/doc/api/ISteamMatchmaking) |
2626
| `networking` | [Legacy P2P networking](networking.md) | [ISteamNetworking](https://partner.steamgames.com/doc/api/ISteamNetworking) |
27+
| `networking.sockets`, `networking.messages` | [Modern P2P networking](networking-modern.md) | [ISteamNetworkingSockets](https://partner.steamgames.com/doc/api/ISteamNetworkingSockets), [ISteamNetworkingMessages](https://partner.steamgames.com/doc/api/ISteamNetworkingMessages) |
2728
| `cloud` | [Cloud files](cloud.md) | [ISteamRemoteStorage](https://partner.steamgames.com/doc/api/ISteamRemoteStorage) |
2829
| `ugc` | [Workshop and UGC](ugc.md) | [ISteamUGC](https://partner.steamgames.com/doc/api/ISteamUGC) |
2930
| `userStats` | [Stats and achievements](user-stats.md) | [ISteamUserStats](https://partner.steamgames.com/doc/api/ISteamUserStats) |

‎docs/api/networking-modern.md‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
# Modern P2P networking
2+
3+
Official references: [ISteamNetworkingSockets](https://partner.steamgames.com/doc/api/ISteamNetworkingSockets) and [ISteamNetworkingMessages](https://partner.steamgames.com/doc/api/ISteamNetworkingMessages).
4+
5+
`networking.sockets` is the modern connection-oriented API. Create a P2P listen
6+
socket with `createListenSocketP2P()`, connect with `connectP2P()`, accept
7+
incoming connection handles with `acceptConnection()`, and use the connection
8+
handle to send or receive messages. `networking.messages` is the modern
9+
connectionless API: use `sendMessageToUser()` and poll a local channel with
10+
`receiveMessagesOnChannel()`.
11+
12+
Both interfaces use decimal-string Steam IDs and Node.js `Buffer` payloads.
13+
Received messages are copied into JavaScript and released by the binding before
14+
they are returned. Reads accept at most 256 messages per call; sent messages
15+
cannot exceed Steam's 512 KiB maximum. Send flags and result values are the
16+
numeric Steamworks constants.
17+
18+
```ts
19+
import { networking } from '@node-3d/steam-api';
20+
21+
networking.messages.sendMessageToUser(peer, Buffer.from('hello'));
22+
for (const message of networking.messages.receiveMessagesOnChannel()) {
23+
console.log(message.steamIdRemote, message.data.toString());
24+
}
25+
```
26+
27+
The socket API reports connection state through Steam callbacks. Keep pumping
28+
`update()` and call `acceptConnection()` promptly for incoming connections.
29+
`update()` reports `networking-connection-status-changed` with `connection`,
30+
`oldState`, `state`, `steamIdRemote`, and `endReason`. The messages API reports
31+
`networking-messages-session-request` (accept it with `acceptSessionWithUser()`)
32+
and `networking-messages-session-failed`.

‎examples/visual/README.md‎

Lines changed: 0 additions & 7 deletions
This file was deleted.

‎install.js‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { install } from '@node-3d/addon-tools';
22

33
const prefix = 'https://github.com/node-3d/steam-api/releases/download';
4-
const tag = '0.3.0';
4+
const tag = '0.4.0';
55

66
await install(`${prefix}/${tag}`);

‎package-lock.json‎

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"author": "Luis Blanco <luisblanco1337@gmail.com>",
33
"name": "@node-3d/steam-api",
4-
"version": "0.3.0",
4+
"version": "0.4.0",
55
"description": "Steamworks API bindings for Node.js",
66
"license": "MIT",
77
"main": "dist/index.js",

‎src/cpp/bindings.cpp‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,10 @@ Napi::Object initModule(Napi::Env env, Napi::Object exports) {
3939
exports.Set("apps", steam_api::apps::createNamespace(env));
4040
exports.Set("friends", steam_api::friends::createNamespace(env));
4141
exports.Set("matchmaking", steam_api::matchmaking::createNamespace(env));
42-
exports.Set("networking", steam_api::networking::createNamespace(env));
42+
Napi::Object networking = steam_api::networking::createNamespace(env);
43+
networking.Set("sockets", steam_api::networking::createSocketsNamespace(env));
44+
networking.Set("messages", steam_api::networking::createMessagesNamespace(env));
45+
exports.Set("networking", networking);
4346
exports.Set("cloud", steam_api::cloud::createNamespace(env));
4447
exports.Set("ugc", steam_api::ugc::createNamespace(env));
4548
exports.Set("userStats", steam_api::user_stats::createNamespace(env));

‎src/cpp/callbacks.cpp‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,9 @@ class CallbackBridge {
134134
this, &CallbackBridge::onFloatingGamepadTextInputDismissed
135135
);
136136
_downloadItemResult.Register(this, &CallbackBridge::onDownloadItemResult);
137+
_connectionStatusChanged.Register(this, &CallbackBridge::onConnectionStatusChanged);
138+
_messagesSessionRequest.Register(this, &CallbackBridge::onMessagesSessionRequest);
139+
_messagesSessionFailed.Register(this, &CallbackBridge::onMessagesSessionFailed);
137140
_isRegistered = true;
138141
}
139142

@@ -171,6 +174,9 @@ class CallbackBridge {
171174
_newUrlLaunchParameters.Unregister();
172175
_floatingGamepadTextInputDismissed.Unregister();
173176
_downloadItemResult.Unregister();
177+
_connectionStatusChanged.Unregister();
178+
_messagesSessionRequest.Unregister();
179+
_messagesSessionFailed.Unregister();
174180
_isRegistered = false;
175181
_events.clear();
176182
}
@@ -417,6 +423,36 @@ class CallbackBridge {
417423
_events.push_back(event);
418424
}
419425

426+
void onConnectionStatusChanged(SteamNetConnectionStatusChangedCallback_t *param) {
427+
Event event = makeEventData("networking-connection-status-changed");
428+
event.fields.push_back(makeInt32Field("connection", param->m_hConn));
429+
event.fields.push_back(makeInt32Field("oldState", param->m_eOldState));
430+
event.fields.push_back(makeInt32Field("state", param->m_info.m_eState));
431+
event.fields.push_back(
432+
makeUint64StringField("steamIdRemote", param->m_info.m_identityRemote.GetSteamID64())
433+
);
434+
event.fields.push_back(makeInt32Field("endReason", param->m_info.m_eEndReason));
435+
_events.push_back(event);
436+
}
437+
438+
void onMessagesSessionRequest(SteamNetworkingMessagesSessionRequest_t *param) {
439+
Event event = makeEventData("networking-messages-session-request");
440+
event.fields.push_back(
441+
makeUint64StringField("steamIdRemote", param->m_identityRemote.GetSteamID64())
442+
);
443+
_events.push_back(event);
444+
}
445+
446+
void onMessagesSessionFailed(SteamNetworkingMessagesSessionFailed_t *param) {
447+
Event event = makeEventData("networking-messages-session-failed");
448+
event.fields.push_back(
449+
makeUint64StringField("steamIdRemote", param->m_info.m_identityRemote.GetSteamID64())
450+
);
451+
event.fields.push_back(makeInt32Field("state", param->m_info.m_eState));
452+
event.fields.push_back(makeInt32Field("endReason", param->m_info.m_eEndReason));
453+
_events.push_back(event);
454+
}
455+
420456
bool _isRegistered = false;
421457
std::vector<Event> _events;
422458
CCallbackManual<CallbackBridge, UserStatsReceived_t> _userStatsReceived;
@@ -448,6 +484,9 @@ class CallbackBridge {
448484
CCallbackManual<CallbackBridge, NewUrlLaunchParameters_t> _newUrlLaunchParameters;
449485
CCallbackManual<CallbackBridge, FloatingGamepadTextInputDismissed_t> _floatingGamepadTextInputDismissed;
450486
CCallbackManual<CallbackBridge, DownloadItemResult_t> _downloadItemResult;
487+
CCallbackManual<CallbackBridge, SteamNetConnectionStatusChangedCallback_t> _connectionStatusChanged;
488+
CCallbackManual<CallbackBridge, SteamNetworkingMessagesSessionRequest_t> _messagesSessionRequest;
489+
CCallbackManual<CallbackBridge, SteamNetworkingMessagesSessionFailed_t> _messagesSessionFailed;
451490
};
452491

453492
std::unique_ptr<CallbackBridge> callbackBridge;

0 commit comments

Comments
 (0)