ENGINE PLUGIN: AGSteam v3.4 (Windows; Linux; Mac OS X)

Started by monkey0506, Thu 27/10/2011 05:05:47

Previous topic - Next topic

CaptainD

I have achievements working fine but I'm unclear on how to tell AGS2Client which leaderboard to upload scores to.

My code is:

Code: ags
            AGS2Client.RequestLeaderboard("Individual_Level_Top_Scores", eAGS2ClientScoresRequestGlobal);  
            AGS2Client.UploadScore(HighScore1);


I have three leaderboards which I reference in code that runs every time I save the high scores, but I have no entries in the Steam leaderboards... I seem to be doing something wrong but not sure what.

 

CaptainD

For anyone else who runs into the issue about, it appears that the only thing I'd messed up with not adding a Wait command after AGS2Client.RequestLeaderboard - I added a "Wait(20)" after it and seems to work fine now.
 

proximity

Hi CaptainD, I'm glad that you solved your problem. Do you have any questions about leaderboards? At first, I thought that it was an exciting feature and put it in my game, then I realized players actually don't care about leaderboards. Only 5% of players have registered themselves into leaderboards in my previous game. I still think it's a cool feature though :)
Proximity Entertainment

CaptainD

Quote from: proximity on Fri 26/06/2020 03:48:19
Hi CaptainD, I'm glad that you solved your problem. Do you have any questions about leaderboards? At first, I thought that it was an exciting feature and put it in my game, then I realized players actually don't care about leaderboards. Only 5% of players have registered themselves into leaderboards in my previous game. I still think it's a cool feature though :)

I haven't released the game on Steam yet (and am likely to only get a handful of players anyway), so I have no idea how much interest there will be, but the particular game I'm working on lends itself to the leaderboard idea - arcade, short gameplay rounds, high customisability so you can make the game easy or much harder (the tougher the setting, the higher the score multipliers etc).  So will have to wait and see...  I'm not aware if the player has to do anything besides have a Steam account for the scores to upload, but will cross that bridge when I come to it!

I did alter the code based on recommendations by Denis (AGS user "Problem") to repeatedly attempt connection to the leaderboard in case it didn't sync properly the first time, I will post the code later in case anyone finds it useful.

Hope your games using the Leaderboard code eventually have more players register to use it!
 

proximity

Quote from: CaptainD on Fri 26/06/2020 11:37:01
Quote from: proximity on Fri 26/06/2020 03:48:19
Hi CaptainD, I'm glad that you solved your problem. Do you have any questions about leaderboards? At first, I thought that it was an exciting feature and put it in my game, then I realized players actually don't care about leaderboards. Only 5% of players have registered themselves into leaderboards in my previous game. I still think it's a cool feature though :)

I haven't released the game on Steam yet (and am likely to only get a handful of players anyway), so I have no idea how much interest there will be, but the particular game I'm working on lends itself to the leaderboard idea - arcade, short gameplay rounds, high customisability so you can make the game easy or much harder (the tougher the setting, the higher the score multipliers etc).  So will have to wait and see...  I'm not aware if the player has to do anything besides have a Steam account for the scores to upload, but will cross that bridge when I come to it!

I did alter the code based on recommendations by Denis (AGS user "Problem") to repeatedly attempt connection to the leaderboard in case it didn't sync properly the first time, I will post the code later in case anyone finds it useful.

Hope your games using the Leaderboard code eventually have more players register to use it!

I did 3 seconds loops of uploads on repeatedly_execute_always while CurrentLeaderboard isn't null. When the game calls UploadScore, it has always uploaded the score for the first time but there is no harm using repeatedly_execute to make sure. The plugin is well optimized and never slows down the engine even if you call it every loop. The only thing bothers me is when Steam Overlay is active, the mouse still controls the game cursor so I can't move the windows cursor over Steam UI.
Proximity Entertainment

pente

