mirror of
https://gitlab.com/Mr_Goldberg/goldberg_emulator.git
synced 2024-06-26 14:08:56 +00:00
Compare commits
7 Commits
00c9c08d85
...
cce1d7d2c1
Author | SHA1 | Date | |
---|---|---|---|
|
cce1d7d2c1 | ||
|
bfa1e95f7b | ||
|
69d5facf4f | ||
|
b9129b3932 | ||
|
122979b276 | ||
|
d608f5f29f | ||
|
2f17ae5c43 |
|
@ -8,7 +8,7 @@ call build_env_x86.bat
|
|||
cl dll/rtlgenrandom.c dll/rtlgenrandom.def
|
||||
cl /LD /DEMU_RELEASE_BUILD /DEMU_EXPERIMENTAL_BUILD /DSTEAMCLIENT_DLL /DCONTROLLER_SUPPORT /DEMU_OVERLAY /DGLEW_STATIC /IImGui /Iglew\include /DNDEBUG /I%PROTOBUF_X86_DIRECTORY%\include\ dll/*.cpp dll/*.cc detours/*.cpp controller/gamepad.c ImGui/*.cpp ImGui/impls/*.cpp ImGui/impls/windows/*.cpp overlay_experimental/*.cpp overlay_experimental/windows/*.cpp "%PROTOBUF_X86_LIBRARY%" glew\glew.c opengl32.lib Iphlpapi.lib Ws2_32.lib rtlgenrandom.lib Shell32.lib Winmm.lib /EHsc /MP12 /Ox /link /debug:none /OUT:release\experimental_steamclient\steamclient.dll
|
||||
"%PROTOC_X64_EXE%" -I.\dll\ --cpp_out=.\dll\ .\dll\net.proto
|
||||
cl steamclient_loader/*.cpp advapi32.lib user32.lib /EHsc /MP12 /Od /link /debug:none /OUT:release\experimental_steamclient\steamclient_loader.exe
|
||||
cl steamclient_loader/*.cpp advapi32.lib user32.lib /EHsc /MP12 /Ox /link /debug:none /OUT:release\experimental_steamclient\steamclient_loader.exe
|
||||
copy steamclient_loader\ColdClientLoader.ini release\experimental_steamclient\
|
||||
call build_env_x64.bat
|
||||
cl dll/rtlgenrandom.c dll/rtlgenrandom.def
|
||||
|
|
101
dll/network.cpp
101
dll/network.cpp
|
@ -16,6 +16,7 @@
|
|||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "network.h"
|
||||
#include "dll.h"
|
||||
|
||||
#define MAX_BROADCASTS 16
|
||||
static int number_broadcasts = -1;
|
||||
|
@ -218,25 +219,26 @@ static int set_socket_nonblocking(sock_t sock)
|
|||
|
||||
static void kill_socket(sock_t sock)
|
||||
{
|
||||
if (is_socket_valid(sock))
|
||||
{
|
||||
#if defined(STEAM_WIN32)
|
||||
closesocket(sock);
|
||||
closesocket(sock);
|
||||
#else
|
||||
close(sock);
|
||||
close(sock);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
static void kill_tcp_socket(struct TCP_Socket &socket)
|
||||
{
|
||||
if (is_socket_valid(socket.sock)) {
|
||||
kill_socket(socket.sock);
|
||||
}
|
||||
kill_socket(socket.sock);
|
||||
|
||||
socket = TCP_Socket();
|
||||
}
|
||||
|
||||
static bool initialed;
|
||||
static void run_at_startup()
|
||||
{
|
||||
static bool initialed = false;
|
||||
if (initialed) {
|
||||
return;
|
||||
}
|
||||
|
@ -886,6 +888,22 @@ void Networking::Run()
|
|||
char data[2048];
|
||||
int len;
|
||||
|
||||
if (query_alive && is_socket_valid(query_socket)) {
|
||||
PRINT_DEBUG("RECV QUERY\n");
|
||||
Steam_Client* client = get_steam_client();
|
||||
sockaddr_in addr;
|
||||
addr.sin_family = AF_INET;
|
||||
|
||||
while ((len = receive_packet(query_socket, &ip_port, data, sizeof(data))) >= 0) {
|
||||
client->steam_gameserver->HandleIncomingPacket(data, len, htonl(ip_port.ip), htons(ip_port.port));
|
||||
len = client->steam_gameserver->GetNextOutgoingPacket(data, sizeof(data), &ip_port.ip, &ip_port.port);
|
||||
|
||||
addr.sin_addr.s_addr = htonl(ip_port.ip);
|
||||
addr.sin_port = htons(ip_port.port);
|
||||
sendto(query_socket, data, len, 0, (sockaddr*)&addr, sizeof(addr));
|
||||
}
|
||||
}
|
||||
|
||||
PRINT_DEBUG("RECV UDP\n");
|
||||
while((len = receive_packet(udp_socket, &ip_port, data, sizeof(data))) >= 0) {
|
||||
PRINT_DEBUG("recv %i %hhu.%hhu.%hhu.%hhu:%hu\n", len, ((unsigned char *)&ip_port.ip)[0], ((unsigned char *)&ip_port.ip)[1], ((unsigned char *)&ip_port.ip)[2], ((unsigned char *)&ip_port.ip)[3], htons(ip_port.port));
|
||||
|
@ -1247,3 +1265,74 @@ bool Networking::isAlive()
|
|||
{
|
||||
return alive;
|
||||
}
|
||||
|
||||
void Networking::startQuery(IP_PORT ip_port)
|
||||
{
|
||||
if (ip_port.port <= 1024)
|
||||
return;
|
||||
|
||||
if (!query_alive)
|
||||
{
|
||||
if (ip_port.port == MASTERSERVERUPDATERPORT_USEGAMESOCKETSHARE)
|
||||
{
|
||||
PRINT_DEBUG("Source Query in Shared Mode\n");
|
||||
return;
|
||||
}
|
||||
|
||||
int retry = 0;
|
||||
constexpr auto max_retry = 10;
|
||||
|
||||
while (retry++ < max_retry)
|
||||
{
|
||||
query_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (is_socket_valid(query_socket))
|
||||
break;
|
||||
if (retry > max_retry)
|
||||
{
|
||||
reset_last_error();
|
||||
return;
|
||||
}
|
||||
}
|
||||
retry = 0;
|
||||
|
||||
sockaddr_in addr;
|
||||
addr.sin_addr.s_addr = htonl(ip_port.ip);
|
||||
addr.sin_port = htons(ip_port.port);
|
||||
addr.sin_family = AF_INET;
|
||||
|
||||
while (retry++ < max_retry)
|
||||
{
|
||||
int res = bind(query_socket, (sockaddr*)&addr, sizeof(sockaddr_in));
|
||||
if (res == 0)
|
||||
{
|
||||
set_socket_nonblocking(query_socket);
|
||||
break;
|
||||
}
|
||||
|
||||
if (retry >= max_retry)
|
||||
{
|
||||
kill_socket(query_socket);
|
||||
query_socket = -1;
|
||||
reset_last_error();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
char str_ip[16];
|
||||
inet_ntop(AF_INET, &(addr.sin_addr), str_ip, 16);
|
||||
|
||||
PRINT_DEBUG("Started query server on %s:%d\n", str_ip, htons(addr.sin_port));
|
||||
}
|
||||
query_alive = true;
|
||||
}
|
||||
|
||||
void Networking::shutDownQuery()
|
||||
{
|
||||
query_alive = false;
|
||||
kill_socket(query_socket);
|
||||
}
|
||||
|
||||
bool Networking::isQueryAlive()
|
||||
{
|
||||
return query_alive;
|
||||
}
|
||||
|
|
|
@ -85,9 +85,10 @@ struct Connection {
|
|||
|
||||
class Networking {
|
||||
bool enabled = false;
|
||||
bool query_alive;
|
||||
bool alive;
|
||||
std::chrono::high_resolution_clock::time_point last_run;
|
||||
sock_t udp_socket, tcp_socket;
|
||||
sock_t query_socket, udp_socket, tcp_socket;
|
||||
uint16 udp_port, tcp_port;
|
||||
uint32 own_ip;
|
||||
std::vector<struct Connection> connections;
|
||||
|
@ -135,6 +136,10 @@ public:
|
|||
|
||||
void shutDown();
|
||||
bool isAlive();
|
||||
|
||||
void startQuery(IP_PORT ip_port);
|
||||
void shutDownQuery();
|
||||
bool isQueryAlive();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -145,6 +145,9 @@ public:
|
|||
//networking
|
||||
bool disable_networking = false;
|
||||
|
||||
//gameserver source query
|
||||
bool disable_source_query = false;
|
||||
|
||||
//overlay
|
||||
bool disable_overlay = false;
|
||||
};
|
||||
|
|
265
dll/source_query.cpp
Normal file
265
dll/source_query.cpp
Normal file
|
@ -0,0 +1,265 @@
|
|||
/* Copyright (C) 2019 Mr Goldberg, , Nemirtingas
|
||||
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 "source_query.h"
|
||||
#include "dll.h"
|
||||
|
||||
using lock_t = std::lock_guard<std::mutex>;
|
||||
|
||||
enum class source_query_magic : uint32_t
|
||||
{
|
||||
simple = 0xFFFFFFFFul,
|
||||
multi = 0xFFFFFFFEul, // <--- TODO ?
|
||||
};
|
||||
|
||||
enum class source_query_header : uint8_t
|
||||
{
|
||||
A2S_INFO = 'T',
|
||||
A2S_PLAYER = 'U',
|
||||
A2S_RULES = 'V',
|
||||
};
|
||||
|
||||
enum class source_response_header : uint8_t
|
||||
{
|
||||
A2S_CHALLENGE = 'A',
|
||||
A2S_INFO = 'I',
|
||||
A2S_PLAYER = 'D',
|
||||
A2S_RULES = 'E',
|
||||
};
|
||||
|
||||
enum class source_server_type : uint8_t
|
||||
{
|
||||
dedicated = 'd',
|
||||
non_dedicated = 'i',
|
||||
source_tc = 'p',
|
||||
};
|
||||
|
||||
enum class source_server_env : uint8_t
|
||||
{
|
||||
linux = 'l',
|
||||
windows = 'w',
|
||||
old_mac = 'm',
|
||||
mac = 'o',
|
||||
};
|
||||
|
||||
enum class source_server_visibility : uint8_t
|
||||
{
|
||||
_public = 0,
|
||||
_private = 1,
|
||||
};
|
||||
|
||||
enum class source_server_vac : uint8_t
|
||||
{
|
||||
unsecured = 0,
|
||||
secured = 1,
|
||||
};
|
||||
|
||||
enum source_server_extra_flag : uint8_t
|
||||
{
|
||||
none = 0x00,
|
||||
gameid = 0x01,
|
||||
steamid = 0x10,
|
||||
keywords = 0x20,
|
||||
spectator = 0x40,
|
||||
port = 0x80,
|
||||
};
|
||||
|
||||
#if defined(STEAM_WIN32)
|
||||
static constexpr source_server_env my_server_env = source_server_env::windows;
|
||||
#else
|
||||
static constexpr source_server_env my_server_env = source_server_env::linux;
|
||||
#endif
|
||||
|
||||
#pragma pack(push)
|
||||
#pragma pack(1)
|
||||
|
||||
constexpr char a2s_info_payload[] = "Source Engine Query";
|
||||
constexpr size_t a2s_info_payload_size = sizeof(a2s_info_payload);
|
||||
|
||||
struct source_query_data
|
||||
{
|
||||
source_query_magic magic;
|
||||
source_query_header header;
|
||||
union
|
||||
{
|
||||
char a2s_info_payload[a2s_info_payload_size];
|
||||
uint32_t challenge;
|
||||
};
|
||||
};
|
||||
|
||||
static constexpr size_t source_query_header_size = sizeof(source_query_magic) + sizeof(source_query_header);
|
||||
static constexpr size_t a2s_query_info_size = source_query_header_size + sizeof(source_query_data::a2s_info_payload);
|
||||
static constexpr size_t a2s_query_challenge_size = source_query_header_size + sizeof(source_query_data::challenge);
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
void serialize_response(std::vector<uint8_t>& buffer, const void* _data, size_t len)
|
||||
{
|
||||
const uint8_t* data = reinterpret_cast<const uint8_t*>(_data);
|
||||
|
||||
buffer.insert(buffer.end(), data, data + len);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void serialize_response(std::vector<uint8_t>& buffer, T const& v)
|
||||
{
|
||||
uint8_t const* data = reinterpret_cast<uint8_t const*>(&v);
|
||||
serialize_response(buffer, data, sizeof(T));
|
||||
}
|
||||
|
||||
template<>
|
||||
void serialize_response<std::string>(std::vector<uint8_t>& buffer, std::string const& v)
|
||||
{
|
||||
uint8_t const* str = reinterpret_cast<uint8_t const*>(v.c_str());
|
||||
serialize_response(buffer, str, v.length()+1);
|
||||
}
|
||||
|
||||
template<typename T, int N>
|
||||
void serialize_response(std::vector <uint8_t>& buffer, char(&str)[N])
|
||||
{
|
||||
serialize_response(buffer, reinterpret_cast<uint8_t const*>(str), N);
|
||||
}
|
||||
|
||||
void get_challenge(std::vector<uint8_t> &challenge_buff)
|
||||
{
|
||||
// TODO: generate the challenge id
|
||||
serialize_response(challenge_buff, source_query_magic::simple);
|
||||
serialize_response(challenge_buff, source_response_header::A2S_CHALLENGE);
|
||||
serialize_response(challenge_buff, static_cast<uint32_t>(0x00112233ul));
|
||||
}
|
||||
|
||||
std::vector<uint8_t> Source_Query::handle_source_query(const void* buffer, size_t len, Gameserver const& gs)
|
||||
{
|
||||
std::vector<uint8_t> output_buffer;
|
||||
|
||||
if (len < source_query_header_size) // its not at least 5 bytes long (0xFF 0xFF 0xFF 0xFF 0x??)
|
||||
return output_buffer;
|
||||
|
||||
source_query_data const& query = *reinterpret_cast<source_query_data const*>(buffer);
|
||||
|
||||
// || gs.max_player_count() == 0
|
||||
if (gs.offline() || query.magic != source_query_magic::simple)
|
||||
return output_buffer;
|
||||
|
||||
switch (query.header)
|
||||
{
|
||||
case source_query_header::A2S_INFO:
|
||||
if (len >= a2s_query_info_size && !strncmp(query.a2s_info_payload, a2s_info_payload, a2s_info_payload_size))
|
||||
{
|
||||
serialize_response(output_buffer, source_query_magic::simple);
|
||||
serialize_response(output_buffer, source_response_header::A2S_INFO);
|
||||
serialize_response(output_buffer, static_cast<uint8_t>(2));
|
||||
serialize_response(output_buffer, gs.server_name());
|
||||
serialize_response(output_buffer, gs.map_name());
|
||||
serialize_response(output_buffer, gs.mod_dir());
|
||||
serialize_response(output_buffer, gs.product());
|
||||
serialize_response(output_buffer, static_cast<uint16_t>(gs.appid()));
|
||||
serialize_response(output_buffer, static_cast<uint8_t>(gs.num_players()));
|
||||
serialize_response(output_buffer, static_cast<uint8_t>(gs.max_player_count()));
|
||||
serialize_response(output_buffer, static_cast<uint8_t>(gs.bot_player_count()));
|
||||
serialize_response(output_buffer, (gs.dedicated_server() ? source_server_type::dedicated : source_server_type::non_dedicated));;
|
||||
serialize_response(output_buffer, my_server_env);
|
||||
serialize_response(output_buffer, source_server_visibility::_public);
|
||||
serialize_response(output_buffer, (gs.secure() ? source_server_vac::secured : source_server_vac::unsecured));
|
||||
serialize_response(output_buffer, std::to_string(gs.version()));
|
||||
|
||||
uint8_t flags = source_server_extra_flag::none;
|
||||
|
||||
if (gs.port() != 0)
|
||||
flags |= source_server_extra_flag::port;
|
||||
|
||||
if (gs.spectator_port() != 0)
|
||||
flags |= source_server_extra_flag::spectator;
|
||||
|
||||
if(CGameID(gs.appid()).IsValid())
|
||||
flags |= source_server_extra_flag::gameid;
|
||||
|
||||
if (flags != source_server_extra_flag::none)
|
||||
serialize_response(output_buffer, flags);
|
||||
|
||||
if (flags & source_server_extra_flag::port)
|
||||
serialize_response(output_buffer, static_cast<uint16_t>(gs.port()));
|
||||
|
||||
// add steamid
|
||||
|
||||
if (flags & source_server_extra_flag::spectator)
|
||||
{
|
||||
serialize_response(output_buffer, static_cast<uint16_t>(gs.spectator_port()));
|
||||
serialize_response(output_buffer, gs.spectator_server_name());
|
||||
}
|
||||
|
||||
// keywords
|
||||
|
||||
if (flags & source_server_extra_flag::gameid)
|
||||
serialize_response(output_buffer, CGameID(gs.appid()).ToUint64());
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case source_query_header::A2S_PLAYER:
|
||||
if (len >= a2s_query_challenge_size)
|
||||
{
|
||||
if (query.challenge == 0xFFFFFFFFul)
|
||||
{
|
||||
get_challenge(output_buffer);
|
||||
}
|
||||
else if (query.challenge == 0x00112233ul)
|
||||
{
|
||||
std::vector<std::pair<CSteamID, Gameserver_Player_Info_t>> const& players = *get_steam_client()->steam_gameserver->get_players();
|
||||
|
||||
serialize_response(output_buffer, source_query_magic::simple);
|
||||
serialize_response(output_buffer, source_response_header::A2S_PLAYER);
|
||||
serialize_response(output_buffer, static_cast<uint8_t>(players.size())); // num_players
|
||||
|
||||
for (int i = 0; i < players.size(); ++i)
|
||||
{
|
||||
serialize_response(output_buffer, static_cast<uint8_t>(i)); // player index
|
||||
serialize_response(output_buffer, players[i].second.name); // player name
|
||||
serialize_response(output_buffer, players[i].second.score); // player score
|
||||
serialize_response(output_buffer, static_cast<float>(std::chrono::duration_cast<std::chrono::seconds>(std::chrono::steady_clock::now() - players[i].second.join_time).count()));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case source_query_header::A2S_RULES:
|
||||
if (len >= a2s_query_challenge_size)
|
||||
{
|
||||
if (query.challenge == 0xFFFFFFFFul)
|
||||
{
|
||||
get_challenge(output_buffer);
|
||||
}
|
||||
else if (query.challenge == 0x00112233ul)
|
||||
{
|
||||
auto values = gs.values();
|
||||
|
||||
serialize_response(output_buffer, source_query_magic::simple);
|
||||
serialize_response(output_buffer, source_response_header::A2S_RULES);
|
||||
serialize_response(output_buffer, static_cast<uint16_t>(values.size()));
|
||||
|
||||
for (auto const& i : values)
|
||||
{
|
||||
serialize_response(output_buffer, i.first);
|
||||
serialize_response(output_buffer, i.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return output_buffer;
|
||||
}
|
32
dll/source_query.h
Normal file
32
dll/source_query.h
Normal file
|
@ -0,0 +1,32 @@
|
|||
/* 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/>. */
|
||||
|
||||
#ifndef __INCLUDED_SOURCE_QUERY__
|
||||
#define __INCLUDED_SOURCE_QUERY__
|
||||
|
||||
#include "base.h"
|
||||
|
||||
class Source_Query
|
||||
{
|
||||
Source_Query () = delete;
|
||||
~Source_Query() = delete;
|
||||
|
||||
public:
|
||||
static std::vector<uint8_t> handle_source_query(const void* buffer, size_t len, Gameserver const& gs);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -27,11 +27,7 @@
|
|||
#include "steam_remote_storage.h"
|
||||
#include "steam_screenshots.h"
|
||||
#include "steam_http.h"
|
||||
#ifdef CONTROLLER_SUPPORT
|
||||
#include "steam_controller.h"
|
||||
#else
|
||||
#include "steam_controller_disabled.h"
|
||||
#endif
|
||||
#include "steam_ugc.h"
|
||||
#include "steam_applist.h"
|
||||
#include "steam_music.h"
|
||||
|
|
|
@ -16,6 +16,18 @@
|
|||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "base.h"
|
||||
#ifndef CONTROLLER_SUPPORT
|
||||
inline void GamepadInit(void) {}
|
||||
inline void GamepadShutdown(void) {}
|
||||
inline void GamepadUpdate(void) {}
|
||||
inline GAMEPAD_BOOL GamepadIsConnected(GAMEPAD_DEVICE device) { return GAMEPAD_FALSE; }
|
||||
inline GAMEPAD_BOOL GamepadButtonDown(GAMEPAD_DEVICE device, GAMEPAD_BUTTON button) { return GAMEPAD_FALSE; }
|
||||
inline float GamepadTriggerLength(GAMEPAD_DEVICE device, GAMEPAD_TRIGGER trigger) { return 0.0; }
|
||||
inline GAMEPAD_STICKDIR GamepadStickDir(GAMEPAD_DEVICE device, GAMEPAD_STICK stick) { return STICKDIR_CENTER; }
|
||||
inline void GamepadStickNormXY(GAMEPAD_DEVICE device, GAMEPAD_STICK stick, float* outX, float* outY) {}
|
||||
inline float GamepadStickLength(GAMEPAD_DEVICE device, GAMEPAD_STICK stick) { return 0.0; }
|
||||
inline void GamepadSetRumble(GAMEPAD_DEVICE device, float left, float right, unsigned int rumble_length_ms) {}
|
||||
#endif
|
||||
|
||||
struct Controller_Map {
|
||||
std::map<ControllerDigitalActionHandle_t, std::set<int>> active_digital;
|
||||
|
@ -756,7 +768,7 @@ int GetGamepadIndexForController( ControllerHandle_t ulControllerHandle )
|
|||
// Returns the associated controller handle for the specified emulated gamepad
|
||||
ControllerHandle_t GetControllerForGamepadIndex( int nIndex )
|
||||
{
|
||||
PRINT_DEBUG("Steam_Controller::GetControllerForGamepadIndex\n");
|
||||
PRINT_DEBUG("Steam_Controller::GetControllerForGamepadIndex %i\n", nIndex);
|
||||
ControllerHandle_t out = nIndex + 1;
|
||||
auto controller = controllers.find(out);
|
||||
if (controller == controllers.end()) return 0;
|
||||
|
@ -890,7 +902,7 @@ const char *GetGlyphForActionOrigin( EInputActionOrigin eOrigin )
|
|||
// Returns the input type for a particular handle
|
||||
ESteamInputType GetInputTypeForHandle( ControllerHandle_t controllerHandle )
|
||||
{
|
||||
PRINT_DEBUG("Steam_Controller::GetInputTypeForHandle\n");
|
||||
PRINT_DEBUG("Steam_Controller::GetInputTypeForHandle %llu\n", controllerHandle);
|
||||
auto controller = controllers.find(controllerHandle);
|
||||
if (controller == controllers.end()) return k_ESteamInputType_Unknown;
|
||||
return k_ESteamInputType_XBox360Controller;
|
||||
|
|
|
@ -1,375 +0,0 @@
|
|||
/* 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 "base.h"
|
||||
|
||||
class Steam_Controller :
|
||||
public ISteamController001,
|
||||
public ISteamController003,
|
||||
public ISteamController004,
|
||||
public ISteamController005,
|
||||
public ISteamController006,
|
||||
public ISteamController,
|
||||
public ISteamInput
|
||||
{
|
||||
public:
|
||||
|
||||
Steam_Controller(class Settings *settings, class SteamCallResults *callback_results, class SteamCallBacks *callbacks, class RunEveryRunCB *run_every_runcb)
|
||||
{
|
||||
}
|
||||
|
||||
// Init and Shutdown must be called when starting/ending use of this interface
|
||||
bool Init()
|
||||
{
|
||||
PRINT_DEBUG("Steam_Controller::Init()\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Init( const char *pchAbsolutePathToControllerConfigVDF )
|
||||
{
|
||||
PRINT_DEBUG("Steam_Controller::Init() old\n");
|
||||
return Init();
|
||||
}
|
||||
|
||||
bool Shutdown()
|
||||
{
|
||||
PRINT_DEBUG("Steam_Controller::Shutdown()\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetOverrideMode( const char *pchMode )
|
||||
{
|
||||
PRINT_DEBUG("Steam_Controller::SetOverrideMode\n");
|
||||
}
|
||||
|
||||
// Synchronize API state with the latest Steam Controller inputs available. This
|
||||
// is performed automatically by SteamAPI_RunCallbacks, but for the absolute lowest
|
||||
// possible latency, you call this directly before reading controller state.
|
||||
void RunFrame()
|
||||
{
|
||||
PRINT_DEBUG("Steam_Controller::RunFrame()\n");
|
||||
}
|
||||
|
||||
bool GetControllerState( uint32 unControllerIndex, SteamControllerState001_t *pState )
|
||||
{
|
||||
PRINT_DEBUG("Steam_Controller::GetControllerState()\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Enumerate currently connected controllers
|
||||
// handlesOut should point to a STEAM_CONTROLLER_MAX_COUNT sized array of ControllerHandle_t handles
|
||||
// Returns the number of handles written to handlesOut
|
||||
int GetConnectedControllers( ControllerHandle_t *handlesOut )
|
||||
{
|
||||
PRINT_DEBUG("GetConnectedControllers\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Invokes the Steam overlay and brings up the binding screen
|
||||
// Returns false is overlay is disabled / unavailable, or the user is not in Big Picture mode
|
||||
bool ShowBindingPanel( ControllerHandle_t controllerHandle )
|
||||
{
|
||||
PRINT_DEBUG("ShowBindingPanel\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// ACTION SETS
|
||||
// Lookup the handle for an Action Set. Best to do this once on startup, and store the handles for all future API calls.
|
||||
ControllerActionSetHandle_t GetActionSetHandle( const char *pszActionSetName )
|
||||
{
|
||||
PRINT_DEBUG("GetActionSetHandle %s\n", pszActionSetName);
|
||||
return 124;
|
||||
}
|
||||
|
||||
|
||||
// Reconfigure the controller to use the specified action set (ie 'Menu', 'Walk' or 'Drive')
|
||||
// This is cheap, and can be safely called repeatedly. It's often easier to repeatedly call it in
|
||||
// your state loops, instead of trying to place it in all of your state transitions.
|
||||
void ActivateActionSet( ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetHandle )
|
||||
{
|
||||
PRINT_DEBUG("ActivateActionSet\n");
|
||||
}
|
||||
|
||||
ControllerActionSetHandle_t GetCurrentActionSet( ControllerHandle_t controllerHandle )
|
||||
{
|
||||
PRINT_DEBUG("GetCurrentActionSet\n");
|
||||
return 124;
|
||||
}
|
||||
|
||||
|
||||
void ActivateActionSetLayer( ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetLayerHandle )
|
||||
{
|
||||
PRINT_DEBUG("ActivateActionSetLayer\n");
|
||||
}
|
||||
|
||||
void DeactivateActionSetLayer( ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetLayerHandle )
|
||||
{
|
||||
PRINT_DEBUG("DeactivateActionSetLayer\n");
|
||||
}
|
||||
|
||||
void DeactivateAllActionSetLayers( ControllerHandle_t controllerHandle )
|
||||
{
|
||||
PRINT_DEBUG("DeactivateAllActionSetLayers\n");
|
||||
}
|
||||
|
||||
int GetActiveActionSetLayers( ControllerHandle_t controllerHandle, ControllerActionSetHandle_t *handlesOut )
|
||||
{
|
||||
PRINT_DEBUG("GetActiveActionSetLayers\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ACTIONS
|
||||
// Lookup the handle for a digital action. Best to do this once on startup, and store the handles for all future API calls.
|
||||
ControllerDigitalActionHandle_t GetDigitalActionHandle( const char *pszActionName )
|
||||
{
|
||||
PRINT_DEBUG("GetDigitalActionHandle %s\n", pszActionName);
|
||||
return 123;
|
||||
}
|
||||
|
||||
|
||||
// Returns the current state of the supplied digital game action
|
||||
ControllerDigitalActionData_t GetDigitalActionData( ControllerHandle_t controllerHandle, ControllerDigitalActionHandle_t digitalActionHandle )
|
||||
{
|
||||
PRINT_DEBUG("GetDigitalActionData\n");
|
||||
ControllerDigitalActionData_t digitalData;
|
||||
digitalData.bActive = false;
|
||||
return digitalData;
|
||||
}
|
||||
|
||||
|
||||
// Get the origin(s) for a digital action within an action set. Returns the number of origins supplied in originsOut. Use this to display the appropriate on-screen prompt for the action.
|
||||
// originsOut should point to a STEAM_CONTROLLER_MAX_ORIGINS sized array of EControllerActionOrigin handles
|
||||
int GetDigitalActionOrigins( ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetHandle, ControllerDigitalActionHandle_t digitalActionHandle, EControllerActionOrigin *originsOut )
|
||||
{
|
||||
PRINT_DEBUG("GetDigitalActionOrigins\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetDigitalActionOrigins( InputHandle_t inputHandle, InputActionSetHandle_t actionSetHandle, InputDigitalActionHandle_t digitalActionHandle, EInputActionOrigin *originsOut )
|
||||
{
|
||||
PRINT_DEBUG("GetDigitalActionOrigins steaminput\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Lookup the handle for an analog action. Best to do this once on startup, and store the handles for all future API calls.
|
||||
ControllerAnalogActionHandle_t GetAnalogActionHandle( const char *pszActionName )
|
||||
{
|
||||
PRINT_DEBUG("GetAnalogActionHandle %s\n", pszActionName);
|
||||
return 125;
|
||||
}
|
||||
|
||||
|
||||
// Returns the current state of these supplied analog game action
|
||||
ControllerAnalogActionData_t GetAnalogActionData( ControllerHandle_t controllerHandle, ControllerAnalogActionHandle_t analogActionHandle )
|
||||
{
|
||||
PRINT_DEBUG("GetAnalogActionData\n");
|
||||
ControllerAnalogActionData_t data;
|
||||
data.eMode = k_EInputSourceMode_None;
|
||||
data.x = data.y = 0;
|
||||
data.bActive = false;
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
// Get the origin(s) for an analog action within an action set. Returns the number of origins supplied in originsOut. Use this to display the appropriate on-screen prompt for the action.
|
||||
// originsOut should point to a STEAM_CONTROLLER_MAX_ORIGINS sized array of EControllerActionOrigin handles
|
||||
int GetAnalogActionOrigins( ControllerHandle_t controllerHandle, ControllerActionSetHandle_t actionSetHandle, ControllerAnalogActionHandle_t analogActionHandle, EControllerActionOrigin *originsOut )
|
||||
{
|
||||
PRINT_DEBUG("GetAnalogActionOrigins\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int GetAnalogActionOrigins( InputHandle_t inputHandle, InputActionSetHandle_t actionSetHandle, InputAnalogActionHandle_t analogActionHandle, EInputActionOrigin *originsOut )
|
||||
{
|
||||
PRINT_DEBUG("GetAnalogActionOrigins steaminput\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void StopAnalogActionMomentum( ControllerHandle_t controllerHandle, ControllerAnalogActionHandle_t eAction )
|
||||
{
|
||||
PRINT_DEBUG("StopAnalogActionMomentum\n");
|
||||
}
|
||||
|
||||
|
||||
// Trigger a haptic pulse on a controller
|
||||
void TriggerHapticPulse( ControllerHandle_t controllerHandle, ESteamControllerPad eTargetPad, unsigned short usDurationMicroSec )
|
||||
{
|
||||
PRINT_DEBUG("TriggerHapticPulse\n");
|
||||
}
|
||||
|
||||
void TriggerHapticPulse( uint32 unControllerIndex, ESteamControllerPad eTargetPad, unsigned short usDurationMicroSec )
|
||||
{
|
||||
PRINT_DEBUG("TriggerHapticPulse old\n");
|
||||
TriggerHapticPulse(unControllerIndex, eTargetPad, usDurationMicroSec );
|
||||
}
|
||||
|
||||
// Trigger a pulse with a duty cycle of usDurationMicroSec / usOffMicroSec, unRepeat times.
|
||||
// nFlags is currently unused and reserved for future use.
|
||||
void TriggerRepeatedHapticPulse( ControllerHandle_t controllerHandle, ESteamControllerPad eTargetPad, unsigned short usDurationMicroSec, unsigned short usOffMicroSec, unsigned short unRepeat, unsigned int nFlags )
|
||||
{
|
||||
PRINT_DEBUG("TriggerRepeatedHapticPulse\n");
|
||||
}
|
||||
|
||||
|
||||
// Tigger a vibration event on supported controllers.
|
||||
void TriggerVibration( ControllerHandle_t controllerHandle, unsigned short usLeftSpeed, unsigned short usRightSpeed )
|
||||
{
|
||||
PRINT_DEBUG("TriggerVibration\n");
|
||||
}
|
||||
|
||||
|
||||
// Set the controller LED color on supported controllers.
|
||||
void SetLEDColor( ControllerHandle_t controllerHandle, uint8 nColorR, uint8 nColorG, uint8 nColorB, unsigned int nFlags )
|
||||
{
|
||||
PRINT_DEBUG("SetLEDColor\n");
|
||||
}
|
||||
|
||||
|
||||
// Returns the associated gamepad index for the specified controller, if emulating a gamepad
|
||||
int GetGamepadIndexForController( ControllerHandle_t ulControllerHandle )
|
||||
{
|
||||
PRINT_DEBUG("GetGamepadIndexForController\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Returns the associated controller handle for the specified emulated gamepad
|
||||
ControllerHandle_t GetControllerForGamepadIndex( int nIndex )
|
||||
{
|
||||
PRINT_DEBUG("GetControllerForGamepadIndex\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// Returns raw motion data from the specified controller
|
||||
ControllerMotionData_t GetMotionData( ControllerHandle_t controllerHandle )
|
||||
{
|
||||
PRINT_DEBUG("GetMotionData\n");
|
||||
ControllerMotionData_t data = {};
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
// Attempt to display origins of given action in the controller HUD, for the currently active action set
|
||||
// Returns false is overlay is disabled / unavailable, or the user is not in Big Picture mode
|
||||
bool ShowDigitalActionOrigins( ControllerHandle_t controllerHandle, ControllerDigitalActionHandle_t digitalActionHandle, float flScale, float flXPosition, float flYPosition )
|
||||
{
|
||||
PRINT_DEBUG("ShowDigitalActionOrigins\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ShowAnalogActionOrigins( ControllerHandle_t controllerHandle, ControllerAnalogActionHandle_t analogActionHandle, float flScale, float flXPosition, float flYPosition )
|
||||
{
|
||||
PRINT_DEBUG("ShowAnalogActionOrigins\n");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Returns a localized string (from Steam's language setting) for the specified origin
|
||||
const char *GetStringForActionOrigin( EControllerActionOrigin eOrigin )
|
||||
{
|
||||
PRINT_DEBUG("GetStringForActionOrigin\n");
|
||||
return "Button String";
|
||||
}
|
||||
|
||||
const char *GetStringForActionOrigin( EInputActionOrigin eOrigin )
|
||||
{
|
||||
PRINT_DEBUG("GetStringForActionOrigin steaminput\n");
|
||||
return "Button String";
|
||||
}
|
||||
|
||||
|
||||
// Get a local path to art for on-screen glyph for a particular origin
|
||||
const char *GetGlyphForActionOrigin( EControllerActionOrigin eOrigin )
|
||||
{
|
||||
PRINT_DEBUG("GetGlyphForActionOrigin\n");
|
||||
return "";
|
||||
}
|
||||
|
||||
const char *GetGlyphForActionOrigin( EInputActionOrigin eOrigin )
|
||||
{
|
||||
PRINT_DEBUG("GetGlyphForActionOrigin steaminput\n");
|
||||
return "";
|
||||
}
|
||||
|
||||
// Returns the input type for a particular handle
|
||||
ESteamInputType GetInputTypeForHandle( ControllerHandle_t controllerHandle )
|
||||
{
|
||||
PRINT_DEBUG("GetInputTypeForHandle\n");
|
||||
return k_ESteamInputType_Unknown;
|
||||
}
|
||||
|
||||
const char *GetStringForXboxOrigin( EXboxOrigin eOrigin )
|
||||
{
|
||||
PRINT_DEBUG("GetStringForXboxOrigin\n");
|
||||
return "";
|
||||
}
|
||||
|
||||
const char *GetGlyphForXboxOrigin( EXboxOrigin eOrigin )
|
||||
{
|
||||
PRINT_DEBUG("GetGlyphForXboxOrigin\n");
|
||||
return "";
|
||||
}
|
||||
|
||||
EControllerActionOrigin GetActionOriginFromXboxOrigin_( ControllerHandle_t controllerHandle, EXboxOrigin eOrigin )
|
||||
{
|
||||
PRINT_DEBUG("GetActionOriginFromXboxOrigin\n");
|
||||
return k_EControllerActionOrigin_None;
|
||||
}
|
||||
|
||||
EInputActionOrigin GetActionOriginFromXboxOrigin( InputHandle_t inputHandle, EXboxOrigin eOrigin )
|
||||
{
|
||||
PRINT_DEBUG("GetActionOriginFromXboxOrigin steaminput\n");
|
||||
return k_EInputActionOrigin_None;
|
||||
}
|
||||
|
||||
EControllerActionOrigin TranslateActionOrigin( ESteamInputType eDestinationInputType, EControllerActionOrigin eSourceOrigin )
|
||||
{
|
||||
PRINT_DEBUG("TranslateActionOrigin\n");
|
||||
return k_EControllerActionOrigin_None;
|
||||
}
|
||||
|
||||
EInputActionOrigin TranslateActionOrigin( ESteamInputType eDestinationInputType, EInputActionOrigin eSourceOrigin )
|
||||
{
|
||||
PRINT_DEBUG("TranslateActionOrigin steaminput\n");
|
||||
return k_EInputActionOrigin_None;
|
||||
}
|
||||
|
||||
bool GetControllerBindingRevision( ControllerHandle_t controllerHandle, int *pMajor, int *pMinor )
|
||||
{
|
||||
PRINT_DEBUG("GetControllerBindingRevision\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool GetDeviceBindingRevision( InputHandle_t inputHandle, int *pMajor, int *pMinor )
|
||||
{
|
||||
PRINT_DEBUG("GetDeviceBindingRevision\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32 GetRemotePlaySessionID( InputHandle_t inputHandle )
|
||||
{
|
||||
PRINT_DEBUG("GetRemotePlaySessionID\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
};
|
|
@ -16,6 +16,7 @@
|
|||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#include "steam_gameserver.h"
|
||||
#include "source_query.h"
|
||||
|
||||
#define SEND_SERVER_RATE 5.0
|
||||
|
||||
|
@ -33,6 +34,11 @@ Steam_GameServer::~Steam_GameServer()
|
|||
delete ticket_manager;
|
||||
}
|
||||
|
||||
std::vector<std::pair<CSteamID, Gameserver_Player_Info_t>>* Steam_GameServer::get_players()
|
||||
{
|
||||
return &players;
|
||||
}
|
||||
|
||||
//
|
||||
// Basic server data. These properties, if set, must be set before before calling LogOn. They
|
||||
// may not be changed after logged in.
|
||||
|
@ -54,6 +60,10 @@ bool Steam_GameServer::InitGameServer( uint32 unIP, uint16 usGamePort, uint16 us
|
|||
server_data.set_port(usGamePort);
|
||||
server_data.set_query_port(usQueryPort);
|
||||
server_data.set_offline(false);
|
||||
|
||||
if (!settings->disable_source_query)
|
||||
network->startQuery({ unIP, usQueryPort });
|
||||
|
||||
if (!settings->get_local_game_id().AppID()) settings->set_game_id(CGameID(nGameAppId));
|
||||
//TODO: flags should be k_unServerFlag
|
||||
flags = unFlags;
|
||||
|
@ -71,7 +81,7 @@ void Steam_GameServer::SetProduct( const char *pszProduct )
|
|||
{
|
||||
PRINT_DEBUG("SetProduct\n");
|
||||
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||
server_data.set_product(pszProduct);
|
||||
server_data.set_product(pszProduct); // Set product to game name if this is empty
|
||||
}
|
||||
|
||||
|
||||
|
@ -344,7 +354,22 @@ bool Steam_GameServer::SendUserConnectAndAuthenticate( uint32 unIPClient, const
|
|||
PRINT_DEBUG("SendUserConnectAndAuthenticate %u %u\n", unIPClient, cubAuthBlobSize);
|
||||
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||
|
||||
return ticket_manager->SendUserConnectAndAuthenticate(unIPClient, pvAuthBlob, cubAuthBlobSize, pSteamIDUser);
|
||||
bool res = ticket_manager->SendUserConnectAndAuthenticate(unIPClient, pvAuthBlob, cubAuthBlobSize, pSteamIDUser);
|
||||
|
||||
if (res)
|
||||
{
|
||||
std::pair<CSteamID, Gameserver_Player_Info_t> infos;
|
||||
if( pSteamIDUser != nullptr)
|
||||
infos.first = *pSteamIDUser;
|
||||
|
||||
infos.second.join_time = std::chrono::steady_clock::now();
|
||||
infos.second.score = 0;
|
||||
infos.second.name = "Player";
|
||||
|
||||
players.emplace_back(std::move(infos));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
@ -357,7 +382,16 @@ CSteamID Steam_GameServer::CreateUnauthenticatedUserConnection()
|
|||
PRINT_DEBUG("CreateUnauthenticatedUserConnection\n");
|
||||
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||
|
||||
return ticket_manager->fakeUser();
|
||||
CSteamID bot_id = ticket_manager->fakeUser();
|
||||
std::pair<CSteamID, Gameserver_Player_Info_t> infos;
|
||||
infos.first = bot_id;
|
||||
infos.second.join_time = std::chrono::steady_clock::now();
|
||||
infos.second.score = 0;
|
||||
infos.second.name = "Bot";
|
||||
|
||||
players.emplace_back(std::move(infos));
|
||||
|
||||
return bot_id;
|
||||
}
|
||||
|
||||
|
||||
|
@ -369,6 +403,16 @@ void Steam_GameServer::SendUserDisconnect( CSteamID steamIDUser )
|
|||
PRINT_DEBUG("SendUserDisconnect\n");
|
||||
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||
|
||||
auto player_it = std::find_if(players.begin(), players.end(), [&steamIDUser](std::pair<CSteamID, Gameserver_Player_Info_t>& player)
|
||||
{
|
||||
return player.first == steamIDUser;
|
||||
});
|
||||
|
||||
if (player_it != players.end())
|
||||
{
|
||||
players.erase(player_it);
|
||||
}
|
||||
|
||||
ticket_manager->endAuth(steamIDUser);
|
||||
}
|
||||
|
||||
|
@ -381,7 +425,21 @@ void Steam_GameServer::SendUserDisconnect( CSteamID steamIDUser )
|
|||
bool Steam_GameServer::BUpdateUserData( CSteamID steamIDUser, const char *pchPlayerName, uint32 uScore )
|
||||
{
|
||||
PRINT_DEBUG("BUpdateUserData\n");
|
||||
return true;
|
||||
|
||||
auto player_it = std::find_if(players.begin(), players.end(), [&steamIDUser](std::pair<CSteamID, Gameserver_Player_Info_t>& player)
|
||||
{
|
||||
return player.first == steamIDUser;
|
||||
});
|
||||
|
||||
if (player_it != players.end())
|
||||
{
|
||||
if( pchPlayerName != nullptr)
|
||||
player_it->second.name = pchPlayerName;
|
||||
|
||||
player_it->second.score = uScore;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// You shouldn't need to call this as it is called internally by SteamGameServer_Init() and can only be called once.
|
||||
|
@ -578,6 +636,18 @@ bool Steam_GameServer::HandleIncomingPacket( const void *pData, int cbData, uint
|
|||
{
|
||||
PRINT_DEBUG("HandleIncomingPacket %i %X %i\n", cbData, srcIP, srcPort);
|
||||
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||
if (settings->disable_source_query) return true;
|
||||
|
||||
Gameserver_Outgoing_Packet packet;
|
||||
packet.data = std::move(Source_Query::handle_source_query(pData, cbData, server_data));
|
||||
if (packet.data.empty())
|
||||
return false;
|
||||
|
||||
|
||||
packet.ip = srcIP;
|
||||
packet.port = srcPort;
|
||||
|
||||
outgoing_packets.emplace_back(std::move(packet));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -590,6 +660,7 @@ int Steam_GameServer::GetNextOutgoingPacket( void *pOut, int cbMaxOut, uint32 *p
|
|||
{
|
||||
PRINT_DEBUG("GetNextOutgoingPacket\n");
|
||||
std::lock_guard<std::recursive_mutex> lock(global_mutex);
|
||||
if (settings->disable_source_query) return 0;
|
||||
if (outgoing_packets.size() == 0) return 0;
|
||||
|
||||
if (outgoing_packets.back().data.size() < cbMaxOut) cbMaxOut = outgoing_packets.back().data.size();
|
||||
|
@ -690,6 +761,10 @@ void Steam_GameServer::RunCallbacks()
|
|||
msg.set_allocated_gameserver(new Gameserver(server_data));
|
||||
msg.mutable_gameserver()->set_offline(true);
|
||||
network->sendToAllIndividuals(&msg, true);
|
||||
// Shutdown Source Query
|
||||
network->shutDownQuery();
|
||||
// And empty the queue if needed
|
||||
outgoing_packets.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,9 @@
|
|||
License along with the Goldberg Emulator; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef __INCLUDED_GAMESERVER__
|
||||
#define __INCLUDED_GAMESERVER__
|
||||
|
||||
#include "base.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
@ -22,12 +25,18 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
struct Gameserver_Outgoing_Packet {
|
||||
std::string data;
|
||||
std::vector<uint8_t> data;
|
||||
|
||||
uint32 ip;
|
||||
uint16 port;
|
||||
};
|
||||
|
||||
struct Gameserver_Player_Info_t {
|
||||
std::chrono::steady_clock::time_point join_time;
|
||||
std::string name;
|
||||
uint32 score;
|
||||
};
|
||||
|
||||
class Steam_GameServer :
|
||||
public ISteamGameServer005,
|
||||
public ISteamGameServer008,
|
||||
|
@ -47,6 +56,7 @@ public ISteamGameServer
|
|||
bool logged_in = false;
|
||||
bool call_servers_disconnected = false;
|
||||
Gameserver server_data;
|
||||
std::vector<std::pair<CSteamID, Gameserver_Player_Info_t>> players;
|
||||
|
||||
uint32 flags;
|
||||
bool policy_response_called;
|
||||
|
@ -59,6 +69,9 @@ public:
|
|||
|
||||
Steam_GameServer(class Settings *settings, class Networking *network, class SteamCallBacks *callbacks);
|
||||
~Steam_GameServer();
|
||||
|
||||
std::vector<std::pair<CSteamID, Gameserver_Player_Info_t>>* get_players();
|
||||
|
||||
//
|
||||
// Basic server data. These properties, if set, must be set before before calling LogOn. They
|
||||
// may not be changed after logged in.
|
||||
|
@ -329,3 +342,5 @@ public:
|
|||
//
|
||||
void RunCallbacks();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -15,6 +15,9 @@
|
|||
License along with the Goldberg Emulator; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef __INCLUDED_STEAM_MATCHMAKING__
|
||||
#define __INCLUDED_STEAM_MATCHMAKING__
|
||||
|
||||
#include "base.h"
|
||||
|
||||
#define SEND_LOBBY_RATE 5.0
|
||||
|
@ -1479,3 +1482,5 @@ void Callback(Common_Message *msg)
|
|||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -15,6 +15,9 @@
|
|||
License along with the Goldberg Emulator; if not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef __INCLUDED_STEAM_UTILS__
|
||||
#define __INCLUDED_STEAM_UTILS__
|
||||
|
||||
#include "base.h"
|
||||
#include "local_storage.h"
|
||||
#include "../overlay_experimental/steam_overlay.h"
|
||||
|
@ -406,3 +409,5 @@ ESteamIPv6ConnectivityState GetIPv6ConnectivityState( ESteamIPv6ConnectivityProt
|
|||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
|
@ -45,7 +45,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
|
|||
}
|
||||
if (GetFileAttributesA(CurrentDirectory) == INVALID_FILE_ATTRIBUTES) {
|
||||
MessageBoxA(NULL, "Couldn't find the configuration file(ColdClientLoader.ini).", "ColdClientLoader", MB_ICONERROR);
|
||||
ExitProcess(NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
GetPrivateProfileStringA("SteamClient", "SteamClient64Dll", "", Client64Path, MAX_PATH, CurrentDirectory);
|
||||
|
@ -60,27 +60,23 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
|
|||
SetEnvironmentVariableA("SteamGameId", AppId);
|
||||
}
|
||||
|
||||
CHAR TMP[MAX_PATH] = { 0 };
|
||||
CHAR TMP[MAX_PATH] = {};
|
||||
if (!IsNotRelativePathOrRemoveFileName(Client64Path, false)) {
|
||||
ZeroMemory(TMP, sizeof(TMP));
|
||||
lstrcpyA(TMP, Client64Path);
|
||||
ZeroMemory(Client64Path, sizeof(Client64Path));
|
||||
GetFullPathNameA(TMP, MAX_PATH, Client64Path, NULL);
|
||||
}
|
||||
if (!IsNotRelativePathOrRemoveFileName(ClientPath, false)) {
|
||||
ZeroMemory(TMP, sizeof(TMP));
|
||||
lstrcpyA(TMP, ClientPath);
|
||||
ZeroMemory(ClientPath, sizeof(ClientPath));
|
||||
GetFullPathNameA(TMP, MAX_PATH, ClientPath, NULL);
|
||||
}
|
||||
if (!IsNotRelativePathOrRemoveFileName(ExeFile, false)) {
|
||||
ZeroMemory(TMP, sizeof(TMP));
|
||||
lstrcpyA(TMP, ExeFile);
|
||||
ZeroMemory(ExeFile, sizeof(ExeFile));
|
||||
GetFullPathNameA(TMP, MAX_PATH, ExeFile, NULL);
|
||||
}
|
||||
if (!IsNotRelativePathOrRemoveFileName(ExeRunDir, false)) {
|
||||
ZeroMemory(TMP, sizeof(TMP));
|
||||
lstrcpyA(TMP, ExeRunDir);
|
||||
ZeroMemory(ExeRunDir, sizeof(ExeRunDir));
|
||||
GetFullPathNameA(TMP, MAX_PATH, ExeRunDir, NULL);
|
||||
|
@ -88,17 +84,17 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
|
|||
|
||||
if (GetFileAttributesA(Client64Path) == INVALID_FILE_ATTRIBUTES) {
|
||||
MessageBoxA(NULL, "Couldn't find the requested SteamClient64Dll.", "ColdClientLoader", MB_ICONERROR);
|
||||
ExitProcess(NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (GetFileAttributesA(ClientPath) == INVALID_FILE_ATTRIBUTES) {
|
||||
MessageBoxA(NULL, "Couldn't find the requested SteamClientDll.", "ColdClientLoader", MB_ICONERROR);
|
||||
ExitProcess(NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (GetFileAttributesA(ExeFile) == INVALID_FILE_ATTRIBUTES) {
|
||||
MessageBoxA(NULL, "Couldn't find the requested Exe file.", "ColdClientLoader", MB_ICONERROR);
|
||||
ExitProcess(NULL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CHAR CommandLine[8192];
|
||||
|
@ -106,98 +102,65 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
|
|||
if (!ExeFile[0] || !CreateProcessA(ExeFile, CommandLine, NULL, NULL, TRUE, CREATE_SUSPENDED, NULL, ExeRunDir, &info, &processInfo))
|
||||
{
|
||||
MessageBoxA(NULL, "Unable to load the requested EXE file.", "ColdClientLoader", MB_ICONERROR);
|
||||
ExitProcess(NULL);
|
||||
return 0;
|
||||
}
|
||||
HKEY Registrykey;
|
||||
// Declare some variables to be used for Steam registry.
|
||||
DWORD UserId = 0x03100004771F810D & 0xffffffff;
|
||||
DWORD ProcessID = GetCurrentProcessId();
|
||||
|
||||
if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Valve\\Steam\\ActiveProcess", 0, KEY_ALL_ACCESS, &Registrykey) != ERROR_SUCCESS)
|
||||
bool orig_steam = false;
|
||||
DWORD keyType = REG_SZ;
|
||||
CHAR OrgSteamCDir[MAX_PATH] = { 0 };
|
||||
CHAR OrgSteamCDir64[MAX_PATH] = { 0 };
|
||||
DWORD Size1 = MAX_PATH;
|
||||
DWORD Size2 = MAX_PATH;
|
||||
if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Valve\\Steam\\ActiveProcess", 0, KEY_ALL_ACCESS, &Registrykey) == ERROR_SUCCESS)
|
||||
{
|
||||
orig_steam = true;
|
||||
// Get original values to restore later.
|
||||
RegQueryValueExA(Registrykey, "SteamClientDll", 0, &keyType, (LPBYTE)& OrgSteamCDir, &Size1);
|
||||
RegQueryValueExA(Registrykey, "SteamClientDll64", 0, &keyType, (LPBYTE)& OrgSteamCDir64, &Size2);
|
||||
} else {
|
||||
if (RegCreateKeyExA(HKEY_CURRENT_USER, "Software\\Valve\\Steam\\ActiveProcess", 0, 0, REG_OPTION_NON_VOLATILE,
|
||||
KEY_ALL_ACCESS, NULL, &Registrykey, NULL) != ERROR_SUCCESS)
|
||||
{
|
||||
MessageBoxA(NULL, "Unable to patch Steam process informations on the Windows registry.", "ColdClientLoader", MB_ICONERROR);
|
||||
TerminateProcess(processInfo.hProcess, NULL);
|
||||
ExitProcess(NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// Set values to Windows registry.
|
||||
RegSetValueExA(Registrykey, "ActiveUser", NULL, REG_DWORD, (LPBYTE)& UserId, sizeof(DWORD));
|
||||
RegSetValueExA(Registrykey, "pid", NULL, REG_DWORD, (LPBYTE)& ProcessID, sizeof(DWORD));
|
||||
|
||||
{
|
||||
// Before saving to the registry check again if the path was valid and if the file exist
|
||||
if (GetFileAttributesA(ClientPath) != INVALID_FILE_ATTRIBUTES) {
|
||||
RegSetValueExA(Registrykey, "SteamClientDll", NULL, REG_SZ, (LPBYTE)ClientPath, (DWORD)lstrlenA(ClientPath) + 1);
|
||||
}
|
||||
else {
|
||||
RegSetValueExA(Registrykey, "SteamClientDll", NULL, REG_SZ, (LPBYTE)"", 0);
|
||||
}
|
||||
if (GetFileAttributesA(Client64Path) != INVALID_FILE_ATTRIBUTES) {
|
||||
RegSetValueExA(Registrykey, "SteamClientDll64", NULL, REG_SZ, (LPBYTE)Client64Path, (DWORD)lstrlenA(Client64Path) + 1);
|
||||
}
|
||||
else {
|
||||
RegSetValueExA(Registrykey, "SteamClientDll64", NULL, REG_SZ, (LPBYTE)"", 0);
|
||||
}
|
||||
}
|
||||
RegSetValueExA(Registrykey, "Universe", NULL, REG_SZ, (LPBYTE)"Public", (DWORD)lstrlenA("Public") + 1);
|
||||
|
||||
// Close the HKEY Handle.
|
||||
RegCloseKey(Registrykey);
|
||||
|
||||
ResumeThread(processInfo.hThread);
|
||||
WaitForSingleObject(processInfo.hThread, INFINITE);
|
||||
CloseHandle(processInfo.hProcess);
|
||||
CloseHandle(processInfo.hThread);
|
||||
ExitProcess(NULL);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
||||
// Set values to Windows registry.
|
||||
RegSetValueExA(Registrykey, "ActiveUser", NULL, REG_DWORD, (LPBYTE)& UserId, sizeof(DWORD));
|
||||
RegSetValueExA(Registrykey, "pid", NULL, REG_DWORD, (LPBYTE)& ProcessID, sizeof(DWORD));
|
||||
|
||||
{
|
||||
DWORD keyType = REG_SZ;
|
||||
CHAR OrgSteamCDir[MAX_PATH] = { 0 };
|
||||
CHAR OrgSteamCDir64[MAX_PATH] = { 0 };
|
||||
DWORD Size1 = MAX_PATH;
|
||||
DWORD Size2 = MAX_PATH;
|
||||
|
||||
// Get original values to restore later.
|
||||
RegQueryValueExA(Registrykey, "SteamClientDll", 0, &keyType, (LPBYTE)& OrgSteamCDir, &Size1);
|
||||
RegQueryValueExA(Registrykey, "SteamClientDll64", 0, &keyType, (LPBYTE)& OrgSteamCDir64, &Size2);
|
||||
|
||||
// Set values to Windows registry.
|
||||
RegSetValueExA(Registrykey, "ActiveUser", NULL, REG_DWORD, (LPBYTE)& UserId, sizeof(DWORD));
|
||||
RegSetValueExA(Registrykey, "pid", NULL, REG_DWORD, (LPBYTE)& ProcessID, sizeof(DWORD));
|
||||
|
||||
|
||||
{
|
||||
// Before saving to the registry check again if the path was valid and if the file exist
|
||||
if (GetFileAttributesA(ClientPath) != INVALID_FILE_ATTRIBUTES) {
|
||||
RegSetValueExA(Registrykey, "SteamClientDll", NULL, REG_SZ, (LPBYTE)ClientPath, (DWORD)lstrlenA(ClientPath) + 1);
|
||||
}
|
||||
else {
|
||||
RegSetValueExA(Registrykey, "SteamClientDll", NULL, REG_SZ, (LPBYTE)"", 0);
|
||||
}
|
||||
if (GetFileAttributesA(Client64Path) != INVALID_FILE_ATTRIBUTES) {
|
||||
RegSetValueExA(Registrykey, "SteamClientDll64", NULL, REG_SZ, (LPBYTE)Client64Path, (DWORD)lstrlenA(Client64Path) + 1);
|
||||
}
|
||||
else {
|
||||
RegSetValueExA(Registrykey, "SteamClientDll64", NULL, REG_SZ, (LPBYTE)"", 0);
|
||||
}
|
||||
// Before saving to the registry check again if the path was valid and if the file exist
|
||||
if (GetFileAttributesA(ClientPath) != INVALID_FILE_ATTRIBUTES) {
|
||||
RegSetValueExA(Registrykey, "SteamClientDll", NULL, REG_SZ, (LPBYTE)ClientPath, (DWORD)lstrlenA(ClientPath) + 1);
|
||||
}
|
||||
RegSetValueExA(Registrykey, "Universe", NULL, REG_SZ, (LPBYTE)"Public", (DWORD)lstrlenA("Public") + 1);
|
||||
else {
|
||||
RegSetValueExA(Registrykey, "SteamClientDll", NULL, REG_SZ, (LPBYTE)"", 0);
|
||||
}
|
||||
if (GetFileAttributesA(Client64Path) != INVALID_FILE_ATTRIBUTES) {
|
||||
RegSetValueExA(Registrykey, "SteamClientDll64", NULL, REG_SZ, (LPBYTE)Client64Path, (DWORD)lstrlenA(Client64Path) + 1);
|
||||
}
|
||||
else {
|
||||
RegSetValueExA(Registrykey, "SteamClientDll64", NULL, REG_SZ, (LPBYTE)"", 0);
|
||||
}
|
||||
}
|
||||
RegSetValueExA(Registrykey, "Universe", NULL, REG_SZ, (LPBYTE)"Public", (DWORD)lstrlenA("Public") + 1);
|
||||
|
||||
// Close the HKEY Handle.
|
||||
RegCloseKey(Registrykey);
|
||||
// Close the HKEY Handle.
|
||||
RegCloseKey(Registrykey);
|
||||
|
||||
ResumeThread(processInfo.hThread);
|
||||
WaitForSingleObject(processInfo.hThread, INFINITE);
|
||||
CloseHandle(processInfo.hProcess);
|
||||
CloseHandle(processInfo.hThread);
|
||||
ResumeThread(processInfo.hThread);
|
||||
WaitForSingleObject(processInfo.hThread, INFINITE);
|
||||
CloseHandle(processInfo.hProcess);
|
||||
CloseHandle(processInfo.hThread);
|
||||
|
||||
if (orig_steam) {
|
||||
if (RegOpenKeyExA(HKEY_CURRENT_USER, "Software\\Valve\\Steam\\ActiveProcess", 0, KEY_ALL_ACCESS, &Registrykey) == ERROR_SUCCESS)
|
||||
{
|
||||
// Restore the values.
|
||||
|
@ -207,9 +170,7 @@ int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance
|
|||
// Close the HKEY Handle.
|
||||
RegCloseKey(Registrykey);
|
||||
}
|
||||
ExitProcess(NULL);
|
||||
}
|
||||
|
||||
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user