mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-29 01:35:06 +01:00
get basic network game working
This commit is contained in:
@@ -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 */
|
||||
|
||||
|
||||
Reference in New Issue
Block a user