Hi, I am experiencing this error: "Runtime error: unresolved import 'Steam::AddAchievement^1'."

This occurs when launching Blackwell: Deception on linux. I have no interest in the steam integration, just in launching the game without crashing.

I am running AGS v.3.5.0.27. I invoked the game with "./ags <path-to-game-directory>/'. The game directory contains several windows exes and dlls, including agsteam, but no linux executables or libraries. I would use "ldd" to check for missing libraries but there is no linux executable for me to run it on.

(When compiling AGS, I had to change the Makefile to compile libdumb and libaldmb dynamically instead of statically as this library is only available dynamically in my distro.)

Let me know if any other information would be helpful, thanks.

(The game runs poorly with wine, using 100% cpu and lagging horribly.)

Crimson Wizard

I thought Wadjet Eye was providing linux builds too...

Quote from: pente on Wed 21/10/2020 02:36:03
Hi, I am experiencing this error: "Runtime error: unresolved import 'Steam::AddAchievement^1'."

I do not know all about steam plugin's history, but it may be that the game was made with older version of steam plugin, and engine does not have any stub registered for this. It has stub for "AGSteam::IsAchievementAchieved^1" for example (these were names suggested by plugin author). Perhaps adding more variants to the list of stubs will resolve the issue.

These could be found in RegisterPluginStubs function (Engine/plugin/global_plugin.cpp).

Also, could you tell, what is the exact name of plugin dll (or .so if any) found with original game?


pente

Quote from: Crimson Wizard on Wed 21/10/2020 05:26:54
I thought Wadjet Eye was providing linux builds too...

[...] Also, could you tell, what is the exact name of plugin dll (or .so if any) found with original game?

Only the first three games had linux builds. Blackwell: Deception ships with agsteam.dll and steam_api.dll, as well as Deception.exe, acsetup.cfg, ags_shell.dll, audio.vox, desktop.ini, prog.bwd, speech.vox, steam_appid.txt, and winsetup.exe.

Are you suggesting I should edit AGS so it has some empty function with the name that is missing?

I've read elsewhere that it was made with an older version of AGS, but I could not figure out any way to determine which version I would need. It was released on 2011 Oct 12.

Crimson Wizard

Quote from: pente on Wed 21/10/2020 19:48:05
Only the first three games had linux builds. Blackwell: Deception ships with agsteam.dll ...

Ah, alright, the stubs are registered for "agsteam" plugin name, so only problem is that function names are different for some reason.

Quote from: pente on Wed 21/10/2020 19:48:05
Are you suggesting I should edit AGS so it has some empty function with the name that is missing?

You could try, if you like, as it may be pretty straightforward: find Engine/plugin/global_plugin.cpp and copy a section of code:
Code: cpp

    if (is_agsteam)
    {
      ccAddExternalStaticFunction("AGSteam::IsAchievementAchieved^1", Sc_PluginStub_Int0);
      ccAddExternalStaticFunction("AGSteam::SetAchievementAchieved^1", Sc_PluginStub_Int0);
      ccAddExternalStaticFunction("AGSteam::ResetAchievement^1", Sc_PluginStub_Int0);
      ccAddExternalStaticFunction("AGSteam::GetIntStat^1", Sc_PluginStub_Int0);
      ccAddExternalStaticFunction("AGSteam::GetFloatStat^1", Sc_PluginStub_Int0);
      ccAddExternalStaticFunction("AGSteam::GetAverageRateStat^1", Sc_PluginStub_Int0);
      ccAddExternalStaticFunction("AGSteam::SetIntStat^2", Sc_PluginStub_Int0);
      ccAddExternalStaticFunction("AGSteam::SetFloatStat^2", Sc_PluginStub_Int0);
      ccAddExternalStaticFunction("AGSteam::UpdateAverageRateStat^3", Sc_PluginStub_Int0);
      ccAddExternalStaticFunction("AGSteam::ResetStatsAndAchievements^0", Sc_PluginStub_Void);
      ccAddExternalStaticFunction("AGSteam::get_Initialized", Sc_PluginStub_Int0);
      ccAddExternalStaticFunction("AGSteam::get_CurrentLeaderboardName", Sc_PluginStub_NullStr);
      ccAddExternalStaticFunction("AGSteam::RequestLeaderboard^3", Sc_PluginStub_Void);
      ccAddExternalStaticFunction("AGSteam::UploadScore^1", Sc_PluginStub_Int0);
      ccAddExternalStaticFunction("AGSteam::geti_LeaderboardNames", Sc_PluginStub_NullStr);
      ccAddExternalStaticFunction("AGSteam::geti_LeaderboardScores", Sc_PluginStub_Int0);
      ccAddExternalStaticFunction("AGSteam::get_LeaderboardCount", Sc_PluginStub_Int0);
      ccAddExternalStaticFunction("AGSteam::GetUserName^0", Sc_PluginStub_NullStr);
      ccAddExternalStaticFunction("AGSteam::GetCurrentGameLanguage^0", Sc_PluginStub_NullStr);
      ccAddExternalStaticFunction("AGSteam::FindLeaderboard^1", Sc_PluginStub_Void);
    }


