Remove Twitch from the rest of the code

This commit is contained in:
Gymnasiast 2020-05-27 16:03:56 +02:00
parent aaece7a435
commit 9a9ab47856
No known key found for this signature in database
GPG Key ID: DBFFF47AB2CA3EDD
15 changed files with 5 additions and 727 deletions

View File

@ -47,7 +47,7 @@ option(USE_MMAP "Use mmap to try loading rct2's data segment into memory.")
option(DISABLE_DISCORD_RPC "Disable Discord-RPC support." OFF)
option(DISABLE_GOOGLE_BENCHMARK "Disable Google Benchmarks support." OFF)
option(DISABLE_HTTP_TWITCH "Disable HTTP and Twitch support.")
option(DISABLE_HTTP "Disable HTTP support.")
option(DISABLE_NETWORK "Disable multiplayer functionality. Mainly for testing.")
option(DISABLE_TTF "Disable support for TTF provided by freetype2.")
option(ENABLE_LIGHTFX "Enable lighting effects." ON)
@ -114,9 +114,8 @@ endif ()
if (DISABLE_NETWORK)
add_definitions(-DDISABLE_NETWORK)
endif ()
if (DISABLE_HTTP_TWITCH)
if (DISABLE_HTTP)
add_definitions(-DDISABLE_HTTP)
add_definitions(-DDISABLE_TWITCH)
endif ()
if (DISABLE_TTF)
add_definitions(-DNO_TTF)

View File

