Basic Steamworks API support

This commit is contained in:
Mathew Velasquez 2016-02-17 17:12:21 -05:00
parent 2df5fd29de
commit 21fcc9e19c
8 changed files with 319 additions and 1 deletions

View file

@ -0,0 +1,109 @@
#ifdef STEAM
#include "steam.h"
#endif
#include "etc.h"
#include "sharedstate.h"
#include "binding-util.h"
#include "binding-types.h"
#include "debugwriter.h"
#ifdef STEAM
static ID achievementIds[Achievement::MAX];
static Achievement::ID toAchievementId(ID id)
{
/* Crude but effective */
for (int i = 0; i < Achievement::MAX; ++i)
{
if (achievementIds[i] == id)
return static_cast<Achievement::ID>(i);
}
return Achievement::Invalid;
}
#endif
RB_METHOD(steamEnabled)
{
RB_UNUSED_PARAM;
#ifdef STEAM
return Qtrue;
#else
return Qfalse;
#endif
}
RB_METHOD(steamUnlock)
{
RB_UNUSED_PARAM;
ID rbid;
rb_get_args(argc, argv, "n", &rbid RB_ARG_END);
#ifdef STEAM
Achievement::ID id = toAchievementId(rbid);
if (id == Achievement::Invalid)
rb_raise(rb_eNameError, "unlocked nonexistent achievement");
else
shState->steam().unlock(id);
#endif
return Qnil;
}
RB_METHOD(steamLock)
{
RB_UNUSED_PARAM;
ID rbid;
rb_get_args(argc, argv, "n", &rbid RB_ARG_END);
#ifdef STEAM
Achievement::ID id = toAchievementId(rbid);
if (id == Achievement::Invalid)
rb_raise(rb_eNameError, "locked nonexistent achievement");
else
shState->steam().lock(id);
#endif
return Qnil;
}
RB_METHOD(steamUnlocked)
{
RB_UNUSED_PARAM;
ID rbid;
rb_get_args(argc, argv, "n", &rbid RB_ARG_END);
#ifdef STEAM
Achievement::ID id = toAchievementId(rbid);
if (id == Achievement::Invalid)
return Qfalse;
return shState->steam().isUnlocked(id) ? Qtrue : Qfalse;
#else
return Qfalse;
#endif
}
void steamBindingInit()
{
VALUE module = rb_define_module("Steam");
/* Constants */
#ifdef STEAM
rb_const_set(module, rb_intern("USER_NAME"), rb_str_new2(shState->steam().userName().c_str()));
#else
rb_const_set(module, rb_intern("USER_NAME"), Qnil);
#endif
/* Functions */
_rb_define_module_function(module, "enabled?", steamEnabled);
_rb_define_module_function(module, "unlock", steamUnlock);
_rb_define_module_function(module, "lock", steamLock);
_rb_define_module_function(module, "unlocked?", steamUnlocked);
#ifdef STEAM
/* Cache achievement ids */
for (int i = 0; i < Achievement::MAX; ++i)
achievementIds[i] = rb_intern(Achievement::names[i]);
#endif
}

View file

