diff --git a/library/SteamworksPy.cpp b/library/SteamworksPy.cpp index 4fe8e15..0e5229d 100644 --- a/library/SteamworksPy.cpp +++ b/library/SteamworksPy.cpp @@ -95,6 +95,7 @@ typedef void(*RemoteStorageSubscribeFileResultCallback_t)(SubscriptionResult); typedef void(*RemoteStorageUnsubscribeFileResultCallback_t)(SubscriptionResult); typedef void(*LeaderboardFindResultCallback_t)(LeaderboardFindResult_t); typedef void(*MicroTxnAuthorizationResponseCallback_t)(MicroTxnAuthorizationResponse_t); +typedef void(*SteamUGCQueryCompletedCallback_t)(SteamUGCQueryCompleted_t); //----------------------------------------------- // Workshop Class @@ -106,11 +107,13 @@ class Workshop { ItemInstalledCallback_t _pyItemInstalledCallback; RemoteStorageSubscribeFileResultCallback_t _pyItemSubscribedCallback; RemoteStorageUnsubscribeFileResultCallback_t _pyItemUnsubscribedCallback; + SteamUGCQueryCompletedCallback_t _pyQueryCompletedCallback; CCallResult _itemCreatedCallback; CCallResult _itemUpdatedCallback; CCallResult _itemSubscribedCallback; CCallResult _itemUnsubscribedCallback; + CCallResult _queryCompletedCallback; CCallback _itemInstalledCallback; @@ -140,6 +143,10 @@ class Workshop { _pyItemUnsubscribedCallback = callback; } + void SetQueryCompletedCallback(SteamUGCQueryCompletedCallback_t callback) { + _pyQueryCompletedCallback = callback; + } + void CreateItem(AppId_t consumerAppId, EWorkshopFileType fileType) { //TODO: Check if fileType is a valid value? SteamAPICall_t createItemCall = SteamUGC()->CreateItem(consumerAppId, fileType); @@ -161,6 +168,11 @@ class Workshop { _itemUnsubscribedCallback.Set(unsubscribeItemCall, this, &Workshop::OnItemUnsubscribed); } + void SendQueryRequest(UGCQueryHandle_t queryHandle) { + SteamAPICall_t queryRequestCall = SteamUGC()->SendQueryUGCRequest(queryHandle); + _queryCompletedCallback.Set(queryRequestCall, this, &Workshop::OnQueryCompleted); + } + private: void OnWorkshopItemCreated(CreateItemResult_t *createItemResult, bool bIOFailure) { if (_pyItemCreatedCallback != nullptr) { @@ -193,6 +205,12 @@ class Workshop { _pyItemUnsubscribedCallback(result); } } + + void OnQueryCompleted(SteamUGCQueryCompleted_t *queryCompletedResult, bool bIOFailure) { + if (_pyQueryCompletedCallback != nullptr) { + _pyQueryCompletedCallback(*queryCompletedResult); + } + } }; static Workshop workshop; @@ -1457,6 +1475,31 @@ SW_PY void Workshop_SuspendDownloads(bool bSuspend) { SteamUGC()->SuspendDownloads(bSuspend); } +SW_PY UGCQueryHandle_t Workshop_CreateQueryUGCDetailsRequest(PublishedFileId_t * pvecPublishedFileID, uint32 unNumPublishedFileIDs) { + return SteamUGC()->CreateQueryUGCDetailsRequest(pvecPublishedFileID, unNumPublishedFileIDs); +} + +SW_PY void Workshop_SetQueryCompletedCallback(SteamUGCQueryCompletedCallback_t callback) { + if (SteamUGC() == NULL) { + return; + } + workshop.SetQueryCompletedCallback(callback); +} + +SW_PY void Workshop_SendQueryUGCRequest(UGCQueryHandle_t handle) { + if(SteamUGC() == NULL){ + return; + } + workshop.SendQueryRequest(handle); +} + +SW_PY bool Workshop_GetQueryUGCResult(UGCQueryHandle_t handle, uint32 index, SteamUGCDetails_t * pDetails) { + if(SteamUGC() == NULL){ + return false; + } + return SteamUGC()->GetQueryUGCResult(handle, index, pDetails); +} + //----------------------------------------------- // Steam Leaderboard //----------------------------------------------- diff --git a/steamworks/interfaces/workshop.py b/steamworks/interfaces/workshop.py index 9366a63..9d40a28 100644 --- a/steamworks/interfaces/workshop.py +++ b/steamworks/interfaces/workshop.py @@ -13,12 +13,14 @@ class SteamWorkshop(object): _ItemInstalled_t = CFUNCTYPE(None, ItemInstalled_t) _RemoteStorageSubscribePublishedFileResult_t = CFUNCTYPE(None, SubscriptionResult) _RemoteStorageUnsubscribePublishedFileResult_t = CFUNCTYPE(None, SubscriptionResult) + _SteamUGCQueryCompleted_t = CFUNCTYPE(None, SteamUGCQueryCompleted_t) _CreateItemResult = None _SubmitItemUpdateResult = None _ItemInstalled = None _RemoteStorageSubscribePublishedFileResult = None _RemoteStorageUnsubscribePublishedFileResult = None + _SteamUGCQueryCompleted = None def __init__(self, steam: object): @@ -376,3 +378,59 @@ def GetItemDownloadInfo(self, published_file_id: int) -> dict: } return {} + + + def CreateQueryUGCDetailsRequest(self, published_file_ids: list) -> int: + """Create UGC item details query request + + :param published_file_ids: int list + :return: int + """ + published_files_c = (c_uint64 * len(published_file_ids))() + for index, published_file_id in enumerate(published_file_ids): + published_files_c[index] = c_uint64(published_file_id) + + return self.steam.Workshop_CreateQueryUGCDetailsRequest(published_files_c, len(published_file_ids)) + + + def SetQueryUGCRequestCallback(self, callback: object) -> bool: + """Set callback for UGC query + + :param callback: callable + :return: bool + """ + self._SteamUGCQueryCompleted = SteamWorkshop._SteamUGCQueryCompleted_t(callback) + self.steam.Workshop_SetQueryCompletedCallback(self._SteamUGCQueryCompleted) + return True + + + def SendQueryUGCRequest(self, handle: int, callback: object = None, override_callback: bool = False) -> None: + """Create UGC item details query request + + :param handle: query handle + :param callback: callable + :param override_callback: bool + :return: + """ + if override_callback: + self.SetQueryUGCRequestCallback(callback) + + elif callback and not self._SteamUGCQueryCompleted: + self.SetQueryUGCRequestCallback(callback) + + if self._SteamUGCQueryCompleted is None: + raise SetupRequired('Call `SetQueryUGCRequestCallback` first or supply a `callback`') + + self.steam.Workshop_SendQueryUGCRequest(handle) + + + def GetQueryUGCResult(self, handle: int, index: int) -> SteamUGCDetails_t: + """Create UGC item details query request + + :param handle: query handle + :param index: int + :return: SteamUGCDetails_t + """ + details = SteamUGCDetails_t() + self.steam.Workshop_GetQueryUGCResult(handle, index, byref(details)) + return details diff --git a/steamworks/methods.py b/steamworks/methods.py index 4d22035..98a8132 100644 --- a/steamworks/methods.py +++ b/steamworks/methods.py @@ -465,6 +465,21 @@ class InputDigitalActionData_t(Structure): 'restype': None, 'argtypes': [c_uint64] }, + 'Workshop_CreateQueryUGCDetailsRequest': { + 'restype': c_uint64, + 'argtypes': [POINTER(c_uint64), c_uint32] + }, + 'Workshop_SetQueryCompletedCallback': { + 'restype': None, + 'argtypes': [MAKE_CALLBACK(None, structs.SteamUGCQueryCompleted_t)] + }, + 'Workshop_SendQueryUGCRequest': { + 'argtypes': [c_uint64] + }, + 'Workshop_GetQueryUGCResult': { + 'restype': bool, + 'argtypes': [c_uint64, c_uint32, POINTER(structs.SteamUGCDetails_t)] + }, 'MicroTxn_SetAuthorizationResponseCallback': { 'restype': None, 'argtypes': [MAKE_CALLBACK(None, structs.MicroTxnAuthorizationResponse_t)] diff --git a/steamworks/structs.py b/steamworks/structs.py index 7f6f7b4..e547ceb 100644 --- a/steamworks/structs.py +++ b/steamworks/structs.py @@ -38,6 +38,48 @@ class SubscriptionResult(Structure): ("publishedFileId", c_uint64) ] + +class SteamUGCQueryCompleted_t(Structure): + _fields_ = [ + ("handle", c_uint64), + ("result", c_int), + ("numResultsReturned", c_uint32), + ("totalMatchingResults", c_uint32), + ("cachedData", c_bool) + ] + + +class SteamUGCDetails_t(Structure): + _fields_ = [ + ("publishedFileId", c_uint64), + ("result", c_int), + ("fileType", c_int), + ("creatorAppID", c_uint32), + ("consumerAppID", c_uint32), + ("title", c_char * 129), + ("description", c_char * 8000), + ("steamIDOwner", c_uint64), + ("timeCreated", c_uint32), + ("timeUpdated", c_uint32), + ("timeAddedToUserList", c_uint32), + ("visibility", c_int), + ("banned", c_bool), + ("acceptedForUse", c_bool), + ("tagsTruncated", c_bool), + ("tags", c_char * 1025), + ("file", c_uint64), + ("previewFile", c_uint64), + ("fileName", c_char * 260), + ("fileSize", c_uint32), + ("previewFileSize", c_uint32), + ("URL", c_char * 256), + ("votesUp", c_uint32), + ("votesDown", c_uint32), + ("score", c_float), + ("numChildren", c_uint32), + ] + + class MicroTxnAuthorizationResponse_t(Structure): _fields_ = [ ("appId", c_uint32),