mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-15 11:03:00 +01:00
get basic network game working
This commit is contained in:
@@ -1,21 +1,23 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<ShowAllFiles>false</ShowAllFiles>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LocalDebuggerCommand>$(TargetDir)\openrct2.exe</LocalDebuggerCommand>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
<LocalDebuggerWorkingDirectory>$(TargetDir)</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LocalDebuggerWorkingDirectory>$(TargetDir)</LocalDebuggerWorkingDirectory>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
<LocalDebuggerCommand>$(TargetDir)\openrct2.exe</LocalDebuggerCommand>
|
||||
<LocalDebuggerCommandArguments>
|
||||
</LocalDebuggerCommandArguments>
|
||||
<LocalDebuggerCommandArguments>"C:\Program Files (x86)\Infogrames\RollerCoaster Tycoon 2\Scenarios\Crazy Castle.SC6" --port 5552 --server 127.0.0.1</LocalDebuggerCommandArguments>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release with Tests|Win32'">
|
||||
<LocalDebuggerWorkingDirectory>$(TargetDir)</LocalDebuggerWorkingDirectory>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
<LocalDebuggerCommand>$(TargetDir)\openrct2.exe</LocalDebuggerCommand>
|
||||
<LocalDebuggerCommandArguments>
|
||||
</LocalDebuggerCommandArguments>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ShowAllFiles>false</ShowAllFiles>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LocalDebuggerCommand>$(TargetDir)\openrct2.exe</LocalDebuggerCommand>
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
#include "addresses.h"
|
||||
#include "cmdline.h"
|
||||
#include "interface/screenshot.h"
|
||||
#include "network/network.h"
|
||||
#include "openrct2.h"
|
||||
#include "platform/platform.h"
|
||||
#include "util/util.h"
|
||||
@@ -64,13 +65,16 @@ static const char *const usage[] = {
|
||||
int cmdline_run(const char **argv, int argc)
|
||||
{
|
||||
//
|
||||
int version = 0, verbose = 0, width = 0, height = 0;
|
||||
int version = 0, verbose = 0, width = 0, height = 0, port = 0;
|
||||
char *server = NULL;
|
||||
|
||||
argparse_option_t options[] = {
|
||||
OPT_HELP(),
|
||||
OPT_BOOLEAN('v', "version", &version, "show version information and exit"),
|
||||
OPT_BOOLEAN(0, "verbose", &verbose, "log verbose messages"),
|
||||
OPT_INTEGER('m', "mode", &sprite_mode, "the type of sprite conversion. 0 = default, 1 = simple closest pixel match, 2 = dithering"),
|
||||
OPT_STRING(0, "server", &server, "server to connect to"),
|
||||
OPT_INTEGER(0, "port", &port, "port"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
@@ -88,6 +92,16 @@ int cmdline_run(const char **argv, int argc)
|
||||
if (verbose)
|
||||
_log_levels[DIAGNOSTIC_LEVEL_VERBOSE] = 1;
|
||||
|
||||
if (port != 0) {
|
||||
gNetworkStart = NETWORK_SERVER;
|
||||
gNetworkStartPort = port;
|
||||
}
|
||||
|
||||
if (server != NULL) {
|
||||
gNetworkStart = NETWORK_CLIENT;
|
||||
strncpy(gNetworkStartHost, server, sizeof(gNetworkStartHost));
|
||||
}
|
||||
|
||||
if (argc != 0) {
|
||||
gExitCode = cmdline_call_action(argv, argc);
|
||||
if (gExitCode != 0)
|
||||
|
||||
30
src/game.c
30
src/game.c
@@ -34,6 +34,7 @@
|
||||
#include "management/marketing.h"
|
||||
#include "management/news_item.h"
|
||||
#include "management/research.h"
|
||||
#include "network/network.h"
|
||||
#include "object.h"
|
||||
#include "openrct2.h"
|
||||
#include "peep/peep.h"
|
||||
@@ -389,6 +390,35 @@ int game_do_command_p(int command, int *eax, int *ebx, int *ecx, int *edx, int *
|
||||
int cost, flags, insufficientFunds;
|
||||
int original_ebx, original_edx, original_esi, original_edi, original_ebp;
|
||||
|
||||
int sendPacket = 0;
|
||||
if (gNetworkStatus == NETWORK_CLIENT) {
|
||||
if (command & (1 << 31)) {
|
||||
command &= ~(1 << 31);
|
||||
} else {
|
||||
sendPacket = 1;
|
||||
}
|
||||
} else if (gNetworkStatus == NETWORK_SERVER) {
|
||||
sendPacket = 1;
|
||||
}
|
||||
|
||||
if (sendPacket) {
|
||||
network_packet packet;
|
||||
packet.size = 8 * 4;
|
||||
uint32 *args = (uint32*)&packet.data;
|
||||
args[0] = command;
|
||||
args[1] = *eax;
|
||||
args[2] = *ebx;
|
||||
args[3] = *ecx;
|
||||
args[4] = *edx;
|
||||
args[5] = *esi;
|
||||
args[6] = *edi;
|
||||
args[7] = *ebp;
|
||||
network_send_packet(&packet);
|
||||
|
||||
if (gNetworkStatus == NETWORK_CLIENT)
|
||||
return MONEY32_UNDEFINED;
|
||||
}
|
||||
|
||||
*esi = command;
|
||||
original_ebx = *ebx;
|
||||
original_edx = *edx;
|
||||
|
||||
@@ -20,14 +20,24 @@
|
||||
|
||||
#ifndef DISABLE_NETWORK
|
||||
|
||||
#include "../game.h"
|
||||
#include "network.h"
|
||||
|
||||
#pragma comment(lib, "Ws2_32.lib")
|
||||
|
||||
int gNetworkStart = NETWORK_NONE;
|
||||
char gNetworkStartHost[128];
|
||||
int gNetworkStartPort = NETWORK_DEFAULT_PORT;
|
||||
int gNetworkStatus = NETWORK_NONE;
|
||||
|
||||
static int _wsaInitialised = 0;
|
||||
static WSADATA _wsaData;
|
||||
static SOCKET _serverSocket;
|
||||
static SOCKET _clientSocket;
|
||||
|
||||
static int network_get_next_packet(network_packet *outPacket);
|
||||
static void network_process_packet(network_packet *packet);
|
||||
|
||||
int network_init()
|
||||
{
|
||||
if (!_wsaInitialised) {
|
||||
@@ -44,15 +54,63 @@ int network_init()
|
||||
|
||||
void network_close()
|
||||
{
|
||||
if (!_wsaInitialised)
|
||||
return;
|
||||
|
||||
if (gNetworkStatus == NETWORK_CLIENT)
|
||||
network_end_client();
|
||||
else if (gNetworkStatus == NETWORK_SERVER)
|
||||
network_end_server();
|
||||
|
||||
log_verbose("Closing WSA");
|
||||
WSACleanup();
|
||||
_wsaInitialised = 0;
|
||||
}
|
||||
|
||||
int network_begin_client(const char *host, int port)
|
||||
{
|
||||
SOCKADDR_IN serverAddress;
|
||||
u_long iMode;
|
||||
|
||||
if (!network_init())
|
||||
return 0;
|
||||
|
||||
_serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
if (_serverSocket == INVALID_SOCKET) {
|
||||
log_error("Unable to create socket.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
serverAddress.sin_family = AF_INET;
|
||||
serverAddress.sin_addr.S_un.S_addr = inet_addr(host);
|
||||
serverAddress.sin_port = htons(port);
|
||||
|
||||
if (connect(_serverSocket, (SOCKADDR*)&serverAddress, sizeof(SOCKADDR_IN)) != 0) {
|
||||
log_error("Unable to connect to host.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
iMode = 1;
|
||||
if (ioctlsocket(_serverSocket, FIONBIO, &iMode) != NO_ERROR) {
|
||||
closesocket(_serverSocket);
|
||||
log_error("Failed to set non-blocking mode.");
|
||||
}
|
||||
|
||||
gNetworkStatus = NETWORK_CLIENT;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void network_end_client()
|
||||
{
|
||||
gNetworkStatus = NETWORK_NONE;
|
||||
closesocket(_serverSocket);
|
||||
}
|
||||
|
||||
int network_begin_server(int port)
|
||||
{
|
||||
SOCKET listeningSocket;
|
||||
SOCKADDR_IN localAddress;
|
||||
u_long iMode;
|
||||
|
||||
if (!network_init())
|
||||
return 0;
|
||||
@@ -65,7 +123,7 @@ int network_begin_server(int port)
|
||||
}
|
||||
|
||||
localAddress.sin_family = AF_INET;
|
||||
localAddress.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
|
||||
localAddress.sin_addr.S_un.S_addr = INADDR_ANY;
|
||||
localAddress.sin_port = htons(port);
|
||||
|
||||
if (bind(listeningSocket, (SOCKADDR*)&localAddress, sizeof(SOCKADDR_IN)) != 0) {
|
||||
@@ -89,23 +147,106 @@ int network_begin_server(int port)
|
||||
}
|
||||
|
||||
closesocket(listeningSocket);
|
||||
printf("Connected to client!");
|
||||
|
||||
iMode = 1;
|
||||
if (ioctlsocket(_clientSocket, FIONBIO, &iMode) != NO_ERROR) {
|
||||
closesocket(_clientSocket);
|
||||
log_error("Failed to set non-blocking mode.");
|
||||
}
|
||||
|
||||
printf("Connected to client!\n");
|
||||
gNetworkStatus = NETWORK_SERVER;
|
||||
return 1;
|
||||
}
|
||||
|
||||
void network_end_server()
|
||||
{
|
||||
gNetworkStatus = NETWORK_NONE;
|
||||
closesocket(_clientSocket);
|
||||
}
|
||||
|
||||
int network_send_data(uint8 *data, int length)
|
||||
void network_update()
|
||||
{
|
||||
return send(_clientSocket, data, length, 0);
|
||||
SOCKET socket;
|
||||
int packetStatus;
|
||||
network_packet packet;
|
||||
|
||||
if (gNetworkStatus == NETWORK_NONE)
|
||||
return;
|
||||
|
||||
socket = gNetworkStatus == NETWORK_CLIENT ? _serverSocket : _clientSocket;
|
||||
|
||||
do {
|
||||
packetStatus = network_get_next_packet(&packet);
|
||||
if (packetStatus == NETWORK_DISCONNECTED) {
|
||||
network_print_error();
|
||||
if (gNetworkStatus == NETWORK_CLIENT) {
|
||||
network_end_client();
|
||||
printf("Server disconnected...\n");
|
||||
return;
|
||||
} else if (gNetworkStatus == NETWORK_SERVER) {
|
||||
network_end_server();
|
||||
printf("client disconnected...\n");
|
||||
return;
|
||||
}
|
||||
} else if (packetStatus == NETWORK_SUCCESS) {
|
||||
network_process_packet(&packet);
|
||||
}
|
||||
} while (packetStatus == NETWORK_SUCCESS);
|
||||
}
|
||||
|
||||
int network_receive_data(uint8 *data, int maxLength)
|
||||
static int network_get_next_packet(network_packet *outPacket)
|
||||
{
|
||||
return recv(_clientSocket, data, maxLength, 0);
|
||||
SOCKET socket;
|
||||
int readBytes;
|
||||
|
||||
socket = gNetworkStatus == NETWORK_CLIENT ? _serverSocket : _clientSocket;
|
||||
|
||||
readBytes = recv(socket, (char*)&outPacket->size, sizeof(outPacket->size), 0);
|
||||
if (readBytes == SOCKET_ERROR && WSAGetLastError() != WSAEWOULDBLOCK)
|
||||
return NETWORK_DISCONNECTED;
|
||||
|
||||
if (readBytes != sizeof(outPacket->size))
|
||||
return NETWORK_NO_DATA;
|
||||
|
||||
readBytes = recv(socket, (char*)&outPacket->data, outPacket->size, 0);
|
||||
if (readBytes != outPacket->size)
|
||||
return NETWORK_NO_DATA;
|
||||
|
||||
return NETWORK_SUCCESS;
|
||||
}
|
||||
|
||||
static void network_process_packet(network_packet *packet)
|
||||
{
|
||||
uint32 *args;
|
||||
int command;
|
||||
|
||||
args = (uint32*)&packet->data;
|
||||
command = args[0];
|
||||
|
||||
if (gNetworkStatus == NETWORK_CLIENT)
|
||||
command |= (1 << 31);
|
||||
|
||||
game_do_command_p(command, &args[1], &args[2], &args[3], &args[4], &args[5], &args[6], &args[7]);
|
||||
}
|
||||
|
||||
void network_send_packet(network_packet *packet)
|
||||
{
|
||||
SOCKET socket;
|
||||
|
||||
if (gNetworkStatus == NETWORK_NONE)
|
||||
return;
|
||||
|
||||
socket = gNetworkStatus == NETWORK_CLIENT ? _serverSocket : _clientSocket;
|
||||
send(socket, (char*)packet, 2 + packet->size, 0);
|
||||
}
|
||||
|
||||
void network_print_error()
|
||||
{
|
||||
wchar_t *s = NULL;
|
||||
FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&s, 0, NULL);
|
||||
fprintf(stderr, "%S\n", s);
|
||||
LocalFree(s);
|
||||
}
|
||||
|
||||
#endif /* DISABLE_NETWORK */
|
||||
@@ -27,15 +27,41 @@
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
typedef struct {
|
||||
uint16 size;
|
||||
uint8 data[128];
|
||||
} network_packet;
|
||||
|
||||
#define NETWORK_DEFAULT_PORT 11753
|
||||
|
||||
enum {
|
||||
NETWORK_NONE,
|
||||
NETWORK_CLIENT,
|
||||
NETWORK_SERVER
|
||||
};
|
||||
|
||||
enum {
|
||||
NETWORK_SUCCESS,
|
||||
NETWORK_NO_DATA,
|
||||
NETWORK_DISCONNECTED
|
||||
};
|
||||
|
||||
extern int gNetworkStart;
|
||||
extern char gNetworkStartHost[128];
|
||||
extern int gNetworkStartPort;
|
||||
extern int gNetworkStatus;
|
||||
|
||||
int network_init();
|
||||
void network_close();
|
||||
int network_begin_client(const char *host, int port);
|
||||
void network_end_client();
|
||||
int network_begin_server(int port);
|
||||
void network_end_server();
|
||||
|
||||
int network_send_data(uint8 *data, int length);
|
||||
int network_receive_data(uint8 *data, int maxLength);
|
||||
void network_update();
|
||||
void network_send_packet(network_packet *packet);
|
||||
|
||||
void network_print_error();
|
||||
|
||||
#endif /* DISABLE_NETWORK */
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "interface/viewport.h"
|
||||
#include "localisation/localisation.h"
|
||||
#include "network/http.h"
|
||||
#include "network/network.h"
|
||||
#include "openrct2.h"
|
||||
#include "platform/platform.h"
|
||||
#include "ride/ride.h"
|
||||
@@ -168,10 +169,10 @@ bool openrct2_initialise()
|
||||
config_save_default();
|
||||
|
||||
// TODO add configuration option to allow multiple instances
|
||||
if (!gOpenRCT2Headless && !platform_lock_single_instance()) {
|
||||
log_fatal("OpenRCT2 is already running.");
|
||||
return false;
|
||||
}
|
||||
// if (!gOpenRCT2Headless && !platform_lock_single_instance()) {
|
||||
// log_fatal("OpenRCT2 is already running.");
|
||||
// return false;
|
||||
// }
|
||||
|
||||
get_system_info();
|
||||
if (!gOpenRCT2Headless) {
|
||||
@@ -248,7 +249,14 @@ void openrct2_launch()
|
||||
editor_load_landscape(gOpenRCT2StartupActionPath);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (gNetworkStart == NETWORK_CLIENT) {
|
||||
network_begin_client(gNetworkStartHost, gNetworkStartPort);
|
||||
} else if (gNetworkStart == NETWORK_SERVER) {
|
||||
network_begin_server(gNetworkStartPort);
|
||||
}
|
||||
|
||||
openrct2_loop();
|
||||
}
|
||||
openrct2_dispose();
|
||||
@@ -259,6 +267,7 @@ void openrct2_launch()
|
||||
|
||||
void openrct2_dispose()
|
||||
{
|
||||
network_close();
|
||||
http_dispose();
|
||||
language_close_all();
|
||||
platform_free();
|
||||
@@ -344,6 +353,7 @@ static void openrct2_loop()
|
||||
}
|
||||
|
||||
platform_process_messages();
|
||||
network_update();
|
||||
rct2_draw();
|
||||
platform_draw();
|
||||
fps++;
|
||||
@@ -373,6 +383,7 @@ static void openrct2_loop()
|
||||
lastTick = currentTick;
|
||||
|
||||
platform_process_messages();
|
||||
network_update();
|
||||
|
||||
rct2_update();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user