@ -14,6 +14,13 @@ isEmpty(BINDING) {
BINDING = MRI BINDING = MRI
} }
isEmpty(STEAMWORKS) {
STEAMWORKS = /home/mathew/Software/Steamworks
}
isEmpty(STEAMARCH) {
STEAMARCH = 64
}
contains(BINDING, MRI) { contains(BINDING, MRI) {
contains(_HAVE_BINDING, YES) { contains(_HAVE_BINDING, YES) {
error("Only one binding may be selected") error("Only one binding may be selected")
@ -51,10 +58,16 @@ unix {
CONFIG -= app_bundle CONFIG -= app_bundle
INCLUDEPATH += /System/Library/Frameworks/OpenAL.framework/Headers INCLUDEPATH += /System/Library/Frameworks/OpenAL.framework/Headers
LIBS += -framework OpenAL LIBS += -framework OpenAL
STEAM {
LIBS += -L$$STEAMWORKS/redistributable_bin/osx32 -lsteam_api
}
} }
!macx: { !macx: {
PKGCONFIG += openal PKGCONFIG += openal
INCLUDEPATH += /usr/include/AL /usr/local/include/AL INCLUDEPATH += /usr/include/AL /usr/local/include/AL
STEAM {
LIBS += -L$$STEAMWORKS/redistributable_bin/linux$$STEAMARCH -lsteam_api
}
} }
SHARED_FLUID { SHARED_FLUID {
@ -92,6 +105,14 @@ win32 {
sdl2 SDL2_image SDL2_ttf openal SDL_sound vorbisfile freetype2 sdl2 SDL2_image SDL2_ttf openal SDL_sound vorbisfile freetype2
LIBS += -lphysfs -lboost_program_options-mt -lsecur32 LIBS += -lphysfs -lboost_program_options-mt -lsecur32
STEAM {
equals(STEAMARCH, 64) {
LIBS += -l$$STEAMWORKS/redistributable_bin/win64/steam_api64.lib
} else {
LIBS += -l$$STEAMWORKS/redistributable_bin/steam_api.lib
}
}
# Deal with boost paths... # Deal with boost paths...
isEmpty(BOOST_I) { isEmpty(BOOST_I) {
BOOST_I = $$(BOOST_I) BOOST_I = $$(BOOST_I)
@ -119,6 +140,11 @@ win32 {
} }
} }
STEAM {
INCLUDEPATH += $$STEAMWORKS/public
DEFINES += STEAM
}
# Input # Input
HEADERS += \ HEADERS += \
src/quadarray.h \ src/quadarray.h \
@ -225,7 +251,13 @@ SOURCES += \
src/autotilesvx.cpp \ src/autotilesvx.cpp \
src/midisource.cpp \ src/midisource.cpp \
src/fluid-fun.cpp \ src/fluid-fun.cpp \
src/oneshot.cpp src/oneshot.cpp \
binding-mri/steam-binding.cpp
STEAM {
HEADERS += src/steam.h
SOURCES += src/steam.cpp
}
EMBED = \ EMBED = \
shader/common.h \ shader/common.h \

View file

@ -41,7 +41,12 @@
#include "binding.h" #include "binding.h"
#include "icon.png.xxd" #include "icon.png.xxd"
#ifdef STEAM
#include <steam/steam_api.h>
#else
#include "gamecontrollerdb.txt.xxd" #include "gamecontrollerdb.txt.xxd"
#endif
static void static void
rgssThreadError(RGSSThreadData *rtData, const std::string &msg) rgssThreadError(RGSSThreadData *rtData, const std::string &msg)
@ -179,6 +184,14 @@ int main(int argc, char *argv[])
return 0; return 0;
} }
#ifdef STEAM
if (!SteamAPI_Init())
{
showInitError("Could not initialize Steamworks API");
return 0;
}
#endif
if (!EventThread::allocUserEvents()) if (!EventThread::allocUserEvents())
{ {
showInitError("Error allocating SDL user events"); showInitError("Error allocating SDL user events");
@ -294,10 +307,12 @@ int main(int argc, char *argv[])
RGSSThreadData rtData(&eventThread, argv[0], win, RGSSThreadData rtData(&eventThread, argv[0], win,
alcDev, mode.refresh_rate, conf); alcDev, mode.refresh_rate, conf);
#ifndef STEAM
/* Add controller bindings from embedded controller DB */ /* Add controller bindings from embedded controller DB */
SDL_RWops *controllerDB = SDL_RWFromConstMem(assets_gamecontrollerdb_txt, SDL_RWops *controllerDB = SDL_RWFromConstMem(assets_gamecontrollerdb_txt,
assets_gamecontrollerdb_txt_len); assets_gamecontrollerdb_txt_len);
SDL_GameControllerAddMappingsFromRW(controllerDB, 1); SDL_GameControllerAddMappingsFromRW(controllerDB, 1);
#endif
int winW, winH; int winW, winH;
SDL_GetWindowSize(win, &winW, &winH); SDL_GetWindowSize(win, &winW, &winH);
@ -358,5 +373,9 @@ int main(int argc, char *argv[])
IMG_Quit(); IMG_Quit();
SDL_Quit(); SDL_Quit();
#ifdef STEAM
SteamAPI_Shutdown();
#endif
return 0; return 0;
} }

View file

@ -27,6 +27,9 @@
#include "input.h" #include "input.h"
#include "audio.h" #include "audio.h"
#include "oneshot.h" #include "oneshot.h"
#ifdef STEAM
#include "steam.h"
#endif
#include "glstate.h" #include "glstate.h"
#include "shader.h" #include "shader.h"
#include "texpool.h" #include "texpool.h"
@ -79,6 +82,9 @@ struct SharedStatePrivate
Audio audio; Audio audio;
Oneshot oneshot; Oneshot oneshot;
#ifdef STEAM
Steam steam;
#endif
GLState _glState; GLState _glState;
@ -229,6 +235,9 @@ GSATT(Graphics&, graphics)
GSATT(Input&, input) GSATT(Input&, input)
GSATT(Audio&, audio) GSATT(Audio&, audio)
GSATT(Oneshot&, oneshot) GSATT(Oneshot&, oneshot)
#ifdef STEAM
GSATT(Steam&, steam)
#endif
GSATT(GLState&, _glState) GSATT(GLState&, _glState)
GSATT(ShaderSet&, shaders) GSATT(ShaderSet&, shaders)
GSATT(TexPool&, texPool) GSATT(TexPool&, texPool)

View file

@ -43,6 +43,9 @@ class Graphics;
class Input; class Input;
class Audio; class Audio;
class Oneshot; class Oneshot;
#ifdef STEAM
class Steam;
#endif
class GLState; class GLState;
class TexPool; class TexPool;
class Font; class Font;
@ -73,6 +76,9 @@ struct SharedState
Audio &audio() const; Audio &audio() const;
Oneshot &oneshot() const; Oneshot &oneshot() const;
#ifdef STEAM
Steam &steam() const;
#endif
GLState &_glState() const; GLState &_glState() const;

77
src/steam.cpp Normal file
View file

@ -0,0 +1,77 @@
#include "steam.h"
#include "debugwriter.h"
#include <steam/steam_api.h>
/* Achievements */
const char *const Achievement::names[Achievement::MAX] = {
"SaveWorld",
"SaveNiko",
};
void Achievement::update()
{
SteamUserStats()->GetAchievement(name, &unlocked);
}
void Achievement::unlock()
{
unlocked = true;
SteamUserStats()->SetAchievement(name);
SteamUserStats()->StoreStats();
}
void Achievement::lock()
{
unlocked = false;
SteamUserStats()->ClearAchievement(name);
SteamUserStats()->StoreStats();
}
/* SteamPrivate */
struct SteamPrivate
{
Achievement achievements[Achievement::MAX];
int appid;
std::string userName;
SteamPrivate()
: appid(SteamUtils()->GetAppID()),
userName(SteamFriends()->GetPersonaName())
{
for (int i = 0; i < Achievement::MAX; ++i)
achievements[i] = Achievement(Achievement::names[i]);
}
};
/* Steam */
Steam::Steam()
: p(new SteamPrivate())
{
}
Steam::~Steam()
{
delete p;
}
const std::string &Steam::userName() const
{
return p->userName;
}
void Steam::unlock(Achievement::ID id)
{
p->achievements[id].unlock();
}
void Steam::lock(Achievement::ID id)
{
p->achievements[id].lock();
}
bool Steam::isUnlocked(Achievement::ID id)
{
return p->achievements[id].isUnlocked();
}

65
src/steam.h Normal file
View file

@ -0,0 +1,65 @@
#ifndef STEAM_H
#define STEAM_H
#include <string>
struct SteamPrivate;
class Achievement
{
public:
enum ID
{
Invalid = -1,
SaveWorld = 0,
SaveNiko,
MAX
};
static const char *const names[MAX];
void unlock();
void lock();
bool isUnlocked() { return unlocked; }
private:
const char *name;
bool unlocked;
friend struct SteamPrivate;
Achievement()
: name(0),
unlocked(false)
{}
Achievement(const char *name)
: name(name),
unlocked(false)
{
update();
}
void update();
};
class Steam
{
public:
void unlock(Achievement::ID id);
void lock(Achievement::ID id);
bool isUnlocked(Achievement::ID id);
const std::string &userName() const;
private:
Steam();
~Steam();
friend struct SharedStatePrivate;
SteamPrivate *p;
};
#endif // STEAM_H

1
steam_appid.txt Normal file
View file

@ -0,0 +1 @@
420530