1
0
mirror of https://github.com/OpenRCT2/OpenRCT2 synced 2025-12-23 15:52:55 +01:00

master server list

This commit is contained in:
zsilencer
2015-11-03 16:31:09 -07:00
committed by IntelOrca
parent 9acfd27735
commit 1e9381ef97
12 changed files with 436 additions and 114 deletions

View File

@@ -3899,6 +3899,7 @@ STR_5557 :Stay connected after desynchronisation (Multiplayer)
STR_5558 :A restart is required for this setting to take effect
STR_5559 :10 min. inspections
STR_5560 :{SMALLFONT}{BLACK}Sets the inspection time to 'Every 10 minutes' on all rides
<<<<<<< HEAD
STR_5561 :Failed to load language file
STR_5562 :WARNING!
STR_5563 :This feature is currently unstable, take extra caution.
@@ -3908,6 +3909,13 @@ STR_5566 :Password:
STR_5567 :Advertise
STR_5568 :Password Required
STR_5569 :This server requires a password
STR_5570 :Fetch Servers
STR_5571 :Join Game
STR_5572 :Add To Favorites
STR_5573 :Remove From Favorites
STR_5574 :Server Name:
STR_5575 :Max Players:
STR_5576 :Port:
#####################
# Rides/attractions #

View File