@ -26,7 +26,6 @@
01C6F0C822FD51FC0057E2F7 /* T6Exporter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01C6F0C522FD51FC0057E2F7 /* T6Exporter.cpp */; };
01C6F0C922FD51FC0057E2F7 /* T6Importer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01C6F0C622FD51FC0057E2F7 /* T6Importer.cpp */; };
01DDFE6522FD608500221318 /* Window_internal.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 01DDFE6422FD608500221318 /* Window_internal.cpp */; };
2A1F4FE0221FF4B0003CA045 /* Twitch.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F76C840F1EC4E7CC00FA49E2 /* Twitch.cpp */; };
2A1F4FE1221FF4B0003CA045 /* Audio.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F76C83571EC4E7CC00FA49E2 /* Audio.cpp */; };
2A1F4FE2221FF4B0003CA045 /* macos.mm in Sources */ = {isa = PBXBuildFile; fileRef = F76C845D1EC4E7CC00FA49E2 /* macos.mm */; };
2A5354E922099C4F00A5440F /* Network.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2A5354E822099C4F00A5440F /* Network.cpp */; };
@ -1729,8 +1728,6 @@
F76C840C1EC4E7CC00FA49E2 /* ServerList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ServerList.h; sourceTree = "<group>"; };
F76C840D1EC4E7CC00FA49E2 /* Socket.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Socket.cpp; sourceTree = "<group>"; };
F76C840E1EC4E7CC00FA49E2 /* Socket.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Socket.h; sourceTree = "<group>"; };
F76C840F1EC4E7CC00FA49E2 /* Twitch.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = Twitch.cpp; sourceTree = "<group>"; };
F76C84101EC4E7CC00FA49E2 /* Twitch.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Twitch.h; sourceTree = "<group>"; };
F76C84121EC4E7CC00FA49E2 /* BannerObject.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = BannerObject.cpp; sourceTree = "<group>"; };
F76C84131EC4E7CC00FA49E2 /* BannerObject.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BannerObject.h; sourceTree = "<group>"; };
F76C84141EC4E7CC00FA49E2 /* EntranceObject.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = EntranceObject.cpp; sourceTree = "<group>"; };

View File

@ -50,7 +50,7 @@ The following people are not part of the development team, but have been contrib
* (atmaxinger) - User configuration
* (anyc) - Housecleaning, cross-platform fixes
* Michael Steenbeek (Gymnasiast) - Cheats, RCT1 ride style, misc.
* Miso Zmiric (mzmiric5) - Twitch integration, misc.
* Miso Zmiric (mzmiric5) - Old Twitch integration, misc.
* Inseok Lee (dlunch) - Load save files from command line
* Jørn Lomax (jvlomax) - Configuration parser
* Alexander Overvoorde (Overv) - OpenGL improvements, Steam overlay detection, various bugfixes.

View File

@ -2521,19 +2521,6 @@ STR_5160 :{POP16}{MONTH} {PUSH16}{PUSH16}{STRINGID}, Year {POP16}{COMMA16}
STR_5161 :Date Format:
STR_5162 :Day/Month/Year
STR_5163 :Month/Day/Year
STR_5164 :Twitch Channel name
STR_5165 :Name guests after followers
STR_5166 :{SMALLFONT}{BLACK}Name guests after channel's{NEWLINE}Twitch followers
STR_5167 :Track follower guests
STR_5168 :{SMALLFONT}{BLACK}Enable tracking information for guests named after channel's Twitch followers
STR_5169 :Name guests after people in Twitch chat
STR_5170 :{SMALLFONT}{BLACK}Name guests after people in Twitch chat
STR_5171 :Track chat guests
STR_5172 :{SMALLFONT}{BLACK}Enable tracking information for guests named after Twitch chat participants
STR_5173 :Pull Twitch chat as news
STR_5174 :{SMALLFONT}{BLACK}Use Twitch chat messages preceded by !news for in game notifications
STR_5175 :Input the name of your Twitch channel
STR_5176 :Enable Twitch integration
STR_5177 :Screen mode:
STR_5178 :{SMALLFONT}{BLACK}Show financial cheats
STR_5179 :{SMALLFONT}{BLACK}Show guest cheats
@ -2628,7 +2615,6 @@ STR_5267 :{SMALLFONT}{BLACK}Culture and Units
STR_5268 :{SMALLFONT}{BLACK}Audio
STR_5269 :{SMALLFONT}{BLACK}Controls and interface
STR_5270 :{SMALLFONT}{BLACK}Miscellaneous
STR_5271 :{SMALLFONT}{BLACK}Twitch
STR_5272 :{SMALLFONT}{BLACK}Small Scenery
STR_5273 :{SMALLFONT}{BLACK}Large Scenery
STR_5274 :{SMALLFONT}{BLACK}Footpath
@ -3165,7 +3151,6 @@ STR_5848 :{SMALLFONT}{BLACK}Create and manage custom title sequences
STR_5849 :{SMALLFONT}{BLACK}Automatically place{NEWLINE}newly hired staff members
STR_5850 :<not used anymore>
STR_5851 :{SMALLFONT}{BLACK}Sets the default inspection interval{NEWLINE}on newly built rides
STR_5852 :{SMALLFONT}{BLACK}Set the name of the TwitchTV channel that will be used for Twitch integration
STR_5853 :{SMALLFONT}{BLACK}Toggle sound effects on/off
STR_5854 :{SMALLFONT}{BLACK}Toggle ride music on/off
STR_5855 :{SMALLFONT}{BLACK}Set regular fullscreen, borderless fullscreen{NEWLINE}or windowed display
@ -3564,9 +3549,6 @@ STR_6248 :{WINDOW_COLOUR_1}Do you want to refurbish {STRINGID} for {CURRENCY}
STR_6249 :{WINDOW_COLOUR_1}Do you want to refurbish {STRINGID}?
STR_6250 :{WINDOW_COLOUR_1}Are you sure you want to completely demolish {STRINGID} and gain {CURRENCY}?
STR_6251 :Ride is not empty yet
STR_6252 :Twitch API URL
STR_6253 :{SMALLFONT}{BLACK}Provide URL of Twitch integration API. Required in order to enable Twitch integration.
STR_6254 :URL of Twitch integration API:
STR_6255 :URL is not valid
STR_6256 :Rendering effects
STR_6257 :Glassy (translucent)

View File

@ -139,7 +139,7 @@ include_directories("${CMAKE_BINARY_DIR}/libs/include/SDL2")
# now build app's shared lib
include_directories(./ndk_helper
${ANDROID_NDK}/sources/android/cpufeatures)
add_definitions(-DDISABLE_HTTP -DDISABLE_DISCORD_RPC -DDISABLE_HTTP_TWITCH -DDISABLE_NETWORK -DDISABLE_TWITCH -DDISABLE_OPENGL -DGL_GLEXT_PROTOTYPES -D__STDC_LIMIT_MACROS -DNO_TTF -DSDL_MAIN_HANDLED)
add_definitions(-DDISABLE_HTTP -DDISABLE_DISCORD_RPC -DDISABLE_HTTP -DDISABLE_NETWORK -DDISABLE_OPENGL -DGL_GLEXT_PROTOTYPES -D__STDC_LIMIT_MACROS -DNO_TTF -DSDL_MAIN_HANDLED)
# Fix SpeexDSP compilation
add_definitions(-DHAVE_STDINT_H)

View File

@ -50,7 +50,6 @@
#include <openrct2/interface/Chat.h>
#include <openrct2/interface/InteractiveConsole.h>
#include <openrct2/interface/Screenshot.h>
#include <openrct2/network/Twitch.h>
#include <openrct2/network/network.h>
#include <openrct2/paint/VirtualFloor.h>
#include <openrct2/peep/Staff.h>
@ -122,8 +121,6 @@ enum FILE_MENU_DDIDX {
// separator
DDIDX_QUIT_TO_MENU = 10,
DDIDX_EXIT_OPENRCT2 = 11,
// separator
DDIDX_ENABLE_TWITCH = 13
};
enum TOP_TOOLBAR_VIEW_MENU_DDIDX {
@ -329,7 +326,6 @@ static money32 selection_raise_land(uint8_t flags);
static ClearAction GetClearAction();
static bool _menuDropdownIncludesTwitch;
static bool _landToolBlocked;
static uint8_t _unkF64F0E;
static int16_t _unkF64F0A;
@ -449,7 +445,6 @@ static void window_top_toolbar_mousedown(rct_window* w, rct_widgetindex widgetIn
switch (widgetIndex)
{
case WIDX_FILE_MENU:
_menuDropdownIncludesTwitch = false;
if (gScreenFlags & (SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER))
{
gDropdownItemsFormat[0] = STR_ABOUT;
@ -494,28 +489,10 @@ static void window_top_toolbar_mousedown(rct_window* w, rct_widgetindex widgetIn
gDropdownItemsFormat[10] = STR_QUIT_TO_MENU;
gDropdownItemsFormat[11] = STR_EXIT_OPENRCT2;
numItems = 12;
#ifndef DISABLE_TWITCH
if (gConfigTwitch.channel != nullptr && gConfigTwitch.channel[0] != 0)
{
_menuDropdownIncludesTwitch = true;
gDropdownItemsFormat[12] = STR_EMPTY;
gDropdownItemsFormat[DDIDX_ENABLE_TWITCH] = STR_TOGGLE_OPTION;
gDropdownItemsArgs[DDIDX_ENABLE_TWITCH] = STR_TWITCH_ENABLE;
numItems = 14;
}
#endif
}
window_dropdown_show_text(
{ w->windowPos.x + widget->left, w->windowPos.y + widget->top }, widget->bottom - widget->top + 1,
w->colours[0] | 0x80, DROPDOWN_FLAG_STAY_OPEN, numItems);
#ifndef DISABLE_TWITCH
if (_menuDropdownIncludesTwitch && gTwitchEnable)
{
dropdown_set_checked(DDIDX_ENABLE_TWITCH, true);
}
#endif
break;
case WIDX_CHEATS:
top_toolbar_init_cheats_menu(w, widget);
@ -627,11 +604,6 @@ static void window_top_toolbar_dropdown(rct_window* w, rct_widgetindex widgetInd
case DDIDX_EXIT_OPENRCT2:
context_quit();
break;
#ifndef DISABLE_TWITCH
case DDIDX_ENABLE_TWITCH:
gTwitchEnable = !gTwitchEnable;
break;
#endif
}
break;
case WIDX_CHEATS:

View File

@ -46,7 +46,6 @@
#include "localisation/Localisation.h"
#include "localisation/LocalisationService.h"
#include "network/DiscordService.h"
#include "network/Twitch.h"
#include "network/network.h"
#include "object/ObjectManager.h"
#include "object/ObjectRepository.h"
@ -1030,7 +1029,6 @@ namespace OpenRCT2
}
#endif
Twitch::Update();
chat_update();
#ifdef ENABLE_SCRIPTING
_scriptEngine.Update();

View File

@ -477,34 +477,6 @@ namespace Config
writer->WriteBoolean("guest_died", model->guest_died);
}
static void ReadTwitch(IIniReader* reader)
{
if (reader->ReadSection("twitch"))
{
auto model = &gConfigTwitch;
model->api_url = reader->GetCString("api_url", nullptr);
model->channel = reader->GetCString("channel", nullptr);
model->enable_follower_peep_names = reader->GetBoolean("follower_peep_names", true);
model->enable_follower_peep_tracking = reader->GetBoolean("follower_peep_tracking", false);
model->enable_chat_peep_names = reader->GetBoolean("chat_peep_names", true);
model->enable_chat_peep_tracking = reader->GetBoolean("chat_peep_tracking", true);
model->enable_news = reader->GetBoolean("news", false);
}
}
static void WriteTwitch(IIniWriter* writer)
{
auto model = &gConfigTwitch;
writer->WriteSection("twitch");
writer->WriteString("api_url", model->api_url);
writer->WriteString("channel", model->channel);
writer->WriteBoolean("follower_peep_names", model->enable_follower_peep_names);
writer->WriteBoolean("follower_peep_tracking", model->enable_follower_peep_tracking);
writer->WriteBoolean("chat_peep_names", model->enable_chat_peep_names);
writer->WriteBoolean("chat_peep_tracking", model->enable_chat_peep_tracking);
writer->WriteBoolean("news", model->enable_news);
}
static void ReadFont(IIniReader* reader)
{
if (reader->ReadSection("font"))
@ -573,7 +545,6 @@ namespace Config
ReadSound(reader.get());
ReadNetwork(reader.get());
ReadNotifications(reader.get());
ReadTwitch(reader.get());
ReadFont(reader.get());
ReadPlugin(reader.get());
return true;
@ -595,7 +566,6 @@ namespace Config
ReadSound(reader.get());
ReadNetwork(reader.get());
ReadNotifications(reader.get());
ReadTwitch(reader.get());
ReadFont(reader.get());
ReadPlugin(reader.get());
return true;
@ -620,7 +590,6 @@ namespace Config
WriteSound(writer.get());
WriteNetwork(writer.get());
WriteNotifications(writer.get());
WriteTwitch(writer.get());
WriteFont(writer.get());
WritePlugin(writer.get());
return true;
@ -734,7 +703,6 @@ namespace Config
GeneralConfiguration gConfigGeneral;
InterfaceConfiguration gConfigInterface;
SoundConfiguration gConfigSound;
TwitchConfiguration gConfigTwitch;
NetworkConfiguration gConfigNetwork;
NotificationConfiguration gConfigNotifications;
FontConfiguration gConfigFonts;
@ -780,8 +748,6 @@ void config_release()
SafeFree(gConfigInterface.current_theme_preset);
SafeFree(gConfigInterface.current_title_sequence_preset);
SafeFree(gConfigSound.device);
SafeFree(gConfigTwitch.api_url);
SafeFree(gConfigTwitch.channel);
SafeFree(gConfigFonts.file_name);
SafeFree(gConfigFonts.font_name);
}

View File

@ -128,17 +128,6 @@ struct SoundConfiguration
bool audio_focus;
};
struct TwitchConfiguration
{
utf8* channel;
utf8* api_url;
bool enable_follower_peep_names;
bool enable_follower_peep_tracking;
bool enable_chat_peep_names;
bool enable_chat_peep_tracking;
bool enable_news;
};
struct NetworkConfiguration
{
std::string player_name;
@ -238,7 +227,6 @@ enum MEASUREMENT_FORMAT
extern GeneralConfiguration gConfigGeneral;
extern InterfaceConfiguration gConfigInterface;
extern SoundConfiguration gConfigSound;
extern TwitchConfiguration gConfigTwitch;
extern NetworkConfiguration gConfigNetwork;
extern NotificationConfiguration gConfigNotifications;
extern FontConfiguration gConfigFonts;

View File

@ -1035,18 +1035,6 @@ static int32_t cc_set(InteractiveConsole& console, const arguments_t& argv)
return 0;
}
static int32_t cc_twitch([[maybe_unused]] InteractiveConsole& console, [[maybe_unused]] const arguments_t& argv)
{
#ifdef DISABLE_TWITCH
console.WriteLineError("OpenRCT2 build not compiled with Twitch integration.");
#else
// TODO: Add some twitch commands
// Display a message to the player for now
console.WriteLine("To be implemented");
#endif
return 0;
}
static int32_t cc_load_object(InteractiveConsole& console, const arguments_t& argv)
{
if (!argv.empty())
@ -1781,7 +1769,6 @@ static constexpr const console_command console_command_table[] = {
{ "show_limits", cc_show_limits, "Shows the map data counts and limits.", "show_limits" },
{ "staff", cc_staff, "Staff management.", "staff <subcommand>" },
{ "terminate", cc_terminate, "Calls std::terminate(), for testing purposes only.", "terminate" },
{ "twitch", cc_twitch, "Twitch API", "twitch" },
{ "variables", cc_variables, "Lists all the variables that can be used with get and sometimes set.", "variables" },
{ "windows", cc_windows, "Lists all the windows that can be opened.", "windows" },
{ "replay_startrecord", cc_replay_startrecord, "Starts recording a new replay.", "replay_startrecord <name> [max_ticks]"},

View File

@ -2649,19 +2649,6 @@ enum
STR_DATE_FORMAT = 5161,
STR_DATE_FORMAT_DAY_MONTH_YEAR = 5162,
STR_DATE_FORMAT_MONTH_DAY_YEAR = 5163,
STR_TWITCH_NAME = 5164,
STR_TWITCH_PEEP_FOLLOWERS = 5165,
STR_TWITCH_PEEP_FOLLOWERS_TIP = 5166,
STR_TWITCH_FOLLOWERS_TRACK = 5167,
STR_TWITCH_FOLLOWERS_TRACK_TIP = 5168,
STR_TWITCH_PEEP_CHAT = 5169,
STR_TWITCH_PEEP_CHAT_TIP = 5170,
STR_TWITCH_CHAT_TRACK = 5171,
STR_TWITCH_CHAT_TRACK_TIP = 5172,
STR_TWITCH_CHAT_NEWS = 5173,
STR_TWITCH_CHAT_NEWS_TIP = 5174,
STR_TWITCH_NAME_DESC = 5175,
STR_TWITCH_ENABLE = 5176,
STR_FULLSCREEN_MODE = 5177,
STR_FINANCIAL_CHEATS_TIP = 5178,
STR_GUEST_CHEATS_TIP = 5179,
@ -2756,7 +2743,6 @@ enum
STR_OPTIONS_AUDIO_TIP = 5268,
STR_OPTIONS_CONTROLS_AND_INTERFACE_TIP = 5269,
STR_OPTIONS_MISCELLANEOUS_TIP = 5270,
STR_OPTIONS_TWITCH_TIP = 5271,
STR_CLEAR_SCENERY_REMOVE_SMALL_SCENERY_TIP = 5272,
STR_CLEAR_SCENERY_REMOVE_LARGE_SCENERY_TIP = 5273,
STR_CLEAR_SCENERY_REMOVE_FOOTPATHS_TIP = 5274,
@ -3292,7 +3278,6 @@ enum
STR_AUTO_STAFF_PLACEMENT_TIP = 5849,
STR_HANDYMEN_MOW_BY_DEFAULT_TIP = 5850,
STR_DEFAULT_INSPECTION_INTERVAL_TIP = 5851,
STR_TWITCH_NAME_TIP = 5852,
STR_SOUND_EFFECTS_TIP = 5853,
STR_RIDE_MUSIC_TIP = 5854,
STR_FULLSCREEN_MODE_TIP = 5855,
@ -3756,9 +3741,6 @@ enum
STR_DEMOLISH_RIDE_ID_MONEY = 6250,
STR_RIDE_NOT_YET_EMPTY = 6251,
STR_TWITCH_API_URL = 6252,
STR_TWITCH_API_URL_TIP = 6253,
STR_TWITCH_API_URL_DESC = 6254,
STR_INVALID_URL = 6255,
STR_EFFECTS_GROUP = 6256,

View File

@ -1,570 +0,0 @@
/*****************************************************************************
* Copyright (c) 2014-2019 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#ifdef DISABLE_TWITCH
# include "Twitch.h"
namespace Twitch
{
void Update()
{
}
} // namespace Twitch
#else
# ifdef DISABLE_HTTP
# error HTTP must be enabled to use the TWITCH functionality.
# endif
# include "../Context.h"
# include "../Game.h"
# include "../OpenRCT2.h"
# include "../actions/GuestSetFlagsAction.hpp"
# include "../config/Config.h"
# include "../core/Http.h"
# include "../core/Json.hpp"
# include "../core/String.hpp"
# include "../drawing/Drawing.h"
# include "../interface/InteractiveConsole.h"
# include "../localisation/Localisation.h"
# include "../management/NewsItem.h"
# include "../peep/Peep.h"
# include "../platform/platform.h"
# include "../util/Util.h"
# include "../world/Sprite.h"
# include "Twitch.h"
# include <jansson.h>
# include <memory>
# include <vector>
using namespace OpenRCT2;
bool gTwitchEnable = false;
namespace Twitch
{
enum
{
TWITCH_STATE_JOINING,
TWITCH_STATE_JOINED,
TWITCH_STATE_WAITING,
TWITCH_STATE_GET_FOLLOWERS,
TWITCH_STATE_GET_MESSAGES,
TWITCH_STATE_LEAVING,
TWITCH_STATE_LEFT
};
enum
{
TWITCH_STATUS_OK = 200
};
struct AudienceMember
{
const char* Name;
bool IsFollower;
bool IsInChat;
bool IsMod;
bool Exists;
bool ShouldTrack;
static AudienceMember FromJson(json_t* json)
{
AudienceMember member = {};
if (!json_is_object(json))
return member;
json_t* name = json_object_get(json, "name");
json_t* isFollower = json_object_get(json, "isFollower");
json_t* isInChat = json_object_get(json, "inChat");
json_t* isMod = json_object_get(json, "isMod");
member.Name = json_string_value(name);
member.IsFollower = json_is_true(isFollower);
member.IsInChat = json_is_true(isInChat);
member.IsMod = json_is_true(isMod);
member.Exists = false;
member.ShouldTrack = false;
return member;
}
};
/**
* The time between HTTP requests.
* TODO Ideally, the chat message pulse should be more frequent than the followers / chat members so that news messages etc.
* have a lower latency.
*/
constexpr uint32_t PulseTime = 10 * 1000;
static int32_t _twitchState = TWITCH_STATE_LEFT;
static bool _twitchIdle = true;
static uint32_t _twitchLastPulseTick = 0;
static int32_t _twitchLastPulseOperation = 1;
static Http::Response _twitchJsonResponse;
static void Join();
static void Leave();
static void GetFollowers();
static void GetMessages();
static void ParseFollowers();
static void ParseMessages();
static bool ShouldTrackMember(const AudienceMember* member);
static bool ShouldMemberBeGuest(const AudienceMember* member);
static void ManageGuestNames(std::vector<AudienceMember>& members);
static void ParseChatMessage(const char* message);
static void DoChatMessageNews(const char* message);
static bool IsTwitchEnabled()
{
if (!gTwitchEnable)
return false;
if (gScreenFlags & (~SCREEN_FLAGS_PLAYING))
return false;
if (String::IsNullOrEmpty(gConfigTwitch.channel))
return false;
return true;
}
void Update()
{
if (!_twitchIdle)
return;
if (IsTwitchEnabled())
{
if (game_is_paused())
return;
switch (_twitchState)
{
case TWITCH_STATE_LEFT:
{
uint32_t currentTime = platform_get_ticks();
uint32_t timeSinceLastPulse = currentTime - _twitchLastPulseTick;
if (_twitchLastPulseTick == 0 || timeSinceLastPulse > PulseTime)
{
_twitchLastPulseTick = currentTime;
Join();
}
break;
}
case TWITCH_STATE_JOINED:
{
uint32_t currentTime = platform_get_ticks();
uint32_t timeSinceLastPulse = currentTime - _twitchLastPulseTick;
if (_twitchLastPulseTick == 0 || timeSinceLastPulse > PulseTime)
{
_twitchLastPulseTick = currentTime;
_twitchLastPulseOperation = (_twitchLastPulseOperation + 1) % 2;
switch (_twitchLastPulseOperation + TWITCH_STATE_GET_FOLLOWERS)
{
case TWITCH_STATE_GET_FOLLOWERS:
GetFollowers();
break;
case TWITCH_STATE_GET_MESSAGES:
if (gConfigTwitch.enable_news)
{
GetMessages();
}
break;
}
}
break;
}
case TWITCH_STATE_GET_FOLLOWERS:
ParseFollowers();
break;
case TWITCH_STATE_GET_MESSAGES:
ParseMessages();
break;
}
}
else
{
if (_twitchState != TWITCH_STATE_LEFT)
{
Leave();
}
}
}
/**
* GET /leave/:join
*/
static void Join()
{
char url[256];
if (gConfigTwitch.api_url == nullptr || strlen(gConfigTwitch.api_url) == 0)
{
auto context = GetContext();
context->WriteLine("API URL is empty! skipping request...");
return;
}
snprintf(url, sizeof(url), "%s/join/%s", gConfigTwitch.api_url, gConfigTwitch.channel);
_twitchState = TWITCH_STATE_JOINING;
_twitchIdle = false;
Http::Request request;
request.url = url;
request.method = Http::Method::GET;
Http::DoAsync(request, [](Http::Response res) {
std::shared_ptr<void> _(nullptr, [&](...) { _twitchIdle = true; });
if (res.status != Http::Status::OK)
{
_twitchState = TWITCH_STATE_LEFT;
GetContext()->WriteLine("Unable to connect to twitch channel.");
return;
}
auto root = Json::FromString(res.body);
json_t* jsonStatus = json_object_get(root, "status");
if (json_is_number(jsonStatus) && json_integer_value(jsonStatus) == TWITCH_STATUS_OK)
{
_twitchState = TWITCH_STATE_JOINED;
}
else
{
_twitchState = TWITCH_STATE_LEFT;
}
_twitchLastPulseTick = 0;
GetContext()->WriteLine("Connected to twitch channel.");
});
}
/**
* GET /leave/:channel
*/
static void Leave()
{
GetContext()->WriteLine("Left twitch channel.");
_twitchJsonResponse = {};
_twitchState = TWITCH_STATE_LEFT;
_twitchLastPulseTick = 0;
gTwitchEnable = false;
// TODO reset all peeps with twitch flag
// HTTP request no longer used as it could be abused
// char url[256];
// snprintf(url, sizeof(url), "%sleave/%s", TwitchExtendedBaseUrl, gConfigTwitch.channel);
// _twitchState = TWITCH_STATE_LEAVING;
// _twitchIdle = false;
// http_request_json_async(url, [](http_json_response * jsonResponse) -> void
// {
// http_request_json_dispose(jsonResponse);
// _twitchState = TWITCH_STATE_LEFT;
// _twitchIdle = true;
//
// GetContext()->WriteLine("Left twitch channel.");
// });
}
static void Get(const std::string& requestFormat, int operation)
{
char url[256];
if (gConfigTwitch.api_url == nullptr || strlen(gConfigTwitch.api_url) == 0)
{
auto context = GetContext();
context->WriteLine("API URL is empty! skipping request...");
return;
}
snprintf(url, sizeof(url), requestFormat.c_str(), gConfigTwitch.api_url, gConfigTwitch.channel);
_twitchState = TWITCH_STATE_WAITING;
_twitchIdle = false;
Http::DoAsync({ url }, [operation](Http::Response res) {
std::shared_ptr<void> _(nullptr, [&](...) { _twitchIdle = true; });
if (res.status != Http::Status::OK)
{
_twitchState = TWITCH_STATE_JOINED;
return;
}
_twitchJsonResponse = res;
_twitchState = operation;
});
}
/**
* GET /channel/:channel/audience
*/
static void GetFollowers()
{
Get("%s/channel/%s/audience", TWITCH_STATE_GET_FOLLOWERS);
}
/**
* GET /channel/:channel/messages
*/
static void GetMessages()
{
Get("%s/channel/%s/messages", TWITCH_STATE_GET_MESSAGES);
}
static void ParseFollowers()
{
json_t* root = Json::FromString(_twitchJsonResponse.body);
if (json_is_array(root))
{
std::vector<AudienceMember> members;
size_t audienceCount = json_array_size(root);
for (size_t i = 0; i < audienceCount; i++)
{
json_t* jsonAudienceMember = json_array_get(root, i);
auto member = AudienceMember::FromJson(jsonAudienceMember);
if (!String::IsNullOrEmpty(member.Name))
{
member.ShouldTrack = ShouldTrackMember(&member);
if (ShouldMemberBeGuest(&member))
{
members.push_back(member);
}
}
}
ManageGuestNames(members);
}
_twitchJsonResponse = {};
_twitchState = TWITCH_STATE_JOINED;
gfx_invalidate_screen();
}
static void ParseMessages()
{
json_t* root = Json::FromString(_twitchJsonResponse.body);
if (json_is_array(root))
{
size_t messageCount = json_array_size(root);
for (size_t i = 0; i < messageCount; i++)
{
json_t* jsonMessage = json_array_get(root, i);
if (!json_is_object(jsonMessage))
{
continue;
}
json_t* jsonText = json_object_get(jsonMessage, "message");
const char* text = json_string_value(jsonText);
ParseChatMessage(text);
}
}
_twitchJsonResponse = {};
_twitchState = TWITCH_STATE_JOINED;
}
static bool ShouldTrackMember(const AudienceMember* member)
{
if (member->IsInChat && gConfigTwitch.enable_chat_peep_tracking)
{
return true;
}
else if (member->IsFollower && gConfigTwitch.enable_follower_peep_tracking)
{
return true;
}
return false;
}
static bool ShouldMemberBeGuest(const AudienceMember* member)
{
if (gConfigTwitch.enable_chat_peep_names && member->IsInChat)
{
return true;
}
else if (gConfigTwitch.enable_follower_peep_names && member->IsFollower)
{
return true;
}
return false;
}
static void ManageGuestNames(std::vector<AudienceMember>& members)
{
// Check what followers are already in the park
uint16_t spriteIndex;
Peep* peep;
FOR_ALL_GUESTS (spriteIndex, peep)
{
if (peep->name != nullptr)
{
uint8_t args[32]{};
char buffer[256]{};
peep->FormatNameTo(args);
format_string(buffer, sizeof(buffer), STR_STRINGID, args);
AudienceMember* member = nullptr;
for (AudienceMember& m : members)
{
if (String::Equals(buffer, m.Name, true))
{
member = &m;
m.Exists = true;
break;
}
}
if (peep->peep_flags & PEEP_FLAGS_TWITCH)
{
if (member == nullptr)
{
// Member no longer peep name worthy
uint32_t flags = peep->peep_flags & ~(PEEP_FLAGS_TRACKING | PEEP_FLAGS_TWITCH);
auto guestSetFlagsAction = GuestSetFlagsAction(peep->sprite_index, flags);
GameActions::Execute(&guestSetFlagsAction);
// TODO set peep name back to number / real name
}
else
{
uint32_t flags = peep->peep_flags;
if (member->ShouldTrack)
{
flags |= (PEEP_FLAGS_TRACKING);
}
else if (!member->ShouldTrack)
{
flags &= ~(PEEP_FLAGS_TRACKING);
}
if (flags != peep->peep_flags)
{
auto guestSetFlagsAction = GuestSetFlagsAction(peep->sprite_index, flags);
GameActions::Execute(&guestSetFlagsAction);
}
}
}
else if (member != nullptr && !(peep->peep_flags & PEEP_FLAGS_LEAVING_PARK))
{
// Peep with same name already exists but not twitch
uint32_t flags = peep->peep_flags | PEEP_FLAGS_TWITCH;
if (member->ShouldTrack)
{
flags |= PEEP_FLAGS_TRACKING;
}
auto guestSetFlagsAction = GuestSetFlagsAction(peep->sprite_index, flags);
GameActions::Execute(&guestSetFlagsAction);
}
}
}
// Rename non-named peeps to followers that aren't currently in the park.
if (!members.empty())
{
size_t memberIndex = SIZE_MAX;
FOR_ALL_GUESTS (spriteIndex, peep)
{
size_t originalMemberIndex = memberIndex;
for (size_t i = memberIndex + 1; i < members.size(); i++)
{
if (!members[i].Exists)
{
memberIndex = i;
break;
}
}
if (originalMemberIndex == memberIndex)
{
break;
}
AudienceMember* member = &members[memberIndex];
if (peep->name == nullptr && !(peep->peep_flags & PEEP_FLAGS_LEAVING_PARK))
{
// Rename peep and add flags
auto memLen = std::strlen(member->Name) + 1;
peep->name = static_cast<char*>(std::malloc(memLen));
if (peep->name != nullptr)
{
std::memcpy(peep->name, member->Name, memLen);
uint32_t flags = peep->peep_flags | PEEP_FLAGS_TWITCH;
if (member->ShouldTrack)
{
flags |= PEEP_FLAGS_TRACKING;
}
auto guestSetFlagsAction = GuestSetFlagsAction(peep->sprite_index, flags);
GameActions::Execute(&guestSetFlagsAction);
}
}
else
{
// Peep still yet to be found for member
memberIndex--;
}
}
}
}
static char* strskipwhitespace(const char* str)
{
while (*str == ' ' || *str == '\t')
{
str++;
}
return const_cast<char*>(str);
}
static void ParseChatMessage(const char* message)
{
message = strskipwhitespace(message);
if (!String::StartsWith(message, "!"))
{
return;
}
// Skip '!'
message++;
// Check that command is "news"
const char *ch, *cmd;
for (ch = message, cmd = "news"; *cmd != '\0'; ++ch, ++cmd)
{
if (*ch != *cmd)
return;
}
if (!isspace(*ch))
return;
ch = strskipwhitespace(ch);
DoChatMessageNews(ch);
}
static void DoChatMessageNews(const char* message)
{
if (gConfigTwitch.enable_news)
{
utf8 buffer[256];
buffer[0] = static_cast<utf8>(static_cast<uint8_t>(FORMAT_TOPAZ));
safe_strcpy(buffer + 1, message, sizeof(buffer) - 1);
utf8_remove_formatting(buffer, false);
// TODO Create a new news item type for twitch which has twitch icon
news_item_add_to_queue_raw(NEWS_ITEM_BLANK, buffer, 0);
}
}
} // namespace Twitch
#endif

