mirror of
https://github.com/Detanup01/gbe_fork.git
synced 2024-11-23 19:25:35 +08:00
basic impl for steam timeline
This commit is contained in:
parent
ddda06d248
commit
f5ae22a1e6
@ -55,6 +55,7 @@
|
|||||||
#include "steam_gameserver.h"
|
#include "steam_gameserver.h"
|
||||||
#include "steam_gameserverstats.h"
|
#include "steam_gameserverstats.h"
|
||||||
#include "steam_gamestats.h"
|
#include "steam_gamestats.h"
|
||||||
|
#include "steam_timeline.h"
|
||||||
#include "steam_masterserver_updater.h"
|
#include "steam_masterserver_updater.h"
|
||||||
|
|
||||||
#include "overlay/steam_overlay.h"
|
#include "overlay/steam_overlay.h"
|
||||||
@ -138,6 +139,7 @@ public:
|
|||||||
Steam_RemotePlay *steam_remoteplay{};
|
Steam_RemotePlay *steam_remoteplay{};
|
||||||
Steam_TV *steam_tv{};
|
Steam_TV *steam_tv{};
|
||||||
Steam_GameStats *steam_gamestats{};
|
Steam_GameStats *steam_gamestats{};
|
||||||
|
Steam_Timeline *steam_timeline{};
|
||||||
|
|
||||||
Steam_GameServer *steam_gameserver{};
|
Steam_GameServer *steam_gameserver{};
|
||||||
Steam_Utils *steam_gameserver_utils{};
|
Steam_Utils *steam_gameserver_utils{};
|
||||||
@ -236,6 +238,9 @@ public:
|
|||||||
// game stats
|
// game stats
|
||||||
ISteamGameStats *GetISteamGameStats( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion );
|
ISteamGameStats *GetISteamGameStats( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion );
|
||||||
|
|
||||||
|
// game timeline
|
||||||
|
ISteamTimeline *GetISteamTimeline( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion );
|
||||||
|
|
||||||
|
|
||||||
// Deprecated. Applications should use SteamAPI_RunCallbacks() or SteamGameServer_RunCallbacks() instead.
|
// Deprecated. Applications should use SteamAPI_RunCallbacks() or SteamGameServer_RunCallbacks() instead.
|
||||||
STEAM_PRIVATE_API( void RunFrame() );
|
STEAM_PRIVATE_API( void RunFrame() );
|
||||||
|
@ -23,13 +23,57 @@
|
|||||||
class Steam_Timeline :
|
class Steam_Timeline :
|
||||||
public ISteamTimeline
|
public ISteamTimeline
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
struct TimelineEvent_t
|
||||||
|
{
|
||||||
|
// emu specific: time when this event was added to the list via 'Steam_Timeline::AddTimelineEvent()'
|
||||||
|
const std::chrono::system_clock::time_point time_added = std::chrono::system_clock::now();
|
||||||
|
|
||||||
|
// The name of the icon to show at the timeline at this point. This can be one of the icons uploaded through the Steamworks partner Site for your title, or one of the provided icons that start with steam_. The Steam Timelines overview includes a list of available icons.
|
||||||
|
// https://partner.steamgames.com/doc/features/timeline#icons
|
||||||
|
std::string pchIcon{};
|
||||||
|
|
||||||
|
// Title-provided localized string in the language returned by SteamUtils()->GetSteamUILanguage().
|
||||||
|
std::string pchTitle{};
|
||||||
|
|
||||||
|
// Title-provided localized string in the language returned by SteamUtils()->GetSteamUILanguage().
|
||||||
|
std::string pchDescription{};
|
||||||
|
|
||||||
|
// Provide the priority to use when the UI is deciding which icons to display in crowded parts of the timeline. Events with larger priority values will be displayed more prominently than events with smaller priority values. This value must be between 0 and k_unMaxTimelinePriority.
|
||||||
|
uint32 unPriority{};
|
||||||
|
|
||||||
|
// One use of this parameter is to handle events whose significance is not clear until after the fact. For instance if the player starts a damage over time effect on another player, which kills them 3.5 seconds later, the game could pass -3.5 as the start offset and cause the event to appear in the timeline where the effect started.
|
||||||
|
float flStartOffsetSeconds{};
|
||||||
|
|
||||||
|
// The duration of the event, in seconds. Pass 0 for instantaneous events.
|
||||||
|
float flDurationSeconds{};
|
||||||
|
|
||||||
|
// Allows the game to describe events that should be suggested to the user as possible video clips.
|
||||||
|
ETimelineEventClipPriority ePossibleClip{};
|
||||||
|
};
|
||||||
|
|
||||||
|
struct TimelineState_t
|
||||||
|
{
|
||||||
|
// emu specific: time when this state was changed via 'Steam_Timeline::SetTimelineGameMode()'
|
||||||
|
const std::chrono::system_clock::time_point time_added = std::chrono::system_clock::now();
|
||||||
|
|
||||||
|
std::string description{}; // A localized string in the language returned by SteamUtils()->GetSteamUILanguage()
|
||||||
|
ETimelineGameMode bar_color{}; // the color of the timeline bar
|
||||||
|
};
|
||||||
|
|
||||||
class Settings *settings{};
|
class Settings *settings{};
|
||||||
class Networking *network{};
|
class Networking *network{};
|
||||||
class SteamCallResults *callback_results{};
|
class SteamCallResults *callback_results{};
|
||||||
class SteamCallBacks *callbacks{};
|
class SteamCallBacks *callbacks{};
|
||||||
class RunEveryRunCB *run_every_runcb{};
|
class RunEveryRunCB *run_every_runcb{};
|
||||||
std::chrono::time_point<std::chrono::steady_clock> initialized_time = std::chrono::steady_clock::now();
|
|
||||||
FSteamNetworkingSocketsDebugOutput debug_function{};
|
std::vector<TimelineEvent_t> timeline_events{};
|
||||||
|
std::vector<TimelineState_t> timeline_states{TimelineState_t{}}; // it seems to always start with a default event
|
||||||
|
|
||||||
|
// unconditional periodic callback
|
||||||
|
void RunCallbacks();
|
||||||
|
// network callback, triggered once we have a network message
|
||||||
|
void Callback(Common_Message *msg);
|
||||||
|
|
||||||
static void steam_callback(void *object, Common_Message *msg);
|
static void steam_callback(void *object, Common_Message *msg);
|
||||||
static void steam_run_every_runcb(void *object);
|
static void steam_run_every_runcb(void *object);
|
||||||
@ -46,10 +90,6 @@ public:
|
|||||||
|
|
||||||
void SetTimelineGameMode( ETimelineGameMode eMode );
|
void SetTimelineGameMode( ETimelineGameMode eMode );
|
||||||
|
|
||||||
void RunCallbacks();
|
|
||||||
|
|
||||||
void Callback(Common_Message *msg);
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // __INCLUDED_STEAM_TIMELINE_H__
|
#endif // __INCLUDED_STEAM_TIMELINE_H__
|
@ -123,6 +123,7 @@ Steam_Client::Steam_Client()
|
|||||||
steam_remoteplay = new Steam_RemotePlay(settings_client, network, callback_results_client, callbacks_client, run_every_runcb);
|
steam_remoteplay = new Steam_RemotePlay(settings_client, network, callback_results_client, callbacks_client, run_every_runcb);
|
||||||
steam_tv = new Steam_TV(settings_client, network, callback_results_client, callbacks_client, run_every_runcb);
|
steam_tv = new Steam_TV(settings_client, network, callback_results_client, callbacks_client, run_every_runcb);
|
||||||
steam_gamestats = new Steam_GameStats(settings_client, network, callback_results_client, callbacks_client, run_every_runcb);
|
steam_gamestats = new Steam_GameStats(settings_client, network, callback_results_client, callbacks_client, run_every_runcb);
|
||||||
|
steam_timeline = new Steam_Timeline(settings_client, network, callback_results_client, callbacks_client, run_every_runcb);
|
||||||
|
|
||||||
// server
|
// server
|
||||||
PRINT_DEBUG("init gameserver");
|
PRINT_DEBUG("init gameserver");
|
||||||
@ -202,6 +203,7 @@ Steam_Client::~Steam_Client()
|
|||||||
DEL_INST(steam_remoteplay);
|
DEL_INST(steam_remoteplay);
|
||||||
DEL_INST(steam_tv);
|
DEL_INST(steam_tv);
|
||||||
DEL_INST(steam_gamestats);
|
DEL_INST(steam_gamestats);
|
||||||
|
DEL_INST(steam_timeline);
|
||||||
|
|
||||||
DEL_INST(steam_utils);
|
DEL_INST(steam_utils);
|
||||||
DEL_INST(steam_friends);
|
DEL_INST(steam_friends);
|
||||||
|
@ -18,6 +18,19 @@
|
|||||||
#include "dll/steam_client.h"
|
#include "dll/steam_client.h"
|
||||||
|
|
||||||
|
|
||||||
|
// retrieves the ISteamTimeline interface associated with the handle
|
||||||
|
ISteamTimeline *Steam_Client::GetISteamTimeline( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%s", pchVersion);
|
||||||
|
if (!steam_pipes.count(hSteamPipe) || !hSteamUser) return nullptr;
|
||||||
|
|
||||||
|
if (strcmp(pchVersion, STEAMTIMELINE_INTERFACE_VERSION) == 0) {
|
||||||
|
return reinterpret_cast<ISteamTimeline *>(static_cast<ISteamTimeline *>(steam_timeline));
|
||||||
|
}
|
||||||
|
|
||||||
|
report_missing_impl_and_exit(pchVersion, EMU_FUNC_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
// retrieves the ISteamGameStats interface associated with the handle
|
// retrieves the ISteamGameStats interface associated with the handle
|
||||||
ISteamGameStats *Steam_Client::GetISteamGameStats( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion )
|
ISteamGameStats *Steam_Client::GetISteamGameStats( HSteamUser hSteamUser, HSteamPipe hSteamPipe, const char *pchVersion )
|
||||||
{
|
{
|
||||||
|
155
dll/steam_timeline.cpp
Normal file
155
dll/steam_timeline.cpp
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
/* Copyright (C) 2019 Mr Goldberg
|
||||||
|
This file is part of the Goldberg Emulator
|
||||||
|
|
||||||
|
The Goldberg Emulator is free software; you can redistribute it and/or
|
||||||
|
modify it under the terms of the GNU Lesser General Public
|
||||||
|
License as published by the Free Software Foundation; either
|
||||||
|
version 3 of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
The Goldberg Emulator is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
Lesser General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Lesser General Public
|
||||||
|
License along with the Goldberg Emulator; if not, see
|
||||||
|
<http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#include "dll/steam_timeline.h"
|
||||||
|
|
||||||
|
// https://partner.steamgames.com/doc/api/ISteamTimeline
|
||||||
|
|
||||||
|
|
||||||
|
void Steam_Timeline::steam_callback(void *object, Common_Message *msg)
|
||||||
|
{
|
||||||
|
// PRINT_DEBUG_ENTRY();
|
||||||
|
|
||||||
|
auto instance = (Steam_Timeline *)object;
|
||||||
|
instance->Callback(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Steam_Timeline::steam_run_every_runcb(void *object)
|
||||||
|
{
|
||||||
|
// PRINT_DEBUG_ENTRY();
|
||||||
|
|
||||||
|
auto instance = (Steam_Timeline *)object;
|
||||||
|
instance->RunCallbacks();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Steam_Timeline::Steam_Timeline(class Settings *settings, class Networking *network, class SteamCallResults *callback_results, class SteamCallBacks *callbacks, class RunEveryRunCB *run_every_runcb)
|
||||||
|
{
|
||||||
|
this->settings = settings;
|
||||||
|
this->network = network;
|
||||||
|
this->callback_results = callback_results;
|
||||||
|
this->callbacks = callbacks;
|
||||||
|
this->run_every_runcb = run_every_runcb;
|
||||||
|
|
||||||
|
// this->network->setCallback(CALLBACK_ID_USER_STATUS, settings->get_local_steam_id(), &Steam_Timeline::steam_callback, this);
|
||||||
|
this->run_every_runcb->add(&Steam_Timeline::steam_run_every_runcb, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Steam_Timeline::~Steam_Timeline()
|
||||||
|
{
|
||||||
|
// this->network->rmCallback(CALLBACK_ID_USER_STATUS, settings->get_local_steam_id(), &Steam_Timeline::steam_callback, this);
|
||||||
|
this->run_every_runcb->remove(&Steam_Timeline::steam_run_every_runcb, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Steam_Timeline::SetTimelineStateDescription( const char *pchDescription, float flTimeDelta )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("'%s' %f", pchDescription, flTimeDelta);
|
||||||
|
std::lock_guard lock(global_mutex);
|
||||||
|
|
||||||
|
const auto target_timepoint = std::chrono::system_clock::now() + std::chrono::milliseconds(static_cast<long>(flTimeDelta * 1000));
|
||||||
|
|
||||||
|
// reverse iterators to search from end
|
||||||
|
auto event_it = std::find_if(timeline_states.rbegin(), timeline_states.rend(), [this, &target_timepoint](const TimelineState_t &item) {
|
||||||
|
return target_timepoint >= item.time_added;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (timeline_states.rend() != event_it) {
|
||||||
|
PRINT_DEBUG("setting timeline state description");
|
||||||
|
if (pchDescription) {
|
||||||
|
event_it->description = pchDescription;
|
||||||
|
} else {
|
||||||
|
event_it->description.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Steam_Timeline::ClearTimelineStateDescription( float flTimeDelta )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%f", flTimeDelta);
|
||||||
|
std::lock_guard lock(global_mutex);
|
||||||
|
|
||||||
|
const auto target_timepoint = std::chrono::system_clock::now() + std::chrono::milliseconds(static_cast<long>(flTimeDelta * 1000));
|
||||||
|
|
||||||
|
// reverse iterators to search from end
|
||||||
|
auto event_it = std::find_if(timeline_states.rbegin(), timeline_states.rend(), [this, &target_timepoint](const TimelineState_t &item) {
|
||||||
|
return target_timepoint >= item.time_added;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (timeline_states.rend() != event_it) {
|
||||||
|
PRINT_DEBUG("clearing timeline state description");
|
||||||
|
event_it->description.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Steam_Timeline::AddTimelineEvent( const char *pchIcon, const char *pchTitle, const char *pchDescription, uint32 unPriority, float flStartOffsetSeconds, float flDurationSeconds, ETimelineEventClipPriority ePossibleClip )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("'%s' | '%s' - '%s', %u, [%f, %f) %i", pchIcon, pchTitle, pchDescription, unPriority, flStartOffsetSeconds, flDurationSeconds, (int)ePossibleClip);
|
||||||
|
std::lock_guard lock(global_mutex);
|
||||||
|
|
||||||
|
auto &new_event = timeline_events.emplace_back(TimelineEvent_t{});
|
||||||
|
new_event.pchIcon = pchIcon;
|
||||||
|
new_event.pchTitle = pchTitle;
|
||||||
|
new_event.pchDescription = pchDescription;
|
||||||
|
new_event.unPriority = unPriority;
|
||||||
|
|
||||||
|
new_event.flStartOffsetSeconds = flStartOffsetSeconds;
|
||||||
|
|
||||||
|
// for instantanious event with flDurationSeconds=0 steam creates 8 sec clip
|
||||||
|
if (static_cast<long>(flDurationSeconds * 1000) <= 100) { // <= 100ms
|
||||||
|
flDurationSeconds = 8;
|
||||||
|
}
|
||||||
|
new_event.flDurationSeconds = flDurationSeconds;
|
||||||
|
|
||||||
|
new_event.ePossibleClip = ePossibleClip;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void Steam_Timeline::SetTimelineGameMode( ETimelineGameMode eMode )
|
||||||
|
{
|
||||||
|
PRINT_DEBUG("%i", (int)eMode);
|
||||||
|
std::lock_guard lock(global_mutex);
|
||||||
|
|
||||||
|
if (timeline_states.empty()) return;
|
||||||
|
|
||||||
|
timeline_states.back().bar_color = eMode;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Steam_Timeline::RunCallbacks()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void Steam_Timeline::Callback(Common_Message *msg)
|
||||||
|
{
|
||||||
|
if (msg->has_low_level()) {
|
||||||
|
if (msg->low_level().type() == Low_Level::CONNECT) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg->low_level().type() == Low_Level::DISCONNECT) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user