@@ -241,6 +241,9 @@ config_property_definition _networkDefinitions[] = {
{ offsetof(network_configuration, default_port), "default_port", CONFIG_VALUE_TYPE_UINT32, NETWORK_DEFAULT_PORT, NULL },
{ offsetof(network_configuration, stay_connected), "stay_connected", CONFIG_VALUE_TYPE_BOOLEAN, true, NULL },
{ offsetof(network_configuration, advertise), "advertise", CONFIG_VALUE_TYPE_BOOLEAN, false, NULL },
{ offsetof(network_configuration, maxplayers), "maxplayers", CONFIG_VALUE_TYPE_UINT8, 16, NULL },
{ offsetof(network_configuration, server_name), "server_name", CONFIG_VALUE_TYPE_STRING, {.value_string = "Server" }, NULL },
{ offsetof(network_configuration, master_url), "master_url", CONFIG_VALUE_TYPE_STRING, {.value_string = OPENRCT2_MASTER_URL }, NULL }
};
config_section_definition _sectionDefinitions[] = {

View File

@@ -215,6 +215,9 @@ typedef struct {
uint32 default_port;
uint8 stay_connected;
uint8 advertise;
uint8 maxplayers;
utf8string server_name;
utf8string master_url;
} network_configuration;
typedef struct theme_window {

View File

@@ -261,7 +261,7 @@ void game_update()
numUpdates = clamp(1, numUpdates, 4);
}
if (network_get_mode() == NETWORK_MODE_CLIENT && network_get_status() == NETWORK_STATUS_CONNECTED) {
if (network_get_mode() == NETWORK_MODE_CLIENT && network_get_status() == NETWORK_STATUS_CONNECTED && network_get_authstatus() == NETWORK_AUTH_OK) {
if (network_get_server_tick() - RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) >= 10) {
// make sure client doesn't fall behind the server too much
numUpdates += 10;
@@ -340,7 +340,7 @@ void game_logic_update()
gInUpdateCode = true;
///////////////////////////
network_update();
if (network_get_mode() == NETWORK_MODE_CLIENT && network_get_status() == NETWORK_STATUS_CONNECTED) {
if (network_get_mode() == NETWORK_MODE_CLIENT && network_get_status() == NETWORK_STATUS_CONNECTED && network_get_authstatus() == NETWORK_AUTH_OK) {
if (RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) >= network_get_server_tick()) {
// dont run past the server
return;

View File

@@ -60,7 +60,8 @@ void chat_update()
void chat_draw()
{
if (network_get_mode() == NETWORK_MODE_NONE) {
if (network_get_mode() == NETWORK_MODE_NONE || network_get_status() != NETWORK_STATUS_CONNECTED || network_get_authstatus() != NETWORK_AUTH_OK) {
gChatOpen = false;
return;
}
rct_drawpixelinfo *dpi = (rct_drawpixelinfo*)RCT2_ADDRESS_SCREEN_DPI;
@@ -102,7 +103,7 @@ void chat_history_add(const char *src)
{
int index = _chatHistoryIndex % CHAT_HISTORY_SIZE;
memset(_chatHistory[index], 0, CHAT_INPUT_SIZE);
memcpy(_chatHistory[index], src, min(strlen(src), CHAT_INPUT_SIZE));
memcpy(_chatHistory[index], src, min(strlen(src), CHAT_INPUT_SIZE - 1));
_chatHistoryTime[index] = SDL_GetTicks();
_chatHistoryIndex++;
Mixer_Play_Effect(SOUND_NEWS_ITEM, 0, SDL_MIX_MAXVOLUME, 0, 1.5f, true);

View File

@@ -2158,6 +2158,13 @@ enum {
STR_ADVERTISE = 5567,
STR_PASSWORD_REQUIRED = 5568,
STR_PASSWORD_REQUIRED_DESC = 5569,
STR_FETCH_SERVERS = 5570,
STR_JOIN_GAME = 5571,
STR_ADD_TO_FAVORITES = 5572,
STR_REMOVE_FROM_FAVORITES = 5573,
STR_SERVER_NAME = 5574,
STR_MAX_PLAYERS = 5575,
STR_PORT = 5576,
// Have to include resource strings (from scenarios and objects) for the time being now that language is partially working
STR_COUNT = 32768

View File

@@ -41,6 +41,7 @@ extern "C" {
#include "../interface/window.h"
#include "../localisation/date.h"
#include "../localisation/localisation.h"
#include "../network/http.h"
#include "../scenario.h"
#include "../windows/error.h"
#include "../util/util.h"
@@ -67,6 +68,7 @@ enum {
NETWORK_COMMAND_PING,
NETWORK_COMMAND_PINGLIST,
NETWORK_COMMAND_SETDISCONNECTMSG,
NETWORK_COMMAND_GAMEINFO,
NETWORK_COMMAND_MAX,
NETWORK_COMMAND_INVALID = -1
};
@@ -161,8 +163,8 @@ bool NetworkPacket::CommandRequiresAuth()
{
switch (GetCommand()) {
case NETWORK_COMMAND_PING:
return false;
case NETWORK_COMMAND_AUTH:
case NETWORK_COMMAND_GAMEINFO:
return false;
default:
return true;
@@ -254,11 +256,15 @@ bool NetworkConnection::SendPacket(NetworkPacket& packet)
return false;
}
void NetworkConnection::QueuePacket(std::unique_ptr<NetworkPacket> packet)
void NetworkConnection::QueuePacket(std::unique_ptr<NetworkPacket> packet, bool front)
{
if (authstatus == NETWORK_AUTH_OK || !packet->CommandRequiresAuth()) {
packet->size = (uint16)packet->data->size();
outboundpackets.push_back(std::move(packet));
if (front) {
outboundpackets.push_front(std::move(packet));
} else {
outboundpackets.push_back(std::move(packet));
}
}
}
@@ -378,7 +384,7 @@ Network::Network()
status = NETWORK_STATUS_NONE;
last_tick_sent_time = 0;
last_ping_sent_time = 0;
strcpy(password, "");
last_advertise_time = 0;
client_command_handlers.resize(NETWORK_COMMAND_MAX, 0);
client_command_handlers[NETWORK_COMMAND_AUTH] = &Network::Client_Handle_AUTH;
client_command_handlers[NETWORK_COMMAND_MAP] = &Network::Client_Handle_MAP;
@@ -394,6 +400,7 @@ Network::Network()
server_command_handlers[NETWORK_COMMAND_CHAT] = &Network::Server_Handle_CHAT;
server_command_handlers[NETWORK_COMMAND_GAMECMD] = &Network::Server_Handle_GAMECMD;
server_command_handlers[NETWORK_COMMAND_PING] = &Network::Server_Handle_PING;
server_command_handlers[NETWORK_COMMAND_GAMEINFO] = &Network::Server_Handle_GAMEINFO;
}
Network::~Network()
@@ -447,6 +454,10 @@ void Network::Close()
bool Network::BeginClient(const char* host, unsigned short port)
{
if (GetMode() != NETWORK_MODE_NONE) {
return false;
}
Close();
if (!Init())
return false;
@@ -508,6 +519,10 @@ bool Network::BeginServer(unsigned short port, const char* address)
printf("Ready for clients...\n");
mode = NETWORK_MODE_SERVER;
status = NETWORK_STATUS_CONNECTED;
listening_port = port;
Advertise();
return true;
}
@@ -566,14 +581,15 @@ void Network::UpdateServer()
}
}
if (SDL_TICKS_PASSED(SDL_GetTicks(), last_tick_sent_time + 25)) {
last_tick_sent_time = SDL_GetTicks();
Server_Send_TICK();
}
if (SDL_TICKS_PASSED(SDL_GetTicks(), last_ping_sent_time + 3000)) {
last_ping_sent_time = SDL_GetTicks();
Server_Send_PING();
Server_Send_PINGLIST();
}
if (SDL_TICKS_PASSED(SDL_GetTicks(), last_advertise_time + 60000)) {
Advertise();
}
SOCKET socket = accept(listening_socket, NULL, NULL);
if (socket == INVALID_SOCKET) {
if (LAST_SOCKET_ERROR() != EWOULDBLOCK) {
@@ -659,21 +675,19 @@ void Network::UpdateClient()
if (error == 0) {
status = NETWORK_STATUS_CONNECTED;
server_connection.ResetLastPacketTime();
Client_Send_AUTH(OPENRCT2_VERSION, gConfigNetwork.player_name, "");
Client_Send_AUTH(gConfigNetwork.player_name, "");
window_network_status_open("Authenticating...");
}
}
}break;
case NETWORK_STATUS_CONNECTED:
if (!ProcessConnection(server_connection)) {
char errormsg[256];
char reason[100];
reason[0] = 0;
std::string errormsg = "Disconnected";
if (server_connection.last_disconnect_reason) {
sprintf(reason, ": %s", server_connection.last_disconnect_reason);
errormsg += ": ";
errormsg += server_connection.last_disconnect_reason;
}
sprintf(errormsg, "Disconnected%s", reason);
window_network_status_open(errormsg);
window_network_status_open(errormsg.c_str());
Close();
}
ProcessGameCommandQueue();
@@ -722,10 +736,10 @@ const char* Network::FormatChat(NetworkPlayer* fromplayer, const char* text)
return formatted;
}
void Network::SendPacketToClients(NetworkPacket& packet)
void Network::SendPacketToClients(NetworkPacket& packet, bool front)
{
for (auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) {
(*it)->QueuePacket(std::move(NetworkPacket::Duplicate(packet)));
(*it)->QueuePacket(std::move(NetworkPacket::Duplicate(packet)), front);
}
}
@@ -765,14 +779,32 @@ void Network::KickPlayer(int playerId)
void Network::SetPassword(const char* password)
{
safe_strncpy(Network::password, password, sizeof(Network::password));
Network::password = password;
}
void Network::Client_Send_AUTH(const char* gameversion, const char* name, const char* password)
void Network::ShutdownClient()
{
if (GetMode() == NETWORK_MODE_CLIENT) {
shutdown(server_connection.socket, SHUT_RDWR);
}
}
void Network::Advertise()
{
if (gConfigNetwork.advertise && strlen(gConfigNetwork.master_url) > 0) {
last_advertise_time = SDL_GetTicks();
#ifndef DISABLE_HTTP
std::string url = gConfigNetwork.master_url + std::string("?port=") + std::to_string(listening_port);
http_request_json_async(url.c_str(), [](http_json_response *response)->void{});
#endif
}
}
void Network::Client_Send_AUTH(const char* name, const char* password)
{
std::unique_ptr<NetworkPacket> packet = std::move(NetworkPacket::Allocate());
*packet << (uint32)NETWORK_COMMAND_AUTH;
packet->WriteString(gameversion);
packet->WriteString(OPENRCT2_VERSION);
packet->WriteString(name);
packet->WriteString(password);
server_connection.authstatus = NETWORK_AUTH_REQUESTED;
@@ -820,7 +852,7 @@ void Network::Client_Send_CHAT(const char* text)
{
std::unique_ptr<NetworkPacket> packet = std::move(NetworkPacket::Allocate());
*packet << (uint32)NETWORK_COMMAND_CHAT;
packet->Write((uint8*)text, strlen(text) + 1);
packet->WriteString(text);
server_connection.QueuePacket(std::move(packet));
}
@@ -828,7 +860,7 @@ void Network::Server_Send_CHAT(const char* text)
{
std::unique_ptr<NetworkPacket> packet = std::move(NetworkPacket::Allocate());
*packet << (uint32)NETWORK_COMMAND_CHAT;
packet->Write((uint8*)text, strlen(text) + 1);
packet->WriteString(text);
SendPacketToClients(*packet);
}
@@ -848,6 +880,7 @@ void Network::Server_Send_GAMECMD(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx
void Network::Server_Send_TICK()
{
last_tick_sent_time = SDL_GetTicks();
std::unique_ptr<NetworkPacket> packet = std::move(NetworkPacket::Allocate());
*packet << (uint32)NETWORK_COMMAND_TICK << (uint32)RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) << (uint32)RCT2_GLOBAL(RCT2_ADDRESS_SCENARIO_SRAND_0, uint32);
SendPacketToClients(*packet);
@@ -873,12 +906,13 @@ void Network::Client_Send_PING()
void Network::Server_Send_PING()
{
last_ping_sent_time = SDL_GetTicks();
std::unique_ptr<NetworkPacket> packet = std::move(NetworkPacket::Allocate());
*packet << (uint32)NETWORK_COMMAND_PING;
for (auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) {
(*it)->ping_time = SDL_GetTicks();
}
SendPacketToClients(*packet);
SendPacketToClients(*packet, true);
}
void Network::Server_Send_PINGLIST()
@@ -899,6 +933,24 @@ void Network::Server_Send_SETDISCONNECTMSG(NetworkConnection& connection, const
connection.QueuePacket(std::move(packet));
}
void Network::Server_Send_GAMEINFO(NetworkConnection& connection)
{
std::unique_ptr<NetworkPacket> packet = std::move(NetworkPacket::Allocate());
*packet << (uint32)NETWORK_COMMAND_GAMEINFO;
#ifndef DISABLE_HTTP
json_t* obj = json_object();
json_object_set(obj, "name", json_string(gConfigNetwork.server_name));
json_object_set(obj, "haspassword", json_integer(password.size() > 0 ? 1 : 0));
json_object_set(obj, "description", json_string(""));
json_object_set(obj, "version", json_string(OPENRCT2_VERSION));
json_object_set(obj, "players", json_integer(player_list.size()));
json_object_set(obj, "maxplayers", json_integer(gConfigNetwork.maxplayers));
packet->WriteString(json_dumps(obj, 0));
json_object_clear(obj);
#endif
connection.QueuePacket(std::move(packet));
}
bool Network::ProcessConnection(NetworkConnection& connection)
{
int packetStatus;
@@ -927,7 +979,9 @@ bool Network::ProcessConnection(NetworkConnection& connection)
} while (packetStatus == NETWORK_READPACKET_MORE_DATA || packetStatus == NETWORK_READPACKET_SUCCESS);
connection.SendQueuedPackets();
if (!connection.ReceivedPacketRecently()) {
connection.last_disconnect_reason = "No Data";
if (!connection.last_disconnect_reason) {
connection.last_disconnect_reason = "No Data";
}
return false;
}
return true;
@@ -942,7 +996,7 @@ void Network::ProcessPacket(NetworkConnection& connection, NetworkPacket& packet
switch (gNetwork.GetMode()) {
case NETWORK_MODE_SERVER:
if (server_command_handlers[command]) {
if (connection.authstatus == NETWORK_AUTH_OK || command == NETWORK_COMMAND_AUTH) {
if (connection.authstatus == NETWORK_AUTH_OK || !packet.CommandRequiresAuth()) {
(this->*server_command_handlers[command])(connection, packet);
}
}
@@ -988,7 +1042,7 @@ void Network::RemoveClient(std::unique_ptr<NetworkConnection>& connection)
lineCh = utf8_write_codepoint(lineCh, FORMAT_RED);
char reasonstr[100];
reasonstr[0] = 0;
if (connection->last_disconnect_reason) {
if (connection->last_disconnect_reason && strlen(connection->last_disconnect_reason) < sizeof(reasonstr)) {
sprintf(reasonstr, " (%s)", connection->last_disconnect_reason);
}
sprintf(lineCh, "%s has disconnected%s", connection_player->name, reasonstr);
@@ -1057,6 +1111,10 @@ int Network::Client_Handle_AUTH(NetworkConnection& connection, NetworkPacket& pa
connection.last_disconnect_reason = "Bad Password";
shutdown(connection.socket, SHUT_RDWR);
break;
case NETWORK_AUTH_FULL:
connection.last_disconnect_reason = "Server Full";
shutdown(connection.socket, SHUT_RDWR);
break;
case NETWORK_AUTH_REQUIREPASSWORD:
window_network_status_open_password();
break;
@@ -1076,11 +1134,14 @@ int Network::Server_Handle_AUTH(NetworkConnection& connection, NetworkPacket& pa
if (!name) {
connection.authstatus = NETWORK_AUTH_BADNAME;
} else
if (!password || strlen(password) == 0) {
if ((!password || strlen(password) == 0) && Network::password.size() > 0) {
connection.authstatus = NETWORK_AUTH_REQUIREPASSWORD;
} else
if (strcmp(password, Network::password) != 0) {
if (password && Network::password != password) {
connection.authstatus = NETWORK_AUTH_BADPASSWORD;
} else
if (gConfigNetwork.maxplayers <= player_list.size()) {
connection.authstatus = NETWORK_AUTH_FULL;
} else {
connection.authstatus = NETWORK_AUTH_OK;
NetworkPlayer* player = AddPlayer(name);
@@ -1251,15 +1312,21 @@ int Network::Client_Handle_PINGLIST(NetworkConnection& connection, NetworkPacket
int Network::Client_Handle_SETDISCONNECTMSG(NetworkConnection& connection, NetworkPacket& packet)
{
static char msg[100] = {0};
static std::string msg;
const char* disconnectmsg = packet.ReadString();
if (disconnectmsg) {
safe_strncpy(msg, disconnectmsg, sizeof(msg));
connection.last_disconnect_reason = msg;
msg = disconnectmsg;
connection.last_disconnect_reason = msg.c_str();
}
return 1;
}
int Network::Server_Handle_GAMEINFO(NetworkConnection& connection, NetworkPacket& packet)
{
Server_Send_GAMEINFO(connection);
return 1;
}
int network_init()
{
return gNetwork.Init();
@@ -1270,13 +1337,14 @@ void network_close()
gNetwork.Close();
}
void network_shutdown_client()
{
gNetwork.ShutdownClient();
}
int network_begin_client(const char *host, int port)
{
if (gNetwork.GetMode() == NETWORK_MODE_NONE) {
return gNetwork.BeginClient(host, port);
} else {
return false;
}
}
int network_begin_server(int port)
@@ -1371,7 +1439,7 @@ void network_send_gamecmd(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32
void network_send_password(const char* password)
{
gNetwork.Client_Send_AUTH(OPENRCT2_VERSION, gConfigNetwork.player_name, password);
gNetwork.Client_Send_AUTH(gConfigNetwork.player_name, password);
}
void network_kick_player(int playerId)
@@ -1387,6 +1455,7 @@ void network_set_password(const char* password)
#else
int network_get_mode() { return NETWORK_MODE_NONE; }
int network_get_status() { return NETWORK_STATUS_NONE; }
int network_get_authstatus() { return NETWORK_AUTH_NONE; }
uint32 network_get_server_tick() { return RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32); }
void network_send_gamecmd(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp, uint8 callback) {}
void network_send_map() {}
@@ -1399,7 +1468,9 @@ uint32 network_get_player_flags(unsigned int index) { return 0; }
int network_get_player_ping(unsigned int index) { return 0; }
int network_get_player_id(unsigned int index) { return 0; }
void network_send_chat(const char* text) {}
void network_send_password(const char* password) {}
void network_close() {}
void network_shutdown_client() {}
void network_kick_player(int playerId) {}
void network_set_password(const char* password) {}
uint8 network_get_current_player_id() { return 0; }

View File

@@ -38,6 +38,7 @@ enum {
NETWORK_AUTH_BADVERSION,
NETWORK_AUTH_BADNAME,
NETWORK_AUTH_BADPASSWORD,
NETWORK_AUTH_FULL,
NETWORK_AUTH_REQUIREPASSWORD
};
@@ -147,7 +148,7 @@ public:
NetworkConnection();
~NetworkConnection();
int ReadPacket();
void QueuePacket(std::unique_ptr<NetworkPacket> packet);
void QueuePacket(std::unique_ptr<NetworkPacket> packet, bool front = false);
void SendQueuedPackets();
bool SetTCPNoDelay(bool on);
bool SetNonBlocking(bool on);
@@ -212,12 +213,14 @@ public:
void Update();
NetworkPlayer* GetPlayerByID(int id);
const char* FormatChat(NetworkPlayer* fromplayer, const char* text);
void SendPacketToClients(NetworkPacket& packet);
void SendPacketToClients(NetworkPacket& packet, bool front = false);
bool CheckSRAND(uint32 tick, uint32 srand0);
void KickPlayer(int playerId);
void SetPassword(const char* password);
void ShutdownClient();
void Advertise();
void Client_Send_AUTH(const char* gameversion, const char* name, const char* password);
void Client_Send_AUTH(const char* name, const char* password);
void Server_Send_AUTH(NetworkConnection& connection);
void Server_Send_MAP(NetworkConnection* connection = nullptr);
void Client_Send_CHAT(const char* text);
@@ -230,6 +233,7 @@ public:
void Server_Send_PING();
void Server_Send_PINGLIST();
void Server_Send_SETDISCONNECTMSG(NetworkConnection& connection, const char* msg);
void Server_Send_GAMEINFO(NetworkConnection& connection);
std::vector<std::unique_ptr<NetworkPlayer>> player_list;
@@ -259,6 +263,7 @@ private:
NetworkAddress server_address;
bool wsa_initialized;
SOCKET listening_socket;
unsigned short listening_port;
NetworkConnection server_connection;
uint32 last_tick_sent_time;
uint32 last_ping_sent_time;
@@ -269,9 +274,10 @@ private:
std::list<std::unique_ptr<NetworkConnection>> client_connection_list;
std::multiset<GameCommand> game_command_queue;
std::vector<uint8> chunk_buffer;
char password[33];
std::string password;
bool _desynchronised;
uint32 server_connect_time;
uint32 last_advertise_time;
void UpdateServer();
void UpdateClient();
@@ -292,6 +298,7 @@ private:
int Server_Handle_PING(NetworkConnection& connection, NetworkPacket& packet);
int Client_Handle_PINGLIST(NetworkConnection& connection, NetworkPacket& packet);
int Client_Handle_SETDISCONNECTMSG(NetworkConnection& connection, NetworkPacket& packet);
int Server_Handle_GAMEINFO(NetworkConnection& connection, NetworkPacket& packet);
};
#endif // __cplusplus
@@ -302,6 +309,7 @@ extern "C" {
#endif // __cplusplus
int network_init();
void network_close();
void network_shutdown_client();
int network_begin_client(const char *host, int port);
int network_begin_server(int port);

View File

@@ -105,6 +105,7 @@ typedef utf16* utf16string;
#define OPENRCT2_BRANCH "develop"
#define OPENRCT2_COMMIT_SHA1 ""
#define OPENRCT2_COMMIT_SHA1_SHORT ""
#define OPENRCT2_MASTER_URL ""
// Represent fixed point numbers. dp = decimal point
typedef uint8 fixed8_1dp;

View File

@@ -149,7 +149,11 @@ static void window_network_status_textinput(rct_window *w, int widgetIndex, char
safe_strncpy(_password, text, sizeof(_password));
break;
}
network_send_password(_password);
if (text == NULL) {
network_shutdown_client();
} else {
network_send_password(_password);
}
}
static void window_network_status_invalidate(rct_window *w)

View File

@@ -18,12 +18,15 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include "../interface/colour.h"
#include "../interface/themes.h"
#include "../interface/widget.h"
#include "../interface/window.h"
#include "../localisation/localisation.h"
#include "../network/http.h"
#include "../network/network.h"
#include "../sprites.h"
#include "../windows/dropdown.h"
#include "../util/util.h"
#include "error.h"
@@ -31,17 +34,23 @@
#define WHEIGHT_MIN 300
#define WWIDTH_MAX 1200
#define WHEIGHT_MAX 800
#define ITEM_HEIGHT (3 + 11 + 1 + 11 + 3)
#define ITEM_HEIGHT (3 + 9 + 3)
typedef struct {
char *address;
utf8 *name;
bool haspassword;
utf8 *description;
char *version;
bool favorite;
uint8 players;
uint8 maxplayers;
} saved_server;
char _playerName[64];
char _playerName[32 + 1];
saved_server *_savedServers = NULL;
int _numSavedServers = 0;
SDL_mutex *_mutex = 0;
enum {
WIDX_BACKGROUND,
@@ -49,6 +58,7 @@ enum {
WIDX_CLOSE,
WIDX_PLAYER_NAME_INPUT,
WIDX_LIST,
WIDX_FETCH_SERVERS,
WIDX_ADD_SERVER,
WIDX_START_SERVER
};
@@ -64,14 +74,16 @@ static rct_widget window_server_list_widgets[] = {
{ WWT_CLOSEBOX, 0, 327, 337, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button
{ WWT_TEXT_BOX, 1, 100, 344, 20, 31, (uint32)_playerName, STR_NONE }, // player name text box
{ WWT_SCROLL, 1, 6, 337, 37, 50, STR_NONE, STR_NONE }, // server list
{ WWT_DROPDOWN_BUTTON, 1, 6, 106, 53, 64, STR_ADD_SERVER, STR_NONE }, // add server button
{ WWT_DROPDOWN_BUTTON, 1, 112, 212, 53, 64, STR_START_SERVER, STR_NONE }, // start server button
{ WWT_DROPDOWN_BUTTON, 1, 6, 106, 53, 64, STR_FETCH_SERVERS, STR_NONE }, // fetch servers button
{ WWT_DROPDOWN_BUTTON, 1, 112, 212, 53, 64, STR_ADD_SERVER, STR_NONE }, // add server button
{ WWT_DROPDOWN_BUTTON, 1, 218, 318, 53, 64, STR_START_SERVER, STR_NONE }, // start server button
{ WIDGETS_END },
};
static void window_server_list_close(rct_window *w);
static void window_server_list_mouseup(rct_window *w, int widgetIndex);
static void window_server_list_resize(rct_window *w);
static void window_server_list_dropdown(rct_window *w, int widgetIndex, int dropdownIndex);
static void window_server_list_update(rct_window *w);
static void window_server_list_scroll_getsize(rct_window *w, int scrollIndex, int *width, int *height);
static void window_server_list_scroll_mousedown(rct_window *w, int scrollIndex, int x, int y);
@@ -86,7 +98,7 @@ static rct_window_event_list window_server_list_events = {
window_server_list_mouseup,
window_server_list_resize,
NULL,
NULL,
window_server_list_dropdown,
NULL,
window_server_list_update,
NULL,
@@ -112,17 +124,25 @@ static rct_window_event_list window_server_list_events = {
window_server_list_scrollpaint
};
enum {
DDIDX_JOIN,
DDIDX_FAVORITE
};
static int _hoverButtonIndex = -1;
static void server_list_get_item_button(int buttonIndex, int x, int y, int width, int *outX, int *outY);
static void server_list_update_player_name();
static void server_list_load_saved_servers();
static void server_list_save_saved_servers();
static void dispose_saved_server_list();
static void dispose_saved_server(saved_server *serverInfo);
static void add_saved_server(char *address);
static saved_server* add_saved_server(char *address);
static void remove_saved_server(int index);
static void join_server(char *address, bool spectate);
static void join_server(char *address);
static void fetch_servers();
#ifndef DISABLE_HTTP
static void fetch_servers_callback(http_json_response* response);
#endif
void window_server_list_open()
{
@@ -133,12 +153,17 @@ void window_server_list_open()
if (window != NULL)
return;
if (_mutex == 0) {
_mutex = SDL_CreateMutex();
}
window = window_create_centred(WWIDTH_MIN, WHEIGHT_MIN, &window_server_list_events, WC_SERVER_LIST, WF_10 | WF_RESIZABLE);
window->widgets = window_server_list_widgets;
window->enabled_widgets = (
(1 << WIDX_CLOSE) |
(1 << WIDX_PLAYER_NAME_INPUT) |
(1 << WIDX_FETCH_SERVERS) |
(1 << WIDX_ADD_SERVER) |
(1 << WIDX_START_SERVER)
);
@@ -163,12 +188,18 @@ void window_server_list_open()
server_list_load_saved_servers();
window->no_list_items = _numSavedServers;
fetch_servers();
}
static void window_server_list_close(rct_window *w)
{
server_list_update_player_name();
dispose_saved_server_list();
if (_mutex) {
SDL_LockMutex(_mutex);
SDL_DestroyMutex(_mutex);
_mutex = 0;
}
}
static void window_server_list_mouseup(rct_window *w, int widgetIndex)
@@ -180,11 +211,13 @@ static void window_server_list_mouseup(rct_window *w, int widgetIndex)
case WIDX_PLAYER_NAME_INPUT:
window_start_textbox(w, widgetIndex, 1170, (uint32)_playerName, 63);
break;
case WIDX_FETCH_SERVERS:
fetch_servers();
break;
case WIDX_ADD_SERVER:
window_text_input_open(w, widgetIndex, STR_ADD_SERVER, STR_ENTER_HOSTNAME_OR_IP_ADDRESS, STR_NONE, 0, 128);
break;
case WIDX_START_SERVER:
server_list_update_player_name();
window_server_start_open();
break;
}
@@ -195,6 +228,25 @@ static void window_server_list_resize(rct_window *w)
window_set_resize(w, WWIDTH_MIN, WHEIGHT_MIN, WWIDTH_MAX, WHEIGHT_MAX);
}
static void window_server_list_dropdown(rct_window *w, int widgetIndex, int dropdownIndex)
{
int serverIndex = w->selected_list_item;
if (serverIndex < 0) return;
if (serverIndex >= _numSavedServers) return;
char *serverAddress = _savedServers[serverIndex].address;
switch (dropdownIndex) {
case DDIDX_JOIN:
join_server(serverAddress);
break;
case DDIDX_FAVORITE:
_savedServers[serverIndex].favorite = !_savedServers[serverIndex].favorite;
server_list_save_saved_servers();
break;
}
}
static void window_server_list_update(rct_window *w)
{
if (gCurrentTextBox.window.classification == w->classification && gCurrentTextBox.window.number == w->number) {
@@ -217,22 +269,17 @@ static void window_server_list_scroll_mousedown(rct_window *w, int scrollIndex,
char *serverAddress = _savedServers[serverIndex].address;
switch (_hoverButtonIndex) {
case WIDX_LIST_REMOVE:
remove_saved_server(serverIndex);
server_list_save_saved_servers();
w->no_list_items = _numSavedServers;
window_invalidate(w);
break;
case WIDX_LIST_SPECTATE:
server_list_update_player_name();
join_server(serverAddress, true);
break;
default:
server_list_update_player_name();
join_server(serverAddress, false);
break;
rct_widget *listWidget = &w->widgets[WIDX_LIST];
int ddx = w->x + listWidget->left + x;
int ddy = w->y + listWidget->top + y;
gDropdownItemsFormat[0] = STR_JOIN_GAME;
if (_savedServers[serverIndex].favorite) {
gDropdownItemsFormat[1] = STR_REMOVE_FROM_FAVORITES;
} else {
gDropdownItemsFormat[1] = STR_ADD_TO_FAVORITES;
}
window_dropdown_show_text(ddx, ddy, 0, COLOUR_GREY, 0, 2);
}
static void window_server_list_scroll_mouseover(rct_window *w, int scrollIndex, int x, int y)
@@ -281,13 +328,18 @@ static void window_server_list_textinput(rct_window *w, int widgetIndex, char *t
safe_strncpy(_playerName, text, sizeof(_playerName));
}
if (strlen(_playerName) > 0) {
SafeFree(gConfigNetwork.player_name);
gConfigNetwork.player_name = _strdup(_playerName);
config_save_default();
}
widget_invalidate(w, WIDX_PLAYER_NAME_INPUT);
break;
case WIDX_ADD_SERVER:
add_saved_server(text);
server_list_save_saved_servers();
w->no_list_items = _numSavedServers;
window_invalidate(w);
break;
}
@@ -305,23 +357,26 @@ static void window_server_list_invalidate(rct_window *w)
window_server_list_widgets[WIDX_LIST].left = 6;
window_server_list_widgets[WIDX_LIST].right = w->width - 6;
window_server_list_widgets[WIDX_LIST].bottom = w->height - 6 - 11 - 6;
window_server_list_widgets[WIDX_FETCH_SERVERS].top = w->height - 6 - 11;
window_server_list_widgets[WIDX_FETCH_SERVERS].bottom = w->height - 6;
window_server_list_widgets[WIDX_ADD_SERVER].top = w->height - 6 - 11;
window_server_list_widgets[WIDX_ADD_SERVER].bottom = w->height - 6;
window_server_list_widgets[WIDX_START_SERVER].top = w->height - 6 - 11;
window_server_list_widgets[WIDX_START_SERVER].bottom = w->height - 6;
w->no_list_items = _numSavedServers;
}
static void window_server_list_paint(rct_window *w, rct_drawpixelinfo *dpi)
{
window_draw_widgets(w, dpi);
gfx_draw_string_left(dpi, STR_PLAYER_NAME, NULL, w->colours[1], w->x + 6, w->y + w->widgets[WIDX_PLAYER_NAME_INPUT].top);
gfx_draw_string_left(dpi, STR_PLAYER_NAME, NULL, COLOUR_WHITE, w->x + 6, w->y + w->widgets[WIDX_PLAYER_NAME_INPUT].top);
}
static void window_server_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex)
{
uint32 colour;
int bx, by;
colour = ((char*)0x0141FC48)[w->colours[1] * 8];
colour = (colour << 24) | (colour << 16) | (colour << 8) | colour;
@@ -342,27 +397,26 @@ static void window_server_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi
gfx_fill_rect(dpi, 0, y, width, y + ITEM_HEIGHT, 0x02000031);
}
int colour = w->colours[1];
if (serverDetails->favorite) {
colour = COLOUR_YELLOW;
}
// Draw server information
if (highlighted) {
gfx_draw_string(dpi, serverDetails->address, w->colours[1], 3, y + 3);
gfx_draw_string(dpi, serverDetails->address, colour, 3, y + 3);
} else {
gfx_draw_string(dpi, serverDetails->name, w->colours[1], 3, y + 3);
gfx_draw_string(dpi, serverDetails->name, colour, 3, y + 3);
}
gfx_draw_string(dpi, serverDetails->description, w->colours[1], 3, y + 14);
//gfx_draw_string(dpi, serverDetails->description, w->colours[1], 3, y + 14);
// Draw delete server button
server_list_get_item_button(0, 0, y, width, &bx, &by);
if (highlighted && _hoverButtonIndex == WIDX_LIST_REMOVE) {
gfx_fill_rect_inset(dpi, bx, by, bx + 24, by + 24, w->colours[1], 0);
// Draw number of players
char players[32];
players[0] = 0;
if (serverDetails->maxplayers > 0) {
sprintf(players, "%d/%d", serverDetails->players, serverDetails->maxplayers);
}
gfx_draw_sprite(dpi, SPR_DEMOLISH, bx, by, 0);
// Draw spectate server button
server_list_get_item_button(1, 0, y, width, &bx, &by);
if (highlighted && _hoverButtonIndex == WIDX_LIST_SPECTATE) {
gfx_fill_rect_inset(dpi, bx, by, bx + 24, by + 24, w->colours[1], 0);
}
gfx_draw_sprite(dpi, SPR_LOCATE, bx, by, 0);
gfx_draw_string(dpi, players, w->colours[1], width - 3 - 14 - gfx_get_string_width(players), y + 3);
y += ITEM_HEIGHT;
}
@@ -374,15 +428,6 @@ static void server_list_get_item_button(int buttonIndex, int x, int y, int width
*outY = y + 2;
}
static void server_list_update_player_name()
{
if (strlen(_playerName) > 0) {
SafeFree(gConfigNetwork.player_name);
gConfigNetwork.player_name = _strdup(_playerName);
config_save_default();
}
}
static char *freadstralloc(SDL_RWops *file)
{
int capacity = 64;
@@ -421,6 +466,7 @@ static void server_list_load_saved_servers()
return;
}
SDL_LockMutex(_mutex);
dispose_saved_server_list();
// Read number of saved servers
@@ -433,10 +479,16 @@ static void server_list_load_saved_servers()
serverInfo->address = freadstralloc(file);
serverInfo->name = freadstralloc(file);
serverInfo->haspassword = false;
serverInfo->description = freadstralloc(file);
serverInfo->version = _strdup("");
serverInfo->favorite = true;
serverInfo->players = 0;
serverInfo->maxplayers = 0;
}
SDL_RWclose(file);
SDL_UnlockMutex(_mutex);
}
static void server_list_save_saved_servers()
@@ -453,23 +505,34 @@ static void server_list_save_saved_servers()
return;
}
SDL_LockMutex(_mutex);
int count = 0;
for (int i = 0; i < _numSavedServers; i++) {
saved_server *serverInfo = &_savedServers[i];
if (serverInfo->favorite) {
count++;
}
}
// Write number of saved servers
SDL_RWwrite(file, &_numSavedServers, sizeof(uint32), 1);
SDL_RWwrite(file, &count, sizeof(uint32), 1);
// Write each saved server
for (int i = 0; i < _numSavedServers; i++) {
saved_server *serverInfo = &_savedServers[i];
SDL_RWwrite(file, serverInfo->address, strlen(serverInfo->address) + 1, 1);
SDL_RWwrite(file, serverInfo->name, strlen(serverInfo->name) + 1, 1);
SDL_RWwrite(file, serverInfo->description, strlen(serverInfo->description) + 1, 1);
if (serverInfo->favorite) {
SDL_RWwrite(file, serverInfo->address, strlen(serverInfo->address) + 1, 1);
SDL_RWwrite(file, serverInfo->name, strlen(serverInfo->name) + 1, 1);
SDL_RWwrite(file, serverInfo->description, strlen(serverInfo->description) + 1, 1);
}
}
SDL_RWclose(file);
SDL_UnlockMutex(_mutex);
}
static void dispose_saved_server_list()
{
SDL_LockMutex(_mutex);
if (_savedServers != NULL) {
for (int i = 0; i < _numSavedServers; i++) {
dispose_saved_server(&_savedServers[i]);
@@ -478,6 +541,7 @@ static void dispose_saved_server_list()
_savedServers = NULL;
}
_numSavedServers = 0;
SDL_UnlockMutex(_mutex);
}
static void dispose_saved_server(saved_server *serverInfo)
@@ -485,10 +549,19 @@ static void dispose_saved_server(saved_server *serverInfo)
SafeFree(serverInfo->address);
SafeFree(serverInfo->name);
SafeFree(serverInfo->description);
SafeFree(serverInfo->version);
}
static void add_saved_server(char *address)
static saved_server* add_saved_server(char *address)
{
SDL_LockMutex(_mutex);
for (int i = 0; i < _numSavedServers; i++) {
if (strcmp(_savedServers[i].address, address) == 0) {
SDL_UnlockMutex(_mutex);
return &_savedServers[i];
}
}
_numSavedServers++;
if (_savedServers == NULL) {
_savedServers = malloc(_numSavedServers * sizeof(saved_server));
@@ -497,20 +570,30 @@ static void add_saved_server(char *address)
}
int index = _numSavedServers - 1;
_savedServers[index].address = _strdup(address);
_savedServers[index].name = _strdup(address);
_savedServers[index].description = _strdup("");
saved_server* newserver = &_savedServers[index];
newserver->address = _strdup(address);
newserver->name = _strdup(address);
newserver->haspassword = false;
newserver->description = _strdup("");
newserver->version = _strdup("");
newserver->favorite = false;
newserver->players = 0;
newserver->maxplayers = 0;
SDL_UnlockMutex(_mutex);
return newserver;
}
static void remove_saved_server(int index)
{
if (_numSavedServers <= index) return;
SDL_LockMutex(_mutex);
if (_numSavedServers > index) {
int serversToMove = _numSavedServers - index - 1;
memmove(&_savedServers[index], &_savedServers[index + 1], serversToMove * sizeof(saved_server));
int serversToMove = _numSavedServers - index - 1;
memmove(&_savedServers[index], &_savedServers[index + 1], serversToMove * sizeof(saved_server));
_numSavedServers--;
_savedServers = realloc(_savedServers, _numSavedServers * sizeof(saved_server));
_numSavedServers--;
_savedServers = realloc(_savedServers, _numSavedServers * sizeof(saved_server));
}
SDL_UnlockMutex(_mutex);
}
static char *substr(char *start, int length)
@@ -521,7 +604,7 @@ static char *substr(char *start, int length)
return result;
}
static void join_server(char *address, bool spectate)
static void join_server(char *address)
{
int port = gConfigNetwork.default_port;
@@ -551,3 +634,60 @@ static void join_server(char *address, bool spectate)
free(address);
}
}
static void fetch_servers()
{
#ifndef DISABLE_HTTP
if(strlen(gConfigNetwork.master_url) > 0){
SDL_LockMutex(_mutex);
for (int i = 0; i < _numSavedServers; i++) {
if (!_savedServers[i].favorite) {
remove_saved_server(i);
i = 0;
}
}
SDL_UnlockMutex(_mutex);
http_request_json_async(gConfigNetwork.master_url, fetch_servers_callback);
}
#endif
}
#ifndef DISABLE_HTTP
static void fetch_servers_callback(http_json_response* response)
{
if (response && json_is_array(response->root)) {
int count = json_array_size(response->root);
for (int i = 0; i < count; i++) {
json_t *server = json_array_get(response->root, i);
if (!json_is_object(server))
continue;
json_t *address = json_object_get(server, "address");
json_t *name = json_object_get(server, "name");
json_t *haspassword = json_object_get(server, "haspassword");
json_t *description = json_object_get(server, "description");
json_t *version = json_object_get(server, "version");
json_t *players = json_object_get(server, "players");
json_t *maxplayers = json_object_get(server, "maxplayers");
SDL_LockMutex(_mutex);
saved_server* newserver = add_saved_server((char*)json_string_value(address));
SafeFree(newserver->name);
newserver->name = _strdup(json_string_value(name));
newserver->haspassword = (uint8)json_integer_value(haspassword);
SafeFree(newserver->description);
newserver->description = _strdup(json_string_value(description));
SafeFree(newserver->version);
newserver->version = _strdup(json_string_value(version));
newserver->players = (uint8)json_integer_value(players);
newserver->maxplayers = (uint8)json_integer_value(maxplayers);
SDL_UnlockMutex(_mutex);
}
http_request_json_dispose(response);
}
rct_window* window = window_bring_to_front_by_class(WC_SERVER_LIST);
if (window != NULL) {
window_invalidate(window);
}
}
#endif

View File

@@ -28,26 +28,38 @@
#include "../util/util.h"
#include "error.h"
char _port[7];
char _name[65];
char _password[33];
enum {
WIDX_BACKGROUND,
WIDX_TITLE,
WIDX_CLOSE,
WIDX_PORT_INPUT,
WIDX_NAME_INPUT,
WIDX_PASSWORD_INPUT,
WIDX_MAXPLAYERS,
WIDX_MAXPLAYERS_INCREASE,
WIDX_MAXPLAYERS_DECREASE,
WIDX_ADVERTISE_CHECKBOX,
WIDX_START_SERVER
};
#define WW 300
#define WH 100
#define WH 120
static rct_widget window_server_start_widgets[] = {
{ WWT_FRAME, 0, 0, WW-1, 0, WH-1, 0xFFFFFFFF, STR_NONE }, // panel / background
{ WWT_CAPTION, 0, 1, WW-2, 1, 14, STR_START_SERVER, STR_WINDOW_TITLE_TIP }, // title bar
{ WWT_CLOSEBOX, 0, WW-13, WW-3, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button
{ WWT_TEXT_BOX, 1, 150, WW-8, 20, 32, (uint32)_password, STR_NONE }, // password text box
{ WWT_CHECKBOX, 1, 6, WW-8, 36, 45, STR_ADVERTISE, STR_NONE }, // advertise checkbox
{ WWT_TEXT_BOX, 1, 120, WW-8, 20, 32, (uint32)_port, STR_NONE }, // port text box
{ WWT_TEXT_BOX, 1, 120, WW-8, 36, 48, (uint32)_name, STR_NONE }, // name text box
{ WWT_TEXT_BOX, 1, 120, WW-8, 52, 64, (uint32)_password, STR_NONE }, // password text box
{ WWT_SPINNER, 1, 120, WW-8, 68, 77, 1871, STR_NONE }, // max players
{ WWT_DROPDOWN_BUTTON, 1, WW-18, WW-8, 68, 72, STR_NUMERIC_UP, STR_NONE },
{ WWT_DROPDOWN_BUTTON, 1, WW-18, WW-8, 72, 76, STR_NUMERIC_DOWN, STR_NONE },
{ WWT_CHECKBOX, 1, 6, WW-8, 85, 91, STR_ADVERTISE, STR_NONE }, // advertise checkbox
{ WWT_DROPDOWN_BUTTON, 1, 6, 106, WH-6-11, WH-6, STR_START_SERVER, STR_NONE }, // start server button
{ WIDGETS_END },
};
@@ -104,7 +116,12 @@ void window_server_start_open()
window->widgets = window_server_start_widgets;
window->enabled_widgets = (
(1 << WIDX_CLOSE) |
(1 << WIDX_PORT_INPUT) |
(1 << WIDX_NAME_INPUT) |
(1 << WIDX_PASSWORD_INPUT) |
(1 << WIDX_MAXPLAYERS) |
(1 << WIDX_MAXPLAYERS_INCREASE) |
(1 << WIDX_MAXPLAYERS_DECREASE) |
(1 << WIDX_ADVERTISE_CHECKBOX) |
(1 << WIDX_START_SERVER)
);
@@ -122,6 +139,9 @@ void window_server_start_open()
window->colours[0] = 1;
window->colours[1] = 26;
window->colours[2] = 26;
sprintf(_port, "%lu", gConfigNetwork.default_port);
safe_strncpy(_name, gConfigNetwork.server_name, sizeof(_name));
}
static void window_server_start_close(rct_window *w)
@@ -135,9 +155,29 @@ static void window_server_start_mouseup(rct_window *w, int widgetIndex)
case WIDX_CLOSE:
window_close(w);
break;
case WIDX_PORT_INPUT:
window_start_textbox(w, widgetIndex, 1170, (uint32)_port, 6);
break;
case WIDX_NAME_INPUT:
window_start_textbox(w, widgetIndex, 1170, (uint32)_name, 64);
break;
case WIDX_PASSWORD_INPUT:
window_start_textbox(w, widgetIndex, 1170, (uint32)_password, 32);
break;
case WIDX_MAXPLAYERS_INCREASE:
if (gConfigNetwork.maxplayers < 255) {
gConfigNetwork.maxplayers++;
}
config_save_default();
window_invalidate(w);
break;
case WIDX_MAXPLAYERS_DECREASE:
if (gConfigNetwork.maxplayers > 1) {
gConfigNetwork.maxplayers--;
}
config_save_default();
window_invalidate(w);
break;
case WIDX_ADVERTISE_CHECKBOX:
gConfigNetwork.advertise = !gConfigNetwork.advertise;
config_save_default();
@@ -154,6 +194,7 @@ static void window_server_start_update(rct_window *w)
{
if (gCurrentTextBox.window.classification == w->classification && gCurrentTextBox.window.number == w->number) {
window_update_textbox_caret();
widget_invalidate(w, WIDX_NAME_INPUT);
widget_invalidate(w, WIDX_PASSWORD_INPUT);
}
}
@@ -163,6 +204,37 @@ static void window_server_start_textinput(rct_window *w, int widgetIndex, char *
if (text == NULL) return;
switch (widgetIndex) {
case WIDX_PORT_INPUT:
if (strcmp(_port, text) == 0)
return;
memset(_port, 0, sizeof(_port));
if (strlen(text) > 0) {
safe_strncpy(_port, text, sizeof(_port));
}
gConfigNetwork.default_port = atoi(_port);
config_save_default();
widget_invalidate(w, WIDX_NAME_INPUT);
break;
case WIDX_NAME_INPUT:
if (strcmp(_name, text) == 0)
return;
memset(_name, 0, sizeof(_name));
if (strlen(text) > 0) {
safe_strncpy(_name, text, sizeof(_name));
}
if (strlen(_name) > 0) {
SafeFree(gConfigNetwork.server_name);
gConfigNetwork.server_name = _strdup(_name);
config_save_default();
}
widget_invalidate(w, WIDX_NAME_INPUT);
break;
case WIDX_PASSWORD_INPUT:
if (strcmp(_password, text) == 0)
return;
@@ -180,11 +252,15 @@ static void window_server_start_textinput(rct_window *w, int widgetIndex, char *
static void window_server_start_invalidate(rct_window *w)
{
widget_set_checkbox_value(w, WIDX_ADVERTISE_CHECKBOX, gConfigNetwork.advertise);
RCT2_GLOBAL(0x013CE964, uint16) = gConfigNetwork.maxplayers;
}
static void window_server_start_paint(rct_window *w, rct_drawpixelinfo *dpi)
{
window_draw_widgets(w, dpi);
gfx_draw_string_left(dpi, STR_PORT, NULL, w->colours[1], w->x + 6, w->y + w->widgets[WIDX_PORT_INPUT].top);
gfx_draw_string_left(dpi, STR_SERVER_NAME, NULL, w->colours[1], w->x + 6, w->y + w->widgets[WIDX_NAME_INPUT].top);
gfx_draw_string_left(dpi, STR_PASSWORD, NULL, w->colours[1], w->x + 6, w->y + w->widgets[WIDX_PASSWORD_INPUT].top);
gfx_draw_string_left(dpi, STR_MAX_PLAYERS, NULL, w->colours[1], w->x + 6, w->y + w->widgets[WIDX_MAXPLAYERS].top);
}