mirror of
https://github.com/mkxp-z/mkxp-z.git
synced 2025-04-21 21:52:04 +02:00
Implement SteamUserStatsLite
This commit is contained in:
parent
d722c70a07
commit
bc7709fb53
8 changed files with 335 additions and 3 deletions
|
@ -96,6 +96,10 @@ void MiniFFIBindingInit();
|
|||
void DiscordBindingInit();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STEAMWORKS
|
||||
void CUSLBindingInit();
|
||||
#endif
|
||||
|
||||
RB_METHOD(mriPrint);
|
||||
RB_METHOD(mriP);
|
||||
RB_METHOD(mkxpDataDirectory);
|
||||
|
@ -146,6 +150,10 @@ static void mriBindingInit() {
|
|||
DiscordBindingInit();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STEAMWORKS
|
||||
CUSLBindingInit();
|
||||
#endif
|
||||
|
||||
if (rgssVer >= 3) {
|
||||
_rb_define_module_function(rb_mKernel, "rgss_main", mriRgssMain);
|
||||
_rb_define_module_function(rb_mKernel, "rgss_stop", mriRgssStop);
|
||||
|
|
245
binding/cusl-binding.cpp
Normal file
245
binding/cusl-binding.cpp
Normal file
|
@ -0,0 +1,245 @@
|
|||
#include "binding-util.h"
|
||||
#include <steam/isteamapps.h>
|
||||
#include <steam/isteamuserstats.h>
|
||||
|
||||
// This is a simple implementation of Steam's user stats.
|
||||
// Basically, a C++ version of this:
|
||||
// https://github.com/GMMan/RGSS_SteamUserStatsLite
|
||||
|
||||
// May or may not be expanded in the future.
|
||||
|
||||
RB_METHOD(CUSLSetStat) {
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
VALUE name, stat;
|
||||
rb_scan_args(argc, argv, "2", &name, &stat);
|
||||
SafeStringValue(name);
|
||||
|
||||
bool ret;
|
||||
if (RB_TYPE_P(stat, RUBY_T_FLOAT)) {
|
||||
ret =
|
||||
SteamUserStats()->SetStat(RSTRING_PTR(name), (float)RFLOAT_VALUE(stat));
|
||||
} else if (RB_TYPE_P(stat, RUBY_T_FIXNUM)) {
|
||||
ret = SteamUserStats()->SetStat(RSTRING_PTR(name), (int)NUM2INT(stat));
|
||||
} else {
|
||||
rb_raise(rb_eTypeError,
|
||||
"Statistic value must be either an integer or float.");
|
||||
}
|
||||
return rb_bool_new(ret);
|
||||
}
|
||||
|
||||
RB_METHOD(CUSLGetStat) {
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
VALUE name;
|
||||
rb_scan_args(argc, argv, "1", &name);
|
||||
SafeStringValue(name);
|
||||
|
||||
int resi;
|
||||
float resf;
|
||||
|
||||
if (SteamUserStats()->GetStat(RSTRING_PTR(name), &resi)) {
|
||||
return INT2NUM(resi);
|
||||
} else if (SteamUserStats()->GetStat(RSTRING_PTR(name), &resf)) {
|
||||
return rb_float_new(resf);
|
||||
} else {
|
||||
return Qnil;
|
||||
}
|
||||
}
|
||||
|
||||
RB_METHOD(CUSLUpdateAvgRateStat) {
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
VALUE name, sessioncount, sessionlength;
|
||||
rb_scan_args(argc, argv, "3", &name, &sessioncount, &sessionlength);
|
||||
SafeStringValue(name);
|
||||
Check_Type(sessioncount, RUBY_T_FLOAT);
|
||||
Check_Type(sessionlength, RUBY_T_FLOAT);
|
||||
|
||||
bool ret = SteamUserStats()->UpdateAvgRateStat(
|
||||
RSTRING_PTR(name), RFLOAT_VALUE(sessioncount), NUM2DBL(sessionlength));
|
||||
|
||||
return rb_bool_new(ret);
|
||||
}
|
||||
|
||||
RB_METHOD(CUSLGetAchievement) {
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
VALUE name;
|
||||
rb_scan_args(argc, argv, "1", &name);
|
||||
SafeStringValue(name);
|
||||
|
||||
bool ret;
|
||||
bool valid = SteamUserStats()->GetAchievement(RSTRING_PTR(name), &ret);
|
||||
|
||||
if (!valid)
|
||||
return Qnil;
|
||||
|
||||
return rb_bool_new(ret);
|
||||
}
|
||||
|
||||
RB_METHOD(CUSLSetAchievement) {
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
VALUE name;
|
||||
rb_scan_args(argc, argv, "1", &name);
|
||||
SafeStringValue(name);
|
||||
|
||||
bool ret = SteamUserStats()->SetAchievement(RSTRING_PTR(name));
|
||||
return rb_bool_new(ret);
|
||||
}
|
||||
|
||||
RB_METHOD(CUSLClearAchievement) {
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
VALUE name;
|
||||
|
||||
rb_scan_args(argc, argv, "1", &name);
|
||||
SafeStringValue(name);
|
||||
|
||||
bool ret = SteamUserStats()->ClearAchievement(RSTRING_PTR(name));
|
||||
return rb_bool_new(ret);
|
||||
}
|
||||
|
||||
RB_METHOD(CUSLGetAchievementAndUnlockTime) {
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
VALUE name;
|
||||
|
||||
rb_scan_args(argc, argv, "1", &name);
|
||||
SafeStringValue(name);
|
||||
|
||||
bool achieved;
|
||||
uint time;
|
||||
|
||||
if (!SteamUserStats()->GetAchievementAndUnlockTime(RSTRING_PTR(name),
|
||||
&achieved, &time))
|
||||
return Qnil;
|
||||
|
||||
VALUE ret = rb_ary_new();
|
||||
rb_ary_push(ret, rb_bool_new(achieved));
|
||||
|
||||
if (!time) {
|
||||
rb_ary_push(ret, Qnil);
|
||||
return ret;
|
||||
}
|
||||
|
||||
VALUE t = rb_funcall(rb_cTime, rb_intern("at"), 1, UINT2NUM(time));
|
||||
rb_ary_push(ret, t);
|
||||
return ret;
|
||||
}
|
||||
|
||||
RB_METHOD(CUSLGetAchievementDisplayAttribute) {
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
VALUE name, key;
|
||||
rb_scan_args(argc, argv, "2", &name, &key);
|
||||
SafeStringValue(name);
|
||||
SafeStringValue(key);
|
||||
|
||||
const char *ret = SteamUserStats()->GetAchievementDisplayAttribute(
|
||||
RSTRING_PTR(name), RSTRING_PTR(key));
|
||||
|
||||
return rb_str_new_cstr(ret);
|
||||
}
|
||||
|
||||
RB_METHOD(CUSLIndicateAchievementProgress) {
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
VALUE name, progress, max;
|
||||
|
||||
rb_scan_args(argc, argv, "3", &name, &progress, &max);
|
||||
SafeStringValue(name);
|
||||
|
||||
bool ret = SteamUserStats()->IndicateAchievementProgress(
|
||||
RSTRING_PTR(name), NUM2UINT(progress), NUM2UINT(max));
|
||||
|
||||
if (ret)
|
||||
return rb_bool_new(SteamUserStats()->StoreStats());
|
||||
|
||||
return rb_bool_new(ret);
|
||||
}
|
||||
|
||||
RB_METHOD(CUSLGetNumAchievements) {
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
rb_check_argc(argc, 0);
|
||||
|
||||
return UINT2NUM(SteamUserStats()->GetNumAchievements());
|
||||
}
|
||||
|
||||
RB_METHOD(CUSLGetAchievementName) {
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
VALUE index;
|
||||
|
||||
rb_scan_args(argc, argv, "1", &index);
|
||||
|
||||
return rb_str_new_cstr(SteamUserStats()->GetAchievementName(NUM2UINT(index)));
|
||||
}
|
||||
|
||||
RB_METHOD(CUSLStoreStats) {
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
rb_check_argc(argc, 0);
|
||||
|
||||
return rb_bool_new(SteamUserStats()->StoreStats());
|
||||
}
|
||||
|
||||
RB_METHOD(CUSLResetAllStats) {
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
bool achievementsToo;
|
||||
|
||||
rb_get_args(argc, argv, "b", &achievementsToo);
|
||||
|
||||
return rb_bool_new(SteamUserStats()->ResetAllStats(achievementsToo));
|
||||
}
|
||||
|
||||
RB_METHOD(CUSLIsSubscribed) {
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
rb_check_argc(argc, 0);
|
||||
|
||||
return rb_bool_new(SteamApps()->BIsSubscribed());
|
||||
}
|
||||
|
||||
RB_METHOD(CUSLIsDlcInstalled) {
|
||||
RB_UNUSED_PARAM;
|
||||
|
||||
VALUE appid;
|
||||
rb_scan_args(argc, argv, "1", &appid);
|
||||
|
||||
return rb_bool_new(SteamApps()->BIsDlcInstalled(NUM2UINT(appid)));
|
||||
}
|
||||
|
||||
void CUSLBindingInit() {
|
||||
|
||||
SteamUserStats()->RequestCurrentStats();
|
||||
|
||||
VALUE mSteamLite = rb_define_module("SteamLite");
|
||||
|
||||
_rb_define_module_function(mSteamLite, "subscribed?", CUSLIsSubscribed);
|
||||
_rb_define_module_function(mSteamLite, "dlc_installed?", CUSLIsDlcInstalled);
|
||||
|
||||
_rb_define_module_function(mSteamLite, "get_stat", CUSLGetStat);
|
||||
_rb_define_module_function(mSteamLite, "set_stat", CUSLSetStat);
|
||||
|
||||
_rb_define_module_function(mSteamLite, "update_avg_rate_stat",
|
||||
CUSLUpdateAvgRateStat);
|
||||
_rb_define_module_function(mSteamLite, "get_achievement", CUSLGetAchievement);
|
||||
_rb_define_module_function(mSteamLite, "set_achievement", CUSLSetAchievement);
|
||||
_rb_define_module_function(mSteamLite, "clear_achievement",
|
||||
CUSLClearAchievement);
|
||||
_rb_define_module_function(mSteamLite, "get_achievement_and_unlock_time",
|
||||
CUSLGetAchievementAndUnlockTime);
|
||||
_rb_define_module_function(mSteamLite, "get_achievement_display_attribute",
|
||||
CUSLGetAchievementDisplayAttribute);
|
||||
_rb_define_module_function(mSteamLite, "indicate_achievement_progress",
|
||||
CUSLIndicateAchievementProgress);
|
||||
_rb_define_module_function(mSteamLite, "get_num_achievements",
|
||||
CUSLGetNumAchievements);
|
||||
_rb_define_module_function(mSteamLite, "get_achievement_name",
|
||||
CUSLGetAchievementName);
|
||||
_rb_define_module_function(mSteamLite, "reset_all_stats", CUSLResetAllStats);
|
||||
}
|
|
@ -41,6 +41,10 @@ if discord == true
|
|||
binding_source += files('discord-binding.cpp')
|
||||
endif
|
||||
|
||||
if steamworks == true
|
||||
binding_source += files('cusl-binding.cpp')
|
||||
endif
|
||||
|
||||
if miniffi == true
|
||||
binding_source += files('miniffi-binding.cpp')
|
||||
endif
|
||||
|
|
|
@ -269,7 +269,10 @@ RB_METHOD(MiniFFI_call) {
|
|||
(unsigned long)ApiFunction(params[0], params[1], params[2], params[3],
|
||||
params[4], params[5], params[6], params[7]);
|
||||
|
||||
// Setting stdcall doesn't work anymore, I HATE WINDOWS
|
||||
// Telling the compiler that the called function uses stdcall
|
||||
// apparently doesn't work anymore, so assembly is used instead.
|
||||
// Technically also allows for an unlimited number of arguments,
|
||||
// but the above code does not
|
||||
#else
|
||||
unsigned long ret = 0;
|
||||
asm volatile(".intel_syntax noprefix\n"
|
||||
|
|
46
meson.build
46
meson.build
|
@ -18,6 +18,10 @@ global_include_dirs = []
|
|||
global_args = []
|
||||
global_link_args = []
|
||||
|
||||
sizeof = {'void*': compilers['cpp'].sizeof('void*'),
|
||||
'long': compilers['cpp'].sizeof('long')
|
||||
}
|
||||
win64 = (sizeof['void*'] != sizeof['long'])
|
||||
# ====================
|
||||
# Ext libs
|
||||
# ====================
|
||||
|
@ -37,6 +41,46 @@ if discord_libpath != ''
|
|||
endif
|
||||
endif
|
||||
|
||||
# STEAMWORKS
|
||||
|
||||
steamworks = false
|
||||
steamworks_path = get_option('steamworks_path')
|
||||
if steamworks_path != ''
|
||||
libname = 'steam_api'
|
||||
if host_system == 'linux'
|
||||
if sizeof['void*'] == 4
|
||||
bindir = 'linux32'
|
||||
else
|
||||
bindir = 'linux64'
|
||||
endif
|
||||
elif host_system == 'windows'
|
||||
if win64 == true
|
||||
bindir = 'win64'
|
||||
libname += '64'
|
||||
else
|
||||
bindir = ''
|
||||
endif
|
||||
else
|
||||
bindir = 'osx'
|
||||
endif
|
||||
|
||||
steam_libpath = steamworks_path + '/redistributable_bin/' + bindir
|
||||
steamlib = compilers['cpp'].find_library(libname, required: false, dirs: [steam_libpath])
|
||||
|
||||
if steamlib.found() == true
|
||||
if get_option('steam_appid') != ''
|
||||
global_include_dirs += include_directories(steamworks_path + '/public')
|
||||
global_args += ['-I@0@/public'.format(steamworks_path),
|
||||
'-DHAVE_STEAMWORKS',
|
||||
'-DSTEAM_APPID=' + get_option('steam_appid')]
|
||||
global_dependencies += steamlib
|
||||
steamworks = true
|
||||
else
|
||||
error('Steamworks SDK was found, but steam_appid isn\'t set!')
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
# BOOST UNORDERED
|
||||
global_include_dirs += include_directories('boost-unordered')
|
||||
|
||||
|
@ -53,7 +97,7 @@ endif
|
|||
# Decide whether or not to use MiniFFI
|
||||
miniffi = get_option('use_miniffi')
|
||||
if miniffi == true
|
||||
if compilers['cpp'].sizeof('void*') == compilers['cpp'].sizeof('long')
|
||||
if win64 != true
|
||||
miniffi = true
|
||||
global_args += '-DUSE_MINIFFI'
|
||||
else
|
||||
|
|
|
@ -18,4 +18,6 @@ option('workdir_current', type: 'boolean', value: false, description: 'Keep curr
|
|||
|
||||
option('independent_appimage', type: 'boolean', value: true, description: 'Set current directory to the original location of the AppImage when contained within one')
|
||||
option('discord_sdk_path', type: 'string', value: '', description: 'Path to Discord GameSDK')
|
||||
option('steamworks_path', type: 'string', value: '', description: 'Path to Steamworks SDK')
|
||||
option('steam_appid', type: 'string', value: '', description: 'Steam application ID.')
|
||||
option('appimagekit_path', type: 'string', value: '', description: 'Path to AppImageKit, used for building AppImages')
|
||||
|
|
|
@ -48,6 +48,10 @@
|
|||
#include "discordstate.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STEAMWORKS
|
||||
#include "steam/steam_api.h"
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
|
@ -590,6 +594,11 @@ void Graphics::update() {
|
|||
shState->discord().update();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STEAMWORKS
|
||||
if (SteamAPI_IsSteamRunning())
|
||||
SteamAPI_RunCallbacks();
|
||||
#endif
|
||||
|
||||
if (p->frozen)
|
||||
return;
|
||||
|
||||
|
|
19
src/main.mm
19
src/main.mm
|
@ -46,7 +46,9 @@
|
|||
#endif
|
||||
|
||||
#import <ObjFW/ObjFW.h>
|
||||
|
||||
#ifdef HAVE_STEAMWORKS
|
||||
#import <steam/steam_api.h>
|
||||
#endif
|
||||
#import "icon.png.xxd"
|
||||
|
||||
#ifndef THREADED_GLINIT
|
||||
|
@ -157,6 +159,17 @@ static void setupWindowIcon(const Config &conf, SDL_Window *win) {
|
|||
|
||||
int main(int argc, char *argv[]) {
|
||||
@autoreleasepool {
|
||||
#ifdef HAVE_STEAMWORKS
|
||||
if (SteamAPI_RestartAppIfNecessary(STEAM_APPID)) {
|
||||
Debug() << "Restarting with Steam...";
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!SteamAPI_Init()) {
|
||||
showInitError("Steamworks failed to initialize.");
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
|
||||
SDL_SetHint(SDL_HINT_ACCELEROMETER_AS_JOYSTICK, "0");
|
||||
|
||||
|
@ -390,6 +403,10 @@ int main(int argc, char *argv[]) {
|
|||
if (wsadata.wVersion)
|
||||
WSACleanup();
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STEAMWORKS
|
||||
SteamAPI_Shutdown();
|
||||
#endif
|
||||
Sound_Quit();
|
||||
TTF_Quit();
|
||||
IMG_Quit();
|
||||
|
|
Loading…
Add table
Reference in a new issue