View File

@ -1,22 +0,0 @@
/*****************************************************************************
* Copyright (c) 2014-2019 OpenRCT2 developers
*
* For a complete list of all authors, please refer to contributors.md
* Interested in contributing? Visit https://github.com/OpenRCT2/OpenRCT2
*
* OpenRCT2 is licensed under the GNU General Public License version 3.
*****************************************************************************/
#ifndef _TWITCH_H_
#define _TWITCH_H_
#include "../common.h"
extern bool gTwitchEnable;
namespace Twitch
{
void Update();
}
#endif

View File

@ -382,7 +382,7 @@ enum PeepFlags : uint32_t
PEEP_FLAGS_INTAMIN_DEPRECATED = (1 << 27), // Used to make the peep think "I'm so excited - It's an Intamin ride!" while
// riding on a Intamin ride.
PEEP_FLAGS_HERE_WE_ARE = (1 << 28), // Makes the peep think "...and here we are on X!" while riding a ride
PEEP_FLAGS_TWITCH = (1u << 31), // Added for twitch integration
PEEP_FLAGS_TWITCH_DEPRECATED = (1u << 31), // Formerly used for twitch integration
};
enum PeepNextFlags

View File

@ -745,7 +745,6 @@ enum
SPR_G2_FASTFORWARD = SPR_G2_BEGIN + 2,
SPR_G2_SPEED_ARROW = SPR_G2_BEGIN + 3,
SPR_G2_HYPER_ARROW = SPR_G2_BEGIN + 4,
SPR_G2_TAB_TWITCH = SPR_G2_BEGIN + 5,
SPR_G2_TAB_LAND = SPR_G2_BEGIN + 6,
SPR_G2_PLACEHOLDER = SPR_G2_BEGIN + 7,