From: hgn Date: Fri, 3 Dec 2021 20:35:54 +0000 (+0000) Subject: get achievements working again X-Git-Url: https://harrygodden.com/git/?p=fishladder.git;a=commitdiff_plain;h=5cd0365349b88c7774e0e18c0cad591156512c1f get achievements working again --- diff --git a/fishladder.c b/fishladder.c index 73c9210..03d391d 100644 --- a/fishladder.c +++ b/fishladder.c @@ -1,7 +1,7 @@ // Copyright (C) 2021 Harry Godden (hgn) - All Rights Reserved -//#define VG_STEAM -//#define VG_STEAM_APPID 1218140U +#define VG_STEAM +#define VG_STEAM_APPID 1218140U #include "vg/vg.h" #include "fishladder_resources.h" @@ -332,7 +332,6 @@ struct world u32 score; u32 completed; u32 time; - } world = {}; static void map_free(void) @@ -709,6 +708,7 @@ static void map_serialize( FILE *stream ) int main( int argc, char *argv[] ) { vg_init( argc, argv, "Marble Computing | SPACE: Test | LeftClick: Toggle tile | RightClick: Drag wire" ); + return 0; } static int console_credits( int argc, char const *argv[] ) @@ -1512,6 +1512,8 @@ void vg_update(void) if( cell_entry->config == k_cell_type_con_r || cell_entry->config == k_cell_type_con_u || cell_entry->config == k_cell_type_con_l || cell_entry->config == k_cell_type_con_d ) { + sw_set_achievement( "CAN_DO_THAT" ); + fish->state = k_fish_state_soon_alive; fish->dir[0] = 0; diff --git a/maps/spam.map b/maps/spam.map new file mode 100644 index 0000000..1ce9c7c --- /dev/null +++ b/maps/spam.map @@ -0,0 +1,13 @@ +###############; +#####-#########;abab +## ##; +## ##; +## ##; +## ##; +## ##; +## ##; +## ##; +## ##; +## ##; +###+#+#+#+#+###;abab,cccc,ccaa,aabb,bbbb +###############; diff --git a/vg/config.h b/vg/config.h index ac8df55..b9aef41 100644 --- a/vg/config.h +++ b/vg/config.h @@ -17,3 +17,15 @@ static struct axis_binding vg_axis_binds[] = { .name = "horizontal", .positive = GLFW_KEY_D, .negative = GLFW_KEY_A }, { .name = "vertical", .positive = GLFW_KEY_W, .negative = GLFW_KEY_S } }; + +static struct vg_achievement vg_achievements[] = +{ + { .name = "CAN_DO_THAT" }, + { .name = "TUTORIALS" }, + { .name = "GRADUATE" }, + { .name = "BANG" }, + { .name = "GOOD_ENOUGH" }, + { .name = "MIGHTY_CONSUMER" }, + { .name = "SQUEEZE" }, + { .name = "MASTER_ENGINEER" } +}; diff --git a/vg/vg.h b/vg/vg.h index 53670b2..2c86d4d 100644 --- a/vg/vg.h +++ b/vg/vg.h @@ -55,7 +55,7 @@ float vg_time_delta; #include "vg/vg_console.h" #include "vg/vg_debug.h" -#include "steam/steamworks_thin.h" +#include "vg/vg_steamworks.h" // Engine main // =========================================================================================================== @@ -139,14 +139,8 @@ static void vg_init( int argc, char *argv[], const char *window_name ) { #ifdef VG_STEAM // Initialize steamworks - if( !sw_init( VG_STEAM_APPID ) ) - { - vg_exiterr( "Steamworks failed to initialize" ); - } - else - { - vg_register_exit( &sw_SteamAPI_Shutdown, "SteamAPI" ); - } + if( !sw_init() ) + return; #endif // Context creation @@ -239,7 +233,7 @@ static void vg_init( int argc, char *argv[], const char *window_name ) glfwPollEvents(); #ifdef VG_STEAM - sw_RunSteamEventLoop(); + sw_event_loop(); #endif vg_time_last = vg_time; diff --git a/vg/vg_platform.h b/vg/vg_platform.h index 2488284..b1986b9 100644 --- a/vg/vg_platform.h +++ b/vg/vg_platform.h @@ -25,6 +25,12 @@ typedef v3f boxf[2]; // Resource types typedef struct vg_tex2d vg_tex2d; +struct vg_achievement +{ + int is_set; + const char *name; +}; + #define vg_static_assert _Static_assert #define vg_list_size( A ) (sizeof(A)/sizeof(A[0])) diff --git a/vg/vg_steamworks.h b/vg/vg_steamworks.h index e69de29..5bc04f2 100644 --- a/vg/vg_steamworks.h +++ b/vg/vg_steamworks.h @@ -0,0 +1,278 @@ +#if defined(__linux__) || defined(__APPLE__) +// The 32-bit version of gcc has the alignment requirement for uint64 and double set to +// 4 meaning that even with #pragma pack(8) these types will only be four-byte aligned. +// The 64-bit version of gcc has the alignment requirement for these types set to +// 8 meaning that unless we use #pragma pack(4) our structures will get bigger. +// The 64-bit structure packing has to match the 32-bit structure packing for each platform. + #define VALVE_CALLBACK_PACK_SMALL +#else + #define VALVE_CALLBACK_PACK_LARGE +#endif + +#if defined( VALVE_CALLBACK_PACK_SMALL ) + #pragma pack( push, 4 ) +#elif defined( VALVE_CALLBACK_PACK_LARGE ) + #pragma pack( push, 8 ) +#else + #error steam_api_common.h should define VALVE_CALLBACK_PACK_xxx +#endif + +// Types +typedef void ISteamFriends; +typedef void ISteamUserStats; +typedef void ISteamUtils; +typedef void ISteamUser; +typedef void ISteamNetworking; + +typedef i32 HSteamPipe; +typedef i32 HSteamUser; + +typedef int E_iCallBack_t; + +typedef u32 SNetSocket_t; // CreateP2PConnectionSocket() +typedef u32 SNetListenSocket_t; // CreateListenSocket() + +typedef u64 uint64_steamid; +typedef u64 SteamAPICall_t; + +enum { k_iSteamUserCallbacks = 100 }; +enum { k_iSteamGameServerCallbacks = 200 }; +enum { k_iSteamFriendsCallbacks = 300 }; +enum { k_iSteamBillingCallbacks = 400 }; +enum { k_iSteamMatchmakingCallbacks = 500 }; +enum { k_iSteamContentServerCallbacks = 600 }; +enum { k_iSteamUtilsCallbacks = 700 }; +enum { k_iClientFriendsCallbacks = 800 }; +enum { k_iClientUserCallbacks = 900 }; +enum { k_iSteamAppsCallbacks = 1000 }; +enum { k_iSteamUserStatsCallbacks = 1100 }; +enum { k_iSteamNetworkingCallbacks = 1200 }; +enum { k_iSteamNetworkingSocketsCallbacks = 1220 }; +enum { k_iSteamNetworkingMessagesCallbacks = 1250 }; +enum { k_iSteamNetworkingUtilsCallbacks = 1280 }; +enum { k_iClientRemoteStorageCallbacks = 1300 }; +enum { k_iClientDepotBuilderCallbacks = 1400 }; +enum { k_iSteamGameServerItemsCallbacks = 1500 }; +enum { k_iClientUtilsCallbacks = 1600 }; +enum { k_iSteamGameCoordinatorCallbacks = 1700 }; +enum { k_iSteamGameServerStatsCallbacks = 1800 }; +enum { k_iSteam2AsyncCallbacks = 1900 }; +enum { k_iSteamGameStatsCallbacks = 2000 }; +enum { k_iClientHTTPCallbacks = 2100 }; +enum { k_iClientScreenshotsCallbacks = 2200 }; +enum { k_iSteamScreenshotsCallbacks = 2300 }; +enum { k_iClientAudioCallbacks = 2400 }; +enum { k_iClientUnifiedMessagesCallbacks = 2500 }; +enum { k_iSteamStreamLauncherCallbacks = 2600 }; +enum { k_iClientControllerCallbacks = 2700 }; +enum { k_iSteamControllerCallbacks = 2800 }; +enum { k_iClientParentalSettingsCallbacks = 2900 }; +enum { k_iClientDeviceAuthCallbacks = 3000 }; +enum { k_iClientNetworkDeviceManagerCallbacks = 3100 }; +enum { k_iClientMusicCallbacks = 3200 }; +enum { k_iClientRemoteClientManagerCallbacks = 3300 }; +enum { k_iClientUGCCallbacks = 3400 }; +enum { k_iSteamStreamClientCallbacks = 3500 }; +enum { k_IClientProductBuilderCallbacks = 3600 }; +enum { k_iClientShortcutsCallbacks = 3700 }; +enum { k_iClientRemoteControlManagerCallbacks = 3800 }; +enum { k_iSteamAppListCallbacks = 3900 }; +enum { k_iSteamMusicCallbacks = 4000 }; +enum { k_iSteamMusicRemoteCallbacks = 4100 }; +enum { k_iClientVRCallbacks = 4200 }; +enum { k_iClientGameNotificationCallbacks = 4300 }; +enum { k_iSteamGameNotificationCallbacks = 4400 }; +enum { k_iSteamHTMLSurfaceCallbacks = 4500 }; +enum { k_iClientVideoCallbacks = 4600 }; +enum { k_iClientInventoryCallbacks = 4700 }; +enum { k_iClientBluetoothManagerCallbacks = 4800 }; +enum { k_iClientSharedConnectionCallbacks = 4900 }; +enum { k_ISteamParentalSettingsCallbacks = 5000 }; +enum { k_iClientShaderCallbacks = 5100 }; +enum { k_iSteamGameSearchCallbacks = 5200 }; +enum { k_iSteamPartiesCallbacks = 5300 }; +enum { k_iClientPartiesCallbacks = 5400 }; +enum { k_iSteamSTARCallbacks = 5500 }; +enum { k_iClientSTARCallbacks = 5600 }; +enum { k_iSteamRemotePlayCallbacks = 5700 }; +enum { k_iClientCompatCallbacks = 5800 }; +enum { k_iSteamChatCallbacks = 5900 }; + +// Structures +typedef struct { + u32 m_u32; + u64 m_u64; + u16 m_u16; + double m_d; +} ValvePackingSentinel_t; + +typedef struct { + + HSteamUser m_hSteamUser; // Specific user to whom this callback applies. + int m_iCallback; // Callback identifier. (Corresponds to the k_iCallback enum in the callback structure.) + uint8_t *m_pubParam; // Points to the callback structure + int m_cubParam; // Size of the data pointed to by m_pubParam + +} CallbackMsg_t; + +typedef struct { + + SteamAPICall_t m_hAsyncCall; + int m_iCallback; + u32 m_cubParam; + +} SteamAPICallCompleted_t; +#define SW_CBID_SteamAPICallCompleted (k_iSteamUtilsCallbacks + 3) + + +#pragma pack( pop ) + +// API +void SteamAPI_Shutdown(); +int SteamAPI_Init(); +int SteamAPI_RestartAppIfNecessary( u32 unOwnAppID ); + +void SteamAPI_ManualDispatch_Init(); +void SteamAPI_ManualDispatch_RunFrame( HSteamPipe hSteamPipe ); +int SteamAPI_ManualDispatch_GetNextCallback( HSteamPipe hSteamPipe, CallbackMsg_t *pCallbackMsg ); +void SteamAPI_ManualDispatch_FreeLastCallback( HSteamPipe hSteamPipe ); +int SteamAPI_ManualDispatch_GetAPICallResult( HSteamPipe hSteamPipe, SteamAPICall_t hSteamAPICall, void *pCallback, int cubCallback, int iCallbackExpected, int *pbFailed ); +void SteamAPI_ReleaseCurrentThreadMemory(); + +int SteamAPI_ISteamUserStats_SetAchievement( ISteamUserStats *self, const char *pchName ); + +HSteamPipe SteamAPI_GetHSteamPipe(); +HSteamUser SteamAPI_GetHSteamUser(); + +struct +{ + ISteamFriends *friends; + ISteamUser *user; + ISteamUserStats *stats; + ISteamNetworking *net; + + HSteamPipe pipe; +} steam_api_classes; + +ISteamFriends *SteamAPI_SteamFriends_v017(); +ISteamUser *SteamAPI_SteamUser_v021(); +ISteamUserStats *SteamAPI_SteamUserStats_v012(); +ISteamNetworking *SteamAPI_SteamNetworking_v006(); + +static void sw_exit(void) +{ + SteamAPI_Shutdown(); +} + +static int sw_init(void) +{ + #if defined(VALVE_CALLBACK_PACK_SMALL) + if( sizeof(ValvePackingSentinel_t) != 24 ){ + printf( "Struct packing error: ValvePackingSentinel_t expected 24 got %i\nThe application is built incorrectly\n", (int)sizeof(ValvePackingSentinel_t)); + return 0; + } + #else + if( sizeof(ValvePackingSentinel_t) != 32 ){ + printf( "Struct packing error: ValvePackingSentinel_t expected 32 got %i\nThe application is built incorrectly\n", (int)sizeof(ValvePackingSentinel_t)); + return 0; + } + #endif + + vg_info( "Intializing steamworks\n" ); + + if( SteamAPI_RestartAppIfNecessary( VG_STEAM_APPID ) == 1 ) + { + vg_info( "Restarting app via steam\n" ); + return 0; + } + + if( !SteamAPI_Init() ) + { + vg_error( "Steamworks connection failed\n" ); + return 0; + } + + SteamAPI_ManualDispatch_Init(); + + steam_api_classes.friends = SteamAPI_SteamFriends_v017(); + steam_api_classes.user = SteamAPI_SteamUser_v021(); + steam_api_classes.stats = SteamAPI_SteamUserStats_v012(); + steam_api_classes.net = SteamAPI_SteamNetworking_v006(); + + if( !steam_api_classes.friends || !steam_api_classes.user || !steam_api_classes.stats || !steam_api_classes.net ) + { + vg_error( "Steamworks interface pointers failed. Steamworks DLL may be old\n" ); + SteamAPI_Shutdown(); + return 0; + } + + steam_api_classes.pipe = SteamAPI_GetHSteamPipe(); + vg_success( "Steamworks API running\n" ); + + vg_register_exit( &sw_exit, "SteamAPI" ); + return 1; +} + +static void sw_event_loop(void) +{ + SteamAPI_ManualDispatch_RunFrame( steam_api_classes.pipe ); + CallbackMsg_t callback; + + while( SteamAPI_ManualDispatch_GetNextCallback( steam_api_classes.pipe, &callback ) ) + { + // Check for dispatching API call results + if( callback.m_iCallback == SW_CBID_SteamAPICallCompleted ){ + + SteamAPICallCompleted_t *pCallCompleted = (SteamAPICallCompleted_t *)&callback; + void *pTmpCallResult = malloc( pCallCompleted->m_cubParam ); + int bFailed; + + if( SteamAPI_ManualDispatch_GetAPICallResult( + steam_api_classes.pipe, + pCallCompleted->m_hAsyncCall, + pTmpCallResult, + pCallCompleted->m_cubParam, + pCallCompleted->m_iCallback, + &bFailed ) + ) + { + // Dispatch the call result to the registered handler(s) for the + // call identified by pCallCompleted->m_hAsyncCall + } + + free( pTmpCallResult ); + } + else + { + // Look at callback.m_iCallback to see what kind of callback it is, + // and dispatch to appropriate handler(s) + + vg_info( "steamworks_event::callback( %i )\n", callback.m_iCallback ); + + //void *data = callback.m_pubParam; + + switch( callback.m_iCallback ) + { + default: break; + } + } + + SteamAPI_ManualDispatch_FreeLastCallback( steam_api_classes.pipe ); + } +} + +static void sw_set_achievement( const char *vg_ach_name ) +{ + struct vg_achievement *ach = NULL; + + for( int i = 0; i < vg_list_size( vg_achievements ); i ++ ) + if( !strcmp( vg_ach_name, vg_achievements[i].name ) ) + ach = &vg_achievements[i]; + + if( !ach->is_set ) + { + SteamAPI_ISteamUserStats_SetAchievement( steam_api_classes.stats, vg_ach_name ); + ach->is_set = 1; + vg_success( "Achievement set: '%s'\n", vg_ach_name ); + } +}