Hey everyone! Today marks another SDK drop with some great new stuff for you. We are so close to a release candidate; it should be coming in a couple days. We're finishing up the IAP and entitlements portion of the SDK as you read this, and it should be ready for you within one or two days.
This SDK drop is our big polish overhaul before the release candidate. There are a number of naming changes and some small functionality changes that we'll walk through here. The networking layer also got some juice and is now routing W O R L D W I D E. That means no more 200 ms ping time; it'll be lightnin' fast.
Here's everything that's changed:
General
-
All managers in the SDK are now
Get
rather thanCreate
- You no longer need to call
discord.CreateLobbyManager()
and keep that reference around - You can just call
discord.GetLobbyManager()
in whatever context it's needed
- You no longer need to call
-
Managers are now named in the singular form rather than the plural, for Mason's sanity
ActivitiesManager
->ActivityManager
ApplicationsManager
->ApplicationManager
ImagesManager
->ImageManager
LobbiesManager
->LobbyManager
RelationshipsManager
->RelationshipManager
UsersManager
->UserManager
-
Many functions now return
void
instead of theDiscord.Result
- Functions that had a
Discord.Result
in the callback now just return void - Many functions that did not have a failure that could be handled, i.e.
SendMessage()
, now just return void
- Functions that had a
-
OnReady
has been removed. You should useuserManager.OnCurrentUserUpdate
as the "GO!" callback for SDK usage
Activities
-
Register()
renamed toRegisterCommand()
- This more appropriately describes what is being registered to the system
-
Respond()
renamed toSendRequestReply()
- There was some confusion between the old naming convention and the
AcceptInvite()
function
- There was some confusion between the old naming convention and the
-
InviteUser()
renamed toSendInvite()
- Mostly just naming consistency
Lobbies
-
LobbySearch
has been renamed toLobbySearchQuery
- Now reflects that you're really building a query
-
CreateLobbySearch()
has been renamed toGetSearchQuery()
- Matches new struct name
-
CreateLobbyTransaction()
has been renamed toGetLobbyCreateTransaction()
- This transaction is used when creating new lobbies, and is now named as such
-
GetLobbyTransaction
has been renamed toGetLobbyUpdateTransaction()
- This transaction is for updating existing lobbies, now named as such
-
GetMemberUpdateTransaction()
has been renamed toGetMemberUpdateTransaction()
- Consistency with the other transaction methods
-
Connect()
has been renamed toConnectLobby()
- More explicitly states the object you're connecting to
-
ConnectWithActivitySecret()
has been renamed toConnectLobbyWithActivitySecret()
- Naming consistency
-
Disconnect()
has been renamed toDisconnectLobby()
- Naming consistency
-
GetLobbyMetadataCount()
has been renamed toLobbyMetadataCount()
Count()
is an understood accessor name, and theget
was redundant
-
GetMemberCount()
has been renamed toMemberCount()
- Same as above
-
GetMemberMetadataCount()
has been renamed toMemberMetadataCount()
- Same as above
-
GetLobbyCount()
has been renamed toLobbyCount()
- Same as above
-
VoiceConnect()
has been renamed toConnectVoice()
- Naming consistency (action follow by object acted on)
-
VoiceDisconnect()
has been renamed toDisconnectVoice()
- Naming consistency
Overlay
OnLocked
has been renamed toOnToggle
- Toggle is more easily understood than locked or unlocked
Relationships
-
At()
has been renamed toGetAt()
- Matches
StatAt()
accessor in storage manager
- Matches
-
OnRelationshipsUpdate
has been renamed toOnRefresh
- More accurately explains that this fires when the relationship list has been reset
Storage
StatIndex()
has been renamed toStatAt()
- Familiar accessor name
Users
Fetch()
has been renamed toGetUser()
- More accurate explanation of what you're getting
Networking
-
GetSessionId()
has been renamed toGetPeerId()
-
Across the board,
sessionId
,senderSessionId
, andremoteSessionId
has been renamed topeerId
-
OpenReliableChannel()
andOpenUnreliableChannel()
have been removed in favor of oneOpenChannel()
call- This new function takes a third parameter,
bool reliable
, to determine the channel type - Why have two function when one do trick?
- This new function takes a third parameter,
-
OpenPeer()
has been added- It takes a
UInt64 peerId
and astring route
- Needed for scaled network support
- It takes a
-
UpdatePeer()
has been added- It takes a
UInt64 peerId
and astring route
- Needed for scaled network support
- It takes a
-
ClosePeer()
has been added- It takes a
UInt64 peerId
- Needed for scaled network support
- It takes a
-
OnRouteUpdate
has been added- It is a callback for the current user that contains a
string route
- Needed for scaled network support
- It is a callback for the current user that contains a
The NetworkManager has had a couple big changes to support global network scaling. The TL;DR is that there is now a concept of "routes" for players that ties into their peer id. You can think of it like an abstracted IP address. This route normally changes if a user changes networks, like going from WiFi to connected, or between two wifi networks, or IP changes due to service provider, etc. etc. You should implement it with the anticipation that it might change often.
Those of you using our networking layer are also using our lobby system. The below code block are the minimal changes you will need to make to support these routes. They are written under the assumption that lobby metadata is being used to track stateful information:
// When this fires, you should update your own metadata to reflect your new route
networkManager.OnRouteUpdate += route =>
{
var txn = lobbyManager.GetMemberUpdateTransaction();
txn.SetMetadata("route", route);
lobbyManager.UpdateMember(lobbyId, myUserId, txn, (_) => {});
}
// When users update their metadata with new route info, this fires
// You should update your route to them accordingly
lobbyManager.OnMemberUpdate += (lobbyId, userId) =>
{
var peerId = lobbyManager.GetMemberMetadataValue(lobbyId, userId, "peer_id");
var newRoute = lobbyManager.GetMemberMetadataValue(lobbyId, userId, "route");
// This updates their route
networkManager.UpdatePeer(peerId, newRoute);
}
// Random general main game loop
void Main()
{
// Before opening channels to users, open the route to them first
// When you connect to the lobby, you probably want to iterate over the member list
// And do this for each person to connect to them all
var peerId = lobbyManager.GetMemberMetadataValue(lobbyId, otherUserId, "peer_id");
var route = lobbyManager.GetMemberMetadataValue(lobbyId, otherUserId, "route");
networkManager.OpenPeer(peerId, route);
networkManager.OpenChannel(peerId, 0, false);
networkManager.OpenChannel(peerId, 1, true);
}
// You now have two channels open to the user, and are updating their route dynamically!
We recognize that for some games, managing these stateful things for a networking layer can be cumbersome. We have plans on the roadmap to more tightly integrate our lobbies to a our networking service, allowing you to effectively wrap your lobbies in our networking layer and have all the route management abstracted and done for you. For those of you trying to march to a deadline or needing a solution now, we encourage you to work with the above examples. Doing it the "hard way" will always work, regardless of helper functions we make in the future. If you have not yet integrated our networking layer and are not working towards an immediate deadline, you may want to hold off for helper functions.
Thanks for reading this all, and as always, please hit up @Mason with any questions.
<3 Discord