basic player list

This commit is contained in:
zsilencer 2015-07-16 11:32:43 -06:00
parent c0dc591152
commit 7ccb0eb655
7 changed files with 404 additions and 39 deletions

View File

@ -3834,3 +3834,4 @@ STR_5492 :Scenario options
STR_6000 :Send Message
STR_6001 :Type the message you would like to send.
STR_6002 :Player List

View File

@ -447,6 +447,7 @@ enum {
WC_TITLE_EDITOR = 122,
WC_TITLE_COMMAND_EDITOR = 123,
WC_CHAT_HOST = 124,
WC_PLAYER_LIST = 125,
// Only used for colour schemes
WC_STAFF = 220,
@ -612,6 +613,7 @@ void window_sign_open(rct_windownumber number);
void window_sign_small_open(rct_windownumber number);
void window_cheats_open();
void window_chat_open();
void window_player_list_open();
void window_research_open();
void window_research_development_page_paint(rct_window *w, rct_drawpixelinfo *dpi, int baseWidgetIndex);

View File

@ -2030,6 +2030,8 @@ enum {
STR_DEBUG_DROPDOWN_INVENTIONS_LIST = 5491,
STR_DEBUG_DROPDOWN_SCENARIO_OPTIONS = 5492,
STR_PLAYER_LIST = 6002,
// Have to include resource strings (from scenarios and objects) for the time being now that language is partially working
STR_COUNT = 32768
};

View File

@ -21,6 +21,7 @@
#ifndef DISABLE_NETWORK
#include <math.h>
#include <algorithm>
#include <set>
#include "network.h"
extern "C" {
@ -49,7 +50,7 @@ enum {
NETWORK_COMMAND_CHAT,
NETWORK_COMMAND_GAMECMD,
NETWORK_COMMAND_TICK,
NETWORK_COMMAND_PLAYER,
NETWORK_COMMAND_PLAYERLIST,
NETWORK_COMMAND_MAX
};
@ -108,6 +109,7 @@ const char* NetworkPacket::ReadString()
if (*strend != 0) {
return 0;
}
read++;
return str;
}
@ -118,9 +120,17 @@ void NetworkPacket::Clear()
data->clear();
}
NetworkPlayer::NetworkPlayer(const char* name)
{
strncpy((char*)NetworkPlayer::name, name, sizeof(NetworkPlayer::name));
NetworkPlayer::name[sizeof(NetworkPlayer::name) - 1] = 0;
ping = 0;
}
NetworkConnection::NetworkConnection()
{
authstatus = NETWORK_AUTH_NONE;
player = 0;
}
int NetworkConnection::ReadPacket()
@ -213,6 +223,7 @@ Network::Network()
client_command_handlers[NETWORK_COMMAND_CHAT] = &Network::Client_Handle_CHAT;
client_command_handlers[NETWORK_COMMAND_GAMECMD] = &Network::Client_Handle_GAMECMD;
client_command_handlers[NETWORK_COMMAND_TICK] = &Network::Client_Handle_TICK;
client_command_handlers[NETWORK_COMMAND_PLAYERLIST] = &Network::Client_Handle_PLAYERLIST;
server_command_handlers.resize(NETWORK_COMMAND_MAX, 0);
server_command_handlers[NETWORK_COMMAND_AUTH] = &Network::Server_Handle_AUTH;
server_command_handlers[NETWORK_COMMAND_CHAT] = &Network::Server_Handle_CHAT;
@ -241,18 +252,21 @@ bool Network::Init()
void Network::Close()
{
if (mode == NETWORK_MODE_CLIENT) {
mode = NETWORK_MODE_NONE;
closesocket(server_socket);
} else
if (mode == NETWORK_MODE_SERVER) {
mode = NETWORK_MODE_NONE;
closesocket(listening_socket);
for(auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) {
closesocket((*it)->socket);
}
client_connection_list.clear();
}
mode = NETWORK_MODE_NONE;
client_connection_list.clear();
game_command_queue.clear();
player_list.clear();
if (wsa_initialized) {
WSACleanup();
wsa_initialized = false;
@ -261,6 +275,7 @@ void Network::Close()
bool Network::BeginClient(const char* host, unsigned short port)
{
Close();
if (!Init())
return false;
@ -298,6 +313,7 @@ bool Network::BeginClient(const char* host, unsigned short port)
bool Network::BeginServer(unsigned short port)
{
Close();
if (!Init())
return false;
@ -332,6 +348,10 @@ bool Network::BeginServer(unsigned short port)
return false;
}
std::unique_ptr<NetworkPlayer> player(new NetworkPlayer("Server Player")); // change to make_unique in c++14
player->flags |= NETWORK_PLAYER_FLAG_ISSERVER;
player_list.push_back(std::move(player));
printf("Ready for clients...\n");
mode = NETWORK_MODE_SERVER;
@ -343,6 +363,17 @@ int Network::GetMode()
return mode;
}
int Network::GetAuthStatus()
{
if (GetMode() == NETWORK_MODE_CLIENT) {
return server_connection.authstatus;
} else
if (GetMode() == NETWORK_MODE_SERVER) {
return NETWORK_AUTH_OK;
}
return NETWORK_AUTH_NONE;
}
uint32 Network::GetServerTick()
{
return server_tick;
@ -362,7 +393,7 @@ void Network::Update()
} else
if (GetMode() == NETWORK_MODE_SERVER) {
auto it = client_connection_list.begin();
while(it != client_connection_list.end()) {
while (it != client_connection_list.end()) {
if (!ProcessConnection(*(*it))) {
RemoveClient((*it));
it = client_connection_list.begin();
@ -416,7 +447,7 @@ void Network::Server_Send_MAP()
std::unique_ptr<NetworkPacket> packet = NetworkPacket::AllocatePacket();
*packet << (uint32)NETWORK_COMMAND_MAP << (uint32)size << (uint32)i;
packet->Write(&buffer[i], datasize);
for(auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) {
for (auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) {
(*it)->QueuePacket(NetworkPacket::DuplicatePacket(*packet));
}
}
@ -436,7 +467,7 @@ void Network::Server_Send_CHAT(const char* text)
std::unique_ptr<NetworkPacket> packet = NetworkPacket::AllocatePacket();
*packet << (uint32)NETWORK_COMMAND_CHAT;
packet->Write((uint8*)text, strlen(text) + 1);
for(auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) {
for (auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) {
(*it)->QueuePacket(NetworkPacket::DuplicatePacket(*packet));
}
}
@ -452,7 +483,7 @@ void Network::Server_Send_GAMECMD(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx
{
std::unique_ptr<NetworkPacket> packet = NetworkPacket::AllocatePacket();
*packet << (uint32)NETWORK_COMMAND_GAMECMD << (uint32)RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32) << eax << (ebx | (1 << 31)) << ecx << edx << esi << edi << ebp;
for(auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) {
for (auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) {
(*it)->QueuePacket(NetworkPacket::DuplicatePacket(*packet));
}
}
@ -461,7 +492,20 @@ void Network::Server_Send_TICK()
{
std::unique_ptr<NetworkPacket> packet = NetworkPacket::AllocatePacket();
*packet << (uint32)NETWORK_COMMAND_TICK << (uint32)RCT2_GLOBAL(RCT2_ADDRESS_CURRENT_TICKS, uint32);
for(auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) {
for (auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) {
(*it)->QueuePacket(NetworkPacket::DuplicatePacket(*packet));
}
}
void Network::Server_Send_PLAYERLIST()
{
std::unique_ptr<NetworkPacket> packet = NetworkPacket::AllocatePacket();
*packet << (uint32)NETWORK_COMMAND_PLAYERLIST << (uint32)player_list.size();
for (unsigned int i = 0; i < player_list.size(); i++) {
packet->WriteString((const char*)player_list[i]->name);
*packet << player_list[i]->id << player_list[i]->flags;
}
for (auto it = client_connection_list.begin(); it != client_connection_list.end(); it++) {
(*it)->QueuePacket(NetworkPacket::DuplicatePacket(*packet));
}
}
@ -534,15 +578,18 @@ void Network::ProcessGameCommandQueue()
void Network::AddClient(SOCKET socket)
{
printf("New client connection\n");
auto networkconnection = std::unique_ptr<NetworkConnection>(new NetworkConnection); // change to make_unique in c++14
networkconnection->socket = socket;
client_connection_list.push_back(std::move(networkconnection));
auto connection = std::unique_ptr<NetworkConnection>(new NetworkConnection); // change to make_unique in c++14
connection->socket = socket;
client_connection_list.push_back(std::move(connection));
}
void Network::RemoveClient(std::unique_ptr<NetworkConnection>& networkconnection)
void Network::RemoveClient(std::unique_ptr<NetworkConnection>& connection)
{
printf("Client removed\n");
client_connection_list.remove(networkconnection);
NetworkPlayer* connection_player = connection->player;
player_list.erase(std::remove_if(player_list.begin(), player_list.end(), [connection_player](std::unique_ptr<NetworkPlayer>& player){ return player.get() == connection_player; }), player_list.end());
client_connection_list.remove(connection);
Server_Send_PLAYERLIST();
}
void Network::PrintError()
@ -561,22 +608,30 @@ int Network::Client_Handle_AUTH(NetworkConnection& connection, NetworkPacket& pa
int Network::Server_Handle_AUTH(NetworkConnection& connection, NetworkPacket& packet)
{
const char* gameversion = packet.ReadString();
const char* name = packet.ReadString();
const char* password = packet.ReadString();
connection.authstatus = NETWORK_AUTH_OK;
if (!gameversion || strcmp(gameversion, OPENRCT2_VERSION) != 0) {
connection.authstatus = NETWORK_AUTH_BADVERSION;
} else
if (!name) {
connection.authstatus = NETWORK_AUTH_BADNAME;
} else
if (!password || strcmp(password, Network::password) != 0) {
connection.authstatus = NETWORK_AUTH_BADPASSWORD;
if (connection.authstatus != NETWORK_AUTH_OK) {
const char* gameversion = packet.ReadString();
const char* name = packet.ReadString();
const char* password = packet.ReadString();
if (!gameversion || strcmp(gameversion, OPENRCT2_VERSION) != 0) {
connection.authstatus = NETWORK_AUTH_BADVERSION;
} else
if (!name) {
connection.authstatus = NETWORK_AUTH_BADNAME;
} else
if (!password || strcmp(password, Network::password) != 0) {
connection.authstatus = NETWORK_AUTH_BADPASSWORD;
} else {
connection.authstatus = NETWORK_AUTH_OK;
std::unique_ptr<NetworkPlayer> player(new NetworkPlayer(name)); // change to make_unique in c++14
printf("New player: %s\n", player->name);
connection.player = player.get();
player_list.push_back(std::move(player));
Server_Send_PLAYERLIST();
}
std::unique_ptr<NetworkPacket> responsepacket = NetworkPacket::AllocatePacket();
*responsepacket << (uint32)NETWORK_COMMAND_AUTH << (uint32)connection.authstatus;
connection.QueuePacket(std::move(responsepacket));
}
std::unique_ptr<NetworkPacket> responsepacket = NetworkPacket::AllocatePacket();
*responsepacket << (uint32)NETWORK_COMMAND_AUTH << (uint32)connection.authstatus;
connection.QueuePacket(std::move(responsepacket));
return 1;
}
@ -598,6 +653,9 @@ int Network::Client_Handle_MAP(NetworkConnection& connection, NetworkPacket& pac
SDL_RWops* rw = SDL_RWFromMem(&chunk_buffer[0], size);
if (game_load_sv6(rw)) {
game_load_init();
if (RCT2_GLOBAL(RCT2_ADDRESS_GAME_PAUSED, uint8) & 1)
pause_toggle();
game_command_queue.clear();
}
SDL_RWclose(rw);
}
@ -661,6 +719,23 @@ int Network::Client_Handle_TICK(NetworkConnection& connection, NetworkPacket& pa
return 1;
}
int Network::Client_Handle_PLAYERLIST(NetworkConnection& connection, NetworkPacket& packet)
{
player_list.clear();
uint32 size;
packet >> size;
for (unsigned int i = 0; i < size; i++) {
const char* name = packet.ReadString();
std::unique_ptr<NetworkPlayer> player(new NetworkPlayer(name)); // change to make_unique in c++14
packet >> player->id >> player->flags;
if (player->flags & NETWORK_PLAYER_FLAG_ISSERVER) {
server_connection.player = player.get();
}
player_list.push_back(std::move(player));
}
return 1;
}
int network_init()
{
return gNetwork.Init();
@ -691,11 +766,26 @@ int network_get_mode()
return gNetwork.GetMode();
}
int network_get_authstatus()
{
return gNetwork.GetAuthStatus();
}
uint32 network_get_server_tick()
{
return gNetwork.GetServerTick();
}
int network_get_num_players()
{
return gNetwork.player_list.size();
}
const char* network_get_player_name(unsigned int index)
{
return (const char*)gNetwork.player_list[index]->name;
}
void network_send_map()
{
gNetwork.Server_Send_MAP();

View File

@ -40,6 +40,10 @@ enum {
NETWORK_AUTH_BADPASSWORD
};
enum {
NETWORK_PLAYER_FLAG_ISSERVER = 1 << 0,
};
#ifdef __cplusplus
#include <list>
@ -54,6 +58,8 @@ extern "C" {
template <std::size_t size>
struct ByteSwapT { };
template <>
struct ByteSwapT<1> { static uint8 SwapBE(uint8 value) { return value; } };
template <>
struct ByteSwapT<2> { static uint16 SwapBE(uint16 value) { return SDL_SwapBE16(value); } };
template <>
struct ByteSwapT<4> { static uint32 SwapBE(uint32 value) { return SDL_SwapBE32(value); } };
@ -83,6 +89,16 @@ public:
int read;
};
class NetworkPlayer
{
public:
NetworkPlayer(const char* name);
uint8 id;
uint8 name[32 + 1];
uint16 ping;
uint32 flags;
};
class NetworkConnection
{
public:
@ -94,19 +110,13 @@ public:
SOCKET socket;
NetworkPacket inboundpacket;
int authstatus;
NetworkPlayer* player;
private:
int SendPacket(NetworkPacket& packet);
std::list<std::unique_ptr<NetworkPacket>> outboundpackets;
};
class NetworkPlayer
{
public:
uint8 name[16 + 1];
uint16 ping;
};
class Network
{
public:
@ -117,6 +127,7 @@ public:
bool BeginClient(const char* host, unsigned short port);
bool BeginServer(unsigned short port);
int GetMode();
int GetAuthStatus();
uint32 GetServerTick();
void Update();
@ -127,6 +138,9 @@ public:
void Client_Send_GAMECMD(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp);
void Server_Send_GAMECMD(uint32 eax, uint32 ebx, uint32 ecx, uint32 edx, uint32 esi, uint32 edi, uint32 ebp);
void Server_Send_TICK();
void Server_Send_PLAYERLIST();
std::vector<std::unique_ptr<NetworkPlayer>> player_list;
private:
bool ProcessConnection(NetworkConnection& connection);
@ -169,6 +183,7 @@ private:
int Client_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket& packet);
int Server_Handle_GAMECMD(NetworkConnection& connection, NetworkPacket& packet);
int Client_Handle_TICK(NetworkConnection& connection, NetworkPacket& packet);
int Client_Handle_PLAYERLIST(NetworkConnection& connection, NetworkPacket& packet);
};
extern "C" {
@ -181,7 +196,10 @@ int network_begin_server(int port);
void network_update();
int network_get_mode();
int network_get_authstatus();
uint32 network_get_server_tick();
int network_get_num_players();
const char* network_get_player_name(unsigned int index);
void network_send_map();
void network_send_chat(const char* text);

View File

@ -18,12 +18,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*****************************************************************************/
#include "../interface/themes.h"
#include "../interface/widget.h"
#include "../interface/window.h"
#include "../localisation/localisation.h"
#include "../network/network.h"
static void window_chat_host_emptysub() { }
static void window_chat_host_textinput(rct_window *w, int widgetIndex, char *text)
{
network_send_chat(text);
@ -71,4 +71,213 @@ void window_chat_open()
w->colours[2] = 0;
w->number = 0;
window_text_input_open(w, 0, 6000, 6001, STR_NONE, 0, 64);
}
enum WINDOW_PLAYER_LIST_WIDGET_IDX {
WIDX_BACKGROUND,
WIDX_TITLE,
WIDX_CLOSE,
WIDX_CONTENT_PANEL,
WIDX_TAB1,
WIDX_LIST,
};
static rct_widget window_player_list_widgets[] = {
{ WWT_FRAME, 0, 0, 319, 0, 269, 0x0FFFFFFFF, 65535 }, // panel / background
{ WWT_CAPTION, 0, 1, 318, 1, 14, STR_PLAYER_LIST, STR_WINDOW_TITLE_TIP }, // title bar
{ WWT_CLOSEBOX, 0, 307, 317, 2, 13, STR_CLOSE_X, STR_CLOSE_WINDOW_TIP }, // close x button
{ WWT_RESIZE, 1, 0, 319, 43, 269, 0x0FFFFFFFF, STR_NONE }, // content panel
{ WWT_TAB, 1, 3, 33, 17, 43, 0x02000144E, STR_NONE }, // tab
{ WWT_SCROLL, 1, 3, 316, 72, 266, 3, 65535 }, // list
{ WIDGETS_END },
};
static void window_player_list_mouseup(rct_window *w, int widgetIndex);
static void window_player_list_resize(rct_window *w);
static void window_player_list_mousedown(int widgetIndex, rct_window* w, rct_widget* widget);
static void window_player_list_update(rct_window *w);
static void window_player_list_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height);
static void window_player_list_invalidate(rct_window *w);
static void window_player_list_paint(rct_window *w, rct_drawpixelinfo *dpi);
static void window_player_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex);
static rct_window_event_list window_player_list_events = {
NULL,
window_player_list_mouseup,
window_player_list_resize,
window_player_list_mousedown,
NULL,
NULL,
window_player_list_update,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
window_player_list_scrollgetsize,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
NULL,
window_player_list_invalidate,
window_player_list_paint,
window_player_list_scrollpaint
};
static void window_player_list_refresh_list(rct_window *w);
void window_player_list_open()
{
rct_window* window;
// Check if window is already open
window = window_bring_to_front_by_class(WC_PLAYER_LIST);
if (window != NULL)
return;
window = window_create_auto_pos(320, 270, &window_player_list_events, WC_PLAYER_LIST, WF_10 | WF_RESIZABLE);
window->widgets = window_player_list_widgets;
window->enabled_widgets = 1 << WIDX_CLOSE;
window->no_list_items = 0;
window->selected_list_item = -1;
window->frame_no = 0;
window->min_width = 320;
window->min_height = 270;
window->max_width = 500;
window->max_height = 450;
window_init_scroll_widgets(window);
window->page = 0;
window->list_information_type = 0;
window->colours[0] = 7;
window->colours[1] = 7;
window->colours[2] = 7;
}
static void window_player_list_mouseup(rct_window *w, int widgetIndex)
{
switch (widgetIndex) {
case WIDX_CLOSE:
window_close(w);
break;
}
}
static void window_player_list_resize(rct_window *w)
{
if (w->width < w->min_width) {
window_invalidate(w);
w->width = w->min_width;
}
if (w->height < w->min_height) {
window_invalidate(w);
w->height = w->min_height;
}
window_player_list_refresh_list(w);
}
static void window_player_list_mousedown(int widgetIndex, rct_window* w, rct_widget* widget)
{
switch (widgetIndex) {
case WIDX_TAB1:
if (w->page != widgetIndex - WIDX_TAB1) {
w->page = widgetIndex - WIDX_TAB1;
w->no_list_items = 0;
w->frame_no = 0;
w->selected_list_item = -1;
window_invalidate(w);
}
break;
}
}
static void window_player_list_update(rct_window *w)
{
widget_invalidate(w, WIDX_TAB1 + w->page);
}
static void window_player_list_scrollgetsize(rct_window *w, int scrollIndex, int *width, int *height)
{
int i;
uint16 playerCount = 0;
if (RCT2_GLOBAL(RCT2_ADDRESS_STAFF_HIGHLIGHTED_INDEX, short) != -1) {
RCT2_GLOBAL(RCT2_ADDRESS_STAFF_HIGHLIGHTED_INDEX, short) = -1;
window_invalidate(w);
}
*height = playerCount * 10;
i = *height - window_player_list_widgets[WIDX_LIST].bottom + window_player_list_widgets[WIDX_LIST].top + 21;
if (i < 0)
i = 0;
if (i < w->scrolls[0].v_top) {
w->scrolls[0].v_top = i;
window_invalidate(w);
}
*width = 420;
}
static void window_player_list_invalidate(rct_window *w)
{
for (int i = 0; i < 1; i++)
w->pressed_widgets &= ~(1 << (WIDX_TAB1 + i));
w->pressed_widgets |= 1LL << (WIDX_TAB1 + w->page);
window_player_list_widgets[WIDX_BACKGROUND].right = w->width - 1;
window_player_list_widgets[WIDX_BACKGROUND].bottom = w->height - 1;
window_player_list_widgets[WIDX_CONTENT_PANEL].right = w->width - 1;
window_player_list_widgets[WIDX_CONTENT_PANEL].bottom = w->height - 1;
window_player_list_widgets[WIDX_TITLE].right = w->width - 2;
window_player_list_widgets[WIDX_CLOSE].left = w->width - 2 - 0x0B;
window_player_list_widgets[WIDX_CLOSE].right = w->width - 2 - 0x0B + 0x0A;
window_player_list_widgets[WIDX_LIST].right = w->width - 4;
window_player_list_widgets[WIDX_LIST].bottom = w->height - 0x0F;
}
static void window_player_list_paint(rct_window *w, rct_drawpixelinfo *dpi)
{
window_draw_widgets(w, dpi);
}
static void window_player_list_scrollpaint(rct_window *w, rct_drawpixelinfo *dpi, int scrollIndex)
{
int y;
gfx_fill_rect(dpi, dpi->x, dpi->y, dpi->x + dpi->width - 1, dpi->y + dpi->height - 1, ((char*)0x0141FC48)[w->colours[1] * 8]);
y = 0;
for (int i = 0; i < network_get_num_players(); i++) {
if (y > dpi->y + dpi->height) {
break;
}
int format = 1191;
if (y + 11 >= dpi->y) {
gfx_draw_string(dpi, (char*)network_get_player_name(i), 255, 0, y - 1);
}
y += 10;
}
}
static void window_player_list_refresh_list(rct_window *w)
{
window_invalidate(w);
w->no_list_items = 1;
w->list_item_positions[0] = 0;
w->selected_list_item = -1;
window_invalidate(w);
}

View File

@ -65,6 +65,7 @@ enum {
WIDX_FINANCES,
WIDX_RESEARCH,
WIDX_NEWS,
WIDX_NETWORK,
WIDX_SEPARATOR,
};
@ -105,6 +106,10 @@ typedef enum {
DDIDX_SCENARIO_OPTIONS = 4
} TOP_TOOLBAR_DEBUG_DDIDX;
typedef enum {
DDIDX_PLAYER_LIST = 0
} TOP_TOOLBAR_NETWORK_DDIDX;
enum {
DDIDX_CHEATS,
DDIDX_ENABLE_SANDBOX_MODE = 2,
@ -129,6 +134,7 @@ static const int left_aligned_widgets_order[] = {
WIDX_ROTATE,
WIDX_VIEW_MENU,
WIDX_MAP,
WIDX_NETWORK,
};
// from right to left
@ -179,6 +185,7 @@ static rct_widget window_top_toolbar_widgets[] = {
{ WWT_TRNBTN, 3, 0x001E, 0x003B, 0, 27, 0x20000000 | 0x15F9, 3235 }, // Finances
{ WWT_TRNBTN, 3, 0x001E, 0x003B, 0, 27, 0x20000000 | 0x15F9, 2275 }, // Research
{ WWT_TRNBTN, 3, 0x001E, 0x003B, 0, 27, 0x20000000 | 0x15F9, STR_SHOW_RECENT_MESSAGES_TIP }, // News
{ WWT_TRNBTN, 1, 0x001E, 0x003B, 0, 27, 0x20000000 | 0x15F9, 2276 }, // Network
{ WWT_EMPTY, 0, 0, 10-1, 0, 0, 0xFFFFFFFF, STR_NONE }, // Artificial widget separator
{ WIDGETS_END },
@ -234,6 +241,8 @@ void top_toolbar_init_rotate_menu(rct_window *window, rct_widget *widget);
void top_toolbar_rotate_menu_dropdown(short dropdownIndex);
void top_toolbar_init_debug_menu(rct_window *window, rct_widget *widget);
void top_toolbar_debug_menu_dropdown(short dropdownIndex);
void top_toolbar_init_network_menu(rct_window *window, rct_widget *widget);
void top_toolbar_network_menu_dropdown(short dropdownIndex);
void toggle_footpath_window();
void toggle_land_window(rct_window *topToolbar, int widgetIndex);
@ -461,6 +470,9 @@ static void window_top_toolbar_mousedown(int widgetIndex, rct_window*w, rct_widg
case WIDX_DEBUG:
top_toolbar_init_debug_menu(w, widget);
break;
case WIDX_NETWORK:
top_toolbar_init_network_menu(w, widget);
break;
}
}
@ -560,6 +572,9 @@ static void window_top_toolbar_dropdown(rct_window *w, int widgetIndex, int drop
case WIDX_DEBUG:
top_toolbar_debug_menu_dropdown(dropdownIndex);
break;
case WIDX_NETWORK:
top_toolbar_network_menu_dropdown(dropdownIndex);
break;
}
}
@ -598,6 +613,7 @@ static void window_top_toolbar_invalidate(rct_window *w)
window_top_toolbar_widgets[WIDX_CHEATS].type = WWT_TRNBTN;
window_top_toolbar_widgets[WIDX_DEBUG].type = gConfigGeneral.debugging_tools ? WWT_TRNBTN : WWT_EMPTY;
window_top_toolbar_widgets[WIDX_NEWS].type = WWT_TRNBTN;
window_top_toolbar_widgets[WIDX_NETWORK].type = WWT_TRNBTN;
if (RCT2_GLOBAL(RCT2_ADDRESS_SCREEN_FLAGS, uint8) & (SCREEN_FLAGS_SCENARIO_EDITOR | SCREEN_FLAGS_TRACK_DESIGNER | SCREEN_FLAGS_TRACK_MANAGER)) {
window_top_toolbar_widgets[WIDX_PAUSE].type = WWT_EMPTY;
@ -645,7 +661,7 @@ static void window_top_toolbar_invalidate(rct_window *w)
}
enabledWidgets = 0;
for (i = WIDX_PAUSE; i <= WIDX_NEWS; i++)
for (i = WIDX_PAUSE; i <= WIDX_NETWORK; i++)
if (window_top_toolbar_widgets[i].type != WWT_EMPTY)
enabledWidgets |= (1 << i);
w->enabled_widgets = enabledWidgets;
@ -2862,6 +2878,21 @@ void top_toolbar_init_debug_menu(rct_window* w, rct_widget* widget) {
RCT2_GLOBAL(0x9DEBA2, uint16) = 0;
}
void top_toolbar_init_network_menu(rct_window* w, rct_widget* widget) {
gDropdownItemsFormat[0] = STR_PLAYER_LIST;
window_dropdown_show_text(
w->x + widget->left,
w->y + widget->top,
widget->bottom - widget->top + 1,
w->colours[1] | 0x80,
0,
1
);
RCT2_GLOBAL(0x9DEBA2, uint16) = 0;
}
void top_toolbar_debug_menu_dropdown(short dropdownIndex) {
if (dropdownIndex == -1) dropdownIndex = RCT2_GLOBAL(0x9DEBA2, uint16);
rct_window* w = window_get_main();
@ -2887,6 +2918,18 @@ void top_toolbar_debug_menu_dropdown(short dropdownIndex) {
}
}
void top_toolbar_network_menu_dropdown(short dropdownIndex) {
if (dropdownIndex == -1) dropdownIndex = RCT2_GLOBAL(0x9DEBA2, uint16);
rct_window* w = window_get_main();
if (w) {
switch (dropdownIndex) {
case DDIDX_PLAYER_LIST:
window_player_list_open();
break;
}
}
}
/**
*
* rct2: 0x0066CDE4