1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2026-01-15 19:13:07 +01:00

Refactor memory handling in ServerList

This commit is contained in:
Ted John
2018-01-26 13:13:51 +00:00
parent 04ea015302
commit 5d51676523
3 changed files with 82 additions and 121 deletions

View File

@@ -15,7 +15,9 @@
#pragma endregion
#include <mutex>
#include <vector>
#include <openrct2/config/Config.h>
#include <openrct2/core/String.hpp>
#include <openrct2/network/network.h>
#include <openrct2/network/ServerList.h>
#include <openrct2/Context.h>
@@ -35,8 +37,7 @@
#define ITEM_HEIGHT (3 + 9 + 3)
static char _playerName[32 + 1];
static server_entry *_serverEntries = nullptr;
static sint32 _numServerEntries = 0;
static std::vector<server_entry> _serverEntries;
static std::mutex _mutex;
static uint32 _numPlayersOnline = 0;
static rct_string_id status_text = STR_SERVER_LIST_CONNECTING;
@@ -119,13 +120,12 @@ enum {
};
static sint32 _hoverButtonIndex = -1;
static char * _version = nullptr;
static std::string _version;
static void server_list_get_item_button(sint32 buttonIndex, sint32 x, sint32 y, sint32 width, sint32 *outX, sint32 *outY);
static void server_list_load_server_entries();
static void server_list_save_server_entries();
static void dispose_server_entry_list();
static void dispose_server_entry(server_entry *serverInfo);
static server_entry* add_server_entry(char *address);
static void remove_server_entry(sint32 index);
static void sort_servers();
@@ -172,7 +172,7 @@ rct_window * window_server_list_open()
safe_strcpy(_playerName, gConfigNetwork.player_name, sizeof(_playerName));
server_list_load_server_entries();
window->no_list_items = _numServerEntries;
window->no_list_items = (uint16)_serverEntries.size();
fetch_servers();
@@ -196,13 +196,13 @@ static void window_server_list_mouseup(rct_window *w, rct_widgetindex widgetInde
break;
case WIDX_LIST:{
sint32 serverIndex = w->selected_list_item;
if (serverIndex >= 0 && serverIndex < _numServerEntries) {
if (strcmp(_serverEntries[serverIndex].version, NETWORK_STREAM_ID) != 0 && strcmp(_serverEntries[serverIndex].version, "") != 0) {
set_format_arg(0, void *, _serverEntries[serverIndex].version);
if (serverIndex >= 0 && serverIndex < _serverEntries.size()) {
if (_serverEntries[serverIndex].version != NETWORK_STREAM_ID && _serverEntries[serverIndex].version != "") {
set_format_arg(0, void *, _serverEntries[serverIndex].version.c_str());
context_show_error(STR_UNABLE_TO_CONNECT_TO_SERVER, STR_MULTIPLAYER_INCORRECT_SOFTWARE_VERSION);
break;
}
char *serverAddress = _serverEntries[serverIndex].address;
char *serverAddress = _strdup(_serverEntries[serverIndex].address.c_str());
join_server(serverAddress);
}
}break;
@@ -227,14 +227,14 @@ static void window_server_list_dropdown(rct_window *w, rct_widgetindex widgetInd
{
sint32 serverIndex = w->selected_list_item;
if (serverIndex < 0) return;
if (serverIndex >= _numServerEntries) return;
if (serverIndex >= _serverEntries.size()) return;
char *serverAddress = _serverEntries[serverIndex].address;
char *serverAddress = _strdup(_serverEntries[serverIndex].address.c_str());
switch (dropdownIndex) {
case DDIDX_JOIN:
if (strcmp(_serverEntries[serverIndex].version, NETWORK_STREAM_ID) != 0 && strcmp(_serverEntries[serverIndex].version, "") != 0) {
set_format_arg(0, void *, _serverEntries[serverIndex].version);
if (_serverEntries[serverIndex].version != NETWORK_STREAM_ID && _serverEntries[serverIndex].version != "") {
set_format_arg(0, void *, _serverEntries[serverIndex].version.c_str());
context_show_error(STR_UNABLE_TO_CONNECT_TO_SERVER, STR_MULTIPLAYER_INCORRECT_SOFTWARE_VERSION);
break;
}
@@ -268,7 +268,7 @@ static void window_server_list_scroll_mousedown(rct_window *w, sint32 scrollInde
{
sint32 serverIndex = w->selected_list_item;
if (serverIndex < 0) return;
if (serverIndex >= _numServerEntries) return;
if (serverIndex >= _serverEntries.size()) return;
rct_widget *listWidget = &w->widgets[WIDX_LIST];
sint32 ddx = w->x + listWidget->left + x + 2 - w->scrolls[0].h_left;
@@ -362,7 +362,7 @@ static void window_server_list_textinput(rct_window *w, rct_widgetindex widgetIn
static void window_server_list_invalidate(rct_window *w)
{
set_format_arg(0, char *, _version);
set_format_arg(0, char *, _version.c_str());
window_server_list_widgets[WIDX_BACKGROUND].right = w->width - 1;
window_server_list_widgets[WIDX_BACKGROUND].bottom = w->height - 1;
window_server_list_widgets[WIDX_TITLE].right = w->width - 2;
@@ -386,7 +386,7 @@ static void window_server_list_invalidate(rct_window *w)
window_server_list_widgets[WIDX_START_SERVER].top = buttonTop;
window_server_list_widgets[WIDX_START_SERVER].bottom = buttonBottom;
w->no_list_items = _numServerEntries;
w->no_list_items = (uint16)_serverEntries.size();
}
static void window_server_list_paint(rct_window *w, rct_drawpixelinfo *dpi)
@@ -431,10 +431,10 @@ static void window_server_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi
}
// Draw server information
if (highlighted && !str_is_null_or_empty(serverDetails->description)) {
gfx_draw_string(dpi, serverDetails->description, colour, 3, y + 3);
if (highlighted && !serverDetails->description.empty()) {
gfx_draw_string(dpi, serverDetails->description.c_str(), colour, 3, y + 3);
} else {
gfx_draw_string(dpi, serverDetails->name, colour, 3, y + 3);
gfx_draw_string(dpi, serverDetails->name.c_str(), colour, 3, y + 3);
}
sint32 right = width - 3 - 14;
@@ -442,12 +442,12 @@ static void window_server_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi
// Draw compatibility icon
right -= 10;
sint32 compatibilitySpriteId;
if (str_is_null_or_empty(serverDetails->version)) {
if (serverDetails->version.empty()) {
// Server not online...
compatibilitySpriteId = SPR_G2_RCT1_CLOSE_BUTTON_0;
} else {
// Server online... check version
bool correctVersion = strcmp(serverDetails->version, NETWORK_STREAM_ID) == 0;
bool correctVersion = serverDetails->version == NETWORK_STREAM_ID;
compatibilitySpriteId = correctVersion ? SPR_G2_RCT1_OPEN_BUTTON_2 : SPR_G2_RCT1_CLOSE_BUTTON_2;
}
gfx_draw_sprite(dpi, compatibilitySpriteId, right, y + 1, 0);
@@ -481,12 +481,10 @@ static void server_list_get_item_button(sint32 buttonIndex, sint32 x, sint32 y,
static void server_list_load_server_entries()
{
uint32 numEntries;
server_entry * entries;
if (server_list_read(&numEntries, &entries)) {
auto entries = server_list_read();
{
std::lock_guard<std::mutex> guard(_mutex);
dispose_server_entry_list();
_numServerEntries = numEntries;
_serverEntries = entries;
sort_servers();
}
@@ -496,7 +494,7 @@ static void server_list_save_server_entries()
{
// Get total number of favourite servers
sint32 count = 0;
for (sint32 i = 0; i < _numServerEntries; i++) {
for (sint32 i = 0; i < _serverEntries.size(); i++) {
server_entry *serverInfo = &_serverEntries[i];
if (serverInfo->favourite) {
count++;
@@ -506,7 +504,7 @@ static void server_list_save_server_entries()
// Create temporary list of just favourite servers
server_entry * entries = (server_entry *)calloc(count, sizeof(server_entry));
sint32 eindex = 0;
for (sint32 i = 0; i < _numServerEntries; i++) {
for (sint32 i = 0; i < _serverEntries.size(); i++) {
server_entry *serverInfo = &_serverEntries[i];
if (serverInfo->favourite) {
entries[eindex++] = *serverInfo;
@@ -514,7 +512,7 @@ static void server_list_save_server_entries()
}
// Save servers
server_list_write(count, entries);
server_list_write(_serverEntries);
// Free temporary list
free(entries);
@@ -522,60 +520,36 @@ static void server_list_save_server_entries()
static void dispose_server_entry_list()
{
if (_serverEntries != nullptr) {
for (sint32 i = 0; i < _numServerEntries; i++) {
dispose_server_entry(&_serverEntries[i]);
}
SafeFree(_serverEntries);
}
_numServerEntries = 0;
}
static void dispose_server_entry(server_entry *serverInfo)
{
SafeFree(serverInfo->address);
SafeFree(serverInfo->name);
SafeFree(serverInfo->description);
SafeFree(serverInfo->version);
_serverEntries.clear();
_serverEntries.shrink_to_fit();
}
static server_entry* add_server_entry(char *address)
{
for (sint32 i = 0; i < _numServerEntries; i++) {
if (strcmp(_serverEntries[i].address, address) == 0) {
for (sint32 i = 0; i < _serverEntries.size(); i++)
{
if (_serverEntries[i].address == address)
{
return &_serverEntries[i];
}
}
_numServerEntries++;
if (_serverEntries == nullptr) {
_serverEntries = (server_entry *)malloc(_numServerEntries * sizeof(server_entry));
} else {
_serverEntries = (server_entry *)realloc(_serverEntries, _numServerEntries * sizeof(server_entry));
}
sint32 index = _numServerEntries - 1;
server_entry* newserver = &_serverEntries[index];
newserver->address = _strdup(address);
newserver->name = _strdup(address);
newserver->requiresPassword = false;
newserver->description = _strdup("");
newserver->version = _strdup("");
newserver->favourite = false;
newserver->players = 0;
newserver->maxplayers = 0;
return newserver;
server_entry newserver;
newserver.address = _strdup(address);
newserver.name = _strdup(address);
newserver.requiresPassword = false;
newserver.description = _strdup("");
newserver.version = _strdup("");
newserver.favourite = false;
newserver.players = 0;
newserver.maxplayers = 0;
_serverEntries.push_back(newserver);
return &_serverEntries.back();
}
static void remove_server_entry(sint32 index)
{
if (_numServerEntries > index) {
sint32 serversToMove = _numServerEntries - index - 1;
memmove(&_serverEntries[index], &_serverEntries[index + 1], serversToMove * sizeof(server_entry));
_numServerEntries--;
_serverEntries = (server_entry *)realloc(_serverEntries, _numServerEntries * sizeof(server_entry));
}
_serverEntries.erase(_serverEntries.begin() + index);
}
static sint32 server_compare(const void *a, const void *b)
@@ -590,8 +564,8 @@ static sint32 server_compare(const void *a, const void *b)
}
// Then by version
bool serverACompatible = strcmp(serverA->version, NETWORK_STREAM_ID) == 0;
bool serverBCompatible = strcmp(serverB->version, NETWORK_STREAM_ID) == 0;
bool serverACompatible = serverA->version == NETWORK_STREAM_ID;
bool serverBCompatible = serverB->version == NETWORK_STREAM_ID;
if (serverACompatible != serverBCompatible) {
if (serverACompatible) return -1;
else return 1;
@@ -604,15 +578,12 @@ static sint32 server_compare(const void *a, const void *b)
}
// Then by name
return _strcmpi(serverA->name, serverB->name);
return String::Equals(serverA->name, serverB->name, true);
}
static void sort_servers()
{
if (_serverEntries == nullptr) {
return;
}
qsort(_serverEntries, _numServerEntries, sizeof(server_entry), server_compare);
qsort(_serverEntries.data(), _serverEntries.size(), sizeof(server_entry), server_compare);
}
static char *substr(char *start, sint32 length)
@@ -657,7 +628,7 @@ static void join_server(char *address)
static uint32 get_total_player_count()
{
uint32 numPlayers = 0;
for (sint32 i = 0; i < _numServerEntries; i++) {
for (sint32 i = 0; i < _serverEntries.size(); i++) {
server_entry *serverDetails = &_serverEntries[i];
numPlayers += serverDetails->players;
}
@@ -674,7 +645,7 @@ static void fetch_servers()
{
std::lock_guard<std::mutex> guard(_mutex);
for (sint32 i = 0; i < _numServerEntries; i++) {
for (sint32 i = 0; i < _serverEntries.size(); i++) {
if (!_serverEntries[i].favourite) {
remove_server_entry(i);
i = 0;
@@ -760,13 +731,10 @@ static void fetch_servers_callback(http_response_t* response)
{
std::lock_guard<std::mutex> guard(_mutex);
server_entry* newserver = add_server_entry(address);
SafeFree(newserver->name);
SafeFree(newserver->description);
SafeFree(newserver->version);
newserver->name = _strdup(json_string_value(name));
newserver->name = json_string_value(name);
newserver->requiresPassword = json_is_true(requiresPassword);
newserver->description = _strdup(description == nullptr ? "" : json_string_value(description));
newserver->version = _strdup(json_string_value(version));
newserver->description = (description == nullptr ? "" : json_string_value(description));
newserver->version = json_string_value(version);
newserver->players = (uint8)json_integer_value(players);
newserver->maxplayers = (uint8)json_integer_value(maxPlayers);
}

View File

@@ -14,14 +14,15 @@
*****************************************************************************/
#pragma endregion
#include <vector>
#include "../core/FileStream.hpp"
#include "../core/Memory.hpp"
#include "../core/Path.hpp"
#include "../core/String.hpp"
#include "../platform/platform.h"
#include "ServerList.h"
#include "../platform/platform.h"
bool server_list_read(uint32 * outNumEntries, server_entry * * outEntries)
std::vector<server_entry> server_list_read()
{
log_verbose("server_list_read(...)");
@@ -29,13 +30,12 @@ bool server_list_read(uint32 * outNumEntries, server_entry * * outEntries)
platform_get_user_directory(path, nullptr, sizeof(path));
Path::Append(path, sizeof(path), "servers.cfg");
uint32 numEntries = 0;
server_entry * entries = nullptr;
std::vector<server_entry> entries;
try
{
auto fs = FileStream(path, FILE_MODE_OPEN);
numEntries = fs.ReadValue<uint32>();
entries = Memory::AllocateArray<server_entry>(numEntries);
auto numEntries = fs.ReadValue<uint32>();
entries.resize(numEntries);
// Load each server entry
for (uint32 i = 0; i < numEntries; i++)
@@ -53,19 +53,14 @@ bool server_list_read(uint32 * outNumEntries, server_entry * * outEntries)
}
catch (const std::exception &)
{
Memory::FreeArray(entries, numEntries);
numEntries = 0;
entries = nullptr;
entries = std::vector<server_entry>();
}
*outNumEntries = numEntries;
*outEntries = entries;
return entries != nullptr;
return entries;
}
bool server_list_write(uint32 numEntries, server_entry * entries)
bool server_list_write(const std::vector<server_entry> &entries)
{
log_verbose("server_list_write(%d, 0x%p)", numEntries, entries);
log_verbose("server_list_write(%d, 0x%p)", entries.size(), entries.data());
utf8 path[MAX_PATH];
platform_get_user_directory(path, nullptr, sizeof(path));
@@ -74,15 +69,14 @@ bool server_list_write(uint32 numEntries, server_entry * entries)
try
{
auto fs = FileStream(path, FILE_MODE_WRITE);
fs.WriteValue<uint32>(numEntries);
fs.WriteValue<uint32>((uint32)entries.size());
// Write each server entry
for (uint32 i = 0; i < numEntries; i++)
for (const auto &entry : entries)
{
server_entry * serverInfo = &entries[i];
fs.WriteString(serverInfo->address);
fs.WriteString(serverInfo->name);
fs.WriteString(serverInfo->description);
fs.WriteString(entry.address);
fs.WriteString(entry.name);
fs.WriteString(entry.description);
}
return true;
}
@@ -91,4 +85,3 @@ bool server_list_write(uint32 numEntries, server_entry * entries)
return false;
}
}

View File

@@ -16,20 +16,20 @@
#pragma once
#include <vector>
#include "../common.h"
typedef struct server_entry
struct server_entry
{
char * address;
utf8 * name;
bool requiresPassword;
utf8 * description;
char * version;
bool favourite;
uint8 players;
uint8 maxplayers;
} server_entry;
bool server_list_read(uint32 * outNumEntries, server_entry * * outEntries);
bool server_list_write(uint32 numEntries, server_entry * entries);
std::string address;
std::string name;
bool requiresPassword;
std::string description;
std::string version;
bool favourite;
uint8 players;
uint8 maxplayers;
};
std::vector<server_entry> server_list_read();
bool server_list_write(const std::vector<server_entry> &entries);