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
}
isEmpty(STEAMWORKS) {
STEAMWORKS = /home/mathew/Software/Steamworks
}
isEmpty(STEAMARCH) {
STEAMARCH = 64
}
contains(BINDING, MRI) {
contains(_HAVE_BINDING, YES) {
error("Only one binding may be selected")
@ -51,10 +58,16 @@ unix {
CONFIG -= app_bundle
INCLUDEPATH += /System/Library/Frameworks/OpenAL.framework/Headers
LIBS += -framework OpenAL
STEAM {
LIBS += -L$$STEAMWORKS/redistributable_bin/osx32 -lsteam_api
}
}
!macx: {
PKGCONFIG += openal
INCLUDEPATH += /usr/include/AL /usr/local/include/AL
STEAM {
LIBS += -L$$STEAMWORKS/redistributable_bin/linux$$STEAMARCH -lsteam_api
}
}
SHARED_FLUID {
@ -92,6 +105,14 @@ win32 {
sdl2 SDL2_image SDL2_ttf openal SDL_sound vorbisfile freetype2
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...
isEmpty(BOOST_I) {
BOOST_I = $$(BOOST_I)
@ -119,6 +140,11 @@ win32 {
}
}
STEAM {
INCLUDEPATH += $$STEAMWORKS/public
DEFINES += STEAM
}
# Input
HEADERS += \
src/quadarray.h \
@ -225,7 +251,13 @@ SOURCES += \
src/autotilesvx.cpp \
src/midisource.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 = \
shader/common.h \

View file

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

View file

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

View file

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