philippj / SteamworksPy

A working Python API system for Valve's Steamworks.
MIT License
212 stars 39 forks source link

GameOverlayActivated_t and GetTicketForWebApiResponse_t callbacks #93

Open D1EGOD opened 1 year ago

D1EGOD commented 1 year ago

Hi! How can I use callbacks for activating overlay (GameOverlayActivated_t) and ISteamUser::GetAuthTicketForWebApi (GetTicketForWebApiResponse_t)? In advance, I understand I need OpenGL/d3d for overlay.

Thanks!

D1EGOD commented 1 year ago

Okay, I figured it out about GetTicketForWebApiResponse_t (I didn't try to do the second function because I didn't need it). I'm not very good at python or c++, but it worked for me, so here's a quick explanation for those who need it.

First, SteamworksPy.cpp. In header: typedef void(*GetTicketForWebApiResponseCallback_t)(GetTicketForWebApiResponse_t);

Under MicroTxn class:

class UserAuth {
public:

    GetTicketForWebApiResponseCallback_t _pyGetTicketForWebApiResponseCallback;

    CCallback <UserAuth, GetTicketForWebApiResponse_t> _getTicketForWebApiResponseCallback;

    UserAuth() : _getTicketForWebApiResponseCallback(this, &UserAuth::OnGetTicketForWebApiResponse) {}

    void SetGetTicketForWebApiResponseCallback(GetTicketForWebApiResponseCallback_t callback) {
        _pyGetTicketForWebApiResponseCallback = callback;
    }

private:
    void OnGetTicketForWebApiResponse(GetTicketForWebApiResponse_t *TicketForWebApiResponse) {
        if (_pyGetTicketForWebApiResponseCallback != nullptr) {
            _pyGetTicketForWebApiResponseCallback(*TicketForWebApiResponse);
        }
    }
};

static UserAuth userauth;

Then define GetAuthTicketForWebApi function. Actually it takes the service identifier parameter, but I didn't need it, so I didn't implement it. You can implement it yourself.

//The calling application must wait for the GetTicketForWebApiResponse_t callback 
//generated by the API call to access the ticket.
SW_PY bool GetAuthTicketForWebApi () {
    if (SteamUser() == NULL) {
        return false;
    }
    SteamUser()->GetAuthTicketForWebApi(NULL);
    return true;
}

And in the bottom of code:

SW_PY void UserAuth_SetGetTicketForWebApiResponseCallback(GetTicketForWebApiResponseCallback_t callback) {
    if (SteamUser() == NULL) {
        return;
    }
    userauth.SetGetTicketForWebApiResponseCallback(callback);
}

Next you have to build library. Then let's move on to methods.py. Add this somewhere after 'GetAuthSessionTicket':

'GetAuthTicketForWebApi': {
        'restype': bool,
    },

and this at the bottom of code:

'UserAuth_SetGetTicketForWebApiResponseCallback': {
        'restype': None,
        'argtypes': [MAKE_CALLBACK(None, structs.GetTicketForWebApiResponse_t)]
    },

Now structs.py. Below:

class GetTicketForWebApiResponse_t(Structure):
    _fields_ = [
        ("m_hAuthTicket", c_uint32),
        ("m_eResult", c_int),
        ("m_cubTicket", c_int),
        ("m_rgubTicket", c_uint8 * 2560)
    ]

Last thing - interfaces/users.py. At the start of SteamUsers class (above the init):

 _GetTicketForWebApiResponse_t = CFUNCTYPE(None, GetTicketForWebApiResponse_t)
 _GetTicketForWebApiResponse = None

And two functions (for request and callback):

def GetAuthTicketForWebApi(self) -> bool:
        return self.steam.GetAuthTicketForWebApi()
def SetGetTicketForWebApiResponseCallback(self, callback: object) -> bool:
        """Set callback for GetTicketForWebApi
        :param callback: callable
        :return: bool
        """
        self._GetTicketForWebApiResponse = SteamUsers._GetTicketForWebApiResponse_t(callback)
        self.steam.UserAuth_SetGetTicketForWebApiResponseCallback(self._GetTicketForWebApiResponse)
        return True

That's it. Here is an EXAMPLE on how I use it. After steamworks.initialize():

steamworks.Users.SetGetTicketForWebApiResponseCallback(getTicketForWebApiResponse) #setting callback called getTicketForWebApiResponse()
steamworks.Users.GetAuthTicketForWebApi() #making a request (again, without service identifier)

And the function itself:

def getTicketForWebApiResponse(result):
    buffer = create_string_buffer(bytes(result.m_rgubTicket))
    ticket = buffer[0:result.m_cubTicket].hex().upper() # web api ticket
    print(ticket) # send it to ISteamUserAuth/AuthenticateUserTicket on your server and get SteamID of the user on success.

Hope it helped. Peace!

philippj commented 1 year ago

Thank you for your investigation, would you mind submitting a PR?