Closed rimpy-custom closed 2 years ago
Hey there! The function run_callbacks needs to be in a loop where it is called every tick or so. This will trigger certain other functions to fire when the callback comes through. Beyond that, I have never used the callbacks in Python. I hope that helps.
Hey there! The function run_callbacks needs to be in a loop where it is called every tick or so. This will trigger certain other functions to fire when the callback comes through. Beyond that, I have never used the callbacks in Python. I hope that helps.
This is the way to go. Use the run_callbacks
method either in a main loop or a different thread depending on use case.
Have tried that, but still no luck:
import os
import sys
if sys.version_info >= (3, 8):
os.add_dll_directory(os.getcwd()) # Required since Python 3.8
from steamworks import STEAMWORKS # Import main STEAMWORKS class
def checkCallbacks(obj):
while True:
obj.run_callbacks()
def call_me():
print("test")
return print("test2")
if __name__ == '__main__':
steamworks = STEAMWORKS()
steamworks.initialize()
from threading import Thread
th = Thread(target=checkCallbacks, args=(steamworks,))
th.start()
steamworks.Workshop.SubscribeItem([steamId], call_me)
Where is the SteamID you're passing to SubscribeItem being set from? I'm also rusty on my Python; that being said, is there a main loop that is still running?
I just run script from command line. Not sure but it is a main loop, probably. Because command line did not close after script was run. Afaik, threads in Python runs concurrently and not parallel. Not sure if that may be a problem in current situation.
I set [steamid] manually as integer, for example 2336610918. It is an item from Rimworld game workshop.
Does your print display?
@rimpy-custom I could confirm your issue. However, I am unsure about what exactly is causing this.
Calling steamworks.Workshop.GetNumSubscribedItems()
makes the entire interface work. I have added the call in the main module init so that it will work consistently.
Have tried but still an issue for me. No text printed. May it be python interpreter? I am on latest 3.9.0. @Gramps yeah, it just prints "test" when function called. Since we run thread, it will print it inthe same command line window.
@philippj made some tests. I was able to get callback. Looks like the issue is in here https://github.com/philippj/SteamworksPy/blob/98272dd1b6b41f25431bb1f30f5ecc2775ffe248/steamworks/interfaces/workshop.py#L124
It checks self._RemoteStorageSubscribePublishedFileResult
, but it always False. Probably, because it is async and result is not ready yet.
So I have removed self._RemoteStorageSubscribePublishedFileResult
from a condition and callback was called.
Not sure, maybe I broke smth also.
P. S. I made tests on your latest master branch with latest changes you have done. Also I have added override_callback=True
to method call and call_me
needs an argument. So the full example is that:
import os
import sys
if sys.version_info >= (3, 8):
os.add_dll_directory(os.getcwd()) # Required since Python 3.8
from steamworks import STEAMWORKS # Import main STEAMWORKS class
def checkCallbacks(obj):
obj.run_forever(0)
def call_me(result):
print(result)
print("It is a callback!")
return print("It is a callback!")
if __name__ == '__main__':
steamworks = STEAMWORKS()
steamworks.initialize()
from threading import Thread
th = Thread(target=checkCallbacks, args=(steamworks,))
th.start()
steamworks.Workshop.SubscribeItem(2336610918, call_me, override_callback=True)
Also I have found that run_callbacks()
may be called later, not in thread. As far as I find out, it should be run after async result arrived. So smth like time.sleep(5)
will work, if you know that answer will received in 5 seconds. But it is still better to run_forever()
in thread and be called in intervals, because you do not know how long that may take to receive a result.
@rimpy-custom See this: https://gist.github.com/philippj/abf45e3e8e5fbe521125ae1cfe4de7d4
What I could not make out from your snippet is whether or not you have a main loop. You can also call the run_callbacks
from your main loop, but that depends on your overall application structure. The threading and thus "async" calling of the run_callbacks
is not required. run_forever
works also just fine as it basically only calls run_callbacks
with a delay. You should never use a base_interval of 0 or generally not sleep between run_callbacks.
Removing self._RemoteStorageSubscribePublishedFileResult
does not actually change anything. Yes it will be None/False as you have not supplied a callback via SetItemSubscribedCallback
. Thats what the second (and third) parameter are for in SubscribeItem
.
So smth like
time.sleep(5)
will work, if you know that answer will received in 5 seconds.
SubscribeItem will not only subscribe the current user to the item but will also initiate some internal stuff. You will only receive the ItemSubscribed event after that has been finished. Using my test script, I receive the events almost instantaneous.
If I run script as is, then I do not have mainloop, am I right? Then I do not have any. That is the cause, probably.
Basicly I spawn a process, where I instantiate and initialize Steamworks object, spawn a new thread in it where call run_callbacks
, then run subscribe methods in there and wait for callbacks. When job done I kill that Process and return to main program.
I need to do that because I do not want to see Steam Overlay in my main PyQt window. Afaik, there is no way to disable steam overlay or shutdown Steam API after it was initialized.
Thank you for your project, time and example. I will try to build smth with that info.
P. S. It is a third-party mod manager and not game itself. So I need sub/unsub only functionality, without overlays or smth.
If you do not have a main loop and just run the script you supplied as is, your script will exit and the callback will never be called. You need to either join the thread or put in a main loop that keeps the process alive.
@philippj I see that in the example you call SetItemSubscribedCallback
and then SubscribeItem
. So _RemoteStorageSubscribePublishedFileResult
will not be None. But you may also call SubscribeItem
with arguments and set callback function in it SubscribeItem(self, published_file_id: int, callback: object = None, override_callback: bool = False)
. If you do so and make override_callback=True
, then _RemoteStorageSubscribePublishedFileResult
will always be False and SetItemSubscribedCallback
never called. Because we check it before running SetItemSubscribedCallback
, which changes it from None Am I right on that?
https://github.com/philippj/SteamworksPy/blob/98272dd1b6b41f25431bb1f30f5ecc2775ffe248/steamworks/interfaces/workshop.py#L115
UPDATE: tested both. Yes, you either need to run SetItemSubscribedCallback
and then SubscribeItem
for callback to work or modify code to run SubscribeItem
if you specify callback in it.
Is this still relevant?
No, thank you
I am trying to use steamworks.Workshop.SubscribeItem([code], callback) where callback is a function that prints a string but it never executes. I want to make sure that item actually was subscribed, but not sure how to do that properly. May I ask for a hand?
May I ask for an example how to use callback properly?