...and replace all instances of "AGSteam::" with "Steam::".

If that works we may add this to main repository too :).

Or later when I have more spare time I could check out the game myself.


Quote from: pente on Wed 21/10/2020 19:48:05
I've read elsewhere that it was made with an older version of AGS, but I could not figure out any way to determine which version I would need. It was released on 2011 Oct 12.

When you run the game, engine should print something like "Game data version: NNN" and "Compiled with: AGS X.X.X" to console, which may give at least approximate idea.
But, I dont think knowing this will help to solve this problem, as older engines did not have any Steam stubs at all (they were added much later).
There was also a Steam stub plugin, created by AGSSteam author (https://github.com/monkey0506/ags2clientstub), but I've got a suspicion that it may have exactly same problem of having newer function names. I dont know if there's an older version of that.

pente

Thank you for your help, it now works!

In any addition to the changes you suggested, I added

ccAddExternalStaticFunction("Steam::AddAchievement^1", Sc_PluginStub_Void);

I just guessed at "void" but the engine hasn't crashed so maybe that's fine. We'll see what happens if I get an in-game achievement.

I don't know how I missed it before (since I was looking), but on startup it says:

Game data version: 42
Compiled with: 3.2.0

Unfortunately the game no longer automatically progresses through dialog; I have to manually advance the conversation after each dialog clip is played. Maybe there's an option somewhere to change that.

adipson

Hello !
Thank you for this Steam plugin which works at the top!

Have a nice week !
POINT AND CLICK
2023-2024 : Magret & FaceDeBouc : https://store.steampowered.com/app/2661780/Magret__FaceDeBouc/
2019-2022 : Grandma Badass : https://store.steampowered.com/app/1606640/
Official website : https://adipson-studio.com/

Laura Hunt

Quote from: proximity on Fri 26/06/2020 14:10:34The only thing bothers me is when Steam Overlay is active, the mouse still controls the game cursor so I can't move the windows cursor over Steam UI.

I know this is a pretty old post, but I figured this would be useful for anybody who has this issue: this happens if you use the Direct3D graphics driver, but if you switch to OpenGL, it works fine.

eri0o

Laura, can you test if the overlay affects the result of input focus? https://adventuregamestudio.github.io/ags-manual/System.html#systemhasinputfocus

In the issue on GitHub it says it used to affect OpenGL too so it is curious what changed - but at least there's a workaround for now.

Also, monkey0506, if you are still here, can you add a boolean to check if the overlay is active?

Edit: I wonder if the sdl2 version of the engine is affected by this.

CaptainD

Quote from: proximity on Fri 26/06/2020 14:10:34
Quote from: CaptainD on Fri 26/06/2020 11:37:01
Quote from: proximity on Fri 26/06/2020 03:48:19
Hi CaptainD, I'm glad that you solved your problem. Do you have any questions about leaderboards? At first, I thought that it was an exciting feature and put it in my game, then I realized players actually don't care about leaderboards. Only 5% of players have registered themselves into leaderboards in my previous game. I still think it's a cool feature though :)

I haven't released the game on Steam yet (and am likely to only get a handful of players anyway), so I have no idea how much interest there will be, but the particular game I'm working on lends itself to the leaderboard idea - arcade, short gameplay rounds, high customisability so you can make the game easy or much harder (the tougher the setting, the higher the score multipliers etc).  So will have to wait and see...  I'm not aware if the player has to do anything besides have a Steam account for the scores to upload, but will cross that bridge when I come to it!

I did alter the code based on recommendations by Denis (AGS user "Problem") to repeatedly attempt connection to the leaderboard in case it didn't sync properly the first time, I will post the code later in case anyone finds it useful.

Hope your games using the Leaderboard code eventually have more players register to use it!

I did 3 seconds loops of uploads on repeatedly_execute_always while CurrentLeaderboard isn't null. When the game calls UploadScore, it has always uploaded the score for the first time but there is no harm using repeatedly_execute to make sure. The plugin is well optimized and never slows down the engine even if you call it every loop. The only thing bothers me is when Steam Overlay is active, the mouse still controls the game cursor so I can't move the windows cursor over Steam UI.

Going back to this, I don't seem to have solved the problem now that I have a live build up for testing. The solution I had in mind was to upload to leaderboards in a function that's only called when you quit the game. The issue is that I have 3 different leaderboards and what I wanted was for it to check one, wait, connect, upload the score (or retry connecting if failed, up to 5 retries) and then check to the next, and the next. However I tried this and the game crashes because of a Null pointer. This may be partially resolved by increasing the Wait time each loop (it was only set to 6 when I first checked it and got the error) but I'm not confident that will prevent the game from crashing still if the user's connection is bad or the Steam servers are busy.

In line with what you said I could maybe go with this but have a null pointer check before trying to update (the current code only checks if the LeaderBoard Name value matches the leaderboard I'm attempting to access at the time). Or potentially I could have it repeatedly execute and have it swap between which leaderboard name it's looking for every n loops.

The (very simple) code I have so far, which is repeated for each different leaderboard (I know, I know...) is this:

Code: ags
function UpdateHighScoreTables()
{
  connectedtocorrectleaderboard=false;
  connectloop=0;
  
  while ((connectedtocorrectleaderboard == false) && (connectloop < 6)) 
    {
      AGS2Client.RequestLeaderboard("Individual_Level_Top_Scores", eAGS2ClientScoresRequestGlobal);  
      Wait(20);
      if (AGS2Client.CurrentLeaderboardName=="Individual_Level_Top_Scores") connectedtocorrectleaderboard=true;     
      connectloop++;
    }
  if (connectedtocorrectleaderboard==true) 
    {         
      AGS2Client.UploadScore(HighScore1);
      Wait(5);
    }           


Maybe this would work?

Code: ags
if ((AGS2Client.CurrentLeaderboardName != null) && (AGS2Client.CurrentLeaderboardName=="Individual_Level_Top_Scores")) connectedtocorrectleaderboard=true;   


Or am I simply creating problems for myself by running it as a one-off function rather than having it check repeatedly?

Currently I have no client-side code that checks if the high score has been uploaded already, but I feel that shouldn't be necessary as Steam automatically handles that.
 

Crimson Wizard

@CaptainD, can't say I understand all the context, but it's absolutely true that you should test an object for null if it *may* be null, prior to using it further.

Another thing that I might mention, in asynchronous programming a usual tradition is to use time as a limitation, rather than the number of tries, e.g. if you'd use DateTime functions to remember the time before you start connecting and wait for X seconds max (where X is whatever you think is okay for players to wait).

Whether to check for connection in one same function or in rep-exec imho depends mostly on whether you want players to retain input while this work is being done. Because that would be the biggest difference: if the reconnect/upload is done within 1 script function, then players won't be able to interact with anything in game until the script ends; at the same time if it's done in rep-exec (one try at a time) then players will be able to interact with the game while this process is happening.

If there's concern about overloading rep-exec with stuff, the common solution is to set a variable telling whether this process is going, and only do these connection tasks if it's active, and not otherwise. Thus you will skip unnecessary actions for the rest of the game.

CaptainD

@CW - many thanks, I'll take on board what you've said and rework my code, your comments are very helpful.
 

Crimson Wizard

Oh, I forgot to mention, if chosen to do in rep-exec - it should be rep-exec-always, so to make it work all the time, because regular rep-exec is disabled during blocking game actions.


CaptainD

For what it's worth, this is the code I ended up with. I couldn't get it to work with Steam at all unless I used the original AGSteam plugin; tried it with AGS2Client and Steam Disjoint but wouldn't do anything. Not sure why.

I may have ended up making the delay a bit longer than necessary as I wasn't sure initially if that's why it wasn't picking up the leaderboards. This way it always waits about a second before trying to access the requested leaderboard and at least half a second for the score to upload to the selected board.

I'm sure my code can be improved on but if anyone's got a game with multiple Steam leaderboards and are having trouble getting it to work, perhaps my example may be of some value.

Code: ags
function repeatedly_execute_always() 
{
  if (LB_loops==0)
    { 
      if (LB_type==1) AGS2Client.RequestLeaderboard("Individual_Level_Top_Scores", eAGS2ClientScoresRequestGlobal);
      if (LB_type==2) AGS2Client.RequestLeaderboard("Challenge_Mode_Top_Scores", eAGS2ClientScoresRequestGlobal);
      if (LB_type==3) AGS2Client.RequestLeaderboard("All_Time_Top_Scores", eAGS2ClientScoresRequestGlobal);
    }
  LB_loops++;
  
  if ((LB_loops>40) && (LB_loops<80) && (AGS2Client.CurrentLeaderboardName !=null))
    { 
      if (AGS2Client.CurrentLeaderboardName=="Individual_Level_Top_Scores") AGS2Client.UploadScore(HighScore1); 
      if (AGS2Client.CurrentLeaderboardName=="Challenge_Mode_Top_Scores") AGS2Client.UploadScore(CMHS1);
      if (AGS2Client.CurrentLeaderboardName=="All_Time_Top_Scores") AGS2Client.UploadScore(All_Time_Score);
      LB_loops=80;
    }
  if (LB_loops==100) 
    {
      LB_loops=0;
      LB_type++;
      if(LB_type==4) LB_type=1;
    }
}


Thanks again to CW for your help, also Laura and Denis for your assistance via Twitter.
 

rongel

Hello, and sorry for bumbing this, but just need a bit of clarification on the install instructions to make sure everything is like it should be.

Windows
I copy the "AGSteam.dll" and "steam_api.dll"to the AGS editor's directory. Everything works fine. Achievements work. All is good.

Linux
Now I have folders Linux32 and Linux64 in the install package. Do I copy the contents to AGS editor's root directory, like with the Windows version, or to the "Linux\lib32" and Linux\lib64 folders? Currently I've done the latter option. When I compile the game I get this warning:



So what I did is that I went to the Linux\lib32 folder and rename the libagsteam-32.so file to libagsteam.so. It feels a bit sketchy, but I got rid of the warning and it compiles fine. As I have no way to test the Linux version myself, I'm still wondering if it is like it should be. So any help is appreciated!

Bonus question: I think I read somewhere that I should copy the AGSteam files to the "_debug" folder also. Is this correct or necessary?

Thanks again!
Dreams in the Witch House on Steam & GOG

SMF spam blocked by CleanTalk