diff --git a/Makefile b/Makefile index 403edbf..d95ab03 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,8 @@ endif LFLAGS = -lhl -lsteam_api -lstdc++ -L sdk/redistributable_bin/$(OS)$(ARCH) SRC = native/cloud.o native/common.o native/controller.o native/friends.o native/gameserver.o \ - native/matchmaking.o native/networking.o native/stats.o native/ugc.o + native/matchmaking.o native/networking.o native/networkingmessages.o native/stats.o \ + native/ugc.o all: ${SRC} ${CC} ${CFLAGS} -shared -o steam.hdll ${SRC} ${LFLAGS} diff --git a/hlsteam.vcxproj b/hlsteam.vcxproj index 95b35b6..a1d581c 100644 --- a/hlsteam.vcxproj +++ b/hlsteam.vcxproj @@ -283,6 +283,7 @@ + diff --git a/hlsteam.vcxproj.filters b/hlsteam.vcxproj.filters index bdb8114..a478bf5 100644 --- a/hlsteam.vcxproj.filters +++ b/hlsteam.vcxproj.filters @@ -9,6 +9,8 @@ + + diff --git a/native/events.h b/native/events.h index 73bd848..a1c3490 100644 --- a/native/events.h +++ b/native/events.h @@ -12,6 +12,10 @@ EVENT_DECL( LobbyJoinRequest, GameLobbyJoinRequested_t ) // networking EVENT_DECL( P2PSessionRequest, P2PSessionRequest_t ) EVENT_DECL( P2PSessionConnectionFail, P2PSessionConnectFail_t ) +EVENT_DECL( SteamNetworkingMessagesSessionRequest, SteamNetworkingMessagesSessionRequest_t ) +EVENT_DECL( SteamNetworkingMessagesSessionFailed, SteamNetworkingMessagesSessionFailed_t ) + +EVENT_DECL( GameRichPresenceJoinRequested, GameRichPresenceJoinRequested_t ) // ugc EVENT_DECL(DownloadItem, DownloadItemResult_t) diff --git a/native/matchmaking.cpp b/native/matchmaking.cpp index 8a811c8..844f2a7 100644 --- a/native/matchmaking.cpp +++ b/native/matchmaking.cpp @@ -156,6 +156,10 @@ HL_PRIM void HL_NAME(set_lobby_member_limit)( vuid uid, int count ) { SteamMatchmaking()->SetLobbyMemberLimit(hl_to_uid(uid), count); } +HL_PRIM void HL_NAME(set_lobby_type)( vuid uid, ELobbyType lobbyType ) { + SteamMatchmaking()->SetLobbyType(hl_to_uid(uid), lobbyType); +} + DEFINE_PRIM(_CRESULT, create_lobby, _I32 _I32 _CALLB(_UID)); DEFINE_PRIM(_VOID, leave_lobby, _UID); DEFINE_PRIM(_CRESULT, join_lobby, _UID _CALLB(_BOOL)); @@ -164,6 +168,7 @@ DEFINE_PRIM(_I32, get_num_lobby_members, _UID); DEFINE_PRIM(_UID, get_lobby_member_by_index, _UID _I32); DEFINE_PRIM(_I32, get_lobby_member_limit, _UID); DEFINE_PRIM(_VOID, set_lobby_member_limit, _UID _I32); +DEFINE_PRIM(_VOID, set_lobby_type, _UID _I32); DEFINE_PRIM(_UID, get_lobby_owner, _UID); DEFINE_PRIM(_VOID, lobby_invite_friends, _UID); diff --git a/native/networkingmessages.cpp b/native/networkingmessages.cpp new file mode 100644 index 0000000..ef13766 --- /dev/null +++ b/native/networkingmessages.cpp @@ -0,0 +1,106 @@ +#include "steamwrap.h" + +SteamNetworkingIdentity hl_to_steamnetid(steamnetid v) { + union { + vbyte b[sizeof(SteamNetworkingIdentity)]; + SteamNetworkingIdentity v; + } data; + memcpy(data.b, v, sizeof(SteamNetworkingIdentity)); + return SteamNetworkingIdentity(data.v); +} + +steamnetid hl_of_steamnetid(SteamNetworkingIdentity v) { + union { + vbyte b[sizeof(SteamNetworkingIdentity)]; + SteamNetworkingIdentity v; + } data; + data.v = v; + return (steamnetid)hl_copy_bytes(data.b, sizeof(SteamNetworkingIdentity)); +} + +HL_PRIM steamnetid HL_NAME(get_identity)() { + SteamNetworkingIdentity identity; + SteamNetworkingSockets()->GetIdentity(&identity); + return hl_of_steamnetid(identity); +} + +HL_PRIM vbyte* HL_NAME(identity_to_string)(steamnetid identity) { + char *buf = (char *)hl_gc_alloc_noptr(SteamNetworkingIdentity::k_cchMaxString); + hl_to_steamnetid(identity).ToString(buf, SteamNetworkingIdentity::k_cchMaxString); + return (vbyte*)buf; +} + +HL_PRIM vbyte* HL_NAME(identity_from_string)(vbyte* v) { + SteamNetworkingIdentity identity; + identity.ParseString((char*)v); + return hl_of_steamnetid(identity); +} + +DEFINE_PRIM(_STEAMNETID, get_identity, _NO_ARG); +DEFINE_PRIM(_BYTES, identity_to_string, _STEAMNETID); +DEFINE_PRIM(_STEAMNETID, identity_from_string, _BYTES); + +HL_PRIM void HL_NAME(init_authentication)() { + SteamNetworkingSockets()->InitAuthentication(); +} + +HL_PRIM bool HL_NAME(accept_session_with_user)(steamnetid identity) { + return SteamNetworkingMessages()->AcceptSessionWithUser(hl_to_steamnetid(identity)); +} + +HL_PRIM bool HL_NAME(close_session_with_user)(steamnetid identity) { + return SteamNetworkingMessages()->CloseSessionWithUser(hl_to_steamnetid(identity)); +} + +HL_PRIM int HL_NAME(send_message_to_user)(steamnetid identityRemote, vbyte* pubData, int cubData, int nSendFlags, int nRemoteChannel) { + return SteamNetworkingMessages()->SendMessageToUser(hl_to_steamnetid(identityRemote), pubData, cubData, nSendFlags, nRemoteChannel); +} + +DEFINE_PRIM(_VOID, init_authentication, _NO_ARG); +DEFINE_PRIM(_BOOL, accept_session_with_user, _STEAMNETID); +DEFINE_PRIM(_BOOL, close_session_with_user, _STEAMNETID); +DEFINE_PRIM(_I32, send_message_to_user, _STEAMNETID _BYTES _I32 _I32 _I32); + +vdynamic *CallbackHandler::EncodeSteamNetworkingMessagesSessionRequest(SteamNetworkingMessagesSessionRequest_t *d) { + HLValue ret; + ret.Set("identity", d->m_identityRemote); + return ret.value; +} + +vdynamic *CallbackHandler::EncodeSteamNetworkingMessagesSessionFailed(SteamNetworkingMessagesSessionFailed_t *d) { + HLValue ret; + // ret.Set("info", d->m_info); + printf("%d %s", d->m_info.m_eEndReason, d->m_info.m_szEndDebug); + return ret.value; +} + +vdynamic *CallbackHandler::EncodeGameRichPresenceJoinRequested(GameRichPresenceJoinRequested_t *d) { + HLValue ret; + ret.Set("friend", d->m_steamIDFriend); + ret.Set("connect", d->m_rgchConnect); + return ret.value; +} + +HL_PRIM SteamNetworkingMessage_t* HL_NAME(receive_message_on_channel)(int nLocalChannel) { + SteamNetworkingMessage_t* message = NULL; + SteamNetworkingMessages()->ReceiveMessagesOnChannel(nLocalChannel, &message, 1); + return message; +} + +HL_PRIM void HL_NAME(release_message)(SteamNetworkingMessage_t* message) { + message->Release(); +} + +HL_PRIM int HL_NAME(get_message_size)(SteamNetworkingMessage_t* message) { + return message->GetSize(); +} + +HL_PRIM vbyte* HL_NAME(get_message_data)(SteamNetworkingMessage_t* message) { + return (vbyte*)message->GetData(); +} + +#define NWMSG _ABSTRACT(steam_networkmsg) +DEFINE_PRIM(NWMSG, receive_message_on_channel, _I32); +DEFINE_PRIM(_VOID, release_message, NWMSG); +DEFINE_PRIM(_I32, get_message_size, NWMSG); +DEFINE_PRIM(_BYTES, get_message_data, NWMSG); \ No newline at end of file diff --git a/native/steamwrap.h b/native/steamwrap.h index 70f64fc..68d1cc4 100644 --- a/native/steamwrap.h +++ b/native/steamwrap.h @@ -16,7 +16,9 @@ #include typedef vbyte * vuid; +typedef vbyte * steamnetid; #define _UID _BYTES +#define _STEAMNETID _BYTES #define hlt_uid hlt_bytes void dyn_call_result( vclosure *c, vdynamic *p, bool error ); @@ -25,6 +27,8 @@ CSteamID hl_to_uid( vuid v ); vuid hl_of_uid( CSteamID id ); uint64 hl_to_uint64(vuid v); vuid hl_of_uint64(uint64 id); +SteamNetworkingIdentity hl_to_steamnetid(steamnetid v); +steamnetid hl_of_steamnetid(SteamNetworkingIdentity v); template< class T > class CClosureCallResult : public CCallResult,T> { @@ -110,6 +114,9 @@ class HLValue { void Set( const char *name, uint64 uid ) { hl_dyn_setp(value, hl_hash_utf8(name), &hlt_uid, hl_of_uint64(uid)); } + void Set( const char *name, SteamNetworkingIdentity uid ) { + hl_dyn_setp(value, hl_hash_utf8(name), &hlt_uid, hl_of_steamnetid(uid)); + } void Set( const char *name, uint32 v ) { Set(name,(int)v); } diff --git a/steam/Api.hx b/steam/Api.hx index 8372399..3d1854a 100644 --- a/steam/Api.hx +++ b/steam/Api.hx @@ -61,6 +61,7 @@ class Api // User-settable Callbacks public static var onOverlay : Bool -> Void; + public static var onGameRichPresenceJoinRequested: UID -> String -> Void; /** * @param appId_ Your Steam APP ID (the numbers on the end of your store page URL - store.steampowered.com/app/XYZ) @@ -92,6 +93,24 @@ class Api } }); + // SteamNetworkingMessagesSessionRequest_t + registerGlobalEvent(1250 + 1, function(data:{identity: SteamNetworkingIdentity}){ + if( NetworkingMessages.onSessionRequest != null ) + NetworkingMessages.onSessionRequest(data.identity); + }); + + // SteamNetworkingMessagesSessionFailed_t + registerGlobalEvent(1250 + 2, function(data:{info: SteamNetConnectionInfo}){ + // if( NetworkingMessages.onSessionRequest != null ) + // NetworkingMessages.onSessionRequest(data.info); + }); + + // GameRichPresenceJoinRequested_t + registerGlobalEvent(300 + 37, function(data:{friend: UID, connect:hl.Bytes}){ + if( onGameRichPresenceJoinRequested != null ) + onGameRichPresenceJoinRequested(data.friend, @:privateAccess String.fromUTF8(data.connect)); + }); + // if we get this far, the dlls loaded ok and we need Steam to init. // otherwise, we're trying to run the Steam version without the Steam client active = _Init(steamWrap_onEvent, onGlobalEvent); @@ -114,6 +133,7 @@ class Api static var globalEvents = new MapVoid>(); static var authTicketCallbacks : MapVoid> = new Map(); + static var authTicketForWebApiCallbacks : MapVoid> = new Map(); @:noComplete public static function registerGlobalEvent( event : Int, callb : Dynamic -> Void ) { globalEvents.set(event, callb); @@ -538,6 +558,8 @@ class Api @:hlNative("?steam","is_steam_running_on_steam_deck") private static function _IsSteamRunningOnSteamDeck() : Bool { return false; } @:hlNative("steam","is_steam_running") private static function _IsSteamRunning() : Bool { return false; } @:hlNative("steam","get_current_game_language") private static function _GetCurrentGameLanguage() : hl.Bytes { return null; } + @:hlNative("?steam","get_launch_command_line") private static function _GetLaunchCommandLine() : hl.Bytes { return null; } + @:hlNative("?steam","get_launch_query_param") private static function _GetLaunchQueryParam( name : hl.Bytes ) : hl.Bytes { return null; } @:hlNative("steam","get_auth_ticket") private static function _GetAuthTicket( size : hl.Ref, authTicket : hl.Ref ) : hl.Bytes { return null; } @:hlNative("?steam","request_encrypted_app_ticket") private static function _RequestEncryptedAppTicket( data : hl.Bytes, size : Int, encryptedAppTicket : (hl.Bytes, Int) -> Void ) : Void { return; } @:hlNative("steam","open_overlay") private static function _OpenOverlay( url : hl.Bytes ) : Bool { return false; } diff --git a/steam/Lobby.hx b/steam/Lobby.hx index cbabc81..9e601f0 100644 --- a/steam/Lobby.hx +++ b/steam/Lobby.hx @@ -177,6 +177,10 @@ class Lobby { return v; } + public function setLobbyType(v) { + set_lobby_type(uid, v); + } + // --- HL stubs ---- static function request_lobby_data( uid : UID ) { @@ -251,4 +255,7 @@ class Lobby { static function set_lobby_member_limit( uid : UID, count : Int ) { } + static function set_lobby_type( uid : UID, count : Matchmaking.LobbyKind ) { + } + } \ No newline at end of file diff --git a/steam/NetworkingMessages.hx b/steam/NetworkingMessages.hx new file mode 100644 index 0000000..6ed17a8 --- /dev/null +++ b/steam/NetworkingMessages.hx @@ -0,0 +1,30 @@ +package steam; + +private typedef NetworkMessage = hl.Abstract<"steam_networkmsg">; + +@:hlNative("steam") +class NetworkingMessages { + public static function getIdentity():SteamNetworkingIdentity return null; + public static function identityToString(identity) return @:privateAccess String.fromUTF8(_IdentityToString(identity)); + public static function identityFromString(v:String) return @:privateAccess _IdentityFromString(v.toUtf8()); + + public static function initAuthentication() {} + public static function acceptSessionWithUser(identity:SteamNetworkingIdentity):Bool return false; + public static function closeSessionWithUser(identity:SteamNetworkingIdentity):Bool return false; + public static function sendMessageToUser(identity:SteamNetworkingIdentity, data:haxe.io.Bytes, length:Int, nSendFlags:Int, nRemoteChannel:Int):Int { + return _SendMessageToUser(identity, hl.Bytes.fromBytes(data), length, nSendFlags, nRemoteChannel); + } + public static var onSessionRequest:SteamNetworkingIdentity -> Void; + + public static function receiveMessageOnChannel(channel:Int):NetworkMessage return null; + public static function releaseMessage(msg:NetworkMessage) {} + public static function getMessageSize(msg:NetworkMessage):Int return -1; + public static function getMessageData(msg:NetworkMessage):haxe.io.Bytes { + return _GetMessageData(msg).toBytes(getMessageSize(msg)); + } + + @:hlNative("?steam", "identity_to_string") private static function _IdentityToString(identity:SteamNetworkingIdentity):hl.Bytes return null; + @:hlNative("?steam", "identity_from_string") private static function _IdentityFromString(v:hl.Bytes):SteamNetworkingIdentity return null; + @:hlNative("?steam", "send_message_to_user") private static function _SendMessageToUser(identity:SteamNetworkingIdentity, pubData:hl.Bytes, cubData:Int, nSendFlags:Int, nRemoteChannel:Int):Int return -1; + @:hlNative("?steam", "get_message_data") private static function _GetMessageData(msg:NetworkMessage):hl.Bytes return null; +} \ No newline at end of file diff --git a/steam/SteamNetConnectionInfo.hx b/steam/SteamNetConnectionInfo.hx new file mode 100644 index 0000000..95594b8 --- /dev/null +++ b/steam/SteamNetConnectionInfo.hx @@ -0,0 +1,7 @@ +package steam; + +abstract SteamNetConnectionInfo(hl.Bytes) { + public function new(b) { + this = b; + } +} \ No newline at end of file diff --git a/steam/SteamNetworkingIdentity.hx b/steam/SteamNetworkingIdentity.hx new file mode 100644 index 0000000..12ef96c --- /dev/null +++ b/steam/SteamNetworkingIdentity.hx @@ -0,0 +1,7 @@ +package steam; + +abstract SteamNetworkingIdentity(hl.Bytes) { + public function new(b) { + this = b; + } +} \ No newline at end of file