summaryrefslogtreecommitdiff
path: root/network
diff options
context:
space:
mode:
authorrubidium <rubidium@openttd.org>2007-01-02 19:19:48 +0000
committerrubidium <rubidium@openttd.org>2007-01-02 19:19:48 +0000
commit66bbf336c6af7353ef0aeed58002c46543b30635 (patch)
treead4a63860df2626b22f77e7dac712e958bea54cb /network
parentccc0a3f4dbf58c005b22341ac8874252924690cd (diff)
downloadopenttd-66bbf336c6af7353ef0aeed58002c46543b30635.tar.xz
(svn r7759) -Merge: makefile rewrite. This merge features:
- A proper ./configure, so everything needs to be configured only once, not for every make. - Usage of makedepend when available. This greatly reduces the time needed for generating the dependencies. - A generator for all project files. There is a single file with sources, which is used to generate Makefiles and the project files for MSVC. - Proper support for OSX universal binaries. - Object files for non-MSVC compiles are also placed in separate directories, making is faster to switch between debug and release compiles and it does not touch the directory with the source files. - Functionality to make a bundle of all needed files for for example a nightly or distribution of a binary with all needed GRFs and language files. Note: as this merge moves almost all files, it is recommended to make a backup of your working copy before updating your working copy.
Diffstat (limited to 'network')
-rw-r--r--network/core/config.h49
-rw-r--r--network/core/game.h47
-rw-r--r--network/core/os_abstraction.h181
-rw-r--r--network/core/packet.c216
-rw-r--r--network/core/packet.h67
-rw-r--r--network/core/tcp.c227
-rw-r--r--network/core/tcp.h60
-rw-r--r--network/core/udp.c277
-rw-r--r--network/core/udp.h62
-rw-r--r--network/network.c1451
-rw-r--r--network/network.h212
-rw-r--r--network/network_client.c819
-rw-r--r--network/network_client.h25
-rw-r--r--network/network_data.c106
-rw-r--r--network/network_data.h167
-rw-r--r--network/network_gamelist.c74
-rw-r--r--network/network_gamelist.h11
-rw-r--r--network/network_gui.c1706
-rw-r--r--network/network_gui.h26
-rw-r--r--network/network_server.c1528
-rw-r--r--network/network_server.h39
-rw-r--r--network/network_udp.c663
-rw-r--r--network/network_udp.h17
23 files changed, 0 insertions, 8030 deletions
diff --git a/network/core/config.h b/network/core/config.h
deleted file mode 100644
index 0b80800f0..000000000
--- a/network/core/config.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* $Id$ */
-
-#ifndef NETWORK_CORE_CONFIG_H
-#define NETWORK_CORE_CONFIG_H
-
-#ifdef ENABLE_NETWORK
-
-/** DNS hostname of the masterserver */
-#define NETWORK_MASTER_SERVER_HOST "master.openttd.org"
-/** Message sent to the masterserver to 'identify' this client as OpenTTD */
-#define NETWORK_MASTER_SERVER_WELCOME_MESSAGE "OpenTTDRegister"
-
-enum {
- NETWORK_MASTER_SERVER_PORT = 3978, ///< The default port of the master server (UDP)
- NETWORK_DEFAULT_PORT = 3979, ///< The default port of the game server (TCP & UDP)
-
- SEND_MTU = 1460, ///< Number of bytes we can pack in a single packet
-
- NETWORK_GAME_INFO_VERSION = 4, ///< What version of game-info do we use?
- NETWORK_COMPANY_INFO_VERSION = 4, ///< What version of company info is this?
- NETWORK_MASTER_SERVER_VERSION = 1, ///< What version of master-server-protocol do we use?
-
- NETWORK_NAME_LENGTH = 80, ///< The maximum length of the server name and map name, in bytes including '\0'
- NETWORK_HOSTNAME_LENGTH = 80, ///< The maximum length of the host name, in bytes including '\0'
- NETWORK_REVISION_LENGTH = 15, ///< The maximum length of the revision, in bytes including '\0'
- NETWORK_PASSWORD_LENGTH = 20, ///< The maximum length of the password, in bytes including '\0'
- NETWORK_PLAYERS_LENGTH = 200, ///< The maximum length for the list of players that controls a company, in bytes including '\0'
- NETWORK_CLIENT_NAME_LENGTH = 25, ///< The maximum length of a player, in bytes including '\0'
- NETWORK_RCONCOMMAND_LENGTH = 500, ///< The maximum length of a rconsole command, in bytes including '\0'
-
- NETWORK_GRF_NAME_LENGTH = 80, ///< Maximum length of the name of a GRF
- /**
- * Maximum number of GRFs that can be sent.
- * This value is related to number of handles (files) OpenTTD can open.
- * This is currently 64 and about 10 are currently used when OpenTTD loads
- * without any NewGRFs. Therefore one can only load about 55 NewGRFs, so
- * this is not a limit, but rather a way to easily check whether the limit
- * imposed by the handle count is reached. Secondly it isn't possible to
- * send much more GRF IDs + MD5sums in the PACKET_UDP_SERVER_RESPONSE, due
- * to the limited size of UDP packets.
- */
- NETWORK_MAX_GRF_COUNT = 55,
-
- NETWORK_NUM_LANGUAGES = 4, ///< Number of known languages (to the network protocol) + 1 for 'any'.
-};
-
-#endif /* ENABLE_NETWORK */
-
-#endif /* NETWORK_CORE_CONFIG_H */
diff --git a/network/core/game.h b/network/core/game.h
deleted file mode 100644
index 71268f7d2..000000000
--- a/network/core/game.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* $Id$ */
-
-#ifndef NETWORK_CORE_GAME_H
-#define NETWORK_CORE_GAME_H
-
-#ifdef ENABLE_NETWORK
-
-/**
- * @file game.h Information about a game that is sent between a
- * game server, game client and masterserver.
- */
-
-/**
- * This is the struct used by both client and server
- * some fields will be empty on the client (like game_password) by default
- * and only filled with data a player enters.
- */
-typedef struct NetworkGameInfo {
- byte game_info_version; ///< Version of the game info
- char server_name[NETWORK_NAME_LENGTH]; ///< Server name
- char hostname[NETWORK_HOSTNAME_LENGTH]; ///< Hostname of the server (if any)
- char server_revision[NETWORK_REVISION_LENGTH]; ///< The version number the server is using (e.g.: 'r304' or 0.5.0)
- bool version_compatible; ///< Can we connect to this server or not? (based on server_revision)
- bool compatible; ///< Can we connect to this server or not? (based on server_revision _and_ grf_match
- byte server_lang; ///< Language of the server (we should make a nice table for this)
- byte use_password; ///< Is set to != 0 if it uses a password
- char server_password[NETWORK_PASSWORD_LENGTH]; ///< On the server: the game password, on the client: != "" if server has password
- byte clients_max; ///< Max clients allowed on server
- byte clients_on; ///< Current count of clients on server
- byte companies_max; ///< Max companies allowed on server
- byte companies_on; ///< How many started companies do we have
- byte spectators_max; ///< Max spectators allowed on server
- byte spectators_on; ///< How many spectators do we have?
- Date game_date; ///< Current date
- Date start_date; ///< When the game started
- char map_name[NETWORK_NAME_LENGTH]; ///< Map which is played ["random" for a randomized map]
- uint16 map_width; ///< Map width
- uint16 map_height; ///< Map height
- byte map_set; ///< Graphical set
- bool dedicated; ///< Is this a dedicated server?
- char rcon_password[NETWORK_PASSWORD_LENGTH]; ///< RCon password for the server. "" if rcon is disabled
- struct GRFConfig *grfconfig; ///< List of NewGRF files used
-} NetworkGameInfo;
-
-#endif /* ENABLE_NETWORK */
-
-#endif /* NETWORK_CORE_GAME_H */
diff --git a/network/core/os_abstraction.h b/network/core/os_abstraction.h
deleted file mode 100644
index c7df16a93..000000000
--- a/network/core/os_abstraction.h
+++ /dev/null
@@ -1,181 +0,0 @@
-/* $Id$ */
-
-#ifndef NETWORK_CORE_OS_ABSTRACTION_H
-#define NETWORK_CORE_OS_ABSTRACTION_H
-
-/**
- * @file os_abstraction.h Network stuff has many things that needs to be
- * included and/or implemented by default.
- * All those things are in this file.
- */
-
-/* Include standard stuff per OS */
-
-#ifdef ENABLE_NETWORK
-
-/* Windows stuff */
-#if defined(WIN32) || defined(WIN64)
-#include <winsock2.h>
-#include <ws2tcpip.h>
-#include <windows.h>
-
-#if !(defined(__MINGW32__) || defined(__CYGWIN__))
- /* Windows has some different names for some types */
- typedef SSIZE_T ssize_t;
- typedef int socklen_t;
-#endif
-
-#define GET_LAST_ERROR() WSAGetLastError()
-#define EWOULDBLOCK WSAEWOULDBLOCK
-/* Windows has some different names for some types */
-typedef unsigned long in_addr_t;
-#endif /* WIN32 */
-
-/* UNIX stuff */
-#if defined(UNIX)
-# define SOCKET int
-# define INVALID_SOCKET -1
-# if !defined(__MORPHOS__) && !defined(__AMIGA__)
-# define ioctlsocket ioctl
-# if !defined(BEOS_NET_SERVER)
-# define closesocket close
-# endif
-# define GET_LAST_ERROR() (errno)
-# endif
-/* Need this for FIONREAD on solaris */
-# define BSD_COMP
-
-/* Includes needed for UNIX-like systems */
-# include <unistd.h>
-# include <sys/ioctl.h>
-# if defined(__BEOS__) && defined(BEOS_NET_SERVER)
-# include <be/net/socket.h>
-# include <be/kernel/OS.h> // snooze()
-# include <be/net/netdb.h>
- typedef unsigned long in_addr_t;
-# define INADDR_NONE INADDR_BROADCAST
-# else
-# include <sys/socket.h>
-# include <netinet/in.h>
-# include <netinet/tcp.h>
-# include <arpa/inet.h>
-# include <net/if.h>
-/* According to glibc/NEWS, <ifaddrs.h> appeared in glibc-2.3. */
-# if !defined(__sgi__) && !defined(SUNOS) && !defined(__MORPHOS__) && !defined(__BEOS__) && !defined(__INNOTEK_LIBC__) \
- && !(defined(__GLIBC__) && (__GLIBC__ <= 2) && (__GLIBC_MINOR__ <= 2)) && !defined(__dietlibc__)
-/* If for any reason ifaddrs.h does not exist on your system, comment out
- * the following two lines and an alternative way will be used to fetch
- * the list of IPs from the system. */
-# include <ifaddrs.h>
-# define HAVE_GETIFADDRS
-# endif
-# if defined(SUNOS) || defined(__MORPHOS__) || defined(__BEOS__)
-# define INADDR_NONE 0xffffffff
-# endif
-# if defined(__BEOS__) && !defined(BEOS_NET_SERVER)
- /* needed on Zeta */
-# include <sys/sockio.h>
-# endif
-# endif /* BEOS_NET_SERVER */
-
-# if !defined(__BEOS__) && defined(__GLIBC__) && (__GLIBC__ <= 2) && (__GLIBC_MINOR__ <= 1)
- typedef uint32_t in_addr_t;
-# endif
-
-# include <errno.h>
-# include <sys/time.h>
-# include <netdb.h>
-#endif // UNIX
-
-#ifdef __BEOS__
- typedef int socklen_t;
-#endif
-
-/* OS/2 stuff */
-#if defined(__OS2__)
-# define SOCKET int
-# define INVALID_SOCKET -1
-# define ioctlsocket ioctl
-# define closesocket close
-# define GET_LAST_ERROR() (sock_errno())
-
-/* Includes needed for OS/2 systems */
-# include <types.h>
-# include <unistd.h>
-# include <sys/ioctl.h>
-# include <sys/socket.h>
-# include <netinet/in.h>
-# include <netinet/tcp.h>
-# include <arpa/inet.h>
-# include <net/if.h>
-# include <errno.h>
-# include <sys/time.h>
-# include <netdb.h>
-# include <nerrno.h>
-# define INADDR_NONE 0xffffffff
-
-typedef int socklen_t;
-#if !defined(__INNOTEK_LIBC__)
-typedef unsigned long in_addr_t;
-#endif /* __INNOTEK_LIBC__ */
-#endif /* OS/2 */
-
-/* MorphOS and Amiga stuff */
-#if defined(__MORPHOS__) || defined(__AMIGA__)
-# include <exec/types.h>
-# include <proto/exec.h> // required for Open/CloseLibrary()
-# if defined(__MORPHOS__)
-# include <sys/filio.h> // FIO* defines
-# include <sys/sockio.h> // SIO* defines
-# include <netinet/in.h>
-# else /* __AMIGA__ */
-# include <proto/socket.h>
-# endif
-
-/* Make the names compatible */
-# define closesocket(s) CloseSocket(s)
-# define GET_LAST_ERROR() Errno()
-# define ioctlsocket(s,request,status) IoctlSocket((LONG)s,(ULONG)request,(char*)status)
-# define ioctl ioctlsocket
-
- typedef unsigned int in_addr_t;
- typedef long socklen_t;
- extern struct Library *SocketBase;
-
-# ifdef __AMIGA__
- /* for usleep() implementation */
- extern struct Device *TimerBase;
- extern struct MsgPort *TimerPort;
- extern struct timerequest *TimerRequest;
-# endif
-#endif // __MORPHOS__ || __AMIGA__
-
-static inline bool SetNonBlocking(int d)
-{
-#ifdef WIN32
- u_long nonblocking = 1;
-#else
- int nonblocking = 1;
-#endif
-#if defined(__BEOS__) && defined(BEOS_NET_SERVER)
- return setsockopt(d, SOL_SOCKET, SO_NONBLOCK, &nonblocking, sizeof(nonblocking)) == 0;
-#else
- return ioctlsocket(d, FIONBIO, &nonblocking) == 0;
-#endif
-}
-
-static inline bool SetNoDelay(int d)
-{
- /* XXX should this be done at all? */
-#if !defined(BEOS_NET_SERVER) // not implemented on BeOS net_server
- int b = 1;
- /* The (const char*) cast is needed for windows */
- return setsockopt(d, IPPROTO_TCP, TCP_NODELAY, (const char*)&b, sizeof(b)) == 0;
-#else
- return true;
-#endif
-}
-
-#endif /* ENABLE_NETWORK */
-
-#endif /* NETWORK_CORE_OS_ABSTRACTION_H */
diff --git a/network/core/packet.c b/network/core/packet.c
deleted file mode 100644
index 957bd2ad6..000000000
--- a/network/core/packet.c
+++ /dev/null
@@ -1,216 +0,0 @@
-/* $Id$ */
-
-#ifdef ENABLE_NETWORK
-
-#include "../../stdafx.h"
-#include "../../macros.h"
-#include "../../string.h"
-
-#include "os_abstraction.h"
-#include "config.h"
-#include "packet.h"
-
-/**
- * @file packet.h Basic functions to create, fill and read packets.
- */
-
-
-/* Do not want to include functions.h and all required headers */
-extern void NORETURN CDECL error(const char *str, ...);
-
-
-/**
- * Create a packet for sending
- * @param type the of packet
- * @return the newly created packet
- */
-Packet *NetworkSend_Init(PacketType type)
-{
- Packet *packet = malloc(sizeof(Packet));
- /* An error is inplace here, because it simply means we ran out of memory. */
- if (packet == NULL) error("Failed to allocate Packet");
-
- /* Skip the size so we can write that in before sending the packet */
- packet->size = sizeof(packet->size);
- packet->buffer[packet->size++] = type;
- packet->pos = 0;
-
- return packet;
-}
-
-/**
- * Writes the packet size from the raw packet from packet->size
- * @param packet the packet to write the size of
- */
-void NetworkSend_FillPacketSize(Packet *packet)
-{
- packet->buffer[0] = GB(packet->size, 0, 8);
- packet->buffer[1] = GB(packet->size, 8, 8);
-}
-
-/**
- * The next couple of functions make sure we can send
- * uint8, uint16, uint32 and uint64 endian-safe
- * over the network. The least significant bytes are
- * sent first.
- *
- * So 0x01234567 would be sent as 67 45 23 01.
- */
-
-void NetworkSend_uint8(Packet *packet, uint8 data)
-{
- assert(packet->size < sizeof(packet->buffer) - sizeof(data));
- packet->buffer[packet->size++] = data;
-}
-
-void NetworkSend_uint16(Packet *packet, uint16 data)
-{
- assert(packet->size < sizeof(packet->buffer) - sizeof(data));
- packet->buffer[packet->size++] = GB(data, 0, 8);
- packet->buffer[packet->size++] = GB(data, 8, 8);
-}
-
-void NetworkSend_uint32(Packet *packet, uint32 data)
-{
- assert(packet->size < sizeof(packet->buffer) - sizeof(data));
- packet->buffer[packet->size++] = GB(data, 0, 8);
- packet->buffer[packet->size++] = GB(data, 8, 8);
- packet->buffer[packet->size++] = GB(data, 16, 8);
- packet->buffer[packet->size++] = GB(data, 24, 8);
-}
-
-void NetworkSend_uint64(Packet *packet, uint64 data)
-{
- assert(packet->size < sizeof(packet->buffer) - sizeof(data));
- packet->buffer[packet->size++] = GB(data, 0, 8);
- packet->buffer[packet->size++] = GB(data, 8, 8);
- packet->buffer[packet->size++] = GB(data, 16, 8);
- packet->buffer[packet->size++] = GB(data, 24, 8);
- packet->buffer[packet->size++] = GB(data, 32, 8);
- packet->buffer[packet->size++] = GB(data, 40, 8);
- packet->buffer[packet->size++] = GB(data, 48, 8);
- packet->buffer[packet->size++] = GB(data, 56, 8);
-}
-
-/**
- * Sends a string over the network. It sends out
- * the string + '\0'. No size-byte or something.
- */
-void NetworkSend_string(Packet *packet, const char* data)
-{
- assert(data != NULL);
- assert(packet->size < sizeof(packet->buffer) - strlen(data) - 1);
- while ((packet->buffer[packet->size++] = *data++) != '\0') {}
-}
-
-
-/**
- * Receiving commands
- * Again, the next couple of functions are endian-safe
- * see the comment before NetworkSend_uint8 for more info.
- */
-
-
-extern uint CloseConnection(NetworkClientState *cs);
-
-/** Is it safe to read from the packet, i.e. didn't we run over the buffer ? */
-static inline bool CanReadFromPacket(NetworkClientState *cs, Packet *packet, uint bytes_to_read)
-{
- /* Don't allow reading from a closed socket */
- if (HasClientQuit(cs)) return false;
-
- /* Check if variable is within packet-size */
- if (packet->pos + bytes_to_read > packet->size) {
- CloseConnection(cs);
- return false;
- }
-
- return true;
-}
-
-/**
- * Reads the packet size from the raw packet and stores it in the packet->size
- * @param packet the packet to read the size of
- */
-void NetworkRecv_ReadPacketSize(Packet *packet)
-{
- packet->size = (uint16)packet->buffer[0];
- packet->size += (uint16)packet->buffer[1] << 8;
-}
-
-uint8 NetworkRecv_uint8(NetworkClientState *cs, Packet *packet)
-{
- uint8 n;
-
- if (!CanReadFromPacket(cs, packet, sizeof(n))) return 0;
-
- n = packet->buffer[packet->pos++];
- return n;
-}
-
-uint16 NetworkRecv_uint16(NetworkClientState *cs, Packet *packet)
-{
- uint16 n;
-
- if (!CanReadFromPacket(cs, packet, sizeof(n))) return 0;
-
- n = (uint16)packet->buffer[packet->pos++];
- n += (uint16)packet->buffer[packet->pos++] << 8;
- return n;
-}
-
-uint32 NetworkRecv_uint32(NetworkClientState *cs, Packet *packet)
-{
- uint32 n;
-
- if (!CanReadFromPacket(cs, packet, sizeof(n))) return 0;
-
- n = (uint32)packet->buffer[packet->pos++];
- n += (uint32)packet->buffer[packet->pos++] << 8;
- n += (uint32)packet->buffer[packet->pos++] << 16;
- n += (uint32)packet->buffer[packet->pos++] << 24;
- return n;
-}
-
-uint64 NetworkRecv_uint64(NetworkClientState *cs, Packet *packet)
-{
- uint64 n;
-
- if (!CanReadFromPacket(cs, packet, sizeof(n))) return 0;
-
- n = (uint64)packet->buffer[packet->pos++];
- n += (uint64)packet->buffer[packet->pos++] << 8;
- n += (uint64)packet->buffer[packet->pos++] << 16;
- n += (uint64)packet->buffer[packet->pos++] << 24;
- n += (uint64)packet->buffer[packet->pos++] << 32;
- n += (uint64)packet->buffer[packet->pos++] << 40;
- n += (uint64)packet->buffer[packet->pos++] << 48;
- n += (uint64)packet->buffer[packet->pos++] << 56;
- return n;
-}
-
-/** Reads a string till it finds a '\0' in the stream */
-void NetworkRecv_string(NetworkClientState *cs, Packet *p, char *buffer, size_t size)
-{
- PacketSize pos;
- char *bufp = buffer;
-
- /* Don't allow reading from a closed socket */
- if (HasClientQuit(cs)) return;
-
- pos = p->pos;
- while (--size > 0 && pos < p->size && (*buffer++ = p->buffer[pos++]) != '\0') {}
-
- if (size == 0 || pos == p->size) {
- *buffer = '\0';
- /* If size was sooner to zero then the string in the stream
- * skip till the \0, so than packet can be read out correctly for the rest */
- while (pos < p->size && p->buffer[pos] != '\0') pos++;
- pos++;
- }
- p->pos = pos;
-
- str_validate(bufp);
-}
-
-#endif /* ENABLE_NETWORK */
diff --git a/network/core/packet.h b/network/core/packet.h
deleted file mode 100644
index 2510c69a7..000000000
--- a/network/core/packet.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* $Id$ */
-
-#ifndef NETWORK_CORE_PACKET_H
-#define NETWORK_CORE_PACKET_H
-
-#ifdef ENABLE_NETWORK
-
-/**
- * @file packet.h Basic functions to create, fill and read packets.
- */
-
-typedef struct NetworkClientState NetworkClientState;
-
-/**
- * Queries the network client state struct to determine whether
- * the client has quit. It indirectly also queries whether the
- * packet is corrupt as the connection will be closed if it is
- * reading beyond the boundary of the received packet.
- * @param cs the state to query
- * @param true if the connection should be considered dropped
- */
-bool HasClientQuit(NetworkClientState *cs);
-
-typedef uint16 PacketSize; ///< Size of the whole packet.
-typedef uint8 PacketType; ///< Identifier for the packet
-
-/**
- * Internal entity of a packet. As everything is sent as a packet,
- * all network communication will need to call the functions that
- * populate the packet.
- * Every packet can be at most SEND_MTU bytes. Overflowing this
- * limit will give an assertion when sending (i.e. writing) the
- * packet. Reading past the size of the packet when receiving
- * will return all 0 values and "" in case of the string.
- */
-typedef struct Packet {
- /** The next packet. Used for queueing packets before sending. */
- struct Packet *next;
- /** The size of the whole packet for received packets. For packets
- * that will be sent, the value is filled in just before the
- * actual transmission. */
- PacketSize size;
- /** The current read/write position in the packet */
- PacketSize pos;
- /** The buffer of this packet */
- byte buffer[SEND_MTU];
-} Packet;
-
-
-Packet *NetworkSend_Init(PacketType type);
-void NetworkSend_FillPacketSize(Packet *packet);
-void NetworkSend_uint8 (Packet *packet, uint8 data);
-void NetworkSend_uint16(Packet *packet, uint16 data);
-void NetworkSend_uint32(Packet *packet, uint32 data);
-void NetworkSend_uint64(Packet *packet, uint64 data);
-void NetworkSend_string(Packet *packet, const char* data);
-
-void NetworkRecv_ReadPacketSize(Packet *packet);
-uint8 NetworkRecv_uint8 (NetworkClientState *cs, Packet *packet);
-uint16 NetworkRecv_uint16(NetworkClientState *cs, Packet *packet);
-uint32 NetworkRecv_uint32(NetworkClientState *cs, Packet *packet);
-uint64 NetworkRecv_uint64(NetworkClientState *cs, Packet *packet);
-void NetworkRecv_string(NetworkClientState *cs, Packet *packet, char* buffer, size_t size);
-
-#endif /* ENABLE_NETWORK */
-
-#endif /* NETWORK_CORE_PACKET_H */
diff --git a/network/core/tcp.c b/network/core/tcp.c
deleted file mode 100644
index 493a97dff..000000000
--- a/network/core/tcp.c
+++ /dev/null
@@ -1,227 +0,0 @@
-/* $Id$ */
-
-#ifdef ENABLE_NETWORK
-
-#include "../../stdafx.h"
-#include "../../debug.h"
-#include "../../openttd.h"
-#include "../../variables.h"
-#include "../../table/strings.h"
-#include "../../functions.h"
-
-#include "os_abstraction.h"
-#include "config.h"
-#include "packet.h"
-#include "../network_data.h"
-#include "tcp.h"
-
-/**
- * @file tcp.c Basic functions to receive and send TCP packets.
- */
-
-/**
- * Functions to help NetworkRecv_Packet/NetworkSend_Packet a bit
- * A socket can make errors. When that happens this handles what to do.
- * For clients: close connection and drop back to main-menu
- * For servers: close connection and that is it
- * @param cs the client to close the connection of
- * @return the new status
- */
-NetworkRecvStatus CloseConnection(NetworkClientState *cs)
-{
- NetworkCloseClient(cs);
-
- /* Clients drop back to the main menu */
- if (!_network_server && _networking) {
- _switch_mode = SM_MENU;
- _networking = false;
- _switch_mode_errorstr = STR_NETWORK_ERR_LOSTCONNECTION;
-
- return NETWORK_RECV_STATUS_CONN_LOST;
- }
-
- return NETWORK_RECV_STATUS_OKAY;
-}
-
-/**
- * Whether the client has quit or not (used in packet.c)
- * @param cs the client to check
- * @return true if the client has quit
- */
-bool HasClientQuit(NetworkClientState *cs)
-{
- return cs->has_quit;
-}
-
-/**
- * This function puts the packet in the send-queue and it is send as
- * soon as possible. This is the next tick, or maybe one tick later
- * if the OS-network-buffer is full)
- * @param packet the packet to send
- * @param cs the client to send to
- */
-void NetworkSend_Packet(Packet *packet, NetworkClientState *cs)
-{
- Packet *p;
- assert(packet != NULL);
-
- packet->pos = 0;
- packet->next = NULL;
-
- NetworkSend_FillPacketSize(packet);
-
- /* Locate last packet buffered for the client */
- p = cs->packet_queue;
- if (p == NULL) {
- /* No packets yet */
- cs->packet_queue = packet;
- } else {
- /* Skip to the last packet */
- while (p->next != NULL) p = p->next;
- p->next = packet;
- }
-}
-
-/**
- * Sends all the buffered packets out for this client. It stops when:
- * 1) all packets are send (queue is empty)
- * 2) the OS reports back that it can not send any more
- * data right now (full network-buffer, it happens ;))
- * 3) sending took too long
- * @param cs the client to send the packets for
- */
-bool NetworkSend_Packets(NetworkClientState *cs)
-{
- ssize_t res;
- Packet *p;
-
- /* We can not write to this socket!! */
- if (!cs->writable) return false;
- if (cs->socket == INVALID_SOCKET) return false;
-
- p = cs->packet_queue;
- while (p != NULL) {
- res = send(cs->socket, p->buffer + p->pos, p->size - p->pos, 0);
- if (res == -1) {
- int err = GET_LAST_ERROR();
- if (err != EWOULDBLOCK) {
- /* Something went wrong.. close client! */
- DEBUG(net, 0, "send failed with error %d", err);
- CloseConnection(cs);
- return false;
- }
- return true;
- }
- if (res == 0) {
- /* Client/server has left us :( */
- CloseConnection(cs);
- return false;
- }
-
- p->pos += res;
-
- /* Is this packet sent? */
- if (p->pos == p->size) {
- /* Go to the next packet */
- cs->packet_queue = p->next;
- free(p);
- p = cs->packet_queue;
- } else {
- return true;
- }
- }
-
- return true;
-}
-
-/**
- * Receives a packet for the given client
- * @param cs the client to (try to) receive a packet for
- * @param status the variable to store the status into
- * @return the received packet (or NULL when it didn't receive one)
- */
-Packet *NetworkRecv_Packet(NetworkClientState *cs, NetworkRecvStatus *status)
-{
- ssize_t res;
- Packet *p;
-
- *status = NETWORK_RECV_STATUS_OKAY;
-
- if (cs->socket == INVALID_SOCKET) return NULL;
-
- if (cs->packet_recv == NULL) {
- cs->packet_recv = malloc(sizeof(Packet));
- if (cs->packet_recv == NULL) error("Failed to allocate packet");
- /* Set pos to zero! */
- cs->packet_recv->pos = 0;
- cs->packet_recv->size = 0; // Can be ommited, just for safety reasons
- }
-
- p = cs->packet_recv;
-
- /* Read packet size */
- if (p->pos < sizeof(PacketSize)) {
- while (p->pos < sizeof(PacketSize)) {
- /* Read the size of the packet */
- res = recv(cs->socket, p->buffer + p->pos, sizeof(PacketSize) - p->pos, 0);
- if (res == -1) {
- int err = GET_LAST_ERROR();
- if (err != EWOULDBLOCK) {
- /* Something went wrong... (104 is connection reset by peer) */
- if (err != 104) DEBUG(net, 0, "recv failed with error %d", err);
- *status = CloseConnection(cs);
- return NULL;
- }
- /* Connection would block, so stop for now */
- return NULL;
- }
- if (res == 0) {
- /* Client/server has left */
- *status = CloseConnection(cs);
- return NULL;
- }
- p->pos += res;
- }
-
- NetworkRecv_ReadPacketSize(p);
-
- if (p->size > SEND_MTU) {
- *status = CloseConnection(cs);
- return NULL;
- }
- }
-
- /* Read rest of packet */
- while (p->pos < p->size) {
- res = recv(cs->socket, p->buffer + p->pos, p->size - p->pos, 0);
- if (res == -1) {
- int err = GET_LAST_ERROR();
- if (err != EWOULDBLOCK) {
- /* Something went wrong... (104 is connection reset by peer) */
- if (err != 104) DEBUG(net, 0, "recv failed with error %d", err);
- *status = CloseConnection(cs);
- return NULL;
- }
- /* Connection would block */
- return NULL;
- }
- if (res == 0) {
- /* Client/server has left */
- *status = CloseConnection(cs);
- return NULL;
- }
-
- p->pos += res;
- }
-
- /* We have a complete packet, return it! */
- p->pos = 2;
- p->next = NULL; // Should not be needed, but who knows...
-
- /* Prepare for receiving a new packet */
- cs->packet_recv = NULL;
-
- return p;
-}
-
-#endif /* ENABLE_NETWORK */
diff --git a/network/core/tcp.h b/network/core/tcp.h
deleted file mode 100644
index e3c307353..000000000
--- a/network/core/tcp.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* $Id$ */
-
-#ifndef NETWORK_CORE_TCP_H
-#define NETWORK_CORE_TCP_H
-
-#ifdef ENABLE_NETWORK
-
-/**
- * @file tcp.h Basic functions to receive and send TCP packets.
- */
-
-/**
- * Enum with all types of UDP packets.
- * The order of the first 4 packets MUST not be changed, as
- * it protects old clients from joining newer servers
- * (because SERVER_ERROR is the respond to a wrong revision)
- */
-enum {
- PACKET_SERVER_FULL,
- PACKET_SERVER_BANNED,
- PACKET_CLIENT_JOIN,
- PACKET_SERVER_ERROR,
- PACKET_CLIENT_COMPANY_INFO,
- PACKET_SERVER_COMPANY_INFO,
- PACKET_SERVER_CLIENT_INFO,
- PACKET_SERVER_NEED_PASSWORD,
- PACKET_CLIENT_PASSWORD,
- PACKET_SERVER_WELCOME,
- PACKET_CLIENT_GETMAP,
- PACKET_SERVER_WAIT,
- PACKET_SERVER_MAP,
- PACKET_CLIENT_MAP_OK,
- PACKET_SERVER_JOIN,
- PACKET_SERVER_FRAME,
- PACKET_SERVER_SYNC,
- PACKET_CLIENT_ACK,
- PACKET_CLIENT_COMMAND,
- PACKET_SERVER_COMMAND,
- PACKET_CLIENT_CHAT,
- PACKET_SERVER_CHAT,
- PACKET_CLIENT_SET_PASSWORD,
- PACKET_CLIENT_SET_NAME,
- PACKET_CLIENT_QUIT,
- PACKET_CLIENT_ERROR,
- PACKET_SERVER_QUIT,
- PACKET_SERVER_ERROR_QUIT,
- PACKET_SERVER_SHUTDOWN,
- PACKET_SERVER_NEWGAME,
- PACKET_SERVER_RCON,
- PACKET_CLIENT_RCON,
- PACKET_END ///< Must ALWAYS be on the end of this list!! (period)
-};
-
-void NetworkSend_Packet(Packet *packet, NetworkClientState *cs);
-Packet *NetworkRecv_Packet(NetworkClientState *cs, NetworkRecvStatus *status);
-bool NetworkSend_Packets(NetworkClientState *cs);
-
-#endif /* ENABLE_NETWORK */
-
-#endif /* NETWORK_CORE_TCP_H */
diff --git a/network/core/udp.c b/network/core/udp.c
deleted file mode 100644
index badd9a532..000000000
--- a/network/core/udp.c
+++ /dev/null
@@ -1,277 +0,0 @@
-/* $Id$ */
-
-#ifdef ENABLE_NETWORK
-
-#include "../../stdafx.h"
-#include "../../date.h"
-#include "../../debug.h"
-#include "../../macros.h"
-#include "../../newgrf_config.h"
-
-#include "os_abstraction.h"
-#include "config.h"
-#include "game.h"
-#include "packet.h"
-#include "udp.h"
-
-/**
- * @file udp.c Basic functions to receive and send UDP packets.
- */
-
-/**
- * Send a packet over UDP
- * @param udp the socket to send over
- * @param p the packet to send
- * @param recv the receiver (target) of the packet
- */
-void NetworkSendUDP_Packet(SOCKET udp, Packet *p, struct sockaddr_in *recv)
-{
- int res;
-
- NetworkSend_FillPacketSize(p);
-
- /* Send the buffer */
- res = sendto(udp, p->buffer, p->size, 0, (struct sockaddr *)recv, sizeof(*recv));
-
- /* Check for any errors, but ignore it otherwise */
- if (res == -1) DEBUG(net, 1, "[udp] sendto failed with: %i", GET_LAST_ERROR());
-}
-
-/**
- * Start listening on the given host and port.
- * @param udp the place where the (references to the) UDP are stored
- * @param host the host (ip) to listen on
- * @param port the port to listen on
- * @param broadcast whether to allow broadcast sending/receiving
- * @return true if the listening succeeded
- */
-bool NetworkUDPListen(SOCKET *udp, uint32 host, uint16 port, bool broadcast)
-{
- struct sockaddr_in sin;
-
- /* Make sure socket is closed */
- closesocket(*udp);
-
- *udp = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
- if (*udp == INVALID_SOCKET) {
- DEBUG(net, 0, "[udp] failed to start UDP listener");
- return false;
- }
-
- /* set nonblocking mode for socket */
- {
- unsigned long blocking = 1;
-#ifndef BEOS_NET_SERVER
- ioctlsocket(*udp, FIONBIO, &blocking);
-#else
- setsockopt(*udp, SOL_SOCKET, SO_NONBLOCK, &blocking, NULL);
-#endif
- }
-
- sin.sin_family = AF_INET;
- /* Listen on all IPs */
- sin.sin_addr.s_addr = host;
- sin.sin_port = htons(port);
-
- if (bind(*udp, (struct sockaddr*)&sin, sizeof(sin)) != 0) {
- DEBUG(net, 0, "[udp] bind failed on %s:%i", inet_ntoa(*(struct in_addr *)&host), port);
- return false;
- }
-
- if (broadcast) {
- /* Enable broadcast */
- unsigned long val = 1;
-#ifndef BEOS_NET_SERVER // will work around this, some day; maybe.
- setsockopt(*udp, SOL_SOCKET, SO_BROADCAST, (char *) &val , sizeof(val));
-#endif
- }
-
- DEBUG(net, 1, "[udp] listening on port %s:%d", inet_ntoa(*(struct in_addr *)&host), port);
-
- return true;
-}
-
-/**
- * Receive a packet at UDP level
- * @param udp the socket to receive the packet on
- */
-void NetworkUDPReceive(SOCKET udp)
-{
- struct sockaddr_in client_addr;
- socklen_t client_len;
- int nbytes;
- Packet p;
- int packet_len;
-
- packet_len = sizeof(p.buffer);
- client_len = sizeof(client_addr);
-
- /* Try to receive anything */
- nbytes = recvfrom(udp, p.buffer, packet_len, 0, (struct sockaddr *)&client_addr, &client_len);
-
- /* We got some bytes for the base header of the packet.
- * Assume we received the whole packet. */
- if (nbytes > 2) {
- NetworkRecv_ReadPacketSize(&p);
-
- /* Put the position on the right place */
- p.pos = 2;
- p.next = NULL;
-
- /* Handle the packet */
- NetworkHandleUDPPacket(&p, &client_addr);
- }
-}
-
-
-/**
- * Serializes the GRFIdentifier (GRF ID and MD5 checksum) to the packet
- * @param p the packet to write the data to
- * @param c the configuration to write the GRF ID and MD5 checksum from
- */
-void NetworkSend_GRFIdentifier(Packet *p, const GRFConfig *c)
-{
- uint j;
- NetworkSend_uint32(p, c->grfid);
- for (j = 0; j < sizeof(c->md5sum); j++) {
- NetworkSend_uint8 (p, c->md5sum[j]);
- }
-}
-
-/**
- * Deserializes the GRFIdentifier (GRF ID and MD5 checksum) from the packet
- * @param cs the client state (for closing connect on out-of-bounds reading etc)
- * @param p the packet to read the data from
- * @param c the configuration to write the GRF ID and MD5 checksum to
- */
-void NetworkRecv_GRFIdentifier(NetworkClientState *cs, Packet *p, GRFConfig *c)
-{
- uint j;
- c->grfid = NetworkRecv_uint32(cs, p);
- for (j = 0; j < sizeof(c->md5sum); j++) {
- c->md5sum[j] = NetworkRecv_uint8(cs, p);
- }
-}
-
-
-/**
- * Serializes the NetworkGameInfo struct to the packet
- * @param p the packet to write the data to
- * @param info the NetworkGameInfo struct to serialize
- */
-void NetworkSend_NetworkGameInfo(Packet *p, const NetworkGameInfo *info)
-{
- NetworkSend_uint8 (p, NETWORK_GAME_INFO_VERSION);
-
- /*
- * Please observe the order.
- * The parts must be read in the same order as they are sent!
- */
-
-
- /* NETWORK_GAME_INFO_VERSION = 4 */
- {
- /* Only send the GRF Identification (GRF_ID and MD5 checksum) of
- * the GRFs that are needed, i.e. the ones that the server has
- * selected in the NewGRF GUI and not the ones that are used due
- * to the fact that they are in [newgrf-static] in openttd.cfg */
- const GRFConfig *c;
- uint count = 0;
-
- /* Count number of GRFs to send information about */
- for (c = info->grfconfig; c != NULL; c = c->next) {
- if (!HASBIT(c->flags, GCF_STATIC)) count++;
- }
- NetworkSend_uint8 (p, count); // Send number of GRFs
-
- /* Send actual GRF Identifications */
- for (c = info->grfconfig; c != NULL; c = c->next) {
- if (!HASBIT(c->flags, GCF_STATIC)) NetworkSend_GRFIdentifier(p, c);
- }
- }
-
- /* NETWORK_GAME_INFO_VERSION = 3 */
- NetworkSend_uint32(p, info->game_date);
- NetworkSend_uint32(p, info->start_date);
-
- /* NETWORK_GAME_INFO_VERSION = 2 */
- NetworkSend_uint8 (p, info->companies_max);
- NetworkSend_uint8 (p, info->companies_on);
- NetworkSend_uint8 (p, info->spectators_max);
-
- /* NETWORK_GAME_INFO_VERSION = 1 */
- NetworkSend_string(p, info->server_name);
- NetworkSend_string(p, info->server_revision);
- NetworkSend_uint8 (p, info->server_lang);
- NetworkSend_uint8 (p, info->use_password);
- NetworkSend_uint8 (p, info->clients_max);
- NetworkSend_uint8 (p, info->clients_on);
- NetworkSend_uint8 (p, info->spectators_on);
- NetworkSend_string(p, info->map_name);
- NetworkSend_uint16(p, info->map_width);
- NetworkSend_uint16(p, info->map_height);
- NetworkSend_uint8 (p, info->map_set);
- NetworkSend_uint8 (p, info->dedicated);
-}
-
-/**
- * Deserializes the NetworkGameInfo struct from the packet
- * @param cs the client state (for closing connect on out-of-bounds reading etc)
- * @param p the packet to read the data from
- * @param info the NetworkGameInfo to deserialize into
- */
-void NetworkRecv_NetworkGameInfo(NetworkClientState *cs, Packet *p, NetworkGameInfo *info)
-{
- info->game_info_version = NetworkRecv_uint8(cs, p);
-
- /*
- * Please observe the order.
- * The parts must be read in the same order as they are sent!
- */
-
- switch (info->game_info_version) {
- case 4: {
- GRFConfig *c, **dst = &info->grfconfig;
- uint i;
- uint num_grfs = NetworkRecv_uint8(cs, p);
-
- for (i = 0; i < num_grfs; i++) {
- c = calloc(1, sizeof(*c));
- NetworkRecv_GRFIdentifier(cs, p, c);
- HandleIncomingNetworkGameInfoGRFConfig(c);
-
- /* Append GRFConfig to the list */
- *dst = c;
- dst = &c->next;
- }
- } /* Fallthrough */
- case 3:
- info->game_date = NetworkRecv_uint32(cs, p);
- info->start_date = NetworkRecv_uint32(cs, p);
- /* Fallthrough */
- case 2:
- info->companies_max = NetworkRecv_uint8 (cs, p);
- info->companies_on = NetworkRecv_uint8 (cs, p);
- info->spectators_max = NetworkRecv_uint8 (cs, p);
- /* Fallthrough */
- case 1:
- NetworkRecv_string(cs, p, info->server_name, sizeof(info->server_name));
- NetworkRecv_string(cs, p, info->server_revision, sizeof(info->server_revision));
- info->server_lang = NetworkRecv_uint8 (cs, p);
- info->use_password = NetworkRecv_uint8 (cs, p);
- info->clients_max = NetworkRecv_uint8 (cs, p);
- info->clients_on = NetworkRecv_uint8 (cs, p);
- info->spectators_on = NetworkRecv_uint8 (cs, p);
- if (info->game_info_version < 3) { // 16 bits dates got scrapped and are read earlier
- info->game_date = NetworkRecv_uint16(cs, p) + DAYS_TILL_ORIGINAL_BASE_YEAR;
- info->start_date = NetworkRecv_uint16(cs, p) + DAYS_TILL_ORIGINAL_BASE_YEAR;
- }
- NetworkRecv_string(cs, p, info->map_name, sizeof(info->map_name));
- info->map_width = NetworkRecv_uint16(cs, p);
- info->map_height = NetworkRecv_uint16(cs, p);
- info->map_set = NetworkRecv_uint8 (cs, p);
- info->dedicated = NetworkRecv_uint8 (cs, p);
- }
-}
-
-#endif /* ENABLE_NETWORK */
diff --git a/network/core/udp.h b/network/core/udp.h
deleted file mode 100644
index 3221e664f..000000000
--- a/network/core/udp.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* $Id$ */
-
-#ifndef NETWORK_CORE_UDP_H
-#define NETWORK_CORE_UDP_H
-
-#ifdef ENABLE_NETWORK
-
-/**
- * @file udp.h Basic functions to receive and send UDP packets.
- */
-
-///** Sending/receiving of UDP packets **////
-
-void NetworkSendUDP_Packet(SOCKET udp, Packet *p, struct sockaddr_in *recv);
-bool NetworkUDPListen(SOCKET *udp, uint32 host, uint16 port, bool broadcast);
-void NetworkUDPReceive(SOCKET udp);
-
-/**
- * Function that is called for every received UDP packet.
- * @param packet the received packet
- * @param client_addr the address of the sender of the packet
- */
-void NetworkHandleUDPPacket(Packet *p, struct sockaddr_in *client_addr);
-
-
-///** Sending/receiving of (large) chuncks of UDP packets **////
-
-
-/** Enum with all types of UDP packets. The order MUST not be changed **/
-enum {
- PACKET_UDP_CLIENT_FIND_SERVER, ///< Queries a game server for game information
- PACKET_UDP_SERVER_RESPONSE, ///< Reply of the game server with game information
- PACKET_UDP_CLIENT_DETAIL_INFO, ///< Queries a game server about details of the game, such as companies
- PACKET_UDP_SERVER_DETAIL_INFO, ///< Reply of the game server about details of the game, such as companies
- PACKET_UDP_SERVER_REGISTER, ///< Packet to register itself to the master server
- PACKET_UDP_MASTER_ACK_REGISTER, ///< Packet indicating registration has succedeed
- PACKET_UDP_CLIENT_GET_LIST, ///< Request for serverlist from master server
- PACKET_UDP_MASTER_RESPONSE_LIST, ///< Response from master server with server ip's + port's
- PACKET_UDP_SERVER_UNREGISTER, ///< Request to be removed from the server-list
- PACKET_UDP_CLIENT_GET_NEWGRFS, ///< Requests the name for a list of GRFs (GRF_ID and MD5)
- PACKET_UDP_SERVER_NEWGRFS, ///< Sends the list of NewGRF's requested.
- PACKET_UDP_END ///< Must ALWAYS be on the end of this list!! (period)
-};
-
-void NetworkSend_GRFIdentifier(Packet *p, const GRFConfig *c);
-void NetworkSend_NetworkGameInfo(Packet *p, const NetworkGameInfo *info);
-
-void NetworkRecv_GRFIdentifier(NetworkClientState *cs, Packet *p, GRFConfig *c);
-void NetworkRecv_NetworkGameInfo(NetworkClientState *cs, Packet *p, NetworkGameInfo *info);
-
-/**
- * Function that is called for every GRFConfig that is read when receiving
- * a NetworkGameInfo. Only grfid and md5sum are set, the rest is zero. This
- * function must set all appropriate fields. This GRF is later appended to
- * the grfconfig list of the NetworkGameInfo.
- * @param config the GRF to handle
- */
-void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config);
-
-#endif /* ENABLE_NETWORK */
-
-#endif /* NETWORK_CORE_UDP_H */
diff --git a/network/network.c b/network/network.c
deleted file mode 100644
index 83f7eedcd..000000000
--- a/network/network.c
+++ /dev/null
@@ -1,1451 +0,0 @@
-/* $Id$ */
-
-#include "../stdafx.h"
-#include "network_data.h"
-
-#if defined(WITH_REV)
- extern const char _openttd_revision[];
-#elif defined(WITH_REV_HACK)
- #define WITH_REV
- const char _openttd_revision[] = WITH_REV_HACK;
-#else
- const char _openttd_revision[] = NOREV_STRING;
-#endif
-
-
-#ifdef ENABLE_NETWORK
-
-#include "../openttd.h"
-#include "../debug.h"
-#include "../functions.h"
-#include "../string.h"
-#include "../strings.h"
-#include "../map.h"
-#include "../command.h"
-#include "../variables.h"
-#include "../date.h"
-#include "../newgrf_config.h"
-#include "../table/strings.h"
-#include "network_client.h"
-#include "network_server.h"
-#include "network_udp.h"
-#include "network_gamelist.h"
-#include "core/udp.h"
-#include "core/tcp.h"
-#include "network_gui.h"
-#include "../console.h" /* IConsoleCmdExec */
-#include <stdarg.h> /* va_list */
-#include "../md5.h"
-
-#ifdef __MORPHOS__
-// the library base is required here
-struct Library *SocketBase = NULL;
-#endif
-
-// The listen socket for the server
-static SOCKET _listensocket;
-
-// The amount of clients connected
-static byte _network_clients_connected = 0;
-// The index counter for new clients (is never decreased)
-static uint16 _network_client_index = NETWORK_SERVER_INDEX + 1;
-
-/* Some externs / forwards */
-extern void StateGameLoop(void);
-
-// Function that looks up the CI for a given client-index
-NetworkClientInfo *NetworkFindClientInfoFromIndex(uint16 client_index)
-{
- NetworkClientInfo *ci;
-
- for (ci = _network_client_info; ci != endof(_network_client_info); ci++) {
- if (ci->client_index == client_index) return ci;
- }
-
- return NULL;
-}
-
-/** Return the CI for a given IP
- * @param ip IP of the client we are looking for. This must be in string-format
- * @return return a pointer to the corresponding NetworkClientInfo struct or NULL on failure */
-NetworkClientInfo *NetworkFindClientInfoFromIP(const char *ip)
-{
- NetworkClientInfo *ci;
- uint32 ip_number = inet_addr(ip);
-
- for (ci = _network_client_info; ci != endof(_network_client_info); ci++) {
- if (ci->client_ip == ip_number) return ci;
- }
-
- return NULL;
-}
-
-// Function that looks up the CS for a given client-index
-NetworkClientState *NetworkFindClientStateFromIndex(uint16 client_index)
-{
- NetworkClientState *cs;
-
- for (cs = _clients; cs != &_clients[MAX_CLIENT_INFO]; cs++) {
- if (cs->index == client_index) return cs;
- }
-
- return NULL;
-}
-
-// NetworkGetClientName is a server-safe function to get the name of the client
-// if the user did not send it yet, Client #<no> is used.
-void NetworkGetClientName(char *client_name, size_t size, const NetworkClientState *cs)
-{
- const NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
-
- if (ci->client_name[0] == '\0') {
- snprintf(client_name, size, "Client #%4d", cs->index);
- } else {
- ttd_strlcpy(client_name, ci->client_name, size);
- }
-}
-
-byte NetworkSpectatorCount(void)
-{
- const NetworkClientState *cs;
- byte count = 0;
-
- FOR_ALL_CLIENTS(cs) {
- if (DEREF_CLIENT_INFO(cs)->client_playas == PLAYER_SPECTATOR) count++;
- }
-
- return count;
-}
-
-// This puts a text-message to the console, or in the future, the chat-box,
-// (to keep it all a bit more general)
-// If 'self_send' is true, this is the client who is sending the message
-void CDECL NetworkTextMessage(NetworkAction action, uint16 color, bool self_send, const char *name, const char *str, ...)
-{
- char buf[1024];
- va_list va;
- const int duration = 10; // Game days the messages stay visible
- char message[1024];
- char temp[1024];
-
- va_start(va, str);
- vsnprintf(buf, lengthof(buf), str, va);
- va_end(va);
-
- switch (action) {
- case NETWORK_ACTION_SERVER_MESSAGE:
- color = 1;
- snprintf(message, sizeof(message), "*** %s", buf);
- break;
- case NETWORK_ACTION_JOIN:
- color = 1;
- GetString(temp, STR_NETWORK_CLIENT_JOINED, lastof(temp));
- snprintf(message, sizeof(message), "*** %s %s", name, temp);
- break;
- case NETWORK_ACTION_LEAVE:
- color = 1;
- GetString(temp, STR_NETWORK_ERR_LEFT, lastof(temp));
- snprintf(message, sizeof(message), "*** %s %s (%s)", name, temp, buf);
- break;
- case NETWORK_ACTION_GIVE_MONEY:
- if (self_send) {
- SetDParamStr(0, name);
- SetDParam(1, atoi(buf));
- GetString(temp, STR_NETWORK_GAVE_MONEY_AWAY, lastof(temp));
- snprintf(message, sizeof(message), "*** %s", temp);
- } else {
- SetDParam(0, atoi(buf));
- GetString(temp, STR_NETWORK_GIVE_MONEY, lastof(temp));
- snprintf(message, sizeof(message), "*** %s %s", name, temp);
- }
- break;
- case NETWORK_ACTION_NAME_CHANGE:
- GetString(temp, STR_NETWORK_NAME_CHANGE, lastof(temp));
- snprintf(message, sizeof(message), "*** %s %s %s", name, temp, buf);
- break;
- case NETWORK_ACTION_CHAT_COMPANY:
- SetDParamStr(0, name);
- SetDParamStr(1, buf);
- GetString(temp, self_send ? STR_NETWORK_CHAT_TO_COMPANY : STR_NETWORK_CHAT_COMPANY, lastof(temp));
- ttd_strlcpy(message, temp, sizeof(message));
- break;
- case NETWORK_ACTION_CHAT_CLIENT:
- SetDParamStr(0, name);
- SetDParamStr(1, buf);
- GetString(temp, self_send ? STR_NETWORK_CHAT_TO_CLIENT : STR_NETWORK_CHAT_CLIENT, lastof(temp));
- ttd_strlcpy(message, temp, sizeof(message));
- break;
- default:
- SetDParamStr(0, name);
- SetDParamStr(1, buf);
- GetString(temp, STR_NETWORK_CHAT_ALL, lastof(temp));
- ttd_strlcpy(message, temp, sizeof(message));
- break;
- }
-
- IConsolePrintF(color, "%s", message);
- AddTextMessage(color, duration, "%s", message);
-}
-
-// Calculate the frame-lag of a client
-uint NetworkCalculateLag(const NetworkClientState *cs)
-{
- int lag = cs->last_frame_server - cs->last_frame;
- // This client has missed his ACK packet after 1 DAY_TICKS..
- // so we increase his lag for every frame that passes!
- // The packet can be out by a max of _net_frame_freq
- if (cs->last_frame_server + DAY_TICKS + _network_frame_freq < _frame_counter)
- lag += _frame_counter - (cs->last_frame_server + DAY_TICKS + _network_frame_freq);
-
- return lag;
-}
-
-
-// There was a non-recoverable error, drop back to the main menu with a nice
-// error
-static void NetworkError(StringID error_string)
-{
- _switch_mode = SM_MENU;
- _switch_mode_errorstr = error_string;
-}
-
-static void ClientStartError(const char *error)
-{
- DEBUG(net, 0, "[client] could not start network: %s",error);
- NetworkError(STR_NETWORK_ERR_CLIENT_START);
-}
-
-static void ServerStartError(const char *error)
-{
- DEBUG(net, 0, "[server] could not start network: %s",error);
- NetworkError(STR_NETWORK_ERR_SERVER_START);
-}
-
-static void NetworkClientError(NetworkRecvStatus res, NetworkClientState* cs)
-{
- // First, send a CLIENT_ERROR to the server, so he knows we are
- // disconnection (and why!)
- NetworkErrorCode errorno;
-
- // We just want to close the connection..
- if (res == NETWORK_RECV_STATUS_CLOSE_QUERY) {
- cs->has_quit = true;
- NetworkCloseClient(cs);
- _networking = false;
-
- DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
- return;
- }
-
- switch (res) {
- case NETWORK_RECV_STATUS_DESYNC: errorno = NETWORK_ERROR_DESYNC; break;
- case NETWORK_RECV_STATUS_SAVEGAME: errorno = NETWORK_ERROR_SAVEGAME_FAILED; break;
- default: errorno = NETWORK_ERROR_GENERAL; break;
- }
- // This means we fucked up and the server closed the connection
- if (res != NETWORK_RECV_STATUS_SERVER_ERROR && res != NETWORK_RECV_STATUS_SERVER_FULL &&
- res != NETWORK_RECV_STATUS_SERVER_BANNED) {
- SEND_COMMAND(PACKET_CLIENT_ERROR)(errorno);
-
- // Dequeue all commands before closing the socket
- NetworkSend_Packets(DEREF_CLIENT(0));
- }
-
- _switch_mode = SM_MENU;
- NetworkCloseClient(cs);
- _networking = false;
-}
-
-/** Retrieve a string representation of an internal error number
- * @param buf buffer where the error message will be stored
- * @param err NetworkErrorCode
- * @return returns a pointer to the error message (buf) */
-char* GetNetworkErrorMsg(char* buf, NetworkErrorCode err, const char* last)
-{
- /* List of possible network errors, used by
- * PACKET_SERVER_ERROR and PACKET_CLIENT_ERROR */
- static const StringID network_error_strings[] = {
- STR_NETWORK_ERR_CLIENT_GENERAL,
- STR_NETWORK_ERR_CLIENT_DESYNC,
- STR_NETWORK_ERR_CLIENT_SAVEGAME,
- STR_NETWORK_ERR_CLIENT_CONNECTION_LOST,
- STR_NETWORK_ERR_CLIENT_PROTOCOL_ERROR,
- STR_NETWORK_ERR_CLIENT_NOT_AUTHORIZED,
- STR_NETWORK_ERR_CLIENT_NOT_EXPECTED,
- STR_NETWORK_ERR_CLIENT_WRONG_REVISION,
- STR_NETWORK_ERR_CLIENT_NAME_IN_USE,
- STR_NETWORK_ERR_CLIENT_WRONG_PASSWORD,
- STR_NETWORK_ERR_CLIENT_PLAYER_MISMATCH,
- STR_NETWORK_ERR_CLIENT_KICKED,
- STR_NETWORK_ERR_CLIENT_CHEATER,
- STR_NETWORK_ERR_CLIENT_SERVER_FULL
- };
-
- if (err >= lengthof(network_error_strings)) err = 0;
-
- return GetString(buf, network_error_strings[err], last);
-}
-
-/* Count the number of active clients connected */
-static uint NetworkCountPlayers(void)
-{
- const NetworkClientState *cs;
- uint count = 0;
-
- FOR_ALL_CLIENTS(cs) {
- const NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
- if (IsValidPlayer(ci->client_playas)) count++;
- }
-
- return count;
-}
-
-static bool _min_players_paused = false;
-
-/* Check if the minimum number of players has been reached and pause or unpause the game as appropriate */
-void CheckMinPlayers(void)
-{
- if (!_network_dedicated) return;
-
- if (NetworkCountPlayers() < _network_min_players) {
- if (_min_players_paused) return;
-
- _min_players_paused = true;
- DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
- NetworkServer_HandleChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game paused (not enough players)", NETWORK_SERVER_INDEX);
- } else {
- if (!_min_players_paused) return;
-
- _min_players_paused = false;
- DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
- NetworkServer_HandleChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused (enough players)", NETWORK_SERVER_INDEX);
- }
-}
-
-// Find all IP-aliases for this host
-static void NetworkFindIPs(void)
-{
- int i;
-
-#if defined(BEOS_NET_SERVER) /* doesn't have neither getifaddrs or net/if.h */
- /* Based on Andrew Bachmann's netstat+.c. Big thanks to him! */
- int _netstat(int fd, char **output, int verbose);
-
- int seek_past_header(char **pos, const char *header) {
- char *new_pos = strstr(*pos, header);
- if (new_pos == 0) {
- return B_ERROR;
- }
- *pos += strlen(header) + new_pos - *pos + 1;
- return B_OK;
- }
-
- int output_length;
- char *output_pointer = NULL;
- char **output;
- int sock = socket(AF_INET, SOCK_DGRAM, 0);
- i = 0;
-
- // If something fails, make sure the list is empty
- _broadcast_list[0] = 0;
-
- if (sock < 0) {
- DEBUG(net, 0, "[core] error creating socket");
- return;
- }
-
- output_length = _netstat(sock, &output_pointer, 1);
- if (output_length < 0) {
- DEBUG(net, 0, "[core] error running _netstat");
- return;
- }
-
- output = &output_pointer;
- if (seek_past_header(output, "IP Interfaces:") == B_OK) {
- for (;;) {
- uint32 n, fields, read;
- uint8 i1, i2, i3, i4, j1, j2, j3, j4;
- struct in_addr inaddr;
- uint32 ip;
- uint32 netmask;
-
- fields = sscanf(*output, "%u: %hhu.%hhu.%hhu.%hhu, netmask %hhu.%hhu.%hhu.%hhu%n",
- &n, &i1,&i2,&i3,&i4, &j1,&j2,&j3,&j4, &read);
- read += 1;
- if (fields != 9) {
- break;
- }
-
- ip = (uint32)i1 << 24 | (uint32)i2 << 16 | (uint32)i3 << 8 | (uint32)i4;
- netmask = (uint32)j1 << 24 | (uint32)j2 << 16 | (uint32)j3 << 8 | (uint32)j4;
-
- if (ip != INADDR_LOOPBACK && ip != INADDR_ANY) {
- inaddr.s_addr = htonl(ip | ~netmask);
- _broadcast_list[i] = inaddr.s_addr;
- i++;
- }
- if (read < 0) {
- break;
- }
- *output += read;
- }
- /* XXX - Using either one of these crashes openttd heavily? - wber */
- /*free(output_pointer);*/
- /*free(output);*/
- closesocket(sock);
- }
-#elif defined(HAVE_GETIFADDRS)
- struct ifaddrs *ifap, *ifa;
-
- // If something fails, make sure the list is empty
- _broadcast_list[0] = 0;
-
- if (getifaddrs(&ifap) != 0)
- return;
-
- i = 0;
- for (ifa = ifap; ifa != NULL; ifa = ifa->ifa_next) {
- if (!(ifa->ifa_flags & IFF_BROADCAST)) continue;
- if (ifa->ifa_broadaddr == NULL) continue;
- if (ifa->ifa_broadaddr->sa_family != AF_INET) continue;
- _broadcast_list[i] = ((struct sockaddr_in*)ifa->ifa_broadaddr)->sin_addr.s_addr;
- i++;
- }
- freeifaddrs(ifap);
-
-#else /* not HAVE_GETIFADDRS */
- SOCKET sock;
-#ifdef WIN32
- DWORD len = 0;
- INTERFACE_INFO ifo[MAX_INTERFACES];
- uint j;
-#else
- char buf[4 * 1024]; // Arbitrary buffer size
- struct ifconf ifconf;
- const char* buf_end;
- const char* p;
-#endif
-
- // If something fails, make sure the list is empty
- _broadcast_list[0] = 0;
-
- sock = socket(AF_INET, SOCK_DGRAM, 0);
- if (sock == INVALID_SOCKET) return;
-
-#ifdef WIN32
- memset(&ifo[0], 0, sizeof(ifo));
- if ((WSAIoctl(sock, SIO_GET_INTERFACE_LIST, NULL, 0, &ifo[0], sizeof(ifo), &len, NULL, NULL)) != 0) {
- closesocket(sock);
- return;
- }
-
- i = 0;
- for (j = 0; j < len / sizeof(*ifo); j++) {
- if (ifo[j].iiFlags & IFF_LOOPBACK) continue;
- if (!(ifo[j].iiFlags & IFF_BROADCAST)) continue;
- /* iiBroadcast is unusable, because it always seems to be set to
- * 255.255.255.255.
- */
- _broadcast_list[i++] =
- ifo[j].iiAddress.AddressIn.sin_addr.s_addr |
- ~ifo[j].iiNetmask.AddressIn.sin_addr.s_addr;
- }
-#else
- ifconf.ifc_len = sizeof(buf);
- ifconf.ifc_buf = buf;
- if (ioctl(sock, SIOCGIFCONF, &ifconf) == -1) {
- closesocket(sock);
- return;
- }
-
- i = 0;
- buf_end = buf + ifconf.ifc_len;
- for (p = buf; p < buf_end;) {
- const struct ifreq* req = (const struct ifreq*)p;
-
- if (req->ifr_addr.sa_family == AF_INET) {
- struct ifreq r;
-
- strncpy(r.ifr_name, req->ifr_name, lengthof(r.ifr_name));
- if (ioctl(sock, SIOCGIFFLAGS, &r) != -1 &&
- r.ifr_flags & IFF_BROADCAST &&
- ioctl(sock, SIOCGIFBRDADDR, &r) != -1) {
- _broadcast_list[i++] =
- ((struct sockaddr_in*)&r.ifr_broadaddr)->sin_addr.s_addr;
- }
- }
-
- p += sizeof(struct ifreq);
-#ifdef AF_LINK
- p += req->ifr_addr.sa_len - sizeof(struct sockaddr);
-#endif
- }
-#endif
-
- closesocket(sock);
-#endif /* not HAVE_GETIFADDRS */
-
- _broadcast_list[i] = 0;
-
- DEBUG(net, 3, "Detected broadcast addresses:");
- // Now display to the debug all the detected ips
- for (i = 0; _broadcast_list[i] != 0; i++) {
- DEBUG(net, 3, "%d) %s", i, inet_ntoa(*(struct in_addr *)&_broadcast_list[i]));//inet_ntoa(inaddr));
- }
-}
-
-// Resolve a hostname to a inet_addr
-unsigned long NetworkResolveHost(const char *hostname)
-{
- in_addr_t ip;
-
- // First try: is it an ip address?
- ip = inet_addr(hostname);
-
- // If not try to resolve the name
- if (ip == INADDR_NONE) {
- struct hostent *he = gethostbyname(hostname);
- if (he == NULL) {
- DEBUG(net, 0, "Cannot resolve '%s'", hostname);
- } else {
- struct in_addr addr = *(struct in_addr *)he->h_addr_list[0];
- DEBUG(net, 1, "Resolved '%s' to %s", hostname, inet_ntoa(addr));
- ip = addr.s_addr;
- }
- }
- return ip;
-}
-
-// Converts a string to ip/port/player
-// Format: IP#player:port
-//
-// connection_string will be re-terminated to seperate out the hostname, and player and port will
-// be set to the player and port strings given by the user, inside the memory area originally
-// occupied by connection_string.
-void ParseConnectionString(const char **player, const char **port, char *connection_string)
-{
- char *p;
- for (p = connection_string; *p != '\0'; p++) {
- if (*p == '#') {
- *p = '\0';
- *player = ++p;
- while (IsValidChar(*p, CS_NUMERAL)) p++;
- if (*p == '\0') break;
- } else if (*p == ':') {
- *port = p + 1;
- *p = '\0';
- }
- }
-}
-
-// Creates a new client from a socket
-// Used both by the server and the client
-static NetworkClientState *NetworkAllocClient(SOCKET s)
-{
- NetworkClientState *cs;
- byte client_no = 0;
-
- if (_network_server) {
- // Can we handle a new client?
- if (_network_clients_connected >= MAX_CLIENTS) return NULL;
- if (_network_game_info.clients_on >= _network_game_info.clients_max) return NULL;
-
- // Register the login
- client_no = _network_clients_connected++;
- }
-
- cs = DEREF_CLIENT(client_no);
- memset(cs, 0, sizeof(*cs));
- cs->socket = s;
- cs->last_frame = 0;
- cs->has_quit = false;
-
- cs->last_frame = _frame_counter;
- cs->last_frame_server = _frame_counter;
-
- if (_network_server) {
- NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
- memset(ci, 0, sizeof(*ci));
-
- cs->index = _network_client_index++;
- ci->client_index = cs->index;
- ci->client_playas = PLAYER_INACTIVE_CLIENT;
- ci->join_date = _date;
-
- InvalidateWindow(WC_CLIENT_LIST, 0);
- }
-
- return cs;
-}
-
-// Close a connection
-void NetworkCloseClient(NetworkClientState *cs)
-{
- NetworkClientInfo *ci;
- // Socket is already dead
- if (cs->socket == INVALID_SOCKET) {
- cs->has_quit = true;
- return;
- }
-
- DEBUG(net, 1, "Closed client connection %d", cs->index);
-
- if (!cs->has_quit && _network_server && cs->status > STATUS_INACTIVE) {
- // We did not receive a leave message from this client...
- NetworkErrorCode errorno = NETWORK_ERROR_CONNECTION_LOST;
- char str[100];
- char client_name[NETWORK_CLIENT_NAME_LENGTH];
- NetworkClientState *new_cs;
-
- NetworkGetClientName(client_name, sizeof(client_name), cs);
-
- GetNetworkErrorMsg(str, errorno, lastof(str));
-
- NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
-
- // Inform other clients of this... strange leaving ;)
- FOR_ALL_CLIENTS(new_cs) {
- if (new_cs->status > STATUS_AUTH && cs != new_cs) {
- SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->index, errorno);
- }
- }
- }
-
- /* When the client was PRE_ACTIVE, the server was in pause mode, so unpause */
- if (cs->status == STATUS_PRE_ACTIVE && _network_pause_on_join) {
- DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
- NetworkServer_HandleChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused", NETWORK_SERVER_INDEX);
- }
-
- closesocket(cs->socket);
- cs->writable = false;
- cs->has_quit = true;
-
- // Free all pending and partially received packets
- while (cs->packet_queue != NULL) {
- Packet *p = cs->packet_queue->next;
- free(cs->packet_queue);
- cs->packet_queue = p;
- }
- free(cs->packet_recv);
- cs->packet_recv = NULL;
-
- while (cs->command_queue != NULL) {
- CommandPacket *p = cs->command_queue->next;
- free(cs->command_queue);
- cs->command_queue = p;
- }
-
- // Close the gap in the client-list
- ci = DEREF_CLIENT_INFO(cs);
-
- if (_network_server) {
- // We just lost one client :(
- if (cs->status > STATUS_INACTIVE) _network_game_info.clients_on--;
- _network_clients_connected--;
-
- while ((cs + 1) != DEREF_CLIENT(MAX_CLIENTS) && (cs + 1)->socket != INVALID_SOCKET) {
- *cs = *(cs + 1);
- *ci = *(ci + 1);
- cs++;
- ci++;
- }
-
- InvalidateWindow(WC_CLIENT_LIST, 0);
- }
-
- // Reset the status of the last socket
- cs->socket = INVALID_SOCKET;
- cs->status = STATUS_INACTIVE;
- cs->index = NETWORK_EMPTY_INDEX;
- ci->client_index = NETWORK_EMPTY_INDEX;
-
- CheckMinPlayers();
-}
-
-// A client wants to connect to a server
-static bool NetworkConnect(const char *hostname, int port)
-{
- SOCKET s;
- struct sockaddr_in sin;
-
- DEBUG(net, 1, "Connecting to %s %d", hostname, port);
-
- s = socket(AF_INET, SOCK_STREAM, 0);
- if (s == INVALID_SOCKET) {
- ClientStartError("socket() failed");
- return false;
- }
-
- if (!SetNoDelay(s)) DEBUG(net, 1, "Setting TCP_NODELAY failed");
-
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = NetworkResolveHost(hostname);
- sin.sin_port = htons(port);
- _network_last_host_ip = sin.sin_addr.s_addr;
-
- /* We failed to connect for which reason what so ever */
- if (connect(s, (struct sockaddr*) &sin, sizeof(sin)) != 0) return false;
-
- if (!SetNonBlocking(s)) DEBUG(net, 0, "Setting non-blocking mode failed"); // XXX should this be an error?
-
- // in client mode, only the first client field is used. it's pointing to the server.
- NetworkAllocClient(s);
-
- _network_join_status = NETWORK_JOIN_STATUS_CONNECTING;
- ShowJoinStatusWindow();
-
- return true;
-}
-
-// For the server, to accept new clients
-static void NetworkAcceptClients(void)
-{
- struct sockaddr_in sin;
- NetworkClientState *cs;
- uint i;
- bool banned;
-
- // Should never ever happen.. is it possible??
- assert(_listensocket != INVALID_SOCKET);
-
- for (;;) {
- socklen_t sin_len = sizeof(sin);
- SOCKET s = accept(_listensocket, (struct sockaddr*)&sin, &sin_len);
- if (s == INVALID_SOCKET) return;
-
- SetNonBlocking(s); // XXX error handling?
-
- DEBUG(net, 1, "Client connected from %s on frame %d", inet_ntoa(sin.sin_addr), _frame_counter);
-
- SetNoDelay(s); // XXX error handling?
-
- /* Check if the client is banned */
- banned = false;
- for (i = 0; i < lengthof(_network_ban_list); i++) {
- if (_network_ban_list[i] == NULL) continue;
-
- if (sin.sin_addr.s_addr == inet_addr(_network_ban_list[i])) {
- Packet *p = NetworkSend_Init(PACKET_SERVER_BANNED);
-
- DEBUG(net, 1, "Banned ip tried to join (%s), refused", _network_ban_list[i]);
-
- p->buffer[0] = p->size & 0xFF;
- p->buffer[1] = p->size >> 8;
-
- send(s, p->buffer, p->size, 0);
- closesocket(s);
-
- free(p);
-
- banned = true;
- break;
- }
- }
- /* If this client is banned, continue with next client */
- if (banned) continue;
-
- cs = NetworkAllocClient(s);
- if (cs == NULL) {
- // no more clients allowed?
- // Send to the client that we are full!
- Packet *p = NetworkSend_Init(PACKET_SERVER_FULL);
-
- p->buffer[0] = p->size & 0xFF;
- p->buffer[1] = p->size >> 8;
-
- send(s, p->buffer, p->size, 0);
- closesocket(s);
-
- free(p);
-
- continue;
- }
-
- // a new client has connected. We set him at inactive for now
- // maybe he is only requesting server-info. Till he has sent a PACKET_CLIENT_MAP_OK
- // the client stays inactive
- cs->status = STATUS_INACTIVE;
-
- DEREF_CLIENT_INFO(cs)->client_ip = sin.sin_addr.s_addr; // Save the IP of the client
- }
-}
-
-// Set up the listen socket for the server
-static bool NetworkListen(void)
-{
- SOCKET ls;
- struct sockaddr_in sin;
-
- DEBUG(net, 1, "Listening on %s:%d", _network_server_bind_ip_host, _network_server_port);
-
- ls = socket(AF_INET, SOCK_STREAM, 0);
- if (ls == INVALID_SOCKET) {
- ServerStartError("socket() on listen socket failed");
- return false;
- }
-
- { // reuse the socket
- int reuse = 1;
- // The (const char*) cast is needed for windows!!
- if (setsockopt(ls, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) == -1) {
- ServerStartError("setsockopt() on listen socket failed");
- return false;
- }
- }
-
- if (!SetNonBlocking(ls)) DEBUG(net, 0, "Setting non-blocking mode failed"); // XXX should this be an error?
-
- sin.sin_family = AF_INET;
- sin.sin_addr.s_addr = _network_server_bind_ip;
- sin.sin_port = htons(_network_server_port);
-
- if (bind(ls, (struct sockaddr*)&sin, sizeof(sin)) != 0) {
- ServerStartError("bind() failed");
- return false;
- }
-
- if (listen(ls, 1) != 0) {
- ServerStartError("listen() failed");
- return false;
- }
-
- _listensocket = ls;
-
- return true;
-}
-
-// Close all current connections
-static void NetworkClose(void)
-{
- NetworkClientState *cs;
-
- FOR_ALL_CLIENTS(cs) {
- if (!_network_server) {
- SEND_COMMAND(PACKET_CLIENT_QUIT)("leaving");
- NetworkSend_Packets(cs);
- }
- NetworkCloseClient(cs);
- }
-
- if (_network_server) {
- // We are a server, also close the listensocket
- closesocket(_listensocket);
- _listensocket = INVALID_SOCKET;
- DEBUG(net, 1, "Closed listener");
- NetworkUDPClose();
- }
-}
-
-// Inits the network (cleans sockets and stuff)
-static void NetworkInitialize(void)
-{
- NetworkClientState *cs;
-
- _local_command_queue = NULL;
-
- // Clean all client-sockets
- memset(_clients, 0, sizeof(_clients));
- for (cs = _clients; cs != &_clients[MAX_CLIENTS]; cs++) {
- cs->socket = INVALID_SOCKET;
- cs->status = STATUS_INACTIVE;
- cs->command_queue = NULL;
- }
-
- // Clean the client_info memory
- memset(&_network_client_info, 0, sizeof(_network_client_info));
- memset(&_network_player_info, 0, sizeof(_network_player_info));
-
- _sync_frame = 0;
- _network_first_time = true;
-
- _network_reconnect = 0;
-
- NetworkUDPInitialize();
-}
-
-// Query a server to fetch his game-info
-// If game_info is true, only the gameinfo is fetched,
-// else only the client_info is fetched
-NetworkGameList *NetworkQueryServer(const char* host, unsigned short port, bool game_info)
-{
- if (!_network_available) return NULL;
-
- NetworkDisconnect();
-
- if (game_info) return NetworkUDPQueryServer(host, port);
-
- NetworkInitialize();
-
- _network_server = false;
-
- // Try to connect
- _networking = NetworkConnect(host, port);
-
- // We are connected
- if (_networking) {
- SEND_COMMAND(PACKET_CLIENT_COMPANY_INFO)();
- } else { // No networking, close everything down again
- NetworkDisconnect();
- }
-
- return NULL;
-}
-
-/* Validates an address entered as a string and adds the server to
- * the list. If you use this function, the games will be marked
- * as manually added. */
-void NetworkAddServer(const char *b)
-{
- if (*b != '\0') {
- NetworkGameList *item;
- const char *port = NULL;
- const char *player = NULL;
- char host[NETWORK_HOSTNAME_LENGTH];
- uint16 rport;
-
- ttd_strlcpy(host, b, lengthof(host));
-
- ttd_strlcpy(_network_default_ip, b, lengthof(_network_default_ip));
- rport = NETWORK_DEFAULT_PORT;
-
- ParseConnectionString(&player, &port, host);
- if (port != NULL) rport = atoi(port);
-
- item = NetworkQueryServer(host, rport, true);
- item->manually = true;
- }
-}
-
-/* Generates the list of manually added hosts from NetworkGameList and
- * dumps them into the array _network_host_list. This array is needed
- * by the function that generates the config file. */
-void NetworkRebuildHostList(void)
-{
- uint i = 0;
- const NetworkGameList *item = _network_game_list;
- while (item != NULL && i != lengthof(_network_host_list)) {
- if (item->manually) {
- free(_network_host_list[i]);
- _network_host_list[i++] = str_fmt("%s:%i", item->info.hostname, item->port);
- }
- item = item->next;
- }
-
- for (; i < lengthof(_network_host_list); i++) {
- free(_network_host_list[i]);
- _network_host_list[i] = NULL;
- }
-}
-
-// Used by clients, to connect to a server
-bool NetworkClientConnectGame(const char *host, uint16 port)
-{
- if (!_network_available) return false;
-
- if (port == 0) return false;
-
- ttd_strlcpy(_network_last_host, host, sizeof(_network_last_host));
- _network_last_port = port;
-
- NetworkDisconnect();
- NetworkUDPClose();
- NetworkInitialize();
-
- // Try to connect
- _networking = NetworkConnect(host, port);
-
- // We are connected
- if (_networking) {
- IConsoleCmdExec("exec scripts/on_client.scr 0");
- NetworkClient_Connected();
- } else {
- // Connecting failed
- NetworkError(STR_NETWORK_ERR_NOCONNECTION);
- }
-
- return _networking;
-}
-
-static void NetworkInitGameInfo(void)
-{
- NetworkClientInfo *ci;
-
- ttd_strlcpy(_network_game_info.server_name, _network_server_name, sizeof(_network_game_info.server_name));
- ttd_strlcpy(_network_game_info.server_password, _network_server_password, sizeof(_network_server_password));
- ttd_strlcpy(_network_game_info.rcon_password, _network_rcon_password, sizeof(_network_rcon_password));
- if (_network_game_info.server_name[0] == '\0')
- snprintf(_network_game_info.server_name, sizeof(_network_game_info.server_name), "Unnamed Server");
-
- ttd_strlcpy(_network_game_info.server_revision, _openttd_revision, sizeof(_network_game_info.server_revision));
-
- // The server is a client too ;)
- if (_network_dedicated) {
- _network_game_info.clients_on = 0;
- _network_game_info.companies_on = 0;
- _network_game_info.dedicated = true;
- } else {
- _network_game_info.clients_on = 1;
- _network_game_info.companies_on = 1;
- _network_game_info.dedicated = false;
- }
-
- _network_game_info.spectators_on = 0;
-
- _network_game_info.game_date = _date;
- _network_game_info.start_date = ConvertYMDToDate(_patches.starting_year, 0, 1);
- _network_game_info.map_width = MapSizeX();
- _network_game_info.map_height = MapSizeY();
- _network_game_info.map_set = _opt.landscape;
-
- _network_game_info.use_password = (_network_server_password[0] != '\0');
-
- // We use _network_client_info[MAX_CLIENT_INFO - 1] to store the server-data in it
- // The index is NETWORK_SERVER_INDEX ( = 1)
- ci = &_network_client_info[MAX_CLIENT_INFO - 1];
- memset(ci, 0, sizeof(*ci));
-
- ci->client_index = NETWORK_SERVER_INDEX;
- ci->client_playas = _network_dedicated ? PLAYER_SPECTATOR : _local_player;
-
- ttd_strlcpy(ci->client_name, _network_player_name, sizeof(ci->client_name));
- ttd_strlcpy(ci->unique_id, _network_unique_id, sizeof(ci->unique_id));
-}
-
-bool NetworkServerStart(void)
-{
- if (!_network_available) return false;
-
- /* Call the pre-scripts */
- IConsoleCmdExec("exec scripts/pre_server.scr 0");
- if (_network_dedicated) IConsoleCmdExec("exec scripts/pre_dedicated.scr 0");
-
- NetworkInitialize();
- if (!NetworkListen()) return false;
-
- // Try to start UDP-server
- _network_udp_server = true;
- _network_udp_server = NetworkUDPListen(&_udp_server_socket, _network_server_bind_ip, _network_server_port, false);
-
- _network_server = true;
- _networking = true;
- _frame_counter = 0;
- _frame_counter_server = 0;
- _frame_counter_max = 0;
- _last_sync_frame = 0;
- _network_own_client_index = NETWORK_SERVER_INDEX;
-
- /* Non-dedicated server will always be player #1 */
- if (!_network_dedicated) _network_playas = 0;
-
- _network_clients_connected = 0;
-
- NetworkInitGameInfo();
-
- // execute server initialization script
- IConsoleCmdExec("exec scripts/on_server.scr 0");
- // if the server is dedicated ... add some other script
- if (_network_dedicated) IConsoleCmdExec("exec scripts/on_dedicated.scr 0");
-
- _min_players_paused = false;
- CheckMinPlayers();
-
- /* Try to register us to the master server */
- _network_last_advertise_frame = 0;
- _network_need_advertise = true;
- NetworkUDPAdvertise();
- return true;
-}
-
-// The server is rebooting...
-// The only difference with NetworkDisconnect, is the packets that is sent
-void NetworkReboot(void)
-{
- if (_network_server) {
- NetworkClientState *cs;
- FOR_ALL_CLIENTS(cs) {
- SEND_COMMAND(PACKET_SERVER_NEWGAME)(cs);
- NetworkSend_Packets(cs);
- }
- }
-
- NetworkClose();
-
- // Free all queued commands
- while (_local_command_queue != NULL) {
- CommandPacket *p = _local_command_queue;
- _local_command_queue = _local_command_queue->next;
- free(p);
- }
-
- _networking = false;
- _network_server = false;
-}
-
-// We want to disconnect from the host/clients
-void NetworkDisconnect(void)
-{
- if (_network_server) {
- NetworkClientState *cs;
- FOR_ALL_CLIENTS(cs) {
- SEND_COMMAND(PACKET_SERVER_SHUTDOWN)(cs);
- NetworkSend_Packets(cs);
- }
- }
-
- if (_network_advertise) NetworkUDPRemoveAdvertise();
-
- DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
-
- NetworkClose();
-
- // Free all queued commands
- while (_local_command_queue != NULL) {
- CommandPacket *p = _local_command_queue;
- _local_command_queue = _local_command_queue->next;
- free(p);
- }
-
- _networking = false;
- _network_server = false;
-}
-
-// Receives something from the network
-static bool NetworkReceive(void)
-{
- NetworkClientState *cs;
- int n;
- fd_set read_fd, write_fd;
- struct timeval tv;
-
- FD_ZERO(&read_fd);
- FD_ZERO(&write_fd);
-
- FOR_ALL_CLIENTS(cs) {
- FD_SET(cs->socket, &read_fd);
- FD_SET(cs->socket, &write_fd);
- }
-
- // take care of listener port
- if (_network_server) FD_SET(_listensocket, &read_fd);
-
- tv.tv_sec = tv.tv_usec = 0; // don't block at all.
-#if !defined(__MORPHOS__) && !defined(__AMIGA__)
- n = select(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv);
-#else
- n = WaitSelect(FD_SETSIZE, &read_fd, &write_fd, NULL, &tv, NULL);
-#endif
- if (n == -1 && !_network_server) NetworkError(STR_NETWORK_ERR_LOSTCONNECTION);
-
- // accept clients..
- if (_network_server && FD_ISSET(_listensocket, &read_fd)) NetworkAcceptClients();
-
- // read stuff from clients
- FOR_ALL_CLIENTS(cs) {
- cs->writable = !!FD_ISSET(cs->socket, &write_fd);
- if (FD_ISSET(cs->socket, &read_fd)) {
- if (_network_server) {
- NetworkServer_ReadPackets(cs);
- } else {
- NetworkRecvStatus res;
-
- // The client already was quiting!
- if (cs->has_quit) return false;
-
- res = NetworkClient_ReadPackets(cs);
- if (res != NETWORK_RECV_STATUS_OKAY) {
- // The client made an error of which we can not recover
- // close the client and drop back to main menu
- NetworkClientError(res, cs);
- return false;
- }
- }
- }
- }
- return true;
-}
-
-// This sends all buffered commands (if possible)
-static void NetworkSend(void)
-{
- NetworkClientState *cs;
- FOR_ALL_CLIENTS(cs) {
- if (cs->writable) {
- NetworkSend_Packets(cs);
-
- if (cs->status == STATUS_MAP) {
- // This client is in the middle of a map-send, call the function for that
- SEND_COMMAND(PACKET_SERVER_MAP)(cs);
- }
- }
- }
-}
-
-// Handle the local-command-queue
-static void NetworkHandleLocalQueue(void)
-{
- CommandPacket *cp, **cp_prev;
-
- cp_prev = &_local_command_queue;
-
- while ( (cp = *cp_prev) != NULL) {
-
- // The queue is always in order, which means
- // that the first element will be executed first.
- if (_frame_counter < cp->frame) break;
-
- if (_frame_counter > cp->frame) {
- // If we reach here, it means for whatever reason, we've already executed
- // past the command we need to execute.
- DEBUG(net, 0, "Trying to execute a packet in the past!");
- assert(0);
- }
-
- // We can execute this command
- NetworkExecuteCommand(cp);
-
- *cp_prev = cp->next;
- free(cp);
- }
-
- // Just a safety check, to be removed in the future.
- // Make sure that no older command appears towards the end of the queue
- // In that case we missed executing it. This will never happen.
- for (cp = _local_command_queue; cp; cp = cp->next) {
- assert(_frame_counter < cp->frame);
- }
-
-}
-
-static bool NetworkDoClientLoop(void)
-{
- _frame_counter++;
-
- NetworkHandleLocalQueue();
-
- StateGameLoop();
-
- // Check if we are in sync!
- if (_sync_frame != 0) {
- if (_sync_frame == _frame_counter) {
-#ifdef NETWORK_SEND_DOUBLE_SEED
- if (_sync_seed_1 != _random_seeds[0][0] || _sync_seed_2 != _random_seeds[0][1]) {
-#else
- if (_sync_seed_1 != _random_seeds[0][0]) {
-#endif
- NetworkError(STR_NETWORK_ERR_DESYNC);
- DEBUG(net, 0, "Sync error detected!");
- NetworkClientError(NETWORK_RECV_STATUS_DESYNC, DEREF_CLIENT(0));
- return false;
- }
-
- // If this is the first time we have a sync-frame, we
- // need to let the server know that we are ready and at the same
- // frame as he is.. so we can start playing!
- if (_network_first_time) {
- _network_first_time = false;
- SEND_COMMAND(PACKET_CLIENT_ACK)();
- }
-
- _sync_frame = 0;
- } else if (_sync_frame < _frame_counter) {
- DEBUG(net, 1, "Missed frame for sync-test (%d / %d)", _sync_frame, _frame_counter);
- _sync_frame = 0;
- }
- }
-
- return true;
-}
-
-// We have to do some UDP checking
-void NetworkUDPGameLoop(void)
-{
- if (_network_udp_server) {
- NetworkUDPReceive(_udp_server_socket);
- if (_udp_master_socket != INVALID_SOCKET) {
- NetworkUDPReceive(_udp_master_socket);
- }
- } else if (_udp_client_socket != INVALID_SOCKET) {
- NetworkUDPReceive(_udp_client_socket);
- if (_network_udp_broadcast > 0) _network_udp_broadcast--;
- }
-}
-
-// The main loop called from ttd.c
-// Here we also have to do StateGameLoop if needed!
-void NetworkGameLoop(void)
-{
- if (!_networking) return;
-
- if (!NetworkReceive()) return;
-
- if (_network_server) {
- bool send_frame = false;
-
- // We first increase the _frame_counter
- _frame_counter++;
- // Update max-frame-counter
- if (_frame_counter > _frame_counter_max) {
- _frame_counter_max = _frame_counter + _network_frame_freq;
- send_frame = true;
- }
-
- NetworkHandleLocalQueue();
-
- // Then we make the frame
- StateGameLoop();
-
- _sync_seed_1 = _random_seeds[0][0];
-#ifdef NETWORK_SEND_DOUBLE_SEED
- _sync_seed_2 = _random_seeds[0][1];
-#endif
-
- NetworkServer_Tick(send_frame);
- } else {
- // Client
-
- // Make sure we are at the frame were the server is (quick-frames)
- if (_frame_counter_server > _frame_counter) {
- while (_frame_counter_server > _frame_counter) {
- if (!NetworkDoClientLoop()) break;
- }
- } else {
- // Else, keep on going till _frame_counter_max
- if (_frame_counter_max > _frame_counter) NetworkDoClientLoop();
- }
- }
-
- NetworkSend();
-}
-
-static void NetworkGenerateUniqueId(void)
-{
- md5_state_t state;
- md5_byte_t digest[16];
- char hex_output[16*2 + 1];
- char coding_string[NETWORK_NAME_LENGTH];
- int di;
-
- snprintf(coding_string, sizeof(coding_string), "%d%s", (uint)Random(), "OpenTTD Unique ID");
-
- /* Generate the MD5 hash */
- md5_init(&state);
- md5_append(&state, (const md5_byte_t*)coding_string, strlen(coding_string));
- md5_finish(&state, digest);
-
- for (di = 0; di < 16; ++di)
- sprintf(hex_output + di * 2, "%02x", digest[di]);
-
- /* _network_unique_id is our id */
- snprintf(_network_unique_id, sizeof(_network_unique_id), "%s", hex_output);
-}
-
-// This tries to launch the network for a given OS
-void NetworkStartUp(void)
-{
- DEBUG(net, 3, "[core] starting network...");
-
-#if defined(__MORPHOS__) || defined(__AMIGA__)
- /*
- * IMPORTANT NOTE: SocketBase needs to be initialized before we use _any_
- * network related function, else: crash.
- */
- DEBUG(net, 3, "[core] loading bsd socket library");
- SocketBase = OpenLibrary("bsdsocket.library", 4);
- if (SocketBase == NULL) {
- DEBUG(net, 0, "[core] can't open bsdsocket.library version 4, network unavailable");
- _network_available = false;
- return;
- }
-
-#if defined(__AMIGA__)
- // for usleep() implementation (only required for legacy AmigaOS builds)
- TimerPort = CreateMsgPort();
- if (TimerPort != NULL) {
- TimerRequest = (struct timerequest*)CreateIORequest(TimerPort, sizeof(struct timerequest);
- if (TimerRequest != NULL) {
- if (OpenDevice("timer.device", UNIT_MICROHZ, (struct IORequest*)TimerRequest, 0) == 0) {
- TimerBase = TimerRequest->tr_node.io_Device;
- if (TimerBase == NULL) {
- // free ressources...
- DEBUG(net, 0, "[core] can't initialize timer, network unavailable");
- _network_available = false;
- return;
- }
- }
- }
- }
-#endif // __AMIGA__
-#endif // __MORPHOS__ / __AMIGA__
-
- // Network is available
- _network_available = true;
- _network_dedicated = false;
- _network_last_advertise_frame = 0;
- _network_need_advertise = true;
- _network_advertise_retries = 0;
-
- /* Load the ip from the openttd.cfg */
- _network_server_bind_ip = inet_addr(_network_server_bind_ip_host);
- /* And put the data back in it in case it was an invalid ip */
- snprintf(_network_server_bind_ip_host, sizeof(_network_server_bind_ip_host), "%s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip));
-
- /* Generate an unique id when there is none yet */
- if (_network_unique_id[0] == '\0') NetworkGenerateUniqueId();
-
- {
- byte cl_max = _network_game_info.clients_max;
- byte cp_max = _network_game_info.companies_max;
- byte sp_max = _network_game_info.spectators_max;
-
- memset(&_network_game_info, 0, sizeof(_network_game_info));
- _network_game_info.clients_max = cl_max;
- _network_game_info.companies_max = cp_max;
- _network_game_info.spectators_max = sp_max;
- }
-
- // Let's load the network in windows
- #if defined(WIN32)
- {
- WSADATA wsa;
- DEBUG(net, 3, "[core] loading windows socket library");
- if (WSAStartup(MAKEWORD(2,0), &wsa) != 0) {
- DEBUG(net, 0, "[core] WSAStartup failed, network unavailable");
- _network_available = false;
- return;
- }
- }
- #endif // WIN32
-
- NetworkInitialize();
- DEBUG(net, 3, "[core] network online, multiplayer available");
- NetworkFindIPs();
-}
-
-// This shuts the network down
-void NetworkShutDown(void)
-{
- NetworkDisconnect();
- NetworkUDPClose();
-
- DEBUG(net, 3, "[core] shutting down network");
-
- _network_available = false;
-
-#if defined(__MORPHOS__) || defined(__AMIGA__)
- // free allocated ressources
-#if defined(__AMIGA__)
- if (TimerBase != NULL) CloseDevice((struct IORequest*)TimerRequest); // XXX This smells wrong
- if (TimerRequest != NULL) DeleteIORequest(TimerRequest);
- if (TimerPort != NULL) DeleteMsgPort(TimerPort);
-#endif
-
- if (SocketBase != NULL) CloseLibrary(SocketBase);
-#endif
-
-#if defined(WIN32)
- WSACleanup();
-#endif
-}
-
-#endif /* ENABLE_NETWORK */
diff --git a/network/network.h b/network/network.h
deleted file mode 100644
index 779fe393e..000000000
--- a/network/network.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/* $Id$ */
-
-#ifndef NETWORK_H
-#define NETWORK_H
-
-#define NOREV_STRING "norev000"
-
-#ifdef ENABLE_NETWORK
-
-#include "../player.h"
-#include "core/config.h"
-#include "core/game.h"
-
-// If this line is enable, every frame will have a sync test
-// this is not needed in normal games. Normal is like 1 sync in 100
-// frames. You can enable this if you have a lot of desyncs on a certain
-// game.
-// Remember: both client and server have to be compiled with this
-// option enabled to make it to work. If one of the two has it disabled
-// nothing will happen.
-//#define ENABLE_NETWORK_SYNC_EVERY_FRAME
-
-// In theory sending 1 of the 2 seeds is enough to check for desyncs
-// so in theory, this next define can be left off.
-//#define NETWORK_SEND_DOUBLE_SEED
-
-// How many clients can we have? Like.. MAX_PLAYERS - 1 is the amount of
-// players that can really play.. so.. a max of 4 spectators.. gives us..
-// MAX_PLAYERS + 3
-#define MAX_CLIENTS (MAX_PLAYERS + 3)
-
-
-// Do not change this next line. It should _ALWAYS_ be MAX_CLIENTS + 1
-#define MAX_CLIENT_INFO (MAX_CLIENTS + 1)
-
-#define MAX_INTERFACES 9
-
-
-// How many vehicle/station types we put over the network
-#define NETWORK_VEHICLE_TYPES 5
-#define NETWORK_STATION_TYPES 5
-
-typedef struct NetworkPlayerInfo {
- char company_name[NETWORK_NAME_LENGTH]; // Company name
- char password[NETWORK_PASSWORD_LENGTH]; // The password for the player
- Year inaugurated_year; // What year the company started in
- int64 company_value; // The company value
- int64 money; // The amount of money the company has
- int64 income; // How much did the company earned last year
- uint16 performance; // What was his performance last month?
- byte use_password; // 0: No password 1: There is a password
- uint16 num_vehicle[NETWORK_VEHICLE_TYPES]; // How many vehicles are there of this type?
- uint16 num_station[NETWORK_STATION_TYPES]; // How many stations are there of this type?
- char players[NETWORK_PLAYERS_LENGTH]; // The players that control this company (Name1, name2, ..)
- uint16 months_empty; // How many months the company is empty
-} NetworkPlayerInfo;
-
-typedef struct NetworkClientInfo {
- uint16 client_index; // Index of the client (same as ClientState->index)
- char client_name[NETWORK_CLIENT_NAME_LENGTH]; // Name of the client
- byte client_lang; // The language of the client
- byte client_playas; // As which player is this client playing (PlayerID)
- uint32 client_ip; // IP-address of the client (so he can be banned)
- Date join_date; // Gamedate the player has joined
- char unique_id[NETWORK_NAME_LENGTH]; // Every play sends an unique id so we can indentify him
-} NetworkClientInfo;
-
-typedef struct NetworkGameList {
- NetworkGameInfo info;
- uint32 ip;
- uint16 port;
- bool online; // False if the server did not respond (default status)
- bool manually; // True if the server was added manually
- struct NetworkGameList *next;
-} NetworkGameList;
-
-typedef enum {
- NETWORK_JOIN_STATUS_CONNECTING,
- NETWORK_JOIN_STATUS_AUTHORIZING,
- NETWORK_JOIN_STATUS_WAITING,
- NETWORK_JOIN_STATUS_DOWNLOADING,
- NETWORK_JOIN_STATUS_PROCESSING,
- NETWORK_JOIN_STATUS_REGISTERING,
-
- NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO,
-} NetworkJoinStatus;
-
-// language ids for server_lang and client_lang
-typedef enum {
- NETLANG_ANY = 0,
- NETLANG_ENGLISH = 1,
- NETLANG_GERMAN = 2,
- NETLANG_FRENCH = 3,
-} NetworkLanguage;
-
-VARDEF NetworkGameList *_network_game_list;
-
-VARDEF NetworkGameInfo _network_game_info;
-VARDEF NetworkPlayerInfo _network_player_info[MAX_PLAYERS];
-VARDEF NetworkClientInfo _network_client_info[MAX_CLIENT_INFO];
-
-VARDEF char _network_player_name[NETWORK_CLIENT_NAME_LENGTH];
-VARDEF char _network_default_ip[NETWORK_HOSTNAME_LENGTH];
-
-VARDEF uint16 _network_own_client_index;
-VARDEF char _network_unique_id[NETWORK_NAME_LENGTH]; // Our own unique ID
-
-VARDEF uint32 _frame_counter_server; // The frame_counter of the server, if in network-mode
-VARDEF uint32 _frame_counter_max; // To where we may go with our clients
-
-VARDEF uint32 _last_sync_frame; // Used in the server to store the last time a sync packet was sent to clients.
-
-// networking settings
-VARDEF uint32 _broadcast_list[MAX_INTERFACES + 1];
-
-VARDEF uint16 _network_server_port;
-/* We use bind_ip and bind_ip_host, where bind_ip_host is the readable form of
- bind_ip_host, and bind_ip the numeric value, because we want a nice number
- in the openttd.cfg, but we wants to use the uint32 internally.. */
-VARDEF uint32 _network_server_bind_ip;
-VARDEF char _network_server_bind_ip_host[NETWORK_HOSTNAME_LENGTH];
-VARDEF bool _is_network_server; // Does this client wants to be a network-server?
-VARDEF char _network_server_name[NETWORK_NAME_LENGTH];
-VARDEF char _network_server_password[NETWORK_PASSWORD_LENGTH];
-VARDEF char _network_rcon_password[NETWORK_PASSWORD_LENGTH];
-
-VARDEF uint16 _network_max_join_time; ///< Time a client can max take to join
-VARDEF bool _network_pause_on_join; ///< Pause the game when a client tries to join (more chance of succeeding join)
-
-VARDEF uint16 _redirect_console_to_client;
-
-VARDEF uint16 _network_sync_freq;
-VARDEF uint8 _network_frame_freq;
-
-VARDEF uint32 _sync_seed_1, _sync_seed_2;
-VARDEF uint32 _sync_frame;
-VARDEF bool _network_first_time;
-// Vars needed for the join-GUI
-VARDEF NetworkJoinStatus _network_join_status;
-VARDEF uint8 _network_join_waiting;
-VARDEF uint16 _network_join_kbytes;
-VARDEF uint16 _network_join_kbytes_total;
-
-VARDEF char _network_last_host[NETWORK_HOSTNAME_LENGTH];
-VARDEF short _network_last_port;
-VARDEF uint32 _network_last_host_ip;
-VARDEF uint8 _network_reconnect;
-
-VARDEF bool _network_udp_server;
-VARDEF uint16 _network_udp_broadcast;
-
-VARDEF byte _network_lan_internet;
-
-VARDEF bool _network_need_advertise;
-VARDEF uint32 _network_last_advertise_frame;
-VARDEF uint8 _network_advertise_retries;
-
-VARDEF bool _network_autoclean_companies;
-VARDEF uint8 _network_autoclean_unprotected; // Remove a company after X months
-VARDEF uint8 _network_autoclean_protected; // Unprotect a company after X months
-
-VARDEF Year _network_restart_game_year; // If this year is reached, the server automaticly restarts
-VARDEF uint8 _network_min_players; // Minimum number of players for game to unpause
-
-NetworkGameList *NetworkQueryServer(const char* host, unsigned short port, bool game_info);
-
-byte NetworkSpectatorCount(void);
-
-VARDEF char *_network_host_list[10];
-VARDEF char *_network_ban_list[25];
-
-void ParseConnectionString(const char **player, const char **port, char *connection_string);
-void NetworkUpdateClientInfo(uint16 client_index);
-void NetworkAddServer(const char *b);
-void NetworkRebuildHostList(void);
-bool NetworkChangeCompanyPassword(byte argc, char *argv[]);
-void NetworkPopulateCompanyInfo(void);
-void UpdateNetworkGameWindow(bool unselect);
-void CheckMinPlayers(void);
-
-void NetworkStartUp(void);
-void NetworkUDPClose(void);
-void NetworkShutDown(void);
-void NetworkGameLoop(void);
-void NetworkUDPGameLoop(void);
-bool NetworkServerStart(void);
-bool NetworkClientConnectGame(const char *host, uint16 port);
-void NetworkReboot(void);
-void NetworkDisconnect(void);
-
-VARDEF bool _networking; ///< are we in networking mode?
-VARDEF bool _network_server; ///< network-server is active
-VARDEF bool _network_available; ///< is network mode available?
-
-#else /* ENABLE_NETWORK */
-/* Network function stubs when networking is disabled */
-
-static inline void NetworkStartUp(void) {}
-static inline void NetworkShutDown(void) {}
-
-#define _networking 0
-#define _network_server 0
-#define _network_available 0
-
-#endif /* ENABLE_NETWORK */
-
-/* These variables must always be registered! */
-VARDEF bool _network_dedicated; ///< are we a dedicated server?
-VARDEF bool _network_advertise; ///< is the server advertising to the master server?
-VARDEF PlayerID _network_playas; ///< an id to play as.. (see players.h:Players)
-
-#endif /* NETWORK_H */
diff --git a/network/network_client.c b/network/network_client.c
deleted file mode 100644
index ce2a71ac1..000000000
--- a/network/network_client.c
+++ /dev/null
@@ -1,819 +0,0 @@
-/* $Id$ */
-
-#ifdef ENABLE_NETWORK
-
-#include "../stdafx.h"
-#include "../debug.h"
-#include "../string.h"
-#include "../strings.h"
-#include "network_data.h"
-#include "core/tcp.h"
-#include "../date.h"
-#include "../table/strings.h"
-#include "../functions.h"
-#include "network_client.h"
-#include "network_gamelist.h"
-#include "network_gui.h"
-#include "../saveload.h"
-#include "../command.h"
-#include "../window.h"
-#include "../console.h"
-#include "../variables.h"
-#include "../ai/ai.h"
-
-
-// This file handles all the client-commands
-
-
-// So we don't make too much typos ;)
-#define MY_CLIENT DEREF_CLIENT(0)
-
-static uint32 last_ack_frame;
-
-// **********
-// Sending functions
-// DEF_CLIENT_SEND_COMMAND has no parameters
-// **********
-
-DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_COMPANY_INFO)
-{
- //
- // Packet: CLIENT_COMPANY_INFO
- // Function: Request company-info (in detail)
- // Data:
- // <none>
- //
- Packet *p;
- _network_join_status = NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO;
- InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
-
- p = NetworkSend_Init(PACKET_CLIENT_COMPANY_INFO);
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_JOIN)
-{
- //
- // Packet: CLIENT_JOIN
- // Function: Try to join the server
- // Data:
- // String: OpenTTD Revision (norev000 if no revision)
- // String: Player Name (max NETWORK_NAME_LENGTH)
- // uint8: Play as Player id (1..MAX_PLAYERS)
- // uint8: Language ID
- // String: Unique id to find the player back in server-listing
- //
-
- extern const char _openttd_revision[];
- Packet *p;
- _network_join_status = NETWORK_JOIN_STATUS_AUTHORIZING;
- InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
-
- p = NetworkSend_Init(PACKET_CLIENT_JOIN);
- NetworkSend_string(p, _openttd_revision);
- NetworkSend_string(p, _network_player_name); // Player name
- NetworkSend_uint8(p, _network_playas); // PlayAs
- NetworkSend_uint8(p, NETLANG_ANY); // Language
- NetworkSend_string(p, _network_unique_id);
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_PASSWORD)(NetworkPasswordType type, const char *password)
-{
- //
- // Packet: CLIENT_PASSWORD
- // Function: Send a password to the server to authorize
- // Data:
- // uint8: NetworkPasswordType
- // String: Password
- //
- Packet *p = NetworkSend_Init(PACKET_CLIENT_PASSWORD);
- NetworkSend_uint8(p, type);
- NetworkSend_string(p, password);
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_GETMAP)
-{
- //
- // Packet: CLIENT_GETMAP
- // Function: Request the map from the server
- // Data:
- // <none>
- //
-
- Packet *p = NetworkSend_Init(PACKET_CLIENT_GETMAP);
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_MAP_OK)
-{
- //
- // Packet: CLIENT_MAP_OK
- // Function: Tell the server that we are done receiving/loading the map
- // Data:
- // <none>
- //
-
- Packet *p = NetworkSend_Init(PACKET_CLIENT_MAP_OK);
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_ACK)
-{
- //
- // Packet: CLIENT_ACK
- // Function: Tell the server we are done with this frame
- // Data:
- // uint32: current FrameCounter of the client
- //
-
- Packet *p = NetworkSend_Init(PACKET_CLIENT_ACK);
-
- NetworkSend_uint32(p, _frame_counter);
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-// Send a command packet to the server
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_COMMAND)(CommandPacket *cp)
-{
- //
- // Packet: CLIENT_COMMAND
- // Function: Send a DoCommand to the Server
- // Data:
- // uint8: PlayerID (0..MAX_PLAYERS-1)
- // uint32: CommandID (see command.h)
- // uint32: P1 (free variables used in DoCommand)
- // uint32: P2
- // uint32: Tile
- // string: text
- // uint8: CallBackID (see callback_table.c)
- //
-
- Packet *p = NetworkSend_Init(PACKET_CLIENT_COMMAND);
-
- NetworkSend_uint8(p, cp->player);
- NetworkSend_uint32(p, cp->cmd);
- NetworkSend_uint32(p, cp->p1);
- NetworkSend_uint32(p, cp->p2);
- NetworkSend_uint32(p, (uint32)cp->tile);
- NetworkSend_string(p, cp->text);
- NetworkSend_uint8(p, cp->callback);
-
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-// Send a chat-packet over the network
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_CHAT)(NetworkAction action, DestType type, int dest, const char *msg)
-{
- //
- // Packet: CLIENT_CHAT
- // Function: Send a chat-packet to the serve
- // Data:
- // uint8: ActionID (see network_data.h, NetworkAction)
- // uint8: Destination Type (see network_data.h, DestType);
- // uint8: Destination Player (1..MAX_PLAYERS)
- // String: Message (max MAX_TEXT_MSG_LEN)
- //
-
- Packet *p = NetworkSend_Init(PACKET_CLIENT_CHAT);
-
- NetworkSend_uint8(p, action);
- NetworkSend_uint8(p, type);
- NetworkSend_uint8(p, dest);
- NetworkSend_string(p, msg);
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-// Send an error-packet over the network
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_ERROR)(NetworkErrorCode errorno)
-{
- //
- // Packet: CLIENT_ERROR
- // Function: The client made an error and is quiting the game
- // Data:
- // uint8: ErrorID (see network_data.h, NetworkErrorCode)
- //
- Packet *p = NetworkSend_Init(PACKET_CLIENT_ERROR);
-
- NetworkSend_uint8(p, errorno);
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_PASSWORD)(const char *password)
-{
- //
- // Packet: PACKET_CLIENT_SET_PASSWORD
- // Function: Set the password for the clients current company
- // Data:
- // String: Password
- //
- Packet *p = NetworkSend_Init(PACKET_CLIENT_SET_PASSWORD);
-
- NetworkSend_string(p, password);
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_NAME)(const char *name)
-{
- //
- // Packet: PACKET_CLIENT_SET_NAME
- // Function: Gives the player a new name
- // Data:
- // String: Name
- //
- Packet *p = NetworkSend_Init(PACKET_CLIENT_SET_NAME);
-
- NetworkSend_string(p, name);
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-// Send an quit-packet over the network
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_QUIT)(const char *leavemsg)
-{
- //
- // Packet: CLIENT_QUIT
- // Function: The client is quiting the game
- // Data:
- // String: leave-message
- //
- Packet *p = NetworkSend_Init(PACKET_CLIENT_QUIT);
-
- NetworkSend_string(p, leavemsg);
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_RCON)(const char *pass, const char *command)
-{
- Packet *p = NetworkSend_Init(PACKET_CLIENT_RCON);
- NetworkSend_string(p, pass);
- NetworkSend_string(p, command);
- NetworkSend_Packet(p, MY_CLIENT);
-}
-
-
-// **********
-// Receiving functions
-// DEF_CLIENT_RECEIVE_COMMAND has parameter: Packet *p
-// **********
-
-extern bool SafeSaveOrLoad(const char *filename, int mode, int newgm);
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_FULL)
-{
- // We try to join a server which is full
- _switch_mode_errorstr = STR_NETWORK_ERR_SERVER_FULL;
- DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
-
- return NETWORK_RECV_STATUS_SERVER_FULL;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_BANNED)
-{
- // We try to join a server where we are banned
- _switch_mode_errorstr = STR_NETWORK_ERR_SERVER_BANNED;
- DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
-
- return NETWORK_RECV_STATUS_SERVER_BANNED;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_COMPANY_INFO)
-{
- byte company_info_version;
- int i;
-
- company_info_version = NetworkRecv_uint8(MY_CLIENT, p);
-
- if (!MY_CLIENT->has_quit && company_info_version == NETWORK_COMPANY_INFO_VERSION) {
- byte total;
- byte current;
-
- total = NetworkRecv_uint8(MY_CLIENT, p);
-
- // There is no data at all..
- if (total == 0) return NETWORK_RECV_STATUS_CLOSE_QUERY;
-
- current = NetworkRecv_uint8(MY_CLIENT, p);
- if (!IsValidPlayer(current)) return NETWORK_RECV_STATUS_CLOSE_QUERY;
-
- NetworkRecv_string(MY_CLIENT, p, _network_player_info[current].company_name, sizeof(_network_player_info[current].company_name));
- _network_player_info[current].inaugurated_year = NetworkRecv_uint32(MY_CLIENT, p);
- _network_player_info[current].company_value = NetworkRecv_uint64(MY_CLIENT, p);
- _network_player_info[current].money = NetworkRecv_uint64(MY_CLIENT, p);
- _network_player_info[current].income = NetworkRecv_uint64(MY_CLIENT, p);
- _network_player_info[current].performance = NetworkRecv_uint16(MY_CLIENT, p);
- _network_player_info[current].use_password = NetworkRecv_uint8(MY_CLIENT, p);
- for (i = 0; i < NETWORK_VEHICLE_TYPES; i++)
- _network_player_info[current].num_vehicle[i] = NetworkRecv_uint16(MY_CLIENT, p);
- for (i = 0; i < NETWORK_STATION_TYPES; i++)
- _network_player_info[current].num_station[i] = NetworkRecv_uint16(MY_CLIENT, p);
-
- NetworkRecv_string(MY_CLIENT, p, _network_player_info[current].players, sizeof(_network_player_info[current].players));
-
- InvalidateWindow(WC_NETWORK_WINDOW, 0);
-
- return NETWORK_RECV_STATUS_OKAY;
- }
-
- return NETWORK_RECV_STATUS_CLOSE_QUERY;
-}
-
-// This packet contains info about the client (playas and name)
-// as client we save this in NetworkClientInfo, linked via 'index'
-// which is always an unique number on a server.
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO)
-{
- NetworkClientInfo *ci;
- uint16 index = NetworkRecv_uint16(MY_CLIENT, p);
- PlayerID playas = NetworkRecv_uint8(MY_CLIENT, p);
- char name[NETWORK_NAME_LENGTH];
- char unique_id[NETWORK_NAME_LENGTH];
-
- NetworkRecv_string(MY_CLIENT, p, name, sizeof(name));
- NetworkRecv_string(MY_CLIENT, p, unique_id, sizeof(unique_id));
-
- if (MY_CLIENT->has_quit) return NETWORK_RECV_STATUS_CONN_LOST;
-
- /* Do we receive a change of data? Most likely we changed playas */
- if (index == _network_own_client_index) _network_playas = playas;
-
- ci = NetworkFindClientInfoFromIndex(index);
- if (ci != NULL) {
- if (playas == ci->client_playas && strcmp(name, ci->client_name) != 0) {
- // Client name changed, display the change
- NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, 1, false, ci->client_name, "%s", name);
- } else if (playas != ci->client_playas) {
- // The player changed from client-player..
- // Do not display that for now
- }
-
- ci->client_playas = playas;
- ttd_strlcpy(ci->client_name, name, sizeof(ci->client_name));
-
- InvalidateWindow(WC_CLIENT_LIST, 0);
-
- return NETWORK_RECV_STATUS_OKAY;
- }
-
- // We don't have this index yet, find an empty index, and put the data there
- ci = NetworkFindClientInfoFromIndex(NETWORK_EMPTY_INDEX);
- if (ci != NULL) {
- ci->client_index = index;
- ci->client_playas = playas;
-
- ttd_strlcpy(ci->client_name, name, sizeof(ci->client_name));
- ttd_strlcpy(ci->unique_id, unique_id, sizeof(ci->unique_id));
-
- InvalidateWindow(WC_CLIENT_LIST, 0);
-
- return NETWORK_RECV_STATUS_OKAY;
- }
-
- // Here the program should never ever come.....
- return NETWORK_RECV_STATUS_MALFORMED_PACKET;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_ERROR)
-{
- NetworkErrorCode error = NetworkRecv_uint8(MY_CLIENT, p);
-
- switch (error) {
- /* We made an error in the protocol, and our connection is closed.... */
- case NETWORK_ERROR_NOT_AUTHORIZED:
- case NETWORK_ERROR_NOT_EXPECTED:
- case NETWORK_ERROR_PLAYER_MISMATCH:
- _switch_mode_errorstr = STR_NETWORK_ERR_SERVER_ERROR;
- break;
- case NETWORK_ERROR_FULL:
- _switch_mode_errorstr = STR_NETWORK_ERR_SERVER_FULL;
- break;
- case NETWORK_ERROR_WRONG_REVISION:
- _switch_mode_errorstr = STR_NETWORK_ERR_WRONG_REVISION;
- break;
- case NETWORK_ERROR_WRONG_PASSWORD:
- _switch_mode_errorstr = STR_NETWORK_ERR_WRONG_PASSWORD;
- break;
- case NETWORK_ERROR_KICKED:
- _switch_mode_errorstr = STR_NETWORK_ERR_KICKED;
- break;
- case NETWORK_ERROR_CHEATER:
- _switch_mode_errorstr = STR_NETWORK_ERR_CHEATER;
- break;
- default:
- _switch_mode_errorstr = STR_NETWORK_ERR_LOSTCONNECTION;
- }
-
- DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
-
- return NETWORK_RECV_STATUS_SERVER_ERROR;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEED_PASSWORD)
-{
- NetworkPasswordType type = NetworkRecv_uint8(MY_CLIENT, p);
-
- switch (type) {
- case NETWORK_GAME_PASSWORD:
- case NETWORK_COMPANY_PASSWORD:
- ShowNetworkNeedPassword(type);
- return NETWORK_RECV_STATUS_OKAY;
-
- default: return NETWORK_RECV_STATUS_MALFORMED_PACKET;
- }
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_WELCOME)
-{
- _network_own_client_index = NetworkRecv_uint16(MY_CLIENT, p);
-
- // Start receiving the map
- SEND_COMMAND(PACKET_CLIENT_GETMAP)();
- return NETWORK_RECV_STATUS_OKAY;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_WAIT)
-{
- _network_join_status = NETWORK_JOIN_STATUS_WAITING;
- _network_join_waiting = NetworkRecv_uint8(MY_CLIENT, p);
- InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
-
- // We are put on hold for receiving the map.. we need GUI for this ;)
- DEBUG(net, 1, "The server is currently busy sending the map to someone else, please wait..." );
- DEBUG(net, 1, "There are %d clients in front of you", _network_join_waiting);
-
- return NETWORK_RECV_STATUS_OKAY;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_MAP)
-{
- static char filename[256];
- static FILE *file_pointer;
-
- byte maptype;
-
- maptype = NetworkRecv_uint8(MY_CLIENT, p);
-
- if (MY_CLIENT->has_quit) return NETWORK_RECV_STATUS_CONN_LOST;
-
- // First packet, init some stuff
- if (maptype == MAP_PACKET_START) {
- // The name for the temp-map
- snprintf(filename, lengthof(filename), "%s%snetwork_client.tmp", _paths.autosave_dir, PATHSEP);
-
- file_pointer = fopen(filename, "wb");
- if (file_pointer == NULL) {
- _switch_mode_errorstr = STR_NETWORK_ERR_SAVEGAMEERROR;
- return NETWORK_RECV_STATUS_SAVEGAME;
- }
-
- _frame_counter = _frame_counter_server = _frame_counter_max = NetworkRecv_uint32(MY_CLIENT, p);
-
- _network_join_status = NETWORK_JOIN_STATUS_DOWNLOADING;
- _network_join_kbytes = 0;
- _network_join_kbytes_total = NetworkRecv_uint32(MY_CLIENT, p) / 1024;
- InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
-
- // The first packet does not contain any more data
- return NETWORK_RECV_STATUS_OKAY;
- }
-
- if (maptype == MAP_PACKET_NORMAL) {
- // We are still receiving data, put it to the file
- fwrite(p->buffer + p->pos, 1, p->size - p->pos, file_pointer);
-
- _network_join_kbytes = ftell(file_pointer) / 1024;
- InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
- }
-
- // Check if this was the last packet
- if (maptype == MAP_PACKET_END) {
- fclose(file_pointer);
-
- _network_join_status = NETWORK_JOIN_STATUS_PROCESSING;
- InvalidateWindow(WC_NETWORK_STATUS_WINDOW, 0);
-
- /* The map is done downloading, load it */
- if (!SafeSaveOrLoad(filename, SL_LOAD, GM_NORMAL)) {
- DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
- _switch_mode_errorstr = STR_NETWORK_ERR_SAVEGAMEERROR;
- return NETWORK_RECV_STATUS_SAVEGAME;
- }
- /* If the savegame has successfully loaded, ALL windows have been removed,
- * only toolbar/statusbar and gamefield are visible */
-
- _opt_ptr = &_opt; // during a network game you are always in-game
-
- // Say we received the map and loaded it correctly!
- SEND_COMMAND(PACKET_CLIENT_MAP_OK)();
-
- /* New company/spectator (invalid player) or company we want to join is not active
- * Switch local player to spectator and await the server's judgement */
- if (_network_playas == PLAYER_NEW_COMPANY || !IsValidPlayer(_network_playas) ||
- !GetPlayer(_network_playas)->is_active) {
-
- SetLocalPlayer(PLAYER_SPECTATOR);
-
- if (_network_playas != PLAYER_SPECTATOR) {
- /* We have arrived and ready to start playing; send a command to make a new player;
- * the server will give us a client-id and let us in */
- _network_join_status = NETWORK_JOIN_STATUS_REGISTERING;
- ShowJoinStatusWindow();
- NetworkSend_Command(0, 0, 0, CMD_PLAYER_CTRL, NULL);
- }
- } else {
- // take control over an existing company
- SetLocalPlayer(_network_playas);
- }
- }
-
- return NETWORK_RECV_STATUS_OKAY;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_FRAME)
-{
- _frame_counter_server = NetworkRecv_uint32(MY_CLIENT, p);
- _frame_counter_max = NetworkRecv_uint32(MY_CLIENT, p);
-#ifdef ENABLE_NETWORK_SYNC_EVERY_FRAME
- // Test if the server supports this option
- // and if we are at the frame the server is
- if (p->pos < p->size) {
- _sync_frame = _frame_counter_server;
- _sync_seed_1 = NetworkRecv_uint32(MY_CLIENT, p);
-#ifdef NETWORK_SEND_DOUBLE_SEED
- _sync_seed_2 = NetworkRecv_uint32(MY_CLIENT, p);
-#endif
- }
-#endif
- DEBUG(net, 5, "Received FRAME %d", _frame_counter_server);
-
- // Let the server know that we received this frame correctly
- // We do this only once per day, to save some bandwidth ;)
- if (!_network_first_time && last_ack_frame < _frame_counter) {
- last_ack_frame = _frame_counter + DAY_TICKS;
- DEBUG(net, 4, "Sent ACK at %d", _frame_counter);
- SEND_COMMAND(PACKET_CLIENT_ACK)();
- }
-
- return NETWORK_RECV_STATUS_OKAY;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_SYNC)
-{
- _sync_frame = NetworkRecv_uint32(MY_CLIENT, p);
- _sync_seed_1 = NetworkRecv_uint32(MY_CLIENT, p);
-#ifdef NETWORK_SEND_DOUBLE_SEED
- _sync_seed_2 = NetworkRecv_uint32(MY_CLIENT, p);
-#endif
-
- return NETWORK_RECV_STATUS_OKAY;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_COMMAND)
-{
- CommandPacket *cp = malloc(sizeof(CommandPacket));
- cp->player = NetworkRecv_uint8(MY_CLIENT, p);
- cp->cmd = NetworkRecv_uint32(MY_CLIENT, p);
- cp->p1 = NetworkRecv_uint32(MY_CLIENT, p);
- cp->p2 = NetworkRecv_uint32(MY_CLIENT, p);
- cp->tile = NetworkRecv_uint32(MY_CLIENT, p);
- NetworkRecv_string(MY_CLIENT, p, cp->text, sizeof(cp->text));
- cp->callback = NetworkRecv_uint8(MY_CLIENT, p);
- cp->frame = NetworkRecv_uint32(MY_CLIENT, p);
- cp->next = NULL;
-
- // The server did send us this command..
- // queue it in our own queue, so we can handle it in the upcoming frame!
-
- if (_local_command_queue == NULL) {
- _local_command_queue = cp;
- } else {
- // Find last packet
- CommandPacket *c = _local_command_queue;
- while (c->next != NULL) c = c->next;
- c->next = cp;
- }
-
- return NETWORK_RECV_STATUS_OKAY;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_CHAT)
-{
- char name[NETWORK_NAME_LENGTH], msg[MAX_TEXT_MSG_LEN];
- const NetworkClientInfo *ci = NULL, *ci_to;
-
- NetworkAction action = NetworkRecv_uint8(MY_CLIENT, p);
- uint16 index = NetworkRecv_uint16(MY_CLIENT, p);
- bool self_send = NetworkRecv_uint8(MY_CLIENT, p);
- NetworkRecv_string(MY_CLIENT, p, msg, MAX_TEXT_MSG_LEN);
-
- ci_to = NetworkFindClientInfoFromIndex(index);
- if (ci_to == NULL) return NETWORK_RECV_STATUS_OKAY;
-
- /* Did we initiate the action locally? */
- if (self_send) {
- switch (action) {
- case NETWORK_ACTION_CHAT_CLIENT:
- /* For speaking to client we need the client-name */
- snprintf(name, sizeof(name), "%s", ci_to->client_name);
- ci = NetworkFindClientInfoFromIndex(_network_own_client_index);
- break;
-
- /* For speaking to company or giving money, we need the player-name */
- case NETWORK_ACTION_GIVE_MONEY:
- if (!IsValidPlayer(ci_to->client_playas)) return NETWORK_RECV_STATUS_OKAY;
- /* fallthrough */
- case NETWORK_ACTION_CHAT_COMPANY: {
- StringID str = IsValidPlayer(ci_to->client_playas) ? GetPlayer(ci_to->client_playas)->name_1 : STR_NETWORK_SPECTATORS;
-
- GetString(name, str, lastof(name));
- ci = NetworkFindClientInfoFromIndex(_network_own_client_index);
- } break;
-
- default: NOT_REACHED(); break;
- }
- } else {
- /* Display message from somebody else */
- snprintf(name, sizeof(name), "%s", ci_to->client_name);
- ci = ci_to;
- }
-
- if (ci != NULL)
- NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), self_send, name, "%s", msg);
- return NETWORK_RECV_STATUS_OKAY;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT)
-{
- char str[100];
- uint16 index;
- NetworkClientInfo *ci;
-
- index = NetworkRecv_uint16(MY_CLIENT, p);
- GetNetworkErrorMsg(str, NetworkRecv_uint8(MY_CLIENT, p), lastof(str));
-
- ci = NetworkFindClientInfoFromIndex(index);
- if (ci != NULL) {
- NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, ci->client_name, "%s", str);
-
- // The client is gone, give the NetworkClientInfo free
- ci->client_index = NETWORK_EMPTY_INDEX;
- }
-
- InvalidateWindow(WC_CLIENT_LIST, 0);
-
- return NETWORK_RECV_STATUS_OKAY;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_QUIT)
-{
- char str[100];
- uint16 index;
- NetworkClientInfo *ci;
-
- index = NetworkRecv_uint16(MY_CLIENT, p);
- NetworkRecv_string(MY_CLIENT, p, str, lengthof(str));
-
- ci = NetworkFindClientInfoFromIndex(index);
- if (ci != NULL) {
- NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, ci->client_name, "%s", str);
-
- // The client is gone, give the NetworkClientInfo free
- ci->client_index = NETWORK_EMPTY_INDEX;
- } else {
- DEBUG(net, 0, "Unknown client (%d) is leaving the game", index);
- }
-
- InvalidateWindow(WC_CLIENT_LIST, 0);
-
- // If we come here it means we could not locate the client.. strange :s
- return NETWORK_RECV_STATUS_OKAY;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_JOIN)
-{
- uint16 index;
- NetworkClientInfo *ci;
-
- index = NetworkRecv_uint16(MY_CLIENT, p);
-
- ci = NetworkFindClientInfoFromIndex(index);
- if (ci != NULL)
- NetworkTextMessage(NETWORK_ACTION_JOIN, 1, false, ci->client_name, "");
-
- InvalidateWindow(WC_CLIENT_LIST, 0);
-
- return NETWORK_RECV_STATUS_OKAY;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_SHUTDOWN)
-{
- _switch_mode_errorstr = STR_NETWORK_SERVER_SHUTDOWN;
-
- return NETWORK_RECV_STATUS_SERVER_ERROR;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_NEWGAME)
-{
- // To trottle the reconnects a bit, every clients waits
- // his _local_player value before reconnecting
- // PLAYER_SPECTATOR is currently 255, so to avoid long wait periods
- // set the max to 10.
- _network_reconnect = min(_local_player + 1, 10);
- _switch_mode_errorstr = STR_NETWORK_SERVER_REBOOT;
-
- return NETWORK_RECV_STATUS_SERVER_ERROR;
-}
-
-DEF_CLIENT_RECEIVE_COMMAND(PACKET_SERVER_RCON)
-{
- char rcon_out[NETWORK_RCONCOMMAND_LENGTH];
- uint16 color_code;
-
- color_code = NetworkRecv_uint16(MY_CLIENT, p);
- NetworkRecv_string(MY_CLIENT, p, rcon_out, sizeof(rcon_out));
-
- IConsolePrint(color_code, rcon_out);
-
- return NETWORK_RECV_STATUS_OKAY;
-}
-
-
-
-// The layout for the receive-functions by the client
-typedef NetworkRecvStatus NetworkClientPacket(Packet *p);
-
-// This array matches PacketType. At an incoming
-// packet it is matches against this array
-// and that way the right function to handle that
-// packet is found.
-static NetworkClientPacket* const _network_client_packet[] = {
- RECEIVE_COMMAND(PACKET_SERVER_FULL),
- RECEIVE_COMMAND(PACKET_SERVER_BANNED),
- NULL, /*PACKET_CLIENT_JOIN,*/
- RECEIVE_COMMAND(PACKET_SERVER_ERROR),
- NULL, /*PACKET_CLIENT_COMPANY_INFO,*/
- RECEIVE_COMMAND(PACKET_SERVER_COMPANY_INFO),
- RECEIVE_COMMAND(PACKET_SERVER_CLIENT_INFO),
- RECEIVE_COMMAND(PACKET_SERVER_NEED_PASSWORD),
- NULL, /*PACKET_CLIENT_PASSWORD,*/
- RECEIVE_COMMAND(PACKET_SERVER_WELCOME),
- NULL, /*PACKET_CLIENT_GETMAP,*/
- RECEIVE_COMMAND(PACKET_SERVER_WAIT),
- RECEIVE_COMMAND(PACKET_SERVER_MAP),
- NULL, /*PACKET_CLIENT_MAP_OK,*/
- RECEIVE_COMMAND(PACKET_SERVER_JOIN),
- RECEIVE_COMMAND(PACKET_SERVER_FRAME),
- RECEIVE_COMMAND(PACKET_SERVER_SYNC),
- NULL, /*PACKET_CLIENT_ACK,*/
- NULL, /*PACKET_CLIENT_COMMAND,*/
- RECEIVE_COMMAND(PACKET_SERVER_COMMAND),
- NULL, /*PACKET_CLIENT_CHAT,*/
- RECEIVE_COMMAND(PACKET_SERVER_CHAT),
- NULL, /*PACKET_CLIENT_SET_PASSWORD,*/
- NULL, /*PACKET_CLIENT_SET_NAME,*/
- NULL, /*PACKET_CLIENT_QUIT,*/
- NULL, /*PACKET_CLIENT_ERROR,*/
- RECEIVE_COMMAND(PACKET_SERVER_QUIT),
- RECEIVE_COMMAND(PACKET_SERVER_ERROR_QUIT),
- RECEIVE_COMMAND(PACKET_SERVER_SHUTDOWN),
- RECEIVE_COMMAND(PACKET_SERVER_NEWGAME),
- RECEIVE_COMMAND(PACKET_SERVER_RCON),
- NULL, /*PACKET_CLIENT_RCON,*/
-};
-
-// If this fails, check the array above with network_data.h
-assert_compile(lengthof(_network_client_packet) == PACKET_END);
-
-// Is called after a client is connected to the server
-void NetworkClient_Connected(void)
-{
- // Set the frame-counter to 0 so nothing happens till we are ready
- _frame_counter = 0;
- _frame_counter_server = 0;
- last_ack_frame = 0;
- // Request the game-info
- SEND_COMMAND(PACKET_CLIENT_JOIN)();
-}
-
-// Reads the packets from the socket-stream, if available
-NetworkRecvStatus NetworkClient_ReadPackets(NetworkClientState *cs)
-{
- Packet *p;
- NetworkRecvStatus res = NETWORK_RECV_STATUS_OKAY;
-
- while (res == NETWORK_RECV_STATUS_OKAY && (p = NetworkRecv_Packet(cs, &res)) != NULL) {
- byte type = NetworkRecv_uint8(MY_CLIENT, p);
- if (type < PACKET_END && _network_client_packet[type] != NULL && !MY_CLIENT->has_quit) {
- res = _network_client_packet[type](p);
- } else {
- res = NETWORK_RECV_STATUS_MALFORMED_PACKET;
- DEBUG(net, 0, "[client] received invalid packet type %d", type);
- }
-
- free(p);
- }
-
- return res;
-}
-
-#endif /* ENABLE_NETWORK */
diff --git a/network/network_client.h b/network/network_client.h
deleted file mode 100644
index 2dd776ac1..000000000
--- a/network/network_client.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/* $Id$ */
-
-#ifndef NETWORK_CLIENT_H
-#define NETWORK_CLIENT_H
-
-#ifdef ENABLE_NETWORK
-
-DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_GAME_INFO);
-DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_COMPANY_INFO);
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_COMMAND)(CommandPacket *cp);
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_ERROR)(NetworkErrorCode errorno);
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_QUIT)(const char *leavemsg);
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_CHAT)(NetworkAction action, DestType desttype, int dest, const char *msg);
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_PASSWORD)(NetworkPasswordType type, const char *password);
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_PASSWORD)(const char *password);
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_SET_NAME)(const char *name);
-DEF_CLIENT_SEND_COMMAND(PACKET_CLIENT_ACK);
-DEF_CLIENT_SEND_COMMAND_PARAM(PACKET_CLIENT_RCON)(const char *pass, const char *command);
-
-NetworkRecvStatus NetworkClient_ReadPackets(NetworkClientState *cs);
-void NetworkClient_Connected(void);
-
-#endif /* ENABLE_NETWORK */
-
-#endif /* NETWORK_CLIENT_H */
diff --git a/network/network_data.c b/network/network_data.c
deleted file mode 100644
index 9e5e6424d..000000000
--- a/network/network_data.c
+++ /dev/null
@@ -1,106 +0,0 @@
-/* $Id$ */
-
-#ifdef ENABLE_NETWORK
-
-#include "../stdafx.h"
-#include "../debug.h"
-#include "network_data.h"
-#include "../string.h"
-#include "network_client.h"
-#include "../command.h"
-#include "../callback_table.h"
-
-// Add a command to the local command queue
-void NetworkAddCommandQueue(NetworkClientState *cs, CommandPacket *cp)
-{
- CommandPacket* new_cp = malloc(sizeof(*new_cp));
-
- *new_cp = *cp;
-
- if (cs->command_queue == NULL) {
- cs->command_queue = new_cp;
- } else {
- CommandPacket *c = cs->command_queue;
- while (c->next != NULL) c = c->next;
- c->next = new_cp;
- }
-}
-
-// Prepare a DoCommand to be send over the network
-void NetworkSend_Command(TileIndex tile, uint32 p1, uint32 p2, uint32 cmd, CommandCallback *callback)
-{
- CommandPacket *c = malloc(sizeof(CommandPacket));
- byte temp_callback;
-
- c->player = _local_player;
- c->next = NULL;
- c->tile = tile;
- c->p1 = p1;
- c->p2 = p2;
- c->cmd = cmd;
- c->callback = 0;
-
- temp_callback = 0;
-
- while (temp_callback < _callback_table_count && _callback_table[temp_callback] != callback)
- temp_callback++;
- if (temp_callback == _callback_table_count) {
- DEBUG(net, 0, "Unknown callback. (Pointer: %p) No callback sent", callback);
- temp_callback = 0; /* _callback_table[0] == NULL */
- }
-
- if (_network_server) {
- // We are the server, so set the command to be executed next possible frame
- c->frame = _frame_counter_max + 1;
- } else {
- c->frame = 0; // The client can't tell which frame, so just make it 0
- }
-
- ttd_strlcpy(c->text, (_cmd_text != NULL) ? _cmd_text : "", lengthof(c->text));
-
- if (_network_server) {
- // If we are the server, we queue the command in our 'special' queue.
- // In theory, we could execute the command right away, but then the
- // client on the server can do everything 1 tick faster than others.
- // So to keep the game fair, we delay the command with 1 tick
- // which gives about the same speed as most clients.
- NetworkClientState *cs;
-
- // And we queue it for delivery to the clients
- FOR_ALL_CLIENTS(cs) {
- if (cs->status > STATUS_AUTH) NetworkAddCommandQueue(cs, c);
- }
-
- // Only the server gets the callback, because clients should not get them
- c->callback = temp_callback;
- if (_local_command_queue == NULL) {
- _local_command_queue = c;
- } else {
- // Find last packet
- CommandPacket *cp = _local_command_queue;
- while (cp->next != NULL) cp = cp->next;
- cp->next = c;
- }
-
- return;
- }
-
- // Clients send their command to the server and forget all about the packet
- c->callback = temp_callback;
- SEND_COMMAND(PACKET_CLIENT_COMMAND)(c);
-}
-
-// Execute a DoCommand we received from the network
-void NetworkExecuteCommand(CommandPacket *cp)
-{
- _current_player = cp->player;
- _cmd_text = cp->text;
- /* cp->callback is unsigned. so we don't need to do lower bounds checking. */
- if (cp->callback > _callback_table_count) {
- DEBUG(net, 0, "Received out-of-bounds callback (%d)", cp->callback);
- cp->callback = 0;
- }
- DoCommandP(cp->tile, cp->p1, cp->p2, _callback_table[cp->callback], cp->cmd | CMD_NETWORK_COMMAND);
-}
-
-#endif /* ENABLE_NETWORK */
diff --git a/network/network_data.h b/network/network_data.h
deleted file mode 100644
index 3e42e00cf..000000000
--- a/network/network_data.h
+++ /dev/null
@@ -1,167 +0,0 @@
-/* $Id$ */
-
-#ifndef NETWORK_DATA_H
-#define NETWORK_DATA_H
-
-// Is the network enabled?
-#ifdef ENABLE_NETWORK
-
-#include "../openttd.h"
-#include "network.h"
-#include "core/os_abstraction.h"
-#include "core/config.h"
-#include "core/packet.h"
-
-#define MAX_TEXT_MSG_LEN 1024 /* long long long long sentences :-) */
-
-// The client-info-server-index is always 1
-#define NETWORK_SERVER_INDEX 1
-#define NETWORK_EMPTY_INDEX 0
-
-typedef struct CommandPacket {
- struct CommandPacket *next;
- PlayerID player; /// player that is executing the command
- uint32 cmd; /// command being executed
- uint32 p1; /// parameter p1
- uint32 p2; /// parameter p2
- TileIndex tile; /// tile command being executed on
- char text[80];
- uint32 frame; /// the frame in which this packet is executed
- byte callback; /// any callback function executed upon successful completion of the command
-} CommandPacket;
-
-typedef enum {
- STATUS_INACTIVE,
- STATUS_AUTH, // This means that the client is authorized
- STATUS_MAP_WAIT, // This means that the client is put on hold because someone else is getting the map
- STATUS_MAP,
- STATUS_DONE_MAP,
- STATUS_PRE_ACTIVE,
- STATUS_ACTIVE,
-} ClientStatus;
-
-typedef enum {
- MAP_PACKET_START,
- MAP_PACKET_NORMAL,
- MAP_PACKET_END,
-} MapPacket;
-
-typedef enum {
- NETWORK_RECV_STATUS_OKAY,
- NETWORK_RECV_STATUS_DESYNC,
- NETWORK_RECV_STATUS_SAVEGAME,
- NETWORK_RECV_STATUS_CONN_LOST,
- NETWORK_RECV_STATUS_MALFORMED_PACKET,
- NETWORK_RECV_STATUS_SERVER_ERROR, // The server told us we made an error
- NETWORK_RECV_STATUS_SERVER_FULL,
- NETWORK_RECV_STATUS_SERVER_BANNED,
- NETWORK_RECV_STATUS_CLOSE_QUERY, // Done quering the server
-} NetworkRecvStatus;
-
-typedef enum {
- NETWORK_ERROR_GENERAL, // Try to use thisone like never
-
- // Signals from clients
- NETWORK_ERROR_DESYNC,
- NETWORK_ERROR_SAVEGAME_FAILED,
- NETWORK_ERROR_CONNECTION_LOST,
- NETWORK_ERROR_ILLEGAL_PACKET,
-
- // Signals from servers
- NETWORK_ERROR_NOT_AUTHORIZED,
- NETWORK_ERROR_NOT_EXPECTED,
- NETWORK_ERROR_WRONG_REVISION,
- NETWORK_ERROR_NAME_IN_USE,
- NETWORK_ERROR_WRONG_PASSWORD,
- NETWORK_ERROR_PLAYER_MISMATCH, // Happens in CLIENT_COMMAND
- NETWORK_ERROR_KICKED,
- NETWORK_ERROR_CHEATER,
- NETWORK_ERROR_FULL,
-} NetworkErrorCode;
-
-// Actions that can be used for NetworkTextMessage
-typedef enum {
- NETWORK_ACTION_JOIN,
- NETWORK_ACTION_LEAVE,
- NETWORK_ACTION_SERVER_MESSAGE,
- NETWORK_ACTION_CHAT,
- NETWORK_ACTION_CHAT_COMPANY,
- NETWORK_ACTION_CHAT_CLIENT,
- NETWORK_ACTION_GIVE_MONEY,
- NETWORK_ACTION_NAME_CHANGE,
-} NetworkAction;
-
-typedef enum {
- NETWORK_GAME_PASSWORD,
- NETWORK_COMPANY_PASSWORD,
-} NetworkPasswordType;
-
-// To keep the clients all together
-struct NetworkClientState { // Typedeffed in network_core/packet.h
- SOCKET socket;
- uint16 index;
- uint32 last_frame;
- uint32 last_frame_server;
- byte lag_test; // This byte is used for lag-testing the client
-
- ClientStatus status;
- bool writable; // is client ready to write to?
- bool has_quit;
-
- Packet *packet_queue; // Packets that are awaiting delivery
- Packet *packet_recv; // Partially received packet
-
- CommandPacket *command_queue; // The command-queue awaiting delivery
-};
-
-typedef enum {
- DESTTYPE_BROADCAST, ///< Send message/notice to all players (All)
- DESTTYPE_TEAM, ///< Send message/notice to everyone playing the same company (Team)
- DESTTYPE_CLIENT, ///< Send message/notice to only a certain player (Private)
-} DestType;
-
-CommandPacket *_local_command_queue;
-
-SOCKET _udp_client_socket; // udp client socket
-SOCKET _udp_server_socket; // udp server socket
-SOCKET _udp_master_socket; // udp master socket
-
-// Here we keep track of the clients
-// (and the client uses [0] for his own communication)
-NetworkClientState _clients[MAX_CLIENTS];
-#define DEREF_CLIENT(i) (&_clients[i])
-// This returns the NetworkClientInfo from a NetworkClientState
-#define DEREF_CLIENT_INFO(cs) (&_network_client_info[cs - _clients])
-
-// Macros to make life a bit more easier
-#define DEF_CLIENT_RECEIVE_COMMAND(type) NetworkRecvStatus NetworkPacketReceive_ ## type ## _command(Packet *p)
-#define DEF_CLIENT_SEND_COMMAND(type) void NetworkPacketSend_ ## type ## _command(void)
-#define DEF_CLIENT_SEND_COMMAND_PARAM(type) void NetworkPacketSend_ ## type ## _command
-#define DEF_SERVER_RECEIVE_COMMAND(type) void NetworkPacketReceive_ ## type ## _command(NetworkClientState *cs, Packet *p)
-#define DEF_SERVER_SEND_COMMAND(type) void NetworkPacketSend_ ## type ## _command(NetworkClientState *cs)
-#define DEF_SERVER_SEND_COMMAND_PARAM(type) void NetworkPacketSend_ ## type ## _command
-
-#define SEND_COMMAND(type) NetworkPacketSend_ ## type ## _command
-#define RECEIVE_COMMAND(type) NetworkPacketReceive_ ## type ## _command
-
-#define FOR_ALL_CLIENTS(cs) for (cs = _clients; cs != endof(_clients) && cs->socket != INVALID_SOCKET; cs++)
-#define FOR_ALL_ACTIVE_CLIENT_INFOS(ci) for (ci = _network_client_info; ci != endof(_network_client_info); ci++) if (ci->client_index != NETWORK_EMPTY_INDEX)
-
-void NetworkExecuteCommand(CommandPacket *cp);
-void NetworkAddCommandQueue(NetworkClientState *cs, CommandPacket *cp);
-
-// from network.c
-void NetworkCloseClient(NetworkClientState *cs);
-void CDECL NetworkTextMessage(NetworkAction action, uint16 color, bool self_send, const char *name, const char *str, ...);
-void NetworkGetClientName(char *clientname, size_t size, const NetworkClientState *cs);
-uint NetworkCalculateLag(const NetworkClientState *cs);
-byte NetworkGetCurrentLanguageIndex(void);
-NetworkClientInfo *NetworkFindClientInfoFromIndex(uint16 client_index);
-NetworkClientInfo *NetworkFindClientInfoFromIP(const char *ip);
-NetworkClientState *NetworkFindClientStateFromIndex(uint16 client_index);
-unsigned long NetworkResolveHost(const char *hostname);
-char* GetNetworkErrorMsg(char* buf, NetworkErrorCode err, const char* last);
-
-#endif /* ENABLE_NETWORK */
-
-#endif /* NETWORK_DATA_H */
diff --git a/network/network_gamelist.c b/network/network_gamelist.c
deleted file mode 100644
index a830073ad..000000000
--- a/network/network_gamelist.c
+++ /dev/null
@@ -1,74 +0,0 @@
-/* $Id$ */
-
-#ifdef ENABLE_NETWORK
-
-#include "../stdafx.h"
-#include "../debug.h"
-#include "network_data.h"
-#include "../newgrf_config.h"
-
-// This file handles the GameList
-// Also, it handles the request to a server for data about the server
-
-/** Add a new item to the linked gamelist. If the IP and Port match
- * return the existing item instead of adding it again
- * @param ip the IP-address (inet_addr) of the to-be added item
- * @param port the port the server is running on
- * @return a point to the newly added or already existing item */
-NetworkGameList *NetworkGameListAddItem(uint32 ip, uint16 port)
-{
- NetworkGameList *item, *prev_item;
-
- prev_item = NULL;
- for (item = _network_game_list; item != NULL; item = item->next) {
- if (item->ip == ip && item->port == port) return item;
- prev_item = item;
- }
-
- item = malloc(sizeof(*item));
- memset(item, 0, sizeof(*item));
- item->next = NULL;
- item->ip = ip;
- item->port = port;
-
- if (prev_item == NULL) {
- _network_game_list = item;
- } else {
- prev_item->next = item;
- }
- DEBUG(net, 4, "[gamelist] added server to list");
-
- UpdateNetworkGameWindow(false);
-
- return item;
-}
-
-/** Remove an item from the gamelist linked list
- * @param remove pointer to the item to be removed */
-void NetworkGameListRemoveItem(NetworkGameList *remove)
-{
- NetworkGameList *item, *prev_item;
-
- prev_item = NULL;
- for (item = _network_game_list; item != NULL; item = item->next) {
- if (remove == item) {
- if (prev_item == NULL) {
- _network_game_list = remove->next;
- } else {
- prev_item->next = remove->next;
- }
-
- /* Remove GRFConfig information */
- ClearGRFConfigList(&remove->info.grfconfig);
- free(remove);
- remove = NULL;
-
- DEBUG(net, 4, "[gamelist] removed server from list");
- UpdateNetworkGameWindow(false);
- return;
- }
- prev_item = item;
- }
-}
-
-#endif /* ENABLE_NETWORK */
diff --git a/network/network_gamelist.h b/network/network_gamelist.h
deleted file mode 100644
index c1a1a0904..000000000
--- a/network/network_gamelist.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/* $Id$ */
-
-#ifndef NETWORK_GAMELIST_H
-#define NETWORK_GAMELIST_H
-
-void NetworkGameListClear(void);
-NetworkGameList *NetworkGameListAddItem(uint32 ip, uint16 port);
-void NetworkGameListRemoveItem(NetworkGameList *remove);
-void NetworkGameListAddQueriedItem(const NetworkGameInfo *info, bool server_online);
-
-#endif /* NETWORK_GAMELIST_H */
diff --git a/network/network_gui.c b/network/network_gui.c
deleted file mode 100644
index 91c990bbc..000000000
--- a/network/network_gui.c
+++ /dev/null
@@ -1,1706 +0,0 @@
-/* $Id$ */
-
-#ifdef ENABLE_NETWORK
-#include "../stdafx.h"
-#include "../openttd.h"
-#include "../string.h"
-#include "../strings.h"
-#include "../table/sprites.h"
-#include "network.h"
-#include "../date.h"
-
-#include "../fios.h"
-#include "../table/strings.h"
-#include "../functions.h"
-#include "network_data.h"
-#include "network_client.h"
-#include "network_gui.h"
-#include "network_gamelist.h"
-#include "../window.h"
-#include "../gui.h"
-#include "../gfx.h"
-#include "../command.h"
-#include "../variables.h"
-#include "network_server.h"
-#include "network_udp.h"
-#include "../settings.h"
-#include "../string.h"
-#include "../town.h"
-#include "../newgrf.h"
-
-#define BGC 5
-#define BTC 15
-
-typedef struct network_d {
- PlayerID company; // select company in network lobby
- byte field; // select text-field in start-server and game-listing
- NetworkGameList *server; // selected server in lobby and game-listing
- FiosItem *map; // selected map in start-server
-} network_d;
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(network_d));
-
-typedef struct network_ql_d {
- network_d n; // see above; general stuff
- querystr_d q; // text-input in start-server and game-listing
- NetworkGameList **sort_list; // list of games (sorted)
- list_d l; // accompanying list-administration
-} network_ql_d;
-assert_compile(WINDOW_CUSTOM_SIZE >= sizeof(network_ql_d));
-
-/* Global to remember sorting after window has been closed */
-static Listing _ng_sorting;
-
-static char _edit_str_buf[150];
-static bool _chat_tab_completion_active;
-
-static void ShowNetworkStartServerWindow(void);
-static void ShowNetworkLobbyWindow(NetworkGameList *ngl);
-extern void SwitchMode(int new_mode);
-
-static const StringID _connection_types_dropdown[] = {
- STR_NETWORK_LAN_INTERNET,
- STR_NETWORK_INTERNET_ADVERTISE,
- INVALID_STRING_ID
-};
-
-static const StringID _lan_internet_types_dropdown[] = {
- STR_NETWORK_LAN,
- STR_NETWORK_INTERNET,
- INVALID_STRING_ID
-};
-
-static const StringID _players_dropdown[] = {
- STR_NETWORK_0_PLAYERS,
- STR_NETWORK_1_PLAYERS,
- STR_NETWORK_2_PLAYERS,
- STR_NETWORK_3_PLAYERS,
- STR_NETWORK_4_PLAYERS,
- STR_NETWORK_5_PLAYERS,
- STR_NETWORK_6_PLAYERS,
- STR_NETWORK_7_PLAYERS,
- STR_NETWORK_8_PLAYERS,
- STR_NETWORK_9_PLAYERS,
- STR_NETWORK_10_PLAYERS,
- INVALID_STRING_ID
-};
-
-static const StringID _language_dropdown[] = {
- STR_NETWORK_LANG_ANY,
- STR_NETWORK_LANG_ENGLISH,
- STR_NETWORK_LANG_GERMAN,
- STR_NETWORK_LANG_FRENCH,
- INVALID_STRING_ID
-};
-
-enum {
- NET_PRC__OFFSET_TOP_WIDGET = 54,
- NET_PRC__OFFSET_TOP_WIDGET_COMPANY = 52,
- NET_PRC__SIZE_OF_ROW = 14,
-};
-
-/** Update the network new window because a new server is
- * found on the network.
- * @param unselect unselect the currently selected item */
-void UpdateNetworkGameWindow(bool unselect)
-{
- SendWindowMessage(WC_NETWORK_WINDOW, 0, unselect, 0, 0);
-}
-
-static bool _internal_sort_order; // Used for Qsort order-flipping
-typedef int CDECL NGameNameSortFunction(const void*, const void*);
-
-/** Qsort function to sort by name. */
-static int CDECL NGameNameSorter(const void *a, const void *b)
-{
- const NetworkGameList *cmp1 = *(const NetworkGameList**)a;
- const NetworkGameList *cmp2 = *(const NetworkGameList**)b;
- int r = strcasecmp(cmp1->info.server_name, cmp2->info.server_name);
-
- return _internal_sort_order ? -r : r;
-}
-
-/** Qsort function to sort by the amount of clients online on a
- * server. If the two servers have the same amount, the one with the
- * higher maximum is preferred. */
-static int CDECL NGameClientSorter(const void *a, const void *b)
-{
- const NetworkGameList *cmp1 = *(const NetworkGameList**)a;
- const NetworkGameList *cmp2 = *(const NetworkGameList**)b;
- /* Reverse as per default we are interested in most-clients first */
- int r = cmp1->info.clients_on - cmp2->info.clients_on;
-
- if (r == 0) r = cmp1->info.clients_max - cmp2->info.clients_max;
- if (r == 0) r = strcasecmp(cmp1->info.server_name, cmp2->info.server_name);
-
- return _internal_sort_order ? -r : r;
-}
-
-/** Qsort function to sort by joinability. If both servers are the
- * same, prefer the non-passworded server first. */
-static int CDECL NGameAllowedSorter(const void *a, const void *b)
-{
- const NetworkGameList *cmp1 = *(const NetworkGameList**)a;
- const NetworkGameList *cmp2 = *(const NetworkGameList**)b;
- /* Reverse default as we are interested in compatible clients first */
- int r = cmp2->info.compatible - cmp1->info.compatible;
-
- if (r == 0) r = cmp1->info.use_password - cmp2->info.use_password;
- if (r == 0) r = strcasecmp(cmp1->info.server_name, cmp2->info.server_name);
-
- return _internal_sort_order ? -r : r;
-}
-
-/** (Re)build the network game list as its amount has changed because
- * an item has been added or deleted for example
- * @param ngl list_d struct that contains all necessary information for sorting */
-static void BuildNetworkGameList(network_ql_d *nqld)
-{
- NetworkGameList *ngl_temp;
- uint n = 0;
-
- if (!(nqld->l.flags & VL_REBUILD)) return;
-
- /* Count the number of games in the list */
- for (ngl_temp = _network_game_list; ngl_temp != NULL; ngl_temp = ngl_temp->next) n++;
- if (n == 0) return;
-
- /* Create temporary array of games to use for listing */
- free(nqld->sort_list);
- nqld->sort_list = malloc(n * sizeof(nqld->sort_list[0]));
- if (nqld->sort_list == NULL) error("Could not allocate memory for the network-game-sorting-list");
- nqld->l.list_length = n;
-
- for (n = 0, ngl_temp = _network_game_list; ngl_temp != NULL; ngl_temp = ngl_temp->next) {
- nqld->sort_list[n++] = ngl_temp;
- }
-
- /* Force resort */
- nqld->l.flags &= ~VL_REBUILD;
- nqld->l.flags |= VL_RESORT;
-}
-
-static void SortNetworkGameList(network_ql_d *nqld)
-{
- static NGameNameSortFunction * const ngame_sorter[] = {
- &NGameNameSorter,
- &NGameClientSorter,
- &NGameAllowedSorter
- };
-
- NetworkGameList *item;
- uint i;
-
- if (!(nqld->l.flags & VL_RESORT)) return;
- if (nqld->l.list_length == 0) return;
-
- _internal_sort_order = !!(nqld->l.flags & VL_DESC);
- qsort(nqld->sort_list, nqld->l.list_length, sizeof(nqld->sort_list[0]), ngame_sorter[nqld->l.sort_type]);
-
- /* After sorting ngl->sort_list contains the sorted items. Put these back
- * into the original list. Basically nothing has changed, we are only
- * shuffling the ->next pointers */
- _network_game_list = nqld->sort_list[0];
- for (item = _network_game_list, i = 1; i != nqld->l.list_length; i++) {
- item->next = nqld->sort_list[i];
- item = item->next;
- }
- item->next = NULL;
-
- nqld->l.flags &= ~VL_RESORT;
-}
-
-/* Uses network_ql_d (network_d, querystr_d and list_d) WP macro */
-static void NetworkGameWindowWndProc(Window *w, WindowEvent *e)
-{
- network_d *nd = &WP(w, network_ql_d).n;
- list_d *ld = &WP(w, network_ql_d).l;
-
- switch (e->event) {
- case WE_CREATE: /* Focus input box */
- nd->field = 3;
- nd->server = NULL;
-
- WP(w, network_ql_d).sort_list = NULL;
- ld->flags = VL_REBUILD | (_ng_sorting.order << (VL_DESC - 1));
- ld->sort_type = _ng_sorting.criteria;
- break;
-
- case WE_PAINT: {
- const NetworkGameList *sel = nd->server;
- const char *arrow = (ld->flags & VL_DESC) ? DOWNARROW : UPARROW;
-
- if (ld->flags & VL_REBUILD) {
- BuildNetworkGameList(&WP(w, network_ql_d));
- SetVScrollCount(w, ld->list_length);
- }
- if (ld->flags & VL_RESORT) SortNetworkGameList(&WP(w, network_ql_d));
-
- SetWindowWidgetDisabledState(w, 17, sel == NULL);
- /* Join Button disabling conditions */
- SetWindowWidgetDisabledState(w, 16, sel == NULL || // no Selected Server
- !sel->online || // Server offline
- sel->info.clients_on >= sel->info.clients_max || // Server full
- !sel->info.compatible); // Revision mismatch
-
- SetWindowWidgetHiddenState(w, 18, sel == NULL ||
- !sel->online ||
- sel->info.grfconfig == NULL);
-
- SetDParam(0, 0x00);
- SetDParam(7, _lan_internet_types_dropdown[_network_lan_internet]);
- DrawWindowWidgets(w);
-
- DrawEditBox(w, &WP(w, network_ql_d).q, 3);
-
- DrawString(9, 23, STR_NETWORK_CONNECTION, 2);
- DrawString(210, 23, STR_NETWORK_PLAYER_NAME, 2);
-
- /* Sort based on widgets: name, clients, compatibility */
- switch (ld->sort_type) {
- case 6 - 6: DoDrawString(arrow, w->widget[6].right - 10, 42, 0x10); break;
- case 7 - 6: DoDrawString(arrow, w->widget[7].right - 10, 42, 0x10); break;
- case 8 - 6: DoDrawString(arrow, w->widget[8].right - 10, 42, 0x10); break;
- }
-
- { // draw list of games
- uint16 y = NET_PRC__OFFSET_TOP_WIDGET + 3;
- int32 n = 0;
- int32 pos = w->vscroll.pos;
- uint max_name_width = w->widget[6].right - w->widget[6].left - 5;
- const NetworkGameList *cur_item = _network_game_list;
-
- while (pos > 0 && cur_item != NULL) {
- pos--;
- cur_item = cur_item->next;
- }
-
- while (cur_item != NULL) {
- // show highlighted item with a different colour
- if (cur_item == sel) GfxFillRect(w->widget[6].left + 1, y - 2, w->widget[8].right - 1, y + 9, 10);
-
- SetDParamStr(0, cur_item->info.server_name);
- DrawStringTruncated(w->widget[6].left + 5, y, STR_02BD, 16, max_name_width);
-
- SetDParam(0, cur_item->info.clients_on);
- SetDParam(1, cur_item->info.clients_max);
- SetDParam(2, cur_item->info.companies_on);
- SetDParam(3, cur_item->info.companies_max);
- DrawStringCentered(210, y, STR_NETWORK_GENERAL_ONLINE, 2);
-
- // only draw icons if the server is online
- if (cur_item->online) {
- // draw a lock if the server is password protected.
- if (cur_item->info.use_password) DrawSprite(SPR_LOCK, w->widget[8].left + 5, y - 1);
-
- // draw red or green icon, depending on compatibility with server.
- DrawSprite(SPR_BLOT | (cur_item->info.compatible ? PALETTE_TO_GREEN : (cur_item->info.version_compatible ? PALETTE_TO_YELLOW : PALETTE_TO_RED)), w->widget[8].left + 15, y);
-
- // draw flag according to server language
- DrawSprite(SPR_FLAGS_BASE + cur_item->info.server_lang, w->widget[8].left + 25, y);
- }
-
- cur_item = cur_item->next;
- y += NET_PRC__SIZE_OF_ROW;
- if (++n == w->vscroll.cap) break; // max number of games in the window
- }
- }
-
- /* Draw the right menu */
- GfxFillRect(311, 43, 539, 92, 157);
- if (sel == NULL) {
- DrawStringCentered(425, 58, STR_NETWORK_GAME_INFO, 0);
- } else if (!sel->online) {
- SetDParamStr(0, sel->info.server_name);
- DrawStringCentered(425, 68, STR_ORANGE, 0); // game name
-
- DrawStringCentered(425, 132, STR_NETWORK_SERVER_OFFLINE, 0); // server offline
- } else { // show game info
- uint16 y = 100;
- const uint16 x = w->widget[15].left + 5;
-
- DrawStringCentered(425, 48, STR_NETWORK_GAME_INFO, 0);
-
-
- SetDParamStr(0, sel->info.server_name);
- DrawStringCenteredTruncated(w->widget[15].left, w->widget[15].right, 62, STR_ORANGE, 16); // game name
-
- SetDParamStr(0, sel->info.map_name);
- DrawStringCenteredTruncated(w->widget[15].left, w->widget[15].right, 74, STR_02BD, 16); // map name
-
- SetDParam(0, sel->info.clients_on);
- SetDParam(1, sel->info.clients_max);
- SetDParam(2, sel->info.companies_on);
- SetDParam(3, sel->info.companies_max);
- DrawString(x, y, STR_NETWORK_CLIENTS, 2);
- y += 10;
-
- SetDParam(0, _language_dropdown[sel->info.server_lang]);
- DrawString(x, y, STR_NETWORK_LANGUAGE, 2); // server language
- y += 10;
-
- SetDParam(0, STR_TEMPERATE_LANDSCAPE + sel->info.map_set);
- DrawString(x, y, STR_NETWORK_TILESET, 2); // tileset
- y += 10;
-
- SetDParam(0, sel->info.map_width);
- SetDParam(1, sel->info.map_height);
- DrawString(x, y, STR_NETWORK_MAP_SIZE, 2); // map size
- y += 10;
-
- SetDParamStr(0, sel->info.server_revision);
- DrawString(x, y, STR_NETWORK_SERVER_VERSION, 2); // server version
- y += 10;
-
- SetDParamStr(0, sel->info.hostname);
- SetDParam(1, sel->port);
- DrawString(x, y, STR_NETWORK_SERVER_ADDRESS, 2); // server address
- y += 10;
-
- SetDParam(0, sel->info.start_date);
- DrawString(x, y, STR_NETWORK_START_DATE, 2); // start date
- y += 10;
-
- SetDParam(0, sel->info.game_date);
- DrawString(x, y, STR_NETWORK_CURRENT_DATE, 2); // current date
- y += 10;
-
- y += 2;
-
- if (!sel->info.compatible) {
- DrawStringCentered(425, y, sel->info.version_compatible ? STR_NETWORK_GRF_MISMATCH : STR_NETWORK_VERSION_MISMATCH, 0); // server mismatch
- } else if (sel->info.clients_on == sel->info.clients_max) {
- // Show: server full, when clients_on == clients_max
- DrawStringCentered(425, y, STR_NETWORK_SERVER_FULL, 0); // server full
- } else if (sel->info.use_password) {
- DrawStringCentered(425, y, STR_NETWORK_PASSWORD, 0); // password warning
- }
-
- y += 10;
- }
- } break;
-
- case WE_CLICK:
- nd->field = e->we.click.widget;
- switch (e->we.click.widget) {
- case 0: case 14: /* Close 'X' | Cancel button */
- DeleteWindowById(WC_NETWORK_WINDOW, 0);
- break;
- case 4: case 5:
- ShowDropDownMenu(w, _lan_internet_types_dropdown, _network_lan_internet, 5, 0, 0); // do it for widget 5
- break;
- case 6: /* Sort by name */
- case 7: /* Sort by connected clients */
- case 8: /* Connectivity (green dot) */
- if (ld->sort_type == e->we.click.widget - 6) ld->flags ^= VL_DESC;
- ld->flags |= VL_RESORT;
- ld->sort_type = e->we.click.widget - 6;
-
- _ng_sorting.order = !!(ld->flags & VL_DESC);
- _ng_sorting.criteria = ld->sort_type;
- SetWindowDirty(w);
- break;
- case 9: { /* Matrix to show networkgames */
- NetworkGameList *cur_item;
- uint32 id_v = (e->we.click.pt.y - NET_PRC__OFFSET_TOP_WIDGET) / NET_PRC__SIZE_OF_ROW;
-
- if (id_v >= w->vscroll.cap) return; // click out of bounds
- id_v += w->vscroll.pos;
-
- cur_item = _network_game_list;
- for (; id_v > 0 && cur_item != NULL; id_v--) cur_item = cur_item->next;
-
- nd->server = cur_item;
- SetWindowDirty(w);
- } break;
- case 11: /* Find server automatically */
- switch (_network_lan_internet) {
- case 0: NetworkUDPSearchGame(); break;
- case 1: NetworkUDPQueryMasterServer(); break;
- }
- break;
- case 12: { // Add a server
- ShowQueryString(
- BindCString(_network_default_ip),
- STR_NETWORK_ENTER_IP,
- 31 | 0x1000, // maximum number of characters OR
- 250, // characters up to this width pixels, whichever is satisfied first
- w, CS_ALPHANUMERAL);
- } break;
- case 13: /* Start server */
- ShowNetworkStartServerWindow();
- break;
- case 16: /* Join Game */
- if (nd->server != NULL) {
- snprintf(_network_last_host, sizeof(_network_last_host), "%s", inet_ntoa(*(struct in_addr *)&nd->server->ip));
- _network_last_port = nd->server->port;
- ShowNetworkLobbyWindow(nd->server);
- }
- break;
- case 17: // Refresh
- if (nd->server != NULL)
- NetworkQueryServer(nd->server->info.hostname, nd->server->port, true);
- break;
- case 18: // NewGRF Settings
- if (nd->server != NULL) ShowNewGRFSettings(false, false, false, &nd->server->info.grfconfig);
- break;
-
- } break;
-
- case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
- switch (e->we.dropdown.button) {
- case 5:
- _network_lan_internet = e->we.dropdown.index;
- break;
- }
-
- SetWindowDirty(w);
- break;
-
- case WE_MOUSELOOP:
- if (nd->field == 3) HandleEditBox(w, &WP(w, network_ql_d).q, 3);
- break;
-
- case WE_MESSAGE:
- if (e->we.message.msg != 0) nd->server = NULL;
- ld->flags |= VL_REBUILD;
- SetWindowDirty(w);
- break;
-
- case WE_KEYPRESS:
- if (nd->field != 3) {
- if (nd->server != NULL) {
- if (e->we.keypress.keycode == WKC_DELETE) { /* Press 'delete' to remove servers */
- NetworkGameListRemoveItem(nd->server);
- NetworkRebuildHostList();
- nd->server = NULL;
- }
- }
- break;
- }
-
- if (HandleEditBoxKey(w, &WP(w, network_ql_d).q, 3, e) == 1) break; // enter pressed
-
- // The name is only allowed when it starts with a letter!
- if (_edit_str_buf[0] != '\0' && _edit_str_buf[0] != ' ') {
- ttd_strlcpy(_network_player_name, _edit_str_buf, lengthof(_network_player_name));
- } else {
- ttd_strlcpy(_network_player_name, "Player", lengthof(_network_player_name));
- }
-
- break;
-
- case WE_ON_EDIT_TEXT:
- NetworkAddServer(e->we.edittext.str);
- NetworkRebuildHostList();
- break;
-
- case WE_DESTROY: /* Nicely clean up the sort-list */
- free(WP(w, network_ql_d).sort_list);
- break;
- }
-}
-
-static const Widget _network_game_window_widgets[] = {
-{ WWT_CLOSEBOX, RESIZE_NONE, BGC, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
-{ WWT_CAPTION, RESIZE_NONE, BGC, 11, 549, 0, 13, STR_NETWORK_MULTIPLAYER, STR_NULL},
-{ WWT_PANEL, RESIZE_NONE, BGC, 0, 549, 14, 263, 0x0, STR_NULL},
-
-/* LEFT SIDE */
-{ WWT_PANEL, RESIZE_NONE, BGC, 310, 461, 22, 33, 0x0, STR_NETWORK_ENTER_NAME_TIP},
-
-{ WWT_INSET, RESIZE_NONE, BGC, 90, 181, 22, 33, STR_NETWORK_COMBO1, STR_NETWORK_CONNECTION_TIP},
-{ WWT_TEXTBTN, RESIZE_NONE, BGC, 170, 180, 23, 32, STR_0225, STR_NETWORK_CONNECTION_TIP},
-
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 10, 170, 42, 53, STR_NETWORK_GAME_NAME, STR_NETWORK_GAME_NAME_TIP},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 171, 250, 42, 53, STR_NETWORK_CLIENTS_CAPTION, STR_NETWORK_CLIENTS_CAPTION_TIP},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 251, 290, 42, 53, STR_EMPTY, STR_NETWORK_INFO_ICONS_TIP},
-
-{ WWT_MATRIX, RESIZE_NONE, BGC, 10, 290, 54, 236, (13 << 8) + 1, STR_NETWORK_CLICK_GAME_TO_SELECT},
-{ WWT_SCROLLBAR, RESIZE_NONE, BGC, 291, 302, 42, 236, STR_NULL, STR_0190_SCROLL_BAR_SCROLLS_LIST},
-
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 30, 130, 246, 257, STR_NETWORK_FIND_SERVER, STR_NETWORK_FIND_SERVER_TIP},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 180, 280, 246, 257, STR_NETWORK_ADD_SERVER, STR_NETWORK_ADD_SERVER_TIP},
-
-/* RIGHT SIDE */
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 315, 415, 246, 257, STR_NETWORK_START_SERVER, STR_NETWORK_START_SERVER_TIP},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 430, 535, 246, 257, STR_012E_CANCEL, STR_NULL},
-
-{ WWT_PANEL, RESIZE_NONE, BGC, 310, 540, 42, 236, 0x0, STR_NULL},
-
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 315, 415, 215, 226, STR_NETWORK_JOIN_GAME, STR_NULL},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 430, 535, 215, 226, STR_NETWORK_REFRESH, STR_NETWORK_REFRESH_TIP},
-
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 430, 535, 197, 208, STR_NEWGRF_SETTINGS_BUTTON, STR_NULL},
-
-{ WIDGETS_END},
-};
-
-static const WindowDesc _network_game_window_desc = {
- WDP_CENTER, WDP_CENTER, 550, 264,
- WC_NETWORK_WINDOW,0,
- WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
- _network_game_window_widgets,
- NetworkGameWindowWndProc,
-};
-
-void ShowNetworkGameWindow(void)
-{
- static bool first = true;
- Window *w;
- DeleteWindowById(WC_NETWORK_WINDOW, 0);
-
- /* Only show once */
- if (first) {
- char* const *srv;
-
- first = false;
- // add all servers from the config file to our list
- for (srv = &_network_host_list[0]; srv != endof(_network_host_list) && *srv != NULL; srv++) {
- NetworkAddServer(*srv);
- }
-
- _ng_sorting.criteria = 2; // sort default by collectivity (green-dots on top)
- _ng_sorting.order = 0; // sort ascending by default
- }
-
- w = AllocateWindowDesc(&_network_game_window_desc);
- if (w != NULL) {
- querystr_d *querystr = &WP(w, network_ql_d).q;
-
- ttd_strlcpy(_edit_str_buf, _network_player_name, lengthof(_edit_str_buf));
- w->vscroll.cap = 13;
-
- querystr->afilter = CS_ALPHANUMERAL;
- InitializeTextBuffer(&querystr->text, _edit_str_buf, lengthof(_edit_str_buf), 120);
-
- UpdateNetworkGameWindow(true);
- }
-}
-
-enum {
- NSSWND_START = 64,
- NSSWND_ROWSIZE = 12
-};
-
-/* Uses network_ql_d (network_d, querystr_d and list_d) WP macro */
-static void NetworkStartServerWindowWndProc(Window *w, WindowEvent *e)
-{
- network_d *nd = &WP(w, network_ql_d).n;
-
- switch (e->event) {
- case WE_CREATE: /* focus input box */
- nd->field = 3;
- _network_game_info.use_password = (_network_server_password[0] != '\0');
- break;
-
- case WE_PAINT: {
- int y = NSSWND_START, pos;
- const FiosItem *item;
-
- SetDParam( 7, _connection_types_dropdown[_network_advertise]);
- SetDParam( 9, _players_dropdown[_network_game_info.clients_max]);
- SetDParam(11, _players_dropdown[_network_game_info.companies_max]);
- SetDParam(13, _players_dropdown[_network_game_info.spectators_max]);
- SetDParam(15, _language_dropdown[_network_game_info.server_lang]);
- DrawWindowWidgets(w);
-
- GfxFillRect(11, 63, 258, 215, 0xD7);
- DrawEditBox(w, &WP(w, network_ql_d).q, 3);
-
- DrawString(10, 22, STR_NETWORK_NEW_GAME_NAME, 2);
-
- DrawString(10, 43, STR_NETWORK_SELECT_MAP, 2);
-
- DrawString(280, 63, STR_NETWORK_CONNECTION, 2);
- DrawString(280, 95, STR_NETWORK_NUMBER_OF_CLIENTS, 2);
- DrawString(280, 127, STR_NETWORK_NUMBER_OF_COMPANIES, 2);
- DrawString(280, 159, STR_NETWORK_NUMBER_OF_SPECTATORS, 2);
- DrawString(280, 191, STR_NETWORK_LANGUAGE_SPOKEN, 2);
-
- if (_network_game_info.use_password) DoDrawString("*", 408, 23, 3);
-
- // draw list of maps
- pos = w->vscroll.pos;
- while (pos < _fios_num + 1) {
- item = _fios_list + pos - 1;
- if (item == nd->map || (pos == 0 && nd->map == NULL))
- GfxFillRect(11, y - 1, 258, y + 10, 155); // show highlighted item with a different colour
-
- if (pos == 0) {
- DrawString(14, y, STR_4010_GENERATE_RANDOM_NEW_GAME, 9);
- } else {
- DoDrawString(item->title, 14, y, _fios_colors[item->type] );
- }
- pos++;
- y += NSSWND_ROWSIZE;
-
- if (y >= w->vscroll.cap * NSSWND_ROWSIZE + NSSWND_START) break;
- }
- } break;
-
- case WE_CLICK:
- nd->field = e->we.click.widget;
- switch (e->we.click.widget) {
- case 0: /* Close 'X' */
- case 19: /* Cancel button */
- ShowNetworkGameWindow();
- break;
-
- case 4: /* Set password button */
- ShowQueryString(BindCString(_network_server_password), STR_NETWORK_SET_PASSWORD, 20, 250, w, CS_ALPHANUMERAL);
- break;
-
- case 5: { /* Select map */
- int y = (e->we.click.pt.y - NSSWND_START) / NSSWND_ROWSIZE;
-
- y += w->vscroll.pos;
- if (y >= w->vscroll.count) return;
-
- nd->map = (y == 0) ? NULL : _fios_list + y - 1;
- SetWindowDirty(w);
- } break;
- case 7: case 8: /* Connection type */
- ShowDropDownMenu(w, _connection_types_dropdown, _network_advertise, 8, 0, 0); // do it for widget 8
- break;
- case 9: case 10: /* Number of Players (hide 0 and 1 players) */
- ShowDropDownMenu(w, _players_dropdown, _network_game_info.clients_max, 10, 0, 3);
- break;
- case 11: case 12: /* Number of Companies (hide 0, 9 and 10 companies; max is 8) */
- ShowDropDownMenu(w, _players_dropdown, _network_game_info.companies_max, 12, 0, 1537);
- break;
- case 13: case 14: /* Number of Spectators */
- ShowDropDownMenu(w, _players_dropdown, _network_game_info.spectators_max, 14, 0, 0);
- break;
- case 15: case 16: /* Language */
- ShowDropDownMenu(w, _language_dropdown, _network_game_info.server_lang, 16, 0, 0);
- break;
- case 17: /* Start game */
- _is_network_server = true;
-
- if (nd->map == NULL) { // start random new game
- ShowGenerateLandscape();
- } else { // load a scenario
- char *name = FiosBrowseTo(nd->map);
- if (name != NULL) {
- SetFiosType(nd->map->type);
- ttd_strlcpy(_file_to_saveload.name, name, sizeof(_file_to_saveload.name));
- ttd_strlcpy(_file_to_saveload.title, nd->map->title, sizeof(_file_to_saveload.title));
-
- DeleteWindow(w);
- SwitchMode(SM_START_SCENARIO);
- }
- }
- break;
- case 18: /* Load game */
- _is_network_server = true;
- /* XXX - WC_NETWORK_WINDOW should stay, but if it stays, it gets
- * copied all the elements of 'load game' and upon closing that, it segfaults */
- DeleteWindowById(WC_NETWORK_WINDOW, 0);
- ShowSaveLoadDialog(SLD_LOAD_GAME);
- break;
- }
- break;
-
- case WE_DROPDOWN_SELECT: /* we have selected a dropdown item in the list */
- switch (e->we.dropdown.button) {
- case 8: _network_advertise = (e->we.dropdown.index != 0); break;
- case 10: _network_game_info.clients_max = e->we.dropdown.index; break;
- case 12: _network_game_info.companies_max = e->we.dropdown.index; break;
- case 14: _network_game_info.spectators_max = e->we.dropdown.index; break;
- case 16: _network_game_info.server_lang = e->we.dropdown.index; break;
- }
-
- SetWindowDirty(w);
- break;
-
- case WE_MOUSELOOP:
- if (nd->field == 3) HandleEditBox(w, &WP(w, network_ql_d).q, 3);
- break;
-
- case WE_KEYPRESS:
- if (nd->field == 3) {
- if (HandleEditBoxKey(w, &WP(w, network_ql_d).q, 3, e) == 1) break; // enter pressed
-
- ttd_strlcpy(_network_server_name, WP(w, network_ql_d).q.text.buf, sizeof(_network_server_name));
- UpdateTextBufferSize(&WP(w, network_ql_d).q.text);
- }
- break;
-
- case WE_ON_EDIT_TEXT: {
- ttd_strlcpy(_network_server_password, e->we.edittext.str, lengthof(_network_server_password));
- _network_game_info.use_password = (_network_server_password[0] != '\0');
- SetWindowDirty(w);
- } break;
- }
-}
-
-static const Widget _network_start_server_window_widgets[] = {
-{ WWT_CLOSEBOX, RESIZE_NONE, BGC, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW },
-{ WWT_CAPTION, RESIZE_NONE, BGC, 11, 419, 0, 13, STR_NETWORK_START_GAME_WINDOW, STR_NULL},
-{ WWT_PANEL, RESIZE_NONE, BGC, 0, 419, 14, 243, 0x0, STR_NULL},
-
-{ WWT_PANEL, RESIZE_NONE, BGC, 100, 272, 22, 33, 0x0, STR_NETWORK_NEW_GAME_NAME_TIP},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 285, 405, 22, 33, STR_NETWORK_SET_PASSWORD, STR_NETWORK_PASSWORD_TIP},
-
-{ WWT_INSET, RESIZE_NONE, BGC, 10, 271, 62, 216, 0x0, STR_NETWORK_SELECT_MAP_TIP},
-{ WWT_SCROLLBAR, RESIZE_NONE, BGC, 259, 270, 63, 215, 0x0, STR_0190_SCROLL_BAR_SCROLLS_LIST},
-/* Combo boxes to control Connection Type / Max Clients / Max Companies / Max Observers / Language */
-{ WWT_INSET, RESIZE_NONE, BGC, 280, 410, 77, 88, STR_NETWORK_COMBO1, STR_NETWORK_CONNECTION_TIP},
-{ WWT_TEXTBTN, RESIZE_NONE, BGC, 399, 409, 78, 87, STR_0225, STR_NETWORK_CONNECTION_TIP},
-{ WWT_INSET, RESIZE_NONE, BGC, 280, 410, 109, 120, STR_NETWORK_COMBO2, STR_NETWORK_NUMBER_OF_CLIENTS_TIP},
-{ WWT_TEXTBTN, RESIZE_NONE, BGC, 399, 409, 110, 119, STR_0225, STR_NETWORK_NUMBER_OF_CLIENTS_TIP},
-{ WWT_INSET, RESIZE_NONE, BGC, 280, 410, 141, 152, STR_NETWORK_COMBO3, STR_NETWORK_NUMBER_OF_COMPANIES_TIP},
-{ WWT_TEXTBTN, RESIZE_NONE, BGC, 399, 409, 142, 151, STR_0225, STR_NETWORK_NUMBER_OF_COMPANIES_TIP},
-{ WWT_INSET, RESIZE_NONE, BGC, 280, 410, 173, 184, STR_NETWORK_COMBO4, STR_NETWORK_NUMBER_OF_SPECTATORS_TIP},
-{ WWT_TEXTBTN, RESIZE_NONE, BGC, 399, 409, 174, 183, STR_0225, STR_NETWORK_NUMBER_OF_SPECTATORS_TIP},
-{ WWT_INSET, RESIZE_NONE, BGC, 280, 410, 205, 216, STR_NETWORK_COMBO5, STR_NETWORK_LANGUAGE_TIP},
-{ WWT_TEXTBTN, RESIZE_NONE, BGC, 399, 409, 206, 215, STR_0225, STR_NETWORK_LANGUAGE_TIP},
-
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 40, 140, 224, 235, STR_NETWORK_START_GAME, STR_NETWORK_START_GAME_TIP},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 150, 250, 224, 235, STR_NETWORK_LOAD_GAME, STR_NETWORK_LOAD_GAME_TIP},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 260, 360, 224, 235, STR_012E_CANCEL, STR_NULL},
-{ WIDGETS_END},
-};
-
-static const WindowDesc _network_start_server_window_desc = {
- WDP_CENTER, WDP_CENTER, 420, 244,
- WC_NETWORK_WINDOW,0,
- WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
- _network_start_server_window_widgets,
- NetworkStartServerWindowWndProc,
-};
-
-static void ShowNetworkStartServerWindow(void)
-{
- Window *w;
- DeleteWindowById(WC_NETWORK_WINDOW, 0);
-
- w = AllocateWindowDesc(&_network_start_server_window_desc);
- ttd_strlcpy(_edit_str_buf, _network_server_name, lengthof(_edit_str_buf));
-
- _saveload_mode = SLD_NEW_GAME;
- BuildFileList();
- w->vscroll.cap = 12;
- w->vscroll.count = _fios_num+1;
-
- WP(w, network_ql_d).q.afilter = CS_ALPHANUMERAL;
- InitializeTextBuffer(&WP(w, network_ql_d).q.text, _edit_str_buf, lengthof(_edit_str_buf), 160);
-}
-
-static byte NetworkLobbyFindCompanyIndex(byte pos)
-{
- byte i;
-
- /* Scroll through all _network_player_info and get the 'pos' item
- that is not empty */
- for (i = 0; i < MAX_PLAYERS; i++) {
- if (_network_player_info[i].company_name[0] != '\0') {
- if (pos-- == 0) return i;
- }
- }
-
- return 0;
-}
-
-/* uses network_d WP macro */
-static void NetworkLobbyWindowWndProc(Window *w, WindowEvent *e)
-{
- network_d *nd = &WP(w, network_d);
-
- switch (e->event) {
- case WE_CREATE:
- nd->company = (byte)-1;
- break;
-
- case WE_PAINT: {
- const NetworkGameInfo *gi = &nd->server->info;
- int y = NET_PRC__OFFSET_TOP_WIDGET_COMPANY, pos;
-
- SetWindowWidgetDisabledState(w, 7, nd->company == (byte)-1);
- SetWindowWidgetDisabledState(w, 8, gi->companies_on >= gi->companies_max);
- /* You can not join a server as spectator when it has no companies active..
- * it causes some nasty crashes */
- SetWindowWidgetDisabledState(w, 9, gi->spectators_on >= gi->spectators_max ||
- gi->companies_on == 0);
-
- DrawWindowWidgets(w);
-
- SetDParamStr(0, gi->server_name);
- DrawString(10, 22, STR_NETWORK_PREPARE_TO_JOIN, 2);
-
- /* Draw company list */
- pos = w->vscroll.pos;
- while (pos < gi->companies_on) {
- byte company = NetworkLobbyFindCompanyIndex(pos);
- bool income = false;
- if (nd->company == company)
- GfxFillRect(11, y - 1, 154, y + 10, 10); // show highlighted item with a different colour
-
- DoDrawStringTruncated(_network_player_info[company].company_name, 13, y, 16, 135 - 13);
- if (_network_player_info[company].use_password != 0) DrawSprite(SPR_LOCK, 135, y);
-
- /* If the company's income was positive puts a green dot else a red dot */
- if (_network_player_info[company].income >= 0) income = true;
- DrawSprite(SPR_BLOT | (income ? PALETTE_TO_GREEN : PALETTE_TO_RED), 145, y);
-
- pos++;
- y += NET_PRC__SIZE_OF_ROW;
- if (pos >= w->vscroll.cap) break;
- }
-
- /* Draw info about selected company when it is selected in the left window */
- GfxFillRect(174, 39, 403, 75, 157);
- DrawStringCentered(290, 50, STR_NETWORK_COMPANY_INFO, 0);
- if (nd->company != (byte)-1) {
- const uint x = 183;
- const uint trunc_width = w->widget[6].right - x;
- y = 80;
-
- SetDParam(0, nd->server->info.clients_on);
- SetDParam(1, nd->server->info.clients_max);
- SetDParam(2, nd->server->info.companies_on);
- SetDParam(3, nd->server->info.companies_max);
- DrawString(x, y, STR_NETWORK_CLIENTS, 2);
- y += 10;
-
- SetDParamStr(0, _network_player_info[nd->company].company_name);
- DrawStringTruncated(x, y, STR_NETWORK_COMPANY_NAME, 2, trunc_width);
- y += 10;
-
- SetDParam(0, _network_player_info[nd->company].inaugurated_year);
- DrawString(x, y, STR_NETWORK_INAUGURATION_YEAR, 2); // inauguration year
- y += 10;
-
- SetDParam64(0, _network_player_info[nd->company].company_value);
- DrawString(x, y, STR_NETWORK_VALUE, 2); // company value
- y += 10;
-
- SetDParam64(0, _network_player_info[nd->company].money);
- DrawString(x, y, STR_NETWORK_CURRENT_BALANCE, 2); // current balance
- y += 10;
-
- SetDParam64(0, _network_player_info[nd->company].income);
- DrawString(x, y, STR_NETWORK_LAST_YEARS_INCOME, 2); // last year's income
- y += 10;
-
- SetDParam(0, _network_player_info[nd->company].performance);
- DrawString(x, y, STR_NETWORK_PERFORMANCE, 2); // performance
- y += 10;
-
- SetDParam(0, _network_player_info[nd->company].num_vehicle[0]);
- SetDParam(1, _network_player_info[nd->company].num_vehicle[1]);
- SetDParam(2, _network_player_info[nd->company].num_vehicle[2]);
- SetDParam(3, _network_player_info[nd->company].num_vehicle[3]);
- SetDParam(4, _network_player_info[nd->company].num_vehicle[4]);
- DrawString(x, y, STR_NETWORK_VEHICLES, 2); // vehicles
- y += 10;
-
- SetDParam(0, _network_player_info[nd->company].num_station[0]);
- SetDParam(1, _network_player_info[nd->company].num_station[1]);
- SetDParam(2, _network_player_info[nd->company].num_station[2]);
- SetDParam(3, _network_player_info[nd->company].num_station[3]);
- SetDParam(4, _network_player_info[nd->company].num_station[4]);
- DrawString(x, y, STR_NETWORK_STATIONS, 2); // stations
- y += 10;
-
- SetDParamStr(0, _network_player_info[nd->company].players);
- DrawStringTruncated(x, y, STR_NETWORK_PLAYERS, 2, trunc_width); // players
- }
- } break;
-
- case WE_CLICK:
- switch (e->we.click.widget) {
- case 0: case 11: /* Close 'X' | Cancel button */
- ShowNetworkGameWindow();
- break;
- case 4: { /* Company list */
- uint32 id_v = (e->we.click.pt.y - NET_PRC__OFFSET_TOP_WIDGET_COMPANY) / NET_PRC__SIZE_OF_ROW;
-
- if (id_v >= w->vscroll.cap) return;
-
- id_v += w->vscroll.pos;
- nd->company = (id_v >= nd->server->info.companies_on) ? (byte)-1 : NetworkLobbyFindCompanyIndex(id_v);
- SetWindowDirty(w);
- } break;
- case 7: /* Join company */
- if (nd->company != (byte)-1) {
- _network_playas = nd->company;
- NetworkClientConnectGame(_network_last_host, _network_last_port);
- }
- break;
- case 8: /* New company */
- _network_playas = PLAYER_NEW_COMPANY;
- NetworkClientConnectGame(_network_last_host, _network_last_port);
- break;
- case 9: /* Spectate game */
- _network_playas = PLAYER_SPECTATOR;
- NetworkClientConnectGame(_network_last_host, _network_last_port);
- break;
- case 10: /* Refresh */
- NetworkQueryServer(_network_last_host, _network_last_port, false); // company info
- NetworkUDPQueryServer(_network_last_host, _network_last_port); // general data
- break;
- } break;
-
- case WE_MESSAGE:
- SetWindowDirty(w);
- break;
- }
-}
-
-static const Widget _network_lobby_window_widgets[] = {
-{ WWT_CLOSEBOX, RESIZE_NONE, BGC, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW },
-{ WWT_CAPTION, RESIZE_NONE, BGC, 11, 419, 0, 13, STR_NETWORK_GAME_LOBBY, STR_NULL},
-{ WWT_PANEL, RESIZE_NONE, BGC, 0, 419, 14, 234, 0x0, STR_NULL},
-
-// company list
-{ WWT_PANEL, RESIZE_NONE, BTC, 10, 155, 38, 49, 0x0, STR_NULL},
-{ WWT_MATRIX, RESIZE_NONE, BGC, 10, 155, 50, 190, (10 << 8) + 1, STR_NETWORK_COMPANY_LIST_TIP},
-{ WWT_SCROLLBAR, RESIZE_NONE, BGC, 156, 167, 38, 190, STR_NULL, STR_0190_SCROLL_BAR_SCROLLS_LIST},
-
-// company/player info
-{ WWT_PANEL, RESIZE_NONE, BGC, 173, 404, 38, 190, 0x0, STR_NULL},
-
-// buttons
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 10, 151, 200, 211, STR_NETWORK_JOIN_COMPANY, STR_NETWORK_JOIN_COMPANY_TIP},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 10, 151, 215, 226, STR_NETWORK_NEW_COMPANY, STR_NETWORK_NEW_COMPANY_TIP},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 158, 268, 200, 211, STR_NETWORK_SPECTATE_GAME, STR_NETWORK_SPECTATE_GAME_TIP},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 158, 268, 215, 226, STR_NETWORK_REFRESH, STR_NETWORK_REFRESH_TIP},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 278, 388, 200, 211, STR_012E_CANCEL, STR_NULL},
-
-{ WIDGETS_END},
-};
-
-static const WindowDesc _network_lobby_window_desc = {
- WDP_CENTER, WDP_CENTER, 420, 235,
- WC_NETWORK_WINDOW,0,
- WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_UNCLICK_BUTTONS,
- _network_lobby_window_widgets,
- NetworkLobbyWindowWndProc,
-};
-
-/* Show the networklobbywindow with the selected server
- * @param ngl Selected game pointer which is passed to the new window */
-static void ShowNetworkLobbyWindow(NetworkGameList *ngl)
-{
- Window *w;
- DeleteWindowById(WC_NETWORK_WINDOW, 0);
-
- NetworkQueryServer(_network_last_host, _network_last_port, false); // company info
- NetworkUDPQueryServer(_network_last_host, _network_last_port); // general data
-
- w = AllocateWindowDesc(&_network_lobby_window_desc);
- if (w != NULL) {
- WP(w, network_ql_d).n.server = ngl;
- strcpy(_edit_str_buf, "");
- w->vscroll.cap = 10;
- }
-}
-
-// The window below gives information about the connected clients
-// and also makes able to give money to them, kick them (if server)
-// and stuff like that.
-
-extern void DrawPlayerIcon(PlayerID pid, int x, int y);
-
-// Every action must be of this form
-typedef void ClientList_Action_Proc(byte client_no);
-
-// Max 10 actions per client
-#define MAX_CLIENTLIST_ACTION 10
-
-// Some standard bullshit.. defines variables ;)
-static void ClientListWndProc(Window *w, WindowEvent *e);
-static void ClientListPopupWndProc(Window *w, WindowEvent *e);
-static byte _selected_clientlist_item = 255;
-static byte _selected_clientlist_y = 0;
-static char _clientlist_action[MAX_CLIENTLIST_ACTION][50];
-static ClientList_Action_Proc *_clientlist_proc[MAX_CLIENTLIST_ACTION];
-
-enum {
- CLNWND_OFFSET = 16,
- CLNWND_ROWSIZE = 10
-};
-
-static const Widget _client_list_widgets[] = {
-{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
-{ WWT_CAPTION, RESIZE_NONE, 14, 11, 249, 0, 13, STR_NETWORK_CLIENT_LIST, STR_018C_WINDOW_TITLE_DRAG_THIS},
-
-{ WWT_PANEL, RESIZE_NONE, 14, 0, 249, 14, 14 + CLNWND_ROWSIZE + 1, 0x0, STR_NULL},
-{ WIDGETS_END},
-};
-
-static const Widget _client_list_popup_widgets[] = {
-{ WWT_PANEL, RESIZE_NONE, 14, 0, 99, 0, 0, 0, STR_NULL},
-{ WIDGETS_END},
-};
-
-static WindowDesc _client_list_desc = {
- WDP_AUTO, WDP_AUTO, 250, 1,
- WC_CLIENT_LIST,0,
- WDF_STD_TOOLTIPS | WDF_STD_BTN | WDF_DEF_WIDGET,
- _client_list_widgets,
- ClientListWndProc
-};
-
-// Finds the Xth client-info that is active
-static const NetworkClientInfo *NetworkFindClientInfo(byte client_no)
-{
- const NetworkClientInfo *ci;
-
- FOR_ALL_ACTIVE_CLIENT_INFOS(ci) {
- if (client_no == 0) return ci;
- client_no--;
- }
-
- return NULL;
-}
-
-// Here we start to define the options out of the menu
-static void ClientList_Kick(byte client_no)
-{
- if (client_no < MAX_PLAYERS)
- SEND_COMMAND(PACKET_SERVER_ERROR)(DEREF_CLIENT(client_no), NETWORK_ERROR_KICKED);
-}
-
-static void ClientList_Ban(byte client_no)
-{
- uint i;
- uint32 ip = NetworkFindClientInfo(client_no)->client_ip;
-
- for (i = 0; i < lengthof(_network_ban_list); i++) {
- if (_network_ban_list[i] == NULL) {
- _network_ban_list[i] = strdup(inet_ntoa(*(struct in_addr *)&ip));
- break;
- }
- }
-
- if (client_no < MAX_PLAYERS)
- SEND_COMMAND(PACKET_SERVER_ERROR)(DEREF_CLIENT(client_no), NETWORK_ERROR_KICKED);
-}
-
-static void ClientList_GiveMoney(byte client_no)
-{
- if (NetworkFindClientInfo(client_no) != NULL)
- ShowNetworkGiveMoneyWindow(NetworkFindClientInfo(client_no)->client_playas);
-}
-
-static void ClientList_SpeakToClient(byte client_no)
-{
- if (NetworkFindClientInfo(client_no) != NULL)
- ShowNetworkChatQueryWindow(DESTTYPE_CLIENT, NetworkFindClientInfo(client_no)->client_index);
-}
-
-static void ClientList_SpeakToCompany(byte client_no)
-{
- if (NetworkFindClientInfo(client_no) != NULL)
- ShowNetworkChatQueryWindow(DESTTYPE_TEAM, NetworkFindClientInfo(client_no)->client_playas);
-}
-
-static void ClientList_SpeakToAll(byte client_no)
-{
- ShowNetworkChatQueryWindow(DESTTYPE_BROADCAST, 0);
-}
-
-static void ClientList_None(byte client_no)
-{
- // No action ;)
-}
-
-
-
-// Help, a action is clicked! What do we do?
-static void HandleClientListPopupClick(byte index, byte clientno) {
- // A click on the Popup of the ClientList.. handle the command
- if (index < MAX_CLIENTLIST_ACTION && _clientlist_proc[index] != NULL) {
- _clientlist_proc[index](clientno);
- }
-}
-
-// Finds the amount of clients and set the height correct
-static bool CheckClientListHeight(Window *w)
-{
- int num = 0;
- const NetworkClientInfo *ci;
-
- // Should be replaced with a loop through all clients
- FOR_ALL_ACTIVE_CLIENT_INFOS(ci) {
- num++;
- }
-
- num *= CLNWND_ROWSIZE;
-
- // If height is changed
- if (w->height != CLNWND_OFFSET + num + 1) {
- // XXX - magic unfortunately; (num + 2) has to be one bigger than heigh (num + 1)
- SetWindowDirty(w);
- w->widget[2].bottom = w->widget[2].top + num + 2;
- w->height = CLNWND_OFFSET + num + 1;
- SetWindowDirty(w);
- return false;
- }
- return true;
-}
-
-// Finds the amount of actions in the popup and set the height correct
-static uint ClientListPopupHeigth(void) {
- int i, num = 0;
-
- // Find the amount of actions
- for (i = 0; i < MAX_CLIENTLIST_ACTION; i++) {
- if (_clientlist_action[i][0] == '\0') continue;
- if (_clientlist_proc[i] == NULL) continue;
- num++;
- }
-
- num *= CLNWND_ROWSIZE;
-
- return num + 1;
-}
-
-// Show the popup (action list)
-static Window *PopupClientList(Window *w, int client_no, int x, int y)
-{
- int i, h;
- const NetworkClientInfo *ci;
- DeleteWindowById(WC_TOOLBAR_MENU, 0);
-
- // Clean the current actions
- for (i = 0; i < MAX_CLIENTLIST_ACTION; i++) {
- _clientlist_action[i][0] = '\0';
- _clientlist_proc[i] = NULL;
- }
-
- // Fill the actions this client has
- // Watch is, max 50 chars long!
-
- ci = NetworkFindClientInfo(client_no);
- if (ci == NULL) return NULL;
-
- i = 0;
- if (_network_own_client_index != ci->client_index) {
- GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_CLIENT, lastof(_clientlist_action[i]));
- _clientlist_proc[i++] = &ClientList_SpeakToClient;
- }
-
- if (IsValidPlayer(ci->client_playas) || ci->client_playas == PLAYER_SPECTATOR) {
- GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_COMPANY, lastof(_clientlist_action[i]));
- _clientlist_proc[i++] = &ClientList_SpeakToCompany;
- }
- GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_SPEAK_TO_ALL, lastof(_clientlist_action[i]));
- _clientlist_proc[i++] = &ClientList_SpeakToAll;
-
- if (_network_own_client_index != ci->client_index) {
- /* We are no spectator and the player we want to give money to is no spectator */
- if (IsValidPlayer(_network_playas) && IsValidPlayer(ci->client_playas)) {
- GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_GIVE_MONEY, lastof(_clientlist_action[i]));
- _clientlist_proc[i++] = &ClientList_GiveMoney;
- }
- }
-
- // A server can kick clients (but not himself)
- if (_network_server && _network_own_client_index != ci->client_index) {
- GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_KICK, lastof(_clientlist_action[i]));
- _clientlist_proc[i++] = &ClientList_Kick;
-
- sprintf(_clientlist_action[i],"Ban"); // XXX GetString?
- _clientlist_proc[i++] = &ClientList_Ban;
- }
-
- if (i == 0) {
- GetString(_clientlist_action[i], STR_NETWORK_CLIENTLIST_NONE, lastof(_clientlist_action[i]));
- _clientlist_proc[i++] = &ClientList_None;
- }
-
- /* Calculate the height */
- h = ClientListPopupHeigth();
-
- // Allocate the popup
- w = AllocateWindow(x, y, 150, h + 1, ClientListPopupWndProc, WC_TOOLBAR_MENU, _client_list_popup_widgets);
- w->widget[0].bottom = w->widget[0].top + h;
- w->widget[0].right = w->widget[0].left + 150;
-
- w->flags4 &= ~WF_WHITE_BORDER_MASK;
- WP(w,menu_d).item_count = 0;
- // Save our client
- WP(w,menu_d).main_button = client_no;
- WP(w,menu_d).sel_index = 0;
- // We are a popup
- _popup_menu_active = true;
-
- return w;
-}
-
-/** Main handle for the client popup list
- * uses menu_d WP macro */
-static void ClientListPopupWndProc(Window *w, WindowEvent *e)
-{
- switch (e->event) {
- case WE_PAINT: {
- int i, y, sel;
- byte colour;
- DrawWindowWidgets(w);
-
- // Draw the actions
- sel = WP(w,menu_d).sel_index;
- y = 1;
- for (i = 0; i < MAX_CLIENTLIST_ACTION; i++, y += CLNWND_ROWSIZE) {
- if (_clientlist_action[i][0] == '\0') continue;
- if (_clientlist_proc[i] == NULL) continue;
-
- if (sel-- == 0) { // Selected item, highlight it
- GfxFillRect(1, y, 150 - 2, y + CLNWND_ROWSIZE - 1, 0);
- colour = 0xC;
- } else {
- colour = 0x10;
- }
-
- DoDrawString(_clientlist_action[i], 4, y, colour);
- }
- } break;
-
- case WE_POPUPMENU_SELECT: {
- // We selected an action
- int index = (e->we.popupmenu.pt.y - w->top) / CLNWND_ROWSIZE;
-
- if (index >= 0 && e->we.popupmenu.pt.y >= w->top)
- HandleClientListPopupClick(index, WP(w,menu_d).main_button);
-
- DeleteWindowById(WC_TOOLBAR_MENU, 0);
- } break;
-
- case WE_POPUPMENU_OVER: {
- // Our mouse hoovers over an action? Select it!
- int index = (e->we.popupmenu.pt.y - w->top) / CLNWND_ROWSIZE;
-
- if (index == -1 || index == WP(w,menu_d).sel_index) return;
-
- WP(w,menu_d).sel_index = index;
- SetWindowDirty(w);
- } break;
-
- }
-}
-
-// Main handle for clientlist
-static void ClientListWndProc(Window *w, WindowEvent *e)
-{
- switch (e->event) {
- case WE_PAINT: {
- NetworkClientInfo *ci;
- int y, i = 0;
- byte colour;
-
- // Check if we need to reset the height
- if (!CheckClientListHeight(w)) break;
-
- DrawWindowWidgets(w);
-
- y = CLNWND_OFFSET;
-
- FOR_ALL_ACTIVE_CLIENT_INFOS(ci) {
- if (_selected_clientlist_item == i++) { // Selected item, highlight it
- GfxFillRect(1, y, 248, y + CLNWND_ROWSIZE - 1, 0);
- colour = 0xC;
- } else {
- colour = 0x10;
- }
-
- if (ci->client_index == NETWORK_SERVER_INDEX) {
- DrawString(4, y, STR_NETWORK_SERVER, colour);
- } else {
- DrawString(4, y, STR_NETWORK_CLIENT, colour);
- }
-
- // Filter out spectators
- if (IsValidPlayer(ci->client_playas)) DrawPlayerIcon(ci->client_playas, 64, y + 1);
-
- DoDrawString(ci->client_name, 81, y, colour);
-
- y += CLNWND_ROWSIZE;
- }
- } break;
-
- case WE_CLICK:
- // Show the popup with option
- if (_selected_clientlist_item != 255) {
- PopupClientList(w, _selected_clientlist_item, e->we.click.pt.x + w->left, e->we.click.pt.y + w->top);
- }
-
- break;
-
- case WE_MOUSEOVER:
- // -1 means we left the current window
- if (e->we.mouseover.pt.y == -1) {
- _selected_clientlist_y = 0;
- _selected_clientlist_item = 255;
- SetWindowDirty(w);
- break;
- }
- // It did not change.. no update!
- if (e->we.mouseover.pt.y == _selected_clientlist_y) break;
-
- // Find the new selected item (if any)
- _selected_clientlist_y = e->we.mouseover.pt.y;
- if (e->we.mouseover.pt.y > CLNWND_OFFSET) {
- _selected_clientlist_item = (e->we.mouseover.pt.y - CLNWND_OFFSET) / CLNWND_ROWSIZE;
- } else {
- _selected_clientlist_item = 255;
- }
-
- // Repaint
- SetWindowDirty(w);
- break;
-
- case WE_DESTROY: case WE_CREATE:
- // When created or destroyed, data is reset
- _selected_clientlist_item = 255;
- _selected_clientlist_y = 0;
- break;
- }
-}
-
-void ShowClientList(void)
-{
- AllocateWindowDescFront(&_client_list_desc, 0);
-}
-
-
-static NetworkPasswordType pw_type;
-
-
-void ShowNetworkNeedPassword(NetworkPasswordType npt)
-{
- StringID caption;
-
- pw_type = npt;
- switch (npt) {
- default: NOT_REACHED();
- case NETWORK_GAME_PASSWORD: caption = STR_NETWORK_NEED_GAME_PASSWORD_CAPTION; break;
- case NETWORK_COMPANY_PASSWORD: caption = STR_NETWORK_NEED_COMPANY_PASSWORD_CAPTION; break;
- }
- ShowQueryString(STR_EMPTY, caption, 20, 180, FindWindowById(WC_NETWORK_STATUS_WINDOW, 0), CS_ALPHANUMERAL);
-}
-
-
-static void NetworkJoinStatusWindowWndProc(Window *w, WindowEvent *e)
-{
- switch (e->event) {
- case WE_PAINT: {
- uint8 progress; // used for progress bar
- DrawWindowWidgets(w);
-
- DrawStringCentered(125, 35, STR_NETWORK_CONNECTING_1 + _network_join_status, 14);
- switch (_network_join_status) {
- case NETWORK_JOIN_STATUS_CONNECTING: case NETWORK_JOIN_STATUS_AUTHORIZING:
- case NETWORK_JOIN_STATUS_GETTING_COMPANY_INFO:
- progress = 10; // first two stages 10%
- break;
- case NETWORK_JOIN_STATUS_WAITING:
- SetDParam(0, _network_join_waiting);
- DrawStringCentered(125, 46, STR_NETWORK_CONNECTING_WAITING, 14);
- progress = 15; // third stage is 15%
- break;
- case NETWORK_JOIN_STATUS_DOWNLOADING:
- SetDParam(0, _network_join_kbytes);
- SetDParam(1, _network_join_kbytes_total);
- DrawStringCentered(125, 46, STR_NETWORK_CONNECTING_DOWNLOADING, 14);
- /* Fallthrough */
- default: /* Waiting is 15%, so the resting receivement of map is maximum 70% */
- progress = 15 + _network_join_kbytes * (100 - 15) / _network_join_kbytes_total;
- }
-
- /* Draw nice progress bar :) */
- DrawFrameRect(20, 18, (int)((w->width - 20) * progress / 100), 28, 10, 0);
- } break;
-
- case WE_CLICK:
- switch (e->we.click.widget) {
- case 2: /* Disconnect button */
- NetworkDisconnect();
- DeleteWindow(w);
- SwitchMode(SM_MENU);
- ShowNetworkGameWindow();
- break;
- }
- break;
-
- /* If the server asks for a password, we need to fill it in */
- case WE_ON_EDIT_TEXT_CANCEL:
- NetworkDisconnect();
- ShowNetworkGameWindow();
- break;
-
- case WE_ON_EDIT_TEXT:
- SEND_COMMAND(PACKET_CLIENT_PASSWORD)(pw_type, e->we.edittext.str);
- break;
- }
-}
-
-static const Widget _network_join_status_window_widget[] = {
-{ WWT_CAPTION, RESIZE_NONE, 14, 0, 249, 0, 13, STR_NETWORK_CONNECTING, STR_018C_WINDOW_TITLE_DRAG_THIS},
-{ WWT_PANEL, RESIZE_NONE, 14, 0, 249, 14, 84, 0x0, STR_NULL},
-{ WWT_PUSHTXTBTN, RESIZE_NONE, BTC, 75, 175, 69, 80, STR_NETWORK_DISCONNECT, STR_NULL},
-{ WIDGETS_END},
-};
-
-static const WindowDesc _network_join_status_window_desc = {
- WDP_CENTER, WDP_CENTER, 250, 85,
- WC_NETWORK_STATUS_WINDOW, 0,
- WDF_STD_TOOLTIPS | WDF_DEF_WIDGET | WDF_MODAL,
- _network_join_status_window_widget,
- NetworkJoinStatusWindowWndProc,
-};
-
-void ShowJoinStatusWindow(void)
-{
- Window *w;
- DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
- w = AllocateWindowDesc(&_network_join_status_window_desc);
- /* Parent the status window to the lobby */
- if (w != NULL) w->parent = FindWindowById(WC_NETWORK_WINDOW, 0);
-}
-
-static void SendChat(const char *buf, DestType type, byte dest)
-{
- if (buf[0] == '\0') return;
- if (!_network_server) {
- SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_CHAT + type, type, dest, buf);
- } else {
- NetworkServer_HandleChat(NETWORK_ACTION_CHAT + type, type, dest, buf, NETWORK_SERVER_INDEX);
- }
-}
-
-/**
- * Find the next item of the list of things that can be auto-completed.
- * @param item The current indexed item to return. This function can, and most
- * likely will, alter item, to skip empty items in the arrays.
- * @return Returns the char that matched to the index.
- */
-static const char *ChatTabCompletionNextItem(uint *item)
-{
- static char chat_tab_temp_buffer[64];
-
- /* First, try clients */
- if (*item < MAX_CLIENT_INFO) {
- /* Skip inactive clients */
- while (_network_client_info[*item].client_index == NETWORK_EMPTY_INDEX && *item < MAX_CLIENT_INFO) (*item)++;
- if (*item < MAX_CLIENT_INFO) return _network_client_info[*item].client_name;
- }
-
- /* Then, try townnames */
- /* Not that the following assumes all town indices are adjacent, ie no
- * towns have been deleted. */
- if (*item <= (uint)MAX_CLIENT_INFO + GetMaxTownIndex()) {
- const Town *t;
-
- FOR_ALL_TOWNS_FROM(t, *item - MAX_CLIENT_INFO) {
- /* Get the town-name via the string-system */
- SetDParam(0, t->townnameparts);
- GetString(chat_tab_temp_buffer, t->townnametype, lastof(chat_tab_temp_buffer));
- return &chat_tab_temp_buffer[0];
- }
- }
-
- return NULL;
-}
-
-/**
- * Find what text to complete. It scans for a space from the left and marks
- * the word right from that as to complete. It also writes a \0 at the
- * position of the space (if any). If nothing found, buf is returned.
- */
-static char *ChatTabCompletionFindText(char *buf)
-{
- char *p = strrchr(buf, ' ');
- if (p == NULL) return buf;
-
- *p = '\0';
- return p + 1;
-}
-
-/**
- * See if we can auto-complete the current text of the user.
- */
-static void ChatTabCompletion(Window *w)
-{
- static char _chat_tab_completion_buf[lengthof(_edit_str_buf)];
- Textbuf *tb = &WP(w, querystr_d).text;
- uint len, tb_len;
- uint item;
- char *tb_buf, *pre_buf;
- const char *cur_name;
- bool second_scan = false;
-
- item = 0;
-
- /* Copy the buffer so we can modify it without damaging the real data */
- pre_buf = (_chat_tab_completion_active) ? strdup(_chat_tab_completion_buf) : strdup(tb->buf);
-
- tb_buf = ChatTabCompletionFindText(pre_buf);
- tb_len = strlen(tb_buf);
-
- while ((cur_name = ChatTabCompletionNextItem(&item)) != NULL) {
- item++;
-
- if (_chat_tab_completion_active) {
- /* We are pressing TAB again on the same name, is there an other name
- * that starts with this? */
- if (!second_scan) {
- uint offset;
- uint length;
-
- /* If we are completing at the begin of the line, skip the ': ' we added */
- if (tb_buf == pre_buf) {
- offset = 0;
- length = tb->length - 2;
- } else {
- /* Else, find the place we are completing at */
- offset = strlen(pre_buf) + 1;
- length = tb->length - offset;
- }
-
- /* Compare if we have a match */
- if (strlen(cur_name) == length && strncmp(cur_name, tb->buf + offset, length) == 0) second_scan = true;
-
- continue;
- }
-
- /* Now any match we make on _chat_tab_completion_buf after this, is perfect */
- }
-
- len = strlen(cur_name);
- if (tb_len < len && strncasecmp(cur_name, tb_buf, tb_len) == 0) {
- /* Save the data it was before completion */
- if (!second_scan) snprintf(_chat_tab_completion_buf, lengthof(_chat_tab_completion_buf), "%s", tb->buf);
- _chat_tab_completion_active = true;
-
- /* Change to the found name. Add ': ' if we are at the start of the line (pretty) */
- if (pre_buf == tb_buf) {
- snprintf(tb->buf, lengthof(_edit_str_buf), "%s: ", cur_name);
- } else {
- snprintf(tb->buf, lengthof(_edit_str_buf), "%s %s", pre_buf, cur_name);
- }
-
- /* Update the textbuffer */
- UpdateTextBufferSize(&WP(w, querystr_d).text);
-
- SetWindowDirty(w);
- free(pre_buf);
- return;
- }
- }
-
- if (second_scan) {
- /* We walked all posibilities, and the user presses tab again.. revert to original text */
- strcpy(tb->buf, _chat_tab_completion_buf);
- _chat_tab_completion_active = false;
-
- /* Update the textbuffer */
- UpdateTextBufferSize(&WP(w, querystr_d).text);
-
- SetWindowDirty(w);
- }
- free(pre_buf);
-}
-
-/* uses querystr_d WP macro
- * uses querystr_d->caption to store
- * - type of chat message (Private/Team/All) in bytes 0-7
- * - destination of chat message in the case of Team/Private in bytes 8-15 */
-static void ChatWindowWndProc(Window *w, WindowEvent *e)
-{
- switch (e->event) {
- case WE_CREATE:
- SendWindowMessage(WC_NEWS_WINDOW, 0, WE_CREATE, w->height, 0);
- SETBIT(_no_scroll, SCROLL_CHAT); // do not scroll the game with the arrow-keys
- break;
-
- case WE_PAINT: {
- static const StringID chat_captions[] = {
- STR_NETWORK_CHAT_ALL_CAPTION,
- STR_NETWORK_CHAT_COMPANY_CAPTION,
- STR_NETWORK_CHAT_CLIENT_CAPTION
- };
- StringID msg;
-
- DrawWindowWidgets(w);
-
- assert(GB(WP(w, querystr_d).caption, 0, 8) < lengthof(chat_captions));
- msg = chat_captions[GB(WP(w, querystr_d).caption, 0, 8)];
- DrawStringRightAligned(w->widget[2].left - 2, w->widget[2].top + 1, msg, 16);
- DrawEditBox(w, &WP(w, querystr_d), 2);
- } break;
-
- case WE_CLICK:
- switch (e->we.click.widget) {
- case 3: { /* Send */
- DestType type = GB(WP(w, querystr_d).caption, 0, 8);
- byte dest = GB(WP(w, querystr_d).caption, 8, 8);
- SendChat(WP(w, querystr_d).text.buf, type, dest);
- } /* FALLTHROUGH */
- case 0: /* Cancel */ DeleteWindow(w); break;
- }
- break;
-
- case WE_MOUSELOOP:
- HandleEditBox(w, &WP(w, querystr_d), 2);
- break;
-
- case WE_KEYPRESS:
- if (e->we.keypress.keycode == WKC_TAB) {
- ChatTabCompletion(w);
- } else {
- _chat_tab_completion_active = false;
- switch (HandleEditBoxKey(w, &WP(w, querystr_d), 2, e)) {
- case 1: { /* Return */
- DestType type = GB(WP(w, querystr_d).caption, 0, 8);
- byte dest = GB(WP(w, querystr_d).caption, 8, 8);
- SendChat(WP(w, querystr_d).text.buf, type, dest);
- } /* FALLTHROUGH */
- case 2: /* Escape */ DeleteWindow(w); break;
- }
- }
- break;
-
- case WE_DESTROY:
- SendWindowMessage(WC_NEWS_WINDOW, 0, WE_DESTROY, 0, 0);
- CLRBIT(_no_scroll, SCROLL_CHAT);
- break;
- }
-}
-
-static const Widget _chat_window_widgets[] = {
-{ WWT_CLOSEBOX, RESIZE_NONE, 14, 0, 10, 0, 13, STR_00C5, STR_018B_CLOSE_WINDOW},
-{ WWT_PANEL, RESIZE_NONE, 14, 11, 639, 0, 13, 0x0, STR_NULL}, // background
-{ WWT_PANEL, RESIZE_NONE, 14, 75, 577, 1, 12, 0x0, STR_NULL}, // text box
-{ WWT_PUSHTXTBTN, RESIZE_NONE, 14, 578, 639, 1, 12, STR_NETWORK_SEND, STR_NULL}, // send button
-{ WIDGETS_END},
-};
-
-static const WindowDesc _chat_window_desc = {
- WDP_CENTER, -26, 640, 14, // x, y, width, height
- WC_SEND_NETWORK_MSG,0,
- WDF_STD_TOOLTIPS | WDF_DEF_WIDGET,
- _chat_window_widgets,
- ChatWindowWndProc
-};
-
-void ShowNetworkChatQueryWindow(DestType type, byte dest)
-{
- Window *w;
-
- DeleteWindowById(WC_SEND_NETWORK_MSG, 0);
-
- _edit_str_buf[0] = '\0';
- _chat_tab_completion_active = false;
-
- w = AllocateWindowDesc(&_chat_window_desc);
-
- LowerWindowWidget(w, 2);
- WP(w, querystr_d).caption = GB(type, 0, 8) | (dest << 8); // Misuse of caption
- WP(w, querystr_d).afilter = CS_ALPHANUMERAL;
- InitializeTextBuffer(&WP(w, querystr_d).text, _edit_str_buf, lengthof(_edit_str_buf), 0);
-}
-
-#endif /* ENABLE_NETWORK */
diff --git a/network/network_gui.h b/network/network_gui.h
deleted file mode 100644
index aa4313eba..000000000
--- a/network/network_gui.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* $Id$ */
-
-#ifndef NETWORK_GUI_H
-#define NETWORK_GUI_H
-
-#ifdef ENABLE_NETWORK
-
-#include "network_data.h"
-
-void ShowNetworkNeedPassword(NetworkPasswordType npt);
-void ShowNetworkGiveMoneyWindow(byte player); // PlayerID
-void ShowNetworkChatQueryWindow(DestType type, byte dest);
-void ShowJoinStatusWindow(void);
-void ShowNetworkGameWindow(void);
-void ShowClientList(void);
-
-#else /* ENABLE_NETWORK */
-/* Network function stubs when networking is disabled */
-
-static inline void ShowNetworkChatQueryWindow(byte desttype, byte dest) {}
-static inline void ShowClientList(void) {}
-static inline void ShowNetworkGameWindow(void) {}
-
-#endif /* ENABLE_NETWORK */
-
-#endif /* NETWORK_GUI_H */
diff --git a/network/network_server.c b/network/network_server.c
deleted file mode 100644
index 2a75d15fe..000000000
--- a/network/network_server.c
+++ /dev/null
@@ -1,1528 +0,0 @@
-/* $Id$ */
-
-#ifdef ENABLE_NETWORK
-
-#include "../stdafx.h"
-#include "../openttd.h" // XXX StringID
-#include "../debug.h"
-#include "../string.h"
-#include "../strings.h"
-#include "network_data.h"
-#include "core/tcp.h"
-#include "../train.h"
-#include "../date.h"
-#include "../table/strings.h"
-#include "../functions.h"
-#include "network_server.h"
-#include "network_udp.h"
-#include "../console.h"
-#include "../command.h"
-#include "../saveload.h"
-#include "../vehicle.h"
-#include "../station.h"
-#include "../variables.h"
-#include "../genworld.h"
-
-// This file handles all the server-commands
-
-static void NetworkHandleCommandQueue(NetworkClientState* cs);
-
-// **********
-// Sending functions
-// DEF_SERVER_SEND_COMMAND has parameter: NetworkClientState *cs
-// **********
-
-DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CLIENT_INFO)(NetworkClientState *cs, NetworkClientInfo *ci)
-{
- //
- // Packet: SERVER_CLIENT_INFO
- // Function: Sends info about a client
- // Data:
- // uint16: The index of the client (always unique on a server. 1 = server)
- // uint8: As which player the client is playing
- // String: The name of the client
- // String: The unique id of the client
- //
-
- if (ci->client_index != NETWORK_EMPTY_INDEX) {
- Packet *p = NetworkSend_Init(PACKET_SERVER_CLIENT_INFO);
- NetworkSend_uint16(p, ci->client_index);
- NetworkSend_uint8 (p, ci->client_playas);
- NetworkSend_string(p, ci->client_name);
- NetworkSend_string(p, ci->unique_id);
-
- NetworkSend_Packet(p, cs);
- }
-}
-
-DEF_SERVER_SEND_COMMAND(PACKET_SERVER_COMPANY_INFO)
-{
-//
- // Packet: SERVER_COMPANY_INFO
- // Function: Sends info about the companies
- // Data:
- //
-
- int i;
-
- Player *player;
- Packet *p;
-
- byte active = ActivePlayerCount();
-
- if (active == 0) {
- p = NetworkSend_Init(PACKET_SERVER_COMPANY_INFO);
-
- NetworkSend_uint8 (p, NETWORK_COMPANY_INFO_VERSION);
- NetworkSend_uint8 (p, active);
-
- NetworkSend_Packet(p, cs);
- return;
- }
-
- NetworkPopulateCompanyInfo();
-
- FOR_ALL_PLAYERS(player) {
- if (!player->is_active) continue;
-
- p = NetworkSend_Init(PACKET_SERVER_COMPANY_INFO);
-
- NetworkSend_uint8 (p, NETWORK_COMPANY_INFO_VERSION);
- NetworkSend_uint8 (p, active);
- NetworkSend_uint8 (p, player->index);
-
- NetworkSend_string(p, _network_player_info[player->index].company_name);
- NetworkSend_uint32(p, _network_player_info[player->index].inaugurated_year);
- NetworkSend_uint64(p, _network_player_info[player->index].company_value);
- NetworkSend_uint64(p, _network_player_info[player->index].money);
- NetworkSend_uint64(p, _network_player_info[player->index].income);
- NetworkSend_uint16(p, _network_player_info[player->index].performance);
-
- /* Send 1 if there is a passord for the company else send 0 */
- if (_network_player_info[player->index].password[0] != '\0') {
- NetworkSend_uint8(p, 1);
- } else {
- NetworkSend_uint8(p, 0);
- }
-
- for (i = 0; i < NETWORK_VEHICLE_TYPES; i++) {
- NetworkSend_uint16(p, _network_player_info[player->index].num_vehicle[i]);
- }
-
- for (i = 0; i < NETWORK_STATION_TYPES; i++) {
- NetworkSend_uint16(p, _network_player_info[player->index].num_station[i]);
- }
-
- if (_network_player_info[player->index].players[0] == '\0') {
- NetworkSend_string(p, "<none>");
- } else {
- NetworkSend_string(p, _network_player_info[player->index].players);
- }
-
- NetworkSend_Packet(p, cs);
- }
-
- p = NetworkSend_Init(PACKET_SERVER_COMPANY_INFO);
-
- NetworkSend_uint8 (p, NETWORK_COMPANY_INFO_VERSION);
- NetworkSend_uint8 (p, 0);
-
- NetworkSend_Packet(p, cs);
-}
-
-DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR)(NetworkClientState *cs, NetworkErrorCode error)
-{
- //
- // Packet: SERVER_ERROR
- // Function: The client made an error
- // Data:
- // uint8: ErrorID (see network_data.h, NetworkErrorCode)
- //
-
- char str[100];
- Packet *p = NetworkSend_Init(PACKET_SERVER_ERROR);
-
- NetworkSend_uint8(p, error);
- NetworkSend_Packet(p, cs);
-
- GetNetworkErrorMsg(str, error, lastof(str));
-
- // Only send when the current client was in game
- if (cs->status > STATUS_AUTH) {
- NetworkClientState *new_cs;
- char client_name[NETWORK_CLIENT_NAME_LENGTH];
-
- NetworkGetClientName(client_name, sizeof(client_name), cs);
-
- DEBUG(net, 1, "'%s' made an error and has been disconnected. Reason: '%s'", client_name, str);
-
- NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
-
- FOR_ALL_CLIENTS(new_cs) {
- if (new_cs->status > STATUS_AUTH && new_cs != cs) {
- // Some errors we filter to a more general error. Clients don't have to know the real
- // reason a joining failed.
- if (error == NETWORK_ERROR_NOT_AUTHORIZED || error == NETWORK_ERROR_NOT_EXPECTED || error == NETWORK_ERROR_WRONG_REVISION)
- error = NETWORK_ERROR_ILLEGAL_PACKET;
-
- SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->index, error);
- }
- }
- } else {
- DEBUG(net, 1, "Client %d made an error and has been disconnected. Reason: '%s'", cs->index, str);
- }
-
- cs->has_quit = true;
-
- // Make sure the data get's there before we close the connection
- NetworkSend_Packets(cs);
-
- // The client made a mistake, so drop his connection now!
- NetworkCloseClient(cs);
-}
-
-DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_NEED_PASSWORD)(NetworkClientState *cs, NetworkPasswordType type)
-{
- //
- // Packet: SERVER_NEED_PASSWORD
- // Function: Indication to the client that the server needs a password
- // Data:
- // uint8: Type of password
- //
-
- Packet *p = NetworkSend_Init(PACKET_SERVER_NEED_PASSWORD);
- NetworkSend_uint8(p, type);
- NetworkSend_Packet(p, cs);
-}
-
-DEF_SERVER_SEND_COMMAND(PACKET_SERVER_WELCOME)
-{
- //
- // Packet: SERVER_WELCOME
- // Function: The client is joined and ready to receive his map
- // Data:
- // uint16: Own ClientID
- //
-
- Packet *p;
- const NetworkClientState *new_cs;
-
- // Invalid packet when status is AUTH or higher
- if (cs->status >= STATUS_AUTH) return;
-
- cs->status = STATUS_AUTH;
- _network_game_info.clients_on++;
-
- p = NetworkSend_Init(PACKET_SERVER_WELCOME);
- NetworkSend_uint16(p, cs->index);
- NetworkSend_Packet(p, cs);
-
- // Transmit info about all the active clients
- FOR_ALL_CLIENTS(new_cs) {
- if (new_cs != cs && new_cs->status > STATUS_AUTH)
- SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(cs, DEREF_CLIENT_INFO(new_cs));
- }
- // Also send the info of the server
- SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(cs, NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX));
-}
-
-DEF_SERVER_SEND_COMMAND(PACKET_SERVER_WAIT)
-{
- //
- // Packet: PACKET_SERVER_WAIT
- // Function: The client can not receive the map at the moment because
- // someone else is already receiving the map
- // Data:
- // uint8: Clients awaiting map
- //
- int waiting = 0;
- NetworkClientState *new_cs;
- Packet *p;
-
- // Count how many players are waiting in the queue
- FOR_ALL_CLIENTS(new_cs) {
- if (new_cs->status == STATUS_MAP_WAIT) waiting++;
- }
-
- p = NetworkSend_Init(PACKET_SERVER_WAIT);
- NetworkSend_uint8(p, waiting);
- NetworkSend_Packet(p, cs);
-}
-
-// This sends the map to the client
-DEF_SERVER_SEND_COMMAND(PACKET_SERVER_MAP)
-{
- //
- // Packet: SERVER_MAP
- // Function: Sends the map to the client, or a part of it (it is splitted in
- // a lot of multiple packets)
- // Data:
- // uint8: packet-type (MAP_PACKET_START, MAP_PACKET_NORMAL and MAP_PACKET_END)
- // if MAP_PACKET_START:
- // uint32: The current FrameCounter
- // if MAP_PACKET_NORMAL:
- // piece of the map (till max-size of packet)
- // if MAP_PACKET_END:
- // uint32: seed0 of player
- // uint32: seed1 of player
- // last 2 are repeated MAX_PLAYERS time
- //
-
- static FILE *file_pointer;
- static uint sent_packets; // How many packets we did send succecfully last time
-
- if (cs->status < STATUS_AUTH) {
- // Illegal call, return error and ignore the packet
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
- return;
- }
-
- if (cs->status == STATUS_AUTH) {
- char filename[256];
- Packet *p;
-
- // Make a dump of the current game
- snprintf(filename, lengthof(filename), "%s%snetwork_server.tmp", _paths.autosave_dir, PATHSEP);
- if (SaveOrLoad(filename, SL_SAVE) != SL_OK) error("network savedump failed");
-
- file_pointer = fopen(filename, "rb");
- fseek(file_pointer, 0, SEEK_END);
-
- // Now send the _frame_counter and how many packets are coming
- p = NetworkSend_Init(PACKET_SERVER_MAP);
- NetworkSend_uint8(p, MAP_PACKET_START);
- NetworkSend_uint32(p, _frame_counter);
- NetworkSend_uint32(p, ftell(file_pointer));
- NetworkSend_Packet(p, cs);
-
- fseek(file_pointer, 0, SEEK_SET);
-
- sent_packets = 4; // We start with trying 4 packets
-
- cs->status = STATUS_MAP;
- /* Mark the start of download */
- cs->last_frame = _frame_counter;
- cs->last_frame_server = _frame_counter;
- }
-
- if (cs->status == STATUS_MAP) {
- uint i;
- int res;
- for (i = 0; i < sent_packets; i++) {
- Packet *p = NetworkSend_Init(PACKET_SERVER_MAP);
- NetworkSend_uint8(p, MAP_PACKET_NORMAL);
- res = (int)fread(p->buffer + p->size, 1, SEND_MTU - p->size, file_pointer);
-
- if (ferror(file_pointer)) error("Error reading temporary network savegame!");
-
- p->size += res;
- NetworkSend_Packet(p, cs);
- if (feof(file_pointer)) {
- // Done reading!
- Packet *p = NetworkSend_Init(PACKET_SERVER_MAP);
- NetworkSend_uint8(p, MAP_PACKET_END);
- NetworkSend_Packet(p, cs);
-
- // Set the status to DONE_MAP, no we will wait for the client
- // to send it is ready (maybe that happens like never ;))
- cs->status = STATUS_DONE_MAP;
- fclose(file_pointer);
-
- {
- NetworkClientState *new_cs;
- bool new_map_client = false;
- // Check if there is a client waiting for receiving the map
- // and start sending him the map
- FOR_ALL_CLIENTS(new_cs) {
- if (new_cs->status == STATUS_MAP_WAIT) {
- // Check if we already have a new client to send the map to
- if (!new_map_client) {
- // If not, this client will get the map
- new_cs->status = STATUS_AUTH;
- new_map_client = true;
- SEND_COMMAND(PACKET_SERVER_MAP)(new_cs);
- } else {
- // Else, send the other clients how many clients are in front of them
- SEND_COMMAND(PACKET_SERVER_WAIT)(new_cs);
- }
- }
- }
- }
-
- // There is no more data, so break the for
- break;
- }
- }
-
- // Send all packets (forced) and check if we have send it all
- NetworkSend_Packets(cs);
- if (cs->packet_queue == NULL) {
- // All are sent, increase the sent_packets
- sent_packets *= 2;
- } else {
- // Not everything is sent, decrease the sent_packets
- if (sent_packets > 1) sent_packets /= 2;
- }
- }
-}
-
-DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_JOIN)(NetworkClientState *cs, uint16 client_index)
-{
- //
- // Packet: SERVER_JOIN
- // Function: A client is joined (all active clients receive this after a
- // PACKET_CLIENT_MAP_OK) Mostly what directly follows is a
- // PACKET_SERVER_CLIENT_INFO
- // Data:
- // uint16: Client-Index
- //
-
- Packet *p = NetworkSend_Init(PACKET_SERVER_JOIN);
-
- NetworkSend_uint16(p, client_index);
-
- NetworkSend_Packet(p, cs);
-}
-
-
-DEF_SERVER_SEND_COMMAND(PACKET_SERVER_FRAME)
-{
- //
- // Packet: SERVER_FRAME
- // Function: Sends the current frame-counter to the client
- // Data:
- // uint32: Frame Counter
- // uint32: Frame Counter Max (how far may the client walk before the server?)
- // [uint32: general-seed-1]
- // [uint32: general-seed-2]
- // (last two depends on compile-settings, and are not default settings)
- //
-
- Packet *p = NetworkSend_Init(PACKET_SERVER_FRAME);
- NetworkSend_uint32(p, _frame_counter);
- NetworkSend_uint32(p, _frame_counter_max);
-#ifdef ENABLE_NETWORK_SYNC_EVERY_FRAME
- NetworkSend_uint32(p, _sync_seed_1);
-#ifdef NETWORK_SEND_DOUBLE_SEED
- NetworkSend_uint32(p, _sync_seed_2);
-#endif
-#endif
- NetworkSend_Packet(p, cs);
-}
-
-DEF_SERVER_SEND_COMMAND(PACKET_SERVER_SYNC)
-{
- //
- // Packet: SERVER_SYNC
- // Function: Sends a sync-check to the client
- // Data:
- // uint32: Frame Counter
- // uint32: General-seed-1
- // [uint32: general-seed-2]
- // (last one depends on compile-settings, and are not default settings)
- //
-
- Packet *p = NetworkSend_Init(PACKET_SERVER_SYNC);
- NetworkSend_uint32(p, _frame_counter);
- NetworkSend_uint32(p, _sync_seed_1);
-
-#ifdef NETWORK_SEND_DOUBLE_SEED
- NetworkSend_uint32(p, _sync_seed_2);
-#endif
- NetworkSend_Packet(p, cs);
-}
-
-DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_COMMAND)(NetworkClientState *cs, CommandPacket *cp)
-{
- //
- // Packet: SERVER_COMMAND
- // Function: Sends a DoCommand to the client
- // Data:
- // uint8: PlayerID (0..MAX_PLAYERS-1)
- // uint32: CommandID (see command.h)
- // uint32: P1 (free variables used in DoCommand)
- // uint32: P2
- // uint32: Tile
- // string: text
- // uint8: CallBackID (see callback_table.c)
- // uint32: Frame of execution
- //
-
- Packet *p = NetworkSend_Init(PACKET_SERVER_COMMAND);
-
- NetworkSend_uint8(p, cp->player);
- NetworkSend_uint32(p, cp->cmd);
- NetworkSend_uint32(p, cp->p1);
- NetworkSend_uint32(p, cp->p2);
- NetworkSend_uint32(p, cp->tile);
- NetworkSend_string(p, cp->text);
- NetworkSend_uint8(p, cp->callback);
- NetworkSend_uint32(p, cp->frame);
-
- NetworkSend_Packet(p, cs);
-}
-
-DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_CHAT)(NetworkClientState *cs, NetworkAction action, uint16 client_index, bool self_send, const char *msg)
-{
- //
- // Packet: SERVER_CHAT
- // Function: Sends a chat-packet to the client
- // Data:
- // uint8: ActionID (see network_data.h, NetworkAction)
- // uint16: Client-index
- // String: Message (max MAX_TEXT_MSG_LEN)
- //
-
- Packet *p = NetworkSend_Init(PACKET_SERVER_CHAT);
-
- NetworkSend_uint8(p, action);
- NetworkSend_uint16(p, client_index);
- NetworkSend_uint8(p, self_send);
- NetworkSend_string(p, msg);
-
- NetworkSend_Packet(p, cs);
-}
-
-DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR_QUIT)(NetworkClientState *cs, uint16 client_index, NetworkErrorCode errorno)
-{
- //
- // Packet: SERVER_ERROR_QUIT
- // Function: One of the clients made an error and is quiting the game
- // This packet informs the other clients of that.
- // Data:
- // uint16: Client-index
- // uint8: ErrorID (see network_data.h, NetworkErrorCode)
- //
-
- Packet *p = NetworkSend_Init(PACKET_SERVER_ERROR_QUIT);
-
- NetworkSend_uint16(p, client_index);
- NetworkSend_uint8(p, errorno);
-
- NetworkSend_Packet(p, cs);
-}
-
-DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_QUIT)(NetworkClientState *cs, uint16 client_index, const char *leavemsg)
-{
- //
- // Packet: SERVER_ERROR_QUIT
- // Function: A client left the game, and this packets informs the other clients
- // of that.
- // Data:
- // uint16: Client-index
- // String: leave-message
- //
-
- Packet *p = NetworkSend_Init(PACKET_SERVER_QUIT);
-
- NetworkSend_uint16(p, client_index);
- NetworkSend_string(p, leavemsg);
-
- NetworkSend_Packet(p, cs);
-}
-
-DEF_SERVER_SEND_COMMAND(PACKET_SERVER_SHUTDOWN)
-{
- //
- // Packet: SERVER_SHUTDOWN
- // Function: Let the clients know that the server is closing
- // Data:
- // <none>
- //
-
- Packet *p = NetworkSend_Init(PACKET_SERVER_SHUTDOWN);
- NetworkSend_Packet(p, cs);
-}
-
-DEF_SERVER_SEND_COMMAND(PACKET_SERVER_NEWGAME)
-{
- //
- // Packet: PACKET_SERVER_NEWGAME
- // Function: Let the clients know that the server is loading a new map
- // Data:
- // <none>
- //
-
- Packet *p = NetworkSend_Init(PACKET_SERVER_NEWGAME);
- NetworkSend_Packet(p, cs);
-}
-
-DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_RCON)(NetworkClientState *cs, uint16 color, const char *command)
-{
- Packet *p = NetworkSend_Init(PACKET_SERVER_RCON);
-
- NetworkSend_uint16(p, color);
- NetworkSend_string(p, command);
- NetworkSend_Packet(p, cs);
-}
-
-// **********
-// Receiving functions
-// DEF_SERVER_RECEIVE_COMMAND has parameter: NetworkClientState *cs, Packet *p
-// **********
-
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_INFO)
-{
- SEND_COMMAND(PACKET_SERVER_COMPANY_INFO)(cs);
-}
-
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_JOIN)
-{
- char name[NETWORK_CLIENT_NAME_LENGTH];
- char unique_id[NETWORK_NAME_LENGTH];
- NetworkClientInfo *ci;
- byte playas;
- NetworkLanguage client_lang;
- char client_revision[NETWORK_REVISION_LENGTH];
-
- NetworkRecv_string(cs, p, client_revision, sizeof(client_revision));
-
-#if defined(WITH_REV) || defined(WITH_REV_HACK)
- // Check if the client has revision control enabled
- if (strcmp(NOREV_STRING, client_revision) != 0 &&
- strcmp(_network_game_info.server_revision, client_revision) != 0) {
- // Different revisions!!
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_REVISION);
- return;
- }
-#endif
-
- NetworkRecv_string(cs, p, name, sizeof(name));
- playas = NetworkRecv_uint8(cs, p);
- client_lang = NetworkRecv_uint8(cs, p);
- NetworkRecv_string(cs, p, unique_id, sizeof(unique_id));
-
- if (cs->has_quit) return;
-
- // join another company does not affect these values
- switch (playas) {
- case PLAYER_NEW_COMPANY: /* New company */
- if (ActivePlayerCount() >= _network_game_info.companies_max) {
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_FULL);
- return;
- }
- break;
- case PLAYER_SPECTATOR: /* Spectator */
- if (NetworkSpectatorCount() >= _network_game_info.spectators_max) {
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_FULL);
- return;
- }
- break;
- default: /* Join another company (companies 1-8 (index 0-7)) */
- if (!IsValidPlayer(playas)) {
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_PLAYER_MISMATCH);
- return;
- }
- break;
- }
-
- // We need a valid name.. make it Player
- if (*name == '\0') ttd_strlcpy(name, "Player", sizeof(name));
-
- if (!NetworkFindName(name)) { // Change name if duplicate
- // We could not create a name for this player
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NAME_IN_USE);
- return;
- }
-
- ci = DEREF_CLIENT_INFO(cs);
-
- ttd_strlcpy(ci->client_name, name, sizeof(ci->client_name));
- ttd_strlcpy(ci->unique_id, unique_id, sizeof(ci->unique_id));
- ci->client_playas = playas;
- ci->client_lang = client_lang;
-
- // We now want a password from the client
- // else we do not allow him in!
- if (_network_game_info.use_password) {
- SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_GAME_PASSWORD);
- } else {
- if (IsValidPlayer(ci->client_playas) && _network_player_info[ci->client_playas].password[0] != '\0') {
- SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_COMPANY_PASSWORD);
- } else {
- SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
- }
- }
-
- /* Make sure companies to which people try to join are not autocleaned */
- if (IsValidPlayer(playas)) _network_player_info[playas].months_empty = 0;
-}
-
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_PASSWORD)
-{
- NetworkPasswordType type;
- char password[NETWORK_PASSWORD_LENGTH];
- const NetworkClientInfo *ci;
-
- type = NetworkRecv_uint8(cs, p);
- NetworkRecv_string(cs, p, password, sizeof(password));
-
- if (cs->status == STATUS_INACTIVE && type == NETWORK_GAME_PASSWORD) {
- // Check game-password
- if (strcmp(password, _network_game_info.server_password) != 0) {
- // Password is invalid
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_PASSWORD);
- return;
- }
-
- ci = DEREF_CLIENT_INFO(cs);
-
- if (IsValidPlayer(ci->client_playas) && _network_player_info[ci->client_playas].password[0] != '\0') {
- SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_COMPANY_PASSWORD);
- return;
- }
-
- // Valid password, allow user
- SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
- return;
- } else if (cs->status == STATUS_INACTIVE && type == NETWORK_COMPANY_PASSWORD) {
- ci = DEREF_CLIENT_INFO(cs);
-
- if (strcmp(password, _network_player_info[ci->client_playas].password) != 0) {
- // Password is invalid
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_PASSWORD);
- return;
- }
-
- SEND_COMMAND(PACKET_SERVER_WELCOME)(cs);
- return;
- }
-
-
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
- return;
-}
-
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_GETMAP)
-{
- const NetworkClientState *new_cs;
-
- // The client was never joined.. so this is impossible, right?
- // Ignore the packet, give the client a warning, and close his connection
- if (cs->status < STATUS_AUTH || cs->has_quit) {
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_AUTHORIZED);
- return;
- }
-
- // Check if someone else is receiving the map
- FOR_ALL_CLIENTS(new_cs) {
- if (new_cs->status == STATUS_MAP) {
- // Tell the new client to wait
- cs->status = STATUS_MAP_WAIT;
- SEND_COMMAND(PACKET_SERVER_WAIT)(cs);
- return;
- }
- }
-
- // We receive a request to upload the map.. give it to the client!
- SEND_COMMAND(PACKET_SERVER_MAP)(cs);
-}
-
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK)
-{
- // Client has the map, now start syncing
- if (cs->status == STATUS_DONE_MAP && !cs->has_quit) {
- char client_name[NETWORK_CLIENT_NAME_LENGTH];
- NetworkClientState *new_cs;
-
- NetworkGetClientName(client_name, sizeof(client_name), cs);
-
- NetworkTextMessage(NETWORK_ACTION_JOIN, 1, false, client_name, "");
-
- // Mark the client as pre-active, and wait for an ACK
- // so we know he is done loading and in sync with us
- cs->status = STATUS_PRE_ACTIVE;
- NetworkHandleCommandQueue(cs);
- SEND_COMMAND(PACKET_SERVER_FRAME)(cs);
- SEND_COMMAND(PACKET_SERVER_SYNC)(cs);
-
- // This is the frame the client receives
- // we need it later on to make sure the client is not too slow
- cs->last_frame = _frame_counter;
- cs->last_frame_server = _frame_counter;
-
- FOR_ALL_CLIENTS(new_cs) {
- if (new_cs->status > STATUS_AUTH) {
- SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(new_cs, DEREF_CLIENT_INFO(cs));
- SEND_COMMAND(PACKET_SERVER_JOIN)(new_cs, cs->index);
- }
- }
-
- if (_network_pause_on_join) {
- /* Now pause the game till the client is in sync */
- DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
-
- NetworkServer_HandleChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game paused (incoming client)", NETWORK_SERVER_INDEX);
- }
- } else {
- // Wrong status for this packet, give a warning to client, and close connection
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
- }
-}
-
-/** Enforce the command flags.
- * Eg a server-only command can only be executed by a server, etc.
- * @param *cp the commandpacket that is going to be checked
- * @param *ci client information for debugging output to console
- */
-static bool CheckCommandFlags(const CommandPacket *cp, const NetworkClientInfo *ci)
-{
- byte flags = GetCommandFlags(cp->cmd);
-
- if (flags & CMD_SERVER && ci->client_index != NETWORK_SERVER_INDEX) {
- IConsolePrintF(_icolour_err, "WARNING: server only command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci));
- return false;
- }
-
- if (flags & CMD_OFFLINE) {
- IConsolePrintF(_icolour_err, "WARNING: offline only command from client %d (IP: %s), kicking...", ci->client_index, GetPlayerIP(ci));
- return false;
- }
-
- return true;
-}
-
-/** The client has done a command and wants us to handle it
- * @param *cs the connected client that has sent the command
- * @param *p the packet in which the command was sent
- */
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_COMMAND)
-{
- NetworkClientState *new_cs;
- const NetworkClientInfo *ci;
- byte callback;
-
- CommandPacket *cp = malloc(sizeof(CommandPacket));
-
- // The client was never joined.. so this is impossible, right?
- // Ignore the packet, give the client a warning, and close his connection
- if (cs->status < STATUS_DONE_MAP || cs->has_quit) {
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
- return;
- }
-
- cp->player = NetworkRecv_uint8(cs, p);
- cp->cmd = NetworkRecv_uint32(cs, p);
- cp->p1 = NetworkRecv_uint32(cs, p);
- cp->p2 = NetworkRecv_uint32(cs, p);
- cp->tile = NetworkRecv_uint32(cs, p);
- NetworkRecv_string(cs, p, cp->text, lengthof(cp->text));
-
- callback = NetworkRecv_uint8(cs, p);
-
- if (cs->has_quit) return;
-
- ci = DEREF_CLIENT_INFO(cs);
-
- /* Check if cp->cmd is valid */
- if (!IsValidCommand(cp->cmd)) {
- IConsolePrintF(_icolour_err, "WARNING: invalid command from client %d (IP: %s).", ci->client_index, GetPlayerIP(ci));
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_NOT_EXPECTED);
- return;
- }
-
- if (!CheckCommandFlags(cp, ci)) {
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_KICKED);
- return;
- }
-
- /** Only CMD_PLAYER_CTRL is always allowed, for the rest, playas needs
- * to match the player in the packet. If it doesn't, the client has done
- * something pretty naughty (or a bug), and will be kicked
- */
- if (!(cp->cmd == CMD_PLAYER_CTRL && cp->p1 == 0) && ci->client_playas != cp->player) {
- IConsolePrintF(_icolour_err, "WARNING: player %d (IP: %s) tried to execute a command as player %d, kicking...",
- ci->client_playas + 1, GetPlayerIP(ci), cp->player + 1);
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_PLAYER_MISMATCH);
- return;
- }
-
- /** @todo CMD_PLAYER_CTRL with p1 = 0 announces a new player to the server. To give the
- * player the correct ID, the server injects p2 and executes the command. Any other p1
- * is prohibited. Pretty ugly and should be redone together with its function.
- * @see CmdPlayerCtrl() players.c:655
- */
- if (cp->cmd == CMD_PLAYER_CTRL) {
- if (cp->p1 != 0) {
- SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_CHEATER);
- return;
- }
-
- /* XXX - Execute the command as a valid player. Normally this would be done by a
- * spectator, but that is not allowed any commands. So do an impersonation. The drawback
- * of this is that the first company's last_built_tile is also updated... */
- cp->player = 0;
- cp->p2 = cs - _clients; // XXX - UGLY! p2 is mis-used to get the client-id in CmdPlayerCtrl
- }
-
- // The frame can be executed in the same frame as the next frame-packet
- // That frame just before that frame is saved in _frame_counter_max
- cp->frame = _frame_counter_max + 1;
- cp->next = NULL;
-
- // Queue the command for the clients (are send at the end of the frame
- // if they can handle it ;))
- FOR_ALL_CLIENTS(new_cs) {
- if (new_cs->status >= STATUS_MAP) {
- // Callbacks are only send back to the client who sent them in the
- // first place. This filters that out.
- cp->callback = (new_cs != cs) ? 0 : callback;
- NetworkAddCommandQueue(new_cs, cp);
- }
- }
-
- cp->callback = 0;
- // Queue the command on the server
- if (_local_command_queue == NULL) {
- _local_command_queue = cp;
- } else {
- // Find last packet
- CommandPacket *c = _local_command_queue;
- while (c->next != NULL) c = c->next;
- c->next = cp;
- }
-}
-
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ERROR)
-{
- // This packets means a client noticed an error and is reporting this
- // to us. Display the error and report it to the other clients
- NetworkClientState *new_cs;
- char str[100];
- char client_name[NETWORK_CLIENT_NAME_LENGTH];
- NetworkErrorCode errorno = NetworkRecv_uint8(cs, p);
-
- // The client was never joined.. thank the client for the packet, but ignore it
- if (cs->status < STATUS_DONE_MAP || cs->has_quit) {
- cs->has_quit = true;
- return;
- }
-
- NetworkGetClientName(client_name, sizeof(client_name), cs);
-
- GetNetworkErrorMsg(str, errorno, lastof(str));
-
- DEBUG(net, 2, "'%s' reported an error and is closing its connection (%s)", client_name, str);
-
- NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
-
- FOR_ALL_CLIENTS(new_cs) {
- if (new_cs->status > STATUS_AUTH) {
- SEND_COMMAND(PACKET_SERVER_ERROR_QUIT)(new_cs, cs->index, errorno);
- }
- }
-
- cs->has_quit = true;
-}
-
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_QUIT)
-{
- // The client wants to leave. Display this and report it to the other
- // clients.
- NetworkClientState *new_cs;
- char str[100];
- char client_name[NETWORK_CLIENT_NAME_LENGTH];
-
- // The client was never joined.. thank the client for the packet, but ignore it
- if (cs->status < STATUS_DONE_MAP || cs->has_quit) {
- cs->has_quit = true;
- return;
- }
-
- NetworkRecv_string(cs, p, str, lengthof(str));
-
- NetworkGetClientName(client_name, sizeof(client_name), cs);
-
- NetworkTextMessage(NETWORK_ACTION_LEAVE, 1, false, client_name, "%s", str);
-
- FOR_ALL_CLIENTS(new_cs) {
- if (new_cs->status > STATUS_AUTH) {
- SEND_COMMAND(PACKET_SERVER_QUIT)(new_cs, cs->index, str);
- }
- }
-
- cs->has_quit = true;
-}
-
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_ACK)
-{
- uint32 frame = NetworkRecv_uint32(cs, p);
-
- /* The client is trying to catch up with the server */
- if (cs->status == STATUS_PRE_ACTIVE) {
- /* The client is not yet catched up? */
- if (frame + DAY_TICKS < _frame_counter) return;
-
- /* Now he is! Unpause the game */
- cs->status = STATUS_ACTIVE;
-
- if (_network_pause_on_join) {
- DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
- NetworkServer_HandleChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused (client connected)", NETWORK_SERVER_INDEX);
- }
-
- CheckMinPlayers();
-
- /* Execute script for, e.g. MOTD */
- IConsoleCmdExec("exec scripts/on_server_connect.scr 0");
- }
-
- // The client received the frame, make note of it
- cs->last_frame = frame;
- // With those 2 values we can calculate the lag realtime
- cs->last_frame_server = _frame_counter;
-}
-
-
-
-void NetworkServer_HandleChat(NetworkAction action, DestType desttype, int dest, const char *msg, uint16 from_index)
-{
- NetworkClientState *cs;
- const NetworkClientInfo *ci, *ci_own, *ci_to;
-
- switch (desttype) {
- case DESTTYPE_CLIENT:
- /* Are we sending to the server? */
- if (dest == NETWORK_SERVER_INDEX) {
- ci = NetworkFindClientInfoFromIndex(from_index);
- /* Display the text locally, and that is it */
- if (ci != NULL)
- NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg);
- } else {
- /* Else find the client to send the message to */
- FOR_ALL_CLIENTS(cs) {
- if (cs->index == dest) {
- SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, from_index, false, msg);
- break;
- }
- }
- }
-
- // Display the message locally (so you know you have sent it)
- if (from_index != dest) {
- if (from_index == NETWORK_SERVER_INDEX) {
- ci = NetworkFindClientInfoFromIndex(from_index);
- ci_to = NetworkFindClientInfoFromIndex(dest);
- if (ci != NULL && ci_to != NULL)
- NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), true, ci_to->client_name, "%s", msg);
- } else {
- FOR_ALL_CLIENTS(cs) {
- if (cs->index == from_index) {
- SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, dest, true, msg);
- break;
- }
- }
- }
- }
- break;
- case DESTTYPE_TEAM: {
- bool show_local = true; // If this is false, the message is already displayed
- // on the client who did sent it.
- /* Find all clients that belong to this player */
- ci_to = NULL;
- FOR_ALL_CLIENTS(cs) {
- ci = DEREF_CLIENT_INFO(cs);
- if (ci->client_playas == dest) {
- SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, from_index, false, msg);
- if (cs->index == from_index) show_local = false;
- ci_to = ci; // Remember a client that is in the company for company-name
- }
- }
-
- ci = NetworkFindClientInfoFromIndex(from_index);
- ci_own = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
- if (ci != NULL && ci_own != NULL && ci_own->client_playas == dest) {
- NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg);
- if (from_index == NETWORK_SERVER_INDEX) show_local = false;
- ci_to = ci_own;
- }
-
- /* There is no such player */
- if (ci_to == NULL) break;
-
- // Display the message locally (so you know you have sent it)
- if (ci != NULL && show_local) {
- if (from_index == NETWORK_SERVER_INDEX) {
- char name[NETWORK_NAME_LENGTH];
- StringID str = IsValidPlayer(ci_to->client_playas) ? GetPlayer(ci_to->client_playas)->name_1 : STR_NETWORK_SPECTATORS;
- GetString(name, str, lastof(name));
- NetworkTextMessage(action, GetDrawStringPlayerColor(ci_own->client_playas), true, name, "%s", msg);
- } else {
- FOR_ALL_CLIENTS(cs) {
- if (cs->index == from_index) {
- SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, ci_to->client_index, true, msg);
- }
- }
- }
- }
- }
- break;
- default:
- DEBUG(net, 0, "[server] received unknown chat destination type %d. Doing broadcast instead", desttype);
- /* fall-through to next case */
- case DESTTYPE_BROADCAST:
- FOR_ALL_CLIENTS(cs) {
- SEND_COMMAND(PACKET_SERVER_CHAT)(cs, action, from_index, false, msg);
- }
- ci = NetworkFindClientInfoFromIndex(from_index);
- if (ci != NULL)
- NetworkTextMessage(action, GetDrawStringPlayerColor(ci->client_playas), false, ci->client_name, "%s", msg);
- break;
- }
-}
-
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_CHAT)
-{
- NetworkAction action = NetworkRecv_uint8(cs, p);
- DestType desttype = NetworkRecv_uint8(cs, p);
- int dest = NetworkRecv_uint8(cs, p);
- char msg[MAX_TEXT_MSG_LEN];
-
- NetworkRecv_string(cs, p, msg, MAX_TEXT_MSG_LEN);
-
- NetworkServer_HandleChat(action, desttype, dest, msg, cs->index);
-}
-
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD)
-{
- char password[NETWORK_PASSWORD_LENGTH];
- const NetworkClientInfo *ci;
-
- NetworkRecv_string(cs, p, password, sizeof(password));
- ci = DEREF_CLIENT_INFO(cs);
-
- if (IsValidPlayer(ci->client_playas)) {
- ttd_strlcpy(_network_player_info[ci->client_playas].password, password, sizeof(_network_player_info[0].password));
- }
-}
-
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_SET_NAME)
-{
- char client_name[NETWORK_CLIENT_NAME_LENGTH];
- NetworkClientInfo *ci;
-
- NetworkRecv_string(cs, p, client_name, sizeof(client_name));
- ci = DEREF_CLIENT_INFO(cs);
-
- if (cs->has_quit) return;
-
- if (ci != NULL) {
- // Display change
- if (NetworkFindName(client_name)) {
- NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, 1, false, ci->client_name, "%s", client_name);
- ttd_strlcpy(ci->client_name, client_name, sizeof(ci->client_name));
- NetworkUpdateClientInfo(ci->client_index);
- }
- }
-}
-
-DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_RCON)
-{
- char pass[NETWORK_PASSWORD_LENGTH];
- char command[NETWORK_RCONCOMMAND_LENGTH];
-
- if (_network_game_info.rcon_password[0] == '\0') return;
-
- NetworkRecv_string(cs, p, pass, sizeof(pass));
- NetworkRecv_string(cs, p, command, sizeof(command));
-
- if (strcmp(pass, _network_game_info.rcon_password) != 0) {
- DEBUG(net, 0, "[rcon] wrong password from client-id %d", cs->index);
- return;
- }
-
- DEBUG(net, 0, "[rcon] client-id %d executed: '%s'", cs->index, command);
-
- _redirect_console_to_client = cs->index;
- IConsoleCmdExec(command);
- _redirect_console_to_client = 0;
- return;
-}
-
-// The layout for the receive-functions by the server
-typedef void NetworkServerPacket(NetworkClientState *cs, Packet *p);
-
-
-// This array matches PacketType. At an incoming
-// packet it is matches against this array
-// and that way the right function to handle that
-// packet is found.
-static NetworkServerPacket* const _network_server_packet[] = {
- NULL, /*PACKET_SERVER_FULL,*/
- NULL, /*PACKET_SERVER_BANNED,*/
- RECEIVE_COMMAND(PACKET_CLIENT_JOIN),
- NULL, /*PACKET_SERVER_ERROR,*/
- RECEIVE_COMMAND(PACKET_CLIENT_COMPANY_INFO),
- NULL, /*PACKET_SERVER_COMPANY_INFO,*/
- NULL, /*PACKET_SERVER_CLIENT_INFO,*/
- NULL, /*PACKET_SERVER_NEED_PASSWORD,*/
- RECEIVE_COMMAND(PACKET_CLIENT_PASSWORD),
- NULL, /*PACKET_SERVER_WELCOME,*/
- RECEIVE_COMMAND(PACKET_CLIENT_GETMAP),
- NULL, /*PACKET_SERVER_WAIT,*/
- NULL, /*PACKET_SERVER_MAP,*/
- RECEIVE_COMMAND(PACKET_CLIENT_MAP_OK),
- NULL, /*PACKET_SERVER_JOIN,*/
- NULL, /*PACKET_SERVER_FRAME,*/
- NULL, /*PACKET_SERVER_SYNC,*/
- RECEIVE_COMMAND(PACKET_CLIENT_ACK),
- RECEIVE_COMMAND(PACKET_CLIENT_COMMAND),
- NULL, /*PACKET_SERVER_COMMAND,*/
- RECEIVE_COMMAND(PACKET_CLIENT_CHAT),
- NULL, /*PACKET_SERVER_CHAT,*/
- RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD),
- RECEIVE_COMMAND(PACKET_CLIENT_SET_NAME),
- RECEIVE_COMMAND(PACKET_CLIENT_QUIT),
- RECEIVE_COMMAND(PACKET_CLIENT_ERROR),
- NULL, /*PACKET_SERVER_QUIT,*/
- NULL, /*PACKET_SERVER_ERROR_QUIT,*/
- NULL, /*PACKET_SERVER_SHUTDOWN,*/
- NULL, /*PACKET_SERVER_NEWGAME,*/
- NULL, /*PACKET_SERVER_RCON,*/
- RECEIVE_COMMAND(PACKET_CLIENT_RCON),
-};
-
-// If this fails, check the array above with network_data.h
-assert_compile(lengthof(_network_server_packet) == PACKET_END);
-
-// This update the company_info-stuff
-void NetworkPopulateCompanyInfo(void)
-{
- char password[NETWORK_PASSWORD_LENGTH];
- const Player *p;
- const Vehicle *v;
- const Station *s;
- const NetworkClientState *cs;
- const NetworkClientInfo *ci;
- uint i;
- uint16 months_empty;
-
- FOR_ALL_PLAYERS(p) {
- if (!p->is_active) {
- memset(&_network_player_info[p->index], 0, sizeof(NetworkPlayerInfo));
- continue;
- }
-
- // Clean the info but not the password
- ttd_strlcpy(password, _network_player_info[p->index].password, sizeof(password));
- months_empty = _network_player_info[p->index].months_empty;
- memset(&_network_player_info[p->index], 0, sizeof(NetworkPlayerInfo));
- _network_player_info[p->index].months_empty = months_empty;
- ttd_strlcpy(_network_player_info[p->index].password, password, sizeof(_network_player_info[p->index].password));
-
- // Grap the company name
- SetDParam(0, p->name_1);
- SetDParam(1, p->name_2);
- GetString(_network_player_info[p->index].company_name, STR_JUST_STRING, lastof(_network_player_info[p->index].company_name));
-
- // Check the income
- if (_cur_year - 1 == p->inaugurated_year) {
- // The player is here just 1 year, so display [2], else display[1]
- for (i = 0; i < lengthof(p->yearly_expenses[2]); i++) {
- _network_player_info[p->index].income -= p->yearly_expenses[2][i];
- }
- } else {
- for (i = 0; i < lengthof(p->yearly_expenses[1]); i++) {
- _network_player_info[p->index].income -= p->yearly_expenses[1][i];
- }
- }
-
- // Set some general stuff
- _network_player_info[p->index].inaugurated_year = p->inaugurated_year;
- _network_player_info[p->index].company_value = p->old_economy[0].company_value;
- _network_player_info[p->index].money = p->money64;
- _network_player_info[p->index].performance = p->old_economy[0].performance_history;
- }
-
- // Go through all vehicles and count the type of vehicles
- FOR_ALL_VEHICLES(v) {
- if (!IsValidPlayer(v->owner)) continue;
-
- switch (v->type) {
- case VEH_Train:
- if (IsFrontEngine(v)) _network_player_info[v->owner].num_vehicle[0]++;
- break;
-
- case VEH_Road:
- if (v->cargo_type != CT_PASSENGERS) {
- _network_player_info[v->owner].num_vehicle[1]++;
- } else {
- _network_player_info[v->owner].num_vehicle[2]++;
- }
- break;
-
- case VEH_Aircraft:
- if (v->subtype <= 2) _network_player_info[v->owner].num_vehicle[3]++;
- break;
-
- case VEH_Ship:
- _network_player_info[v->owner].num_vehicle[4]++;
- break;
-
- case VEH_Special:
- case VEH_Disaster:
- break;
- }
- }
-
- // Go through all stations and count the types of stations
- FOR_ALL_STATIONS(s) {
- if (IsValidPlayer(s->owner)) {
- NetworkPlayerInfo *npi = &_network_player_info[s->owner];
-
- if (s->facilities & FACIL_TRAIN) npi->num_station[0]++;
- if (s->facilities & FACIL_TRUCK_STOP) npi->num_station[1]++;
- if (s->facilities & FACIL_BUS_STOP) npi->num_station[2]++;
- if (s->facilities & FACIL_AIRPORT) npi->num_station[3]++;
- if (s->facilities & FACIL_DOCK) npi->num_station[4]++;
- }
- }
-
- ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
- // Register local player (if not dedicated)
- if (ci != NULL && IsValidPlayer(ci->client_playas))
- ttd_strlcpy(_network_player_info[ci->client_playas].players, ci->client_name, sizeof(_network_player_info[0].players));
-
- FOR_ALL_CLIENTS(cs) {
- char client_name[NETWORK_CLIENT_NAME_LENGTH];
-
- NetworkGetClientName(client_name, sizeof(client_name), cs);
-
- ci = DEREF_CLIENT_INFO(cs);
- if (ci != NULL && IsValidPlayer(ci->client_playas)) {
- if (strlen(_network_player_info[ci->client_playas].players) != 0)
- ttd_strlcat(_network_player_info[ci->client_playas].players, ", ", lengthof(_network_player_info[0].players));
-
- ttd_strlcat(_network_player_info[ci->client_playas].players, client_name, lengthof(_network_player_info[0].players));
- }
- }
-}
-
-// Send a packet to all clients with updated info about this client_index
-void NetworkUpdateClientInfo(uint16 client_index)
-{
- NetworkClientState *cs;
- NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(client_index);
-
- if (ci == NULL) return;
-
- FOR_ALL_CLIENTS(cs) {
- SEND_COMMAND(PACKET_SERVER_CLIENT_INFO)(cs, ci);
- }
-}
-
-/* Check if we want to restart the map */
-static void NetworkCheckRestartMap(void)
-{
- if (_network_restart_game_year != 0 && _cur_year >= _network_restart_game_year) {
- DEBUG(net, 0, "Auto-restarting map. Year %d reached", _cur_year);
-
- StartNewGameWithoutGUI(GENERATE_NEW_SEED);
- }
-}
-
-/* Check if the server has autoclean_companies activated
- Two things happen:
- 1) If a company is not protected, it is closed after 1 year (for example)
- 2) If a company is protected, protection is disabled after 3 years (for example)
- (and item 1. happens a year later) */
-static void NetworkAutoCleanCompanies(void)
-{
- const NetworkClientState *cs;
- const NetworkClientInfo *ci;
- const Player *p;
- bool clients_in_company[MAX_PLAYERS];
-
- if (!_network_autoclean_companies) return;
-
- memset(clients_in_company, 0, sizeof(clients_in_company));
-
- /* Detect the active companies */
- FOR_ALL_CLIENTS(cs) {
- ci = DEREF_CLIENT_INFO(cs);
- if (IsValidPlayer(ci->client_playas)) clients_in_company[ci->client_playas] = true;
- }
-
- if (!_network_dedicated) {
- ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
- if (IsValidPlayer(ci->client_playas)) clients_in_company[ci->client_playas] = true;
- }
-
- /* Go through all the comapnies */
- FOR_ALL_PLAYERS(p) {
- /* Skip the non-active once */
- if (!p->is_active || p->is_ai) continue;
-
- if (!clients_in_company[p->index]) {
- /* The company is empty for one month more */
- _network_player_info[p->index].months_empty++;
-
- /* Is the company empty for autoclean_unprotected-months, and is there no protection? */
- if (_network_player_info[p->index].months_empty > _network_autoclean_unprotected && _network_player_info[p->index].password[0] == '\0') {
- /* Shut the company down */
- DoCommandP(0, 2, p->index, NULL, CMD_PLAYER_CTRL);
- IConsolePrintF(_icolour_def, "Auto-cleaned company #%d", p->index + 1);
- }
- /* Is the compnay empty for autoclean_protected-months, and there is a protection? */
- if (_network_player_info[p->index].months_empty > _network_autoclean_protected && _network_player_info[p->index].password[0] != '\0') {
- /* Unprotect the company */
- _network_player_info[p->index].password[0] = '\0';
- IConsolePrintF(_icolour_def, "Auto-removed protection from company #%d", p->index+1);
- _network_player_info[p->index].months_empty = 0;
- }
- } else {
- /* It is not empty, reset the date */
- _network_player_info[p->index].months_empty = 0;
- }
- }
-}
-
-// This function changes new_name to a name that is unique (by adding #1 ...)
-// and it returns true if that succeeded.
-bool NetworkFindName(char new_name[NETWORK_CLIENT_NAME_LENGTH])
-{
- NetworkClientState *new_cs;
- bool found_name = false;
- byte number = 0;
- char original_name[NETWORK_CLIENT_NAME_LENGTH];
-
- // We use NETWORK_CLIENT_NAME_LENGTH in here, because new_name is really a pointer
- ttd_strlcpy(original_name, new_name, NETWORK_CLIENT_NAME_LENGTH);
-
- while (!found_name) {
- const NetworkClientInfo *ci;
-
- found_name = true;
- FOR_ALL_CLIENTS(new_cs) {
- ci = DEREF_CLIENT_INFO(new_cs);
- if (strcmp(ci->client_name, new_name) == 0) {
- // Name already in use
- found_name = false;
- break;
- }
- }
- // Check if it is the same as the server-name
- ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
- if (ci != NULL) {
- if (strcmp(ci->client_name, new_name) == 0) found_name = false; // name already in use
- }
-
- if (!found_name) {
- // Try a new name (<name> #1, <name> #2, and so on)
-
- // Stop if we tried for more than 50 times..
- if (number++ > 50) break;
- snprintf(new_name, NETWORK_CLIENT_NAME_LENGTH, "%s #%d", original_name, number);
- }
- }
-
- return found_name;
-}
-
-// Reads a packet from the stream
-bool NetworkServer_ReadPackets(NetworkClientState *cs)
-{
- Packet *p;
- NetworkRecvStatus res;
- while ((p = NetworkRecv_Packet(cs, &res)) != NULL) {
- byte type = NetworkRecv_uint8(cs, p);
- if (type < PACKET_END && _network_server_packet[type] != NULL && !cs->has_quit) {
- _network_server_packet[type](cs, p);
- } else {
- DEBUG(net, 0, "[server] received invalid packet type %d", type);
- }
- free(p);
- }
-
- return true;
-}
-
-// Handle the local command-queue
-static void NetworkHandleCommandQueue(NetworkClientState* cs)
-{
- CommandPacket *cp;
-
- while ( (cp = cs->command_queue) != NULL) {
- SEND_COMMAND(PACKET_SERVER_COMMAND)(cs, cp);
-
- cs->command_queue = cp->next;
- free(cp);
- }
-}
-
-// This is called every tick if this is a _network_server
-void NetworkServer_Tick(bool send_frame)
-{
- NetworkClientState *cs;
-#ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
- bool send_sync = false;
-#endif
-
-#ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
- if (_frame_counter >= _last_sync_frame + _network_sync_freq) {
- _last_sync_frame = _frame_counter;
- send_sync = true;
- }
-#endif
-
- // Now we are done with the frame, inform the clients that they can
- // do their frame!
- FOR_ALL_CLIENTS(cs) {
- // Check if the speed of the client is what we can expect from a client
- if (cs->status == STATUS_ACTIVE) {
- // 1 lag-point per day
- int lag = NetworkCalculateLag(cs) / DAY_TICKS;
- if (lag > 0) {
- if (lag > 3) {
- // Client did still not report in after 4 game-day, drop him
- // (that is, the 3 of above, + 1 before any lag is counted)
- IConsolePrintF(_icolour_err,"Client #%d is dropped because the client did not respond for more than 4 game-days", cs->index);
- NetworkCloseClient(cs);
- continue;
- }
-
- // Report once per time we detect the lag
- if (cs->lag_test == 0) {
- IConsolePrintF(_icolour_warn,"[%d] Client #%d is slow, try increasing *net_frame_freq to a higher value!", _frame_counter, cs->index);
- cs->lag_test = 1;
- }
- } else {
- cs->lag_test = 0;
- }
- } else if (cs->status == STATUS_PRE_ACTIVE) {
- int lag = NetworkCalculateLag(cs);
- if (lag > _network_max_join_time) {
- IConsolePrintF(_icolour_err,"Client #%d is dropped because it took longer than %d ticks for him to join", cs->index, _network_max_join_time);
- NetworkCloseClient(cs);
- }
- }
-
- if (cs->status >= STATUS_PRE_ACTIVE) {
- // Check if we can send command, and if we have anything in the queue
- NetworkHandleCommandQueue(cs);
-
- // Send an updated _frame_counter_max to the client
- if (send_frame) SEND_COMMAND(PACKET_SERVER_FRAME)(cs);
-
-#ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
- // Send a sync-check packet
- if (send_sync) SEND_COMMAND(PACKET_SERVER_SYNC)(cs);
-#endif
- }
- }
-
- /* See if we need to advertise */
- NetworkUDPAdvertise();
-}
-
-void NetworkServerYearlyLoop(void)
-{
- NetworkCheckRestartMap();
-}
-
-void NetworkServerMonthlyLoop(void)
-{
- NetworkAutoCleanCompanies();
-}
-
-#endif /* ENABLE_NETWORK */
diff --git a/network/network_server.h b/network/network_server.h
deleted file mode 100644
index c5b2baade..000000000
--- a/network/network_server.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* $Id$ */
-
-#ifndef NETWORK_SERVER_H
-#define NETWORK_SERVER_H
-
-#ifdef ENABLE_NETWORK
-
-DEF_SERVER_SEND_COMMAND(PACKET_SERVER_MAP);
-DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR_QUIT)(NetworkClientState *cs, uint16 client_index, NetworkErrorCode errorno);
-DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_ERROR)(NetworkClientState *cs, NetworkErrorCode error);
-DEF_SERVER_SEND_COMMAND(PACKET_SERVER_SHUTDOWN);
-DEF_SERVER_SEND_COMMAND(PACKET_SERVER_NEWGAME);
-DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_RCON)(NetworkClientState *cs, uint16 color, const char *command);
-
-bool NetworkFindName(char new_name[NETWORK_CLIENT_NAME_LENGTH]);
-void NetworkServer_HandleChat(NetworkAction action, DestType type, int dest, const char *msg, uint16 from_index);
-
-bool NetworkServer_ReadPackets(NetworkClientState *cs);
-void NetworkServer_Tick(bool send_frame);
-void NetworkServerMonthlyLoop(void);
-void NetworkServerYearlyLoop(void);
-
-static inline const char* GetPlayerIP(const NetworkClientInfo* ci)
-{
- struct in_addr addr;
-
- addr.s_addr = ci->client_ip;
- return inet_ntoa(addr);
-}
-
-#else /* ENABLE_NETWORK */
-/* Network function stubs when networking is disabled */
-
-static inline void NetworkServerMonthlyLoop(void) {}
-static inline void NetworkServerYearlyLoop(void) {}
-
-#endif /* ENABLE_NETWORK */
-
-#endif /* NETWORK_SERVER_H */
diff --git a/network/network_udp.c b/network/network_udp.c
deleted file mode 100644
index aeef75e77..000000000
--- a/network/network_udp.c
+++ /dev/null
@@ -1,663 +0,0 @@
-/* $Id$ */
-
-#ifdef ENABLE_NETWORK
-
-#include "../stdafx.h"
-#include "../debug.h"
-#include "../string.h"
-#include "network_data.h"
-#include "../date.h"
-#include "../map.h"
-#include "network_gamelist.h"
-#include "network_udp.h"
-#include "../variables.h"
-#include "../newgrf_config.h"
-
-#include "core/udp.h"
-
-/**
- * @file network_udp.c This file handles the UDP related communication.
- *
- * This is the GameServer <-> MasterServer and GameServer <-> GameClient
- * communication before the game is being joined.
- */
-
-enum {
- ADVERTISE_NORMAL_INTERVAL = 30000, // interval between advertising in ticks (15 minutes)
- ADVERTISE_RETRY_INTERVAL = 300, // readvertise when no response after this many ticks (9 seconds)
- ADVERTISE_RETRY_TIMES = 3 // give up readvertising after this much failed retries
-};
-
-#define DEF_UDP_RECEIVE_COMMAND(type) void NetworkPacketReceive_ ## type ## _command(Packet *p, struct sockaddr_in *client_addr)
-
-static NetworkClientState _udp_cs;
-
-DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER)
-{
- Packet *packet;
- // Just a fail-safe.. should never happen
- if (!_network_udp_server)
- return;
-
- packet = NetworkSend_Init(PACKET_UDP_SERVER_RESPONSE);
-
- // Update some game_info
- _network_game_info.game_date = _date;
- _network_game_info.map_width = MapSizeX();
- _network_game_info.map_height = MapSizeY();
- _network_game_info.map_set = _opt.landscape;
- _network_game_info.companies_on = ActivePlayerCount();
- _network_game_info.spectators_on = NetworkSpectatorCount();
- _network_game_info.grfconfig = _grfconfig;
-
- NetworkSend_NetworkGameInfo(p, &_network_game_info);
-
- // Let the client know that we are here
- NetworkSendUDP_Packet(_udp_server_socket, packet, client_addr);
-
- free(packet);
-
- DEBUG(net, 2, "[udp] queried from '%s'", inet_ntoa(client_addr->sin_addr));
-}
-
-void HandleIncomingNetworkGameInfoGRFConfig(GRFConfig *config)
-{
- /* Find the matching GRF file */
- const GRFConfig *f = FindGRFConfig(config->grfid, config->md5sum);
- if (f == NULL) {
- /* Don't know the GRF, so mark game incompatible and the (possibly)
- * already resolved name for this GRF (another server has sent the
- * name of the GRF already */
- config->name = FindUnknownGRFName(config->grfid, config->md5sum, true);
- SETBIT(config->flags, GCF_NOT_FOUND);
- } else {
- config->filename = f->filename;
- config->name = f->name;
- config->info = f->info;
- }
- SETBIT(config->flags, GCF_COPY);
-}
-
-DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_RESPONSE)
-{
- extern const char _openttd_revision[];
- NetworkGameList *item;
-
- // Just a fail-safe.. should never happen
- if (_network_udp_server || _udp_cs.has_quit) return;
-
- DEBUG(net, 4, "[udp] server response from %s:%d", inet_ntoa(client_addr->sin_addr),ntohs(client_addr->sin_port));
-
- // Find next item
- item = NetworkGameListAddItem(inet_addr(inet_ntoa(client_addr->sin_addr)), ntohs(client_addr->sin_port));
-
- NetworkRecv_NetworkGameInfo(&_udp_cs, p, &item->info);
-
- item->info.compatible = true;
- {
- /* Checks whether there needs to be a request for names of GRFs and makes
- * the request if necessary. GRFs that need to be requested are the GRFs
- * that do not exist on the clients system and we do not have the name
- * resolved of, i.e. the name is still UNKNOWN_GRF_NAME_PLACEHOLDER.
- * The in_request array and in_request_count are used so there is no need
- * to do a second loop over the GRF list, which can be relatively expensive
- * due to the string comparisons. */
- const GRFConfig *in_request[NETWORK_MAX_GRF_COUNT];
- const GRFConfig *c;
- uint in_request_count = 0;
- struct sockaddr_in out_addr;
-
- for (c = item->info.grfconfig; c != NULL; c = c->next) {
- if (HASBIT(c->flags, GCF_NOT_FOUND)) item->info.compatible = false;
- if (!HASBIT(c->flags, GCF_NOT_FOUND) || strcmp(c->name, UNKNOWN_GRF_NAME_PLACEHOLDER) != 0) continue;
- in_request[in_request_count] = c;
- in_request_count++;
- }
-
- if (in_request_count > 0) {
- /* There are 'unknown' GRFs, now send a request for them */
- uint i;
- Packet *packet = NetworkSend_Init(PACKET_UDP_CLIENT_GET_NEWGRFS);
-
- NetworkSend_uint8 (packet, in_request_count);
- for (i = 0; i < in_request_count; i++) {
- NetworkSend_GRFIdentifier(packet, in_request[i]);
- }
-
- out_addr.sin_family = AF_INET;
- out_addr.sin_port = htons(item->port);
- out_addr.sin_addr.s_addr = item->ip;
- NetworkSendUDP_Packet(_udp_client_socket, packet, &out_addr);
- free(packet);
- }
- }
-
- if (item->info.server_lang >= NETWORK_NUM_LANGUAGES) item->info.server_lang = 0;
- if (item->info.map_set >= NUM_LANDSCAPE ) item->info.map_set = 0;
-
- if (item->info.hostname[0] == '\0')
- snprintf(item->info.hostname, sizeof(item->info.hostname), "%s", inet_ntoa(client_addr->sin_addr));
-
- /* Check if we are allowed on this server based on the revision-match */
- item->info.version_compatible =
- strcmp(item->info.server_revision, _openttd_revision) == 0 ||
- strcmp(item->info.server_revision, NOREV_STRING) == 0;
- item->info.compatible &= item->info.version_compatible; // Already contains match for GRFs
-
- item->online = true;
-
- UpdateNetworkGameWindow(false);
-}
-
-DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO)
-{
- NetworkClientState *cs;
- NetworkClientInfo *ci;
- Packet *packet;
- Player *player;
- byte current = 0;
- int i;
-
- // Just a fail-safe.. should never happen
- if (!_network_udp_server) return;
-
- packet = NetworkSend_Init(PACKET_UDP_SERVER_DETAIL_INFO);
-
- /* Send the amount of active companies */
- NetworkSend_uint8 (packet, NETWORK_COMPANY_INFO_VERSION);
- NetworkSend_uint8 (packet, ActivePlayerCount());
-
- /* Fetch the latest version of everything */
- NetworkPopulateCompanyInfo();
-
- /* Go through all the players */
- FOR_ALL_PLAYERS(player) {
- /* Skip non-active players */
- if (!player->is_active) continue;
-
- current++;
-
- /* Send the information */
- NetworkSend_uint8(packet, current);
-
- NetworkSend_string(packet, _network_player_info[player->index].company_name);
- NetworkSend_uint32(packet, _network_player_info[player->index].inaugurated_year);
- NetworkSend_uint64(packet, _network_player_info[player->index].company_value);
- NetworkSend_uint64(packet, _network_player_info[player->index].money);
- NetworkSend_uint64(packet, _network_player_info[player->index].income);
- NetworkSend_uint16(packet, _network_player_info[player->index].performance);
-
- /* Send 1 if there is a passord for the company else send 0 */
- if (_network_player_info[player->index].password[0] != '\0') {
- NetworkSend_uint8(packet, 1);
- } else {
- NetworkSend_uint8(packet, 0);
- }
-
- for (i = 0; i < NETWORK_VEHICLE_TYPES; i++)
- NetworkSend_uint16(packet, _network_player_info[player->index].num_vehicle[i]);
-
- for (i = 0; i < NETWORK_STATION_TYPES; i++)
- NetworkSend_uint16(packet, _network_player_info[player->index].num_station[i]);
-
- /* Find the clients that are connected to this player */
- FOR_ALL_CLIENTS(cs) {
- ci = DEREF_CLIENT_INFO(cs);
- if (ci->client_playas == player->index) {
- /* The uint8 == 1 indicates that a client is following */
- NetworkSend_uint8(packet, 1);
- NetworkSend_string(packet, ci->client_name);
- NetworkSend_string(packet, ci->unique_id);
- NetworkSend_uint32(packet, ci->join_date);
- }
- }
- /* Also check for the server itself */
- ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
- if (ci->client_playas == player->index) {
- /* The uint8 == 1 indicates that a client is following */
- NetworkSend_uint8(packet, 1);
- NetworkSend_string(packet, ci->client_name);
- NetworkSend_string(packet, ci->unique_id);
- NetworkSend_uint32(packet, ci->join_date);
- }
-
- /* Indicates end of client list */
- NetworkSend_uint8(packet, 0);
- }
-
- /* And check if we have any spectators */
- FOR_ALL_CLIENTS(cs) {
- ci = DEREF_CLIENT_INFO(cs);
- if (!IsValidPlayer(ci->client_playas)) {
- /* The uint8 == 1 indicates that a client is following */
- NetworkSend_uint8(packet, 1);
- NetworkSend_string(packet, ci->client_name);
- NetworkSend_string(packet, ci->unique_id);
- NetworkSend_uint32(packet, ci->join_date);
- }
- }
-
- /* Also check for the server itself */
- ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
- if (!IsValidPlayer(ci->client_playas)) {
- /* The uint8 == 1 indicates that a client is following */
- NetworkSend_uint8(packet, 1);
- NetworkSend_string(packet, ci->client_name);
- NetworkSend_string(packet, ci->unique_id);
- NetworkSend_uint32(packet, ci->join_date);
- }
-
- /* Indicates end of client list */
- NetworkSend_uint8(packet, 0);
-
- NetworkSendUDP_Packet(_udp_server_socket, packet, client_addr);
-
- free(packet);
-}
-
-DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST)
-{
- int i;
- struct in_addr ip;
- uint16 port;
- uint8 ver;
-
- /* packet begins with the protocol version (uint8)
- * then an uint16 which indicates how many
- * ip:port pairs are in this packet, after that
- * an uint32 (ip) and an uint16 (port) for each pair
- */
-
- ver = NetworkRecv_uint8(&_udp_cs, p);
-
- if (_udp_cs.has_quit) return;
-
- if (ver == 1) {
- for (i = NetworkRecv_uint16(&_udp_cs, p); i != 0 ; i--) {
- ip.s_addr = TO_LE32(NetworkRecv_uint32(&_udp_cs, p));
- port = NetworkRecv_uint16(&_udp_cs, p);
- NetworkUDPQueryServer(inet_ntoa(ip), port);
- }
- }
-}
-
-DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER)
-{
- _network_advertise_retries = 0;
- DEBUG(net, 2, "[udp] advertising on master server successfull");
-
- /* We are advertised, but we don't want to! */
- if (!_network_advertise) NetworkUDPRemoveAdvertise();
-}
-
-/**
- * A client has requested the names of some NewGRFs.
- *
- * Replying this can be tricky as we have a limit of SEND_MTU bytes
- * in the reply packet and we can send up to 100 bytes per NewGRF
- * (GRF ID, MD5sum and NETWORK_GRF_NAME_LENGTH bytes for the name).
- * As SEND_MTU is _much_ less than 100 * NETWORK_MAX_GRF_COUNT, it
- * could be that a packet overflows. To stop this we only reply
- * with the first N NewGRFs so that if the first N + 1 NewGRFs
- * would be sent, the packet overflows.
- * in_reply and in_reply_count are used to keep a list of GRFs to
- * send in the reply.
- */
-DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS)
-{
- uint8 num_grfs;
- uint i;
-
- const GRFConfig *in_reply[NETWORK_MAX_GRF_COUNT];
- Packet *packet;
- uint8 in_reply_count = 0;
- uint packet_len = 0;
-
- /* Just a fail-safe.. should never happen */
- if (_udp_cs.has_quit) return;
-
- DEBUG(net, 6, "[udp] newgrf data request from %s:%d", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port));
-
- num_grfs = NetworkRecv_uint8 (&_udp_cs, p);
- if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
-
- for (i = 0; i < num_grfs; i++) {
- GRFConfig c;
- const GRFConfig *f;
-
- NetworkRecv_GRFIdentifier(&_udp_cs, p, &c);
-
- /* Find the matching GRF file */
- f = FindGRFConfig(c.grfid, c.md5sum);
- if (f == NULL) continue; // The GRF is unknown to this server
-
- /* If the reply might exceed the size of the packet, only reply
- * the current list and do not send the other data.
- * The name could be an empty string, if so take the filename. */
- packet_len += sizeof(c.grfid) + sizeof(c.md5sum) +
- min(strlen((f->name != NULL && strlen(f->name) > 0) ? f->name : f->filename) + 1, NETWORK_GRF_NAME_LENGTH);
- if (packet_len > SEND_MTU - 4) { // 4 is 3 byte header + grf count in reply
- break;
- }
- in_reply[in_reply_count] = f;
- in_reply_count++;
- }
-
- if (in_reply_count == 0) return;
-
- packet = NetworkSend_Init(PACKET_UDP_SERVER_NEWGRFS);
- NetworkSend_uint8 (packet, in_reply_count);
- for (i = 0; i < in_reply_count; i++) {
- char name[NETWORK_GRF_NAME_LENGTH];
-
- /* The name could be an empty string, if so take the filename */
- ttd_strlcpy(name, (in_reply[i]->name != NULL && strlen(in_reply[i]->name) > 0) ?
- in_reply[i]->name : in_reply[i]->filename, sizeof(name));
- NetworkSend_GRFIdentifier(packet, in_reply[i]);
- NetworkSend_string(packet, name);
- }
-
- NetworkSendUDP_Packet(_udp_server_socket, packet, client_addr);
- free(packet);
-}
-
-/** The return of the client's request of the names of some NewGRFs */
-DEF_UDP_RECEIVE_COMMAND(PACKET_UDP_SERVER_NEWGRFS)
-{
- uint8 num_grfs;
- uint i;
-
- /* Just a fail-safe.. should never happen */
- if (_udp_cs.has_quit) return;
-
- DEBUG(net, 6, "[udp] newgrf data reply from %s:%d", inet_ntoa(client_addr->sin_addr),ntohs(client_addr->sin_port));
-
- num_grfs = NetworkRecv_uint8 (&_udp_cs, p);
- if (num_grfs > NETWORK_MAX_GRF_COUNT) return;
-
- for (i = 0; i < num_grfs; i++) {
- char *unknown_name;
- char name[NETWORK_GRF_NAME_LENGTH];
- GRFConfig c;
-
- NetworkRecv_GRFIdentifier(&_udp_cs, p, &c);
- NetworkRecv_string(&_udp_cs, p, name, sizeof(name));
-
- /* An empty name is not possible under normal circumstances
- * and causes problems when showing the NewGRF list. */
- if (strlen(name) == 0) continue;
-
- /* Finds the fake GRFConfig for the just read GRF ID and MD5sum tuple.
- * If it exists and not resolved yet, then name of the fake GRF is
- * overwritten with the name from the reply. */
- unknown_name = FindUnknownGRFName(c.grfid, c.md5sum, false);
- if (unknown_name != NULL && strcmp(unknown_name, UNKNOWN_GRF_NAME_PLACEHOLDER) == 0) {
- ttd_strlcpy(unknown_name, name, NETWORK_GRF_NAME_LENGTH);
- }
- }
-}
-
-
-// The layout for the receive-functions by UDP
-typedef void NetworkUDPPacket(Packet *p, struct sockaddr_in *client_addr);
-
-static NetworkUDPPacket* const _network_udp_packet[] = {
- RECEIVE_COMMAND(PACKET_UDP_CLIENT_FIND_SERVER),
- RECEIVE_COMMAND(PACKET_UDP_SERVER_RESPONSE),
- RECEIVE_COMMAND(PACKET_UDP_CLIENT_DETAIL_INFO),
- NULL,
- NULL,
- RECEIVE_COMMAND(PACKET_UDP_MASTER_ACK_REGISTER),
- NULL,
- RECEIVE_COMMAND(PACKET_UDP_MASTER_RESPONSE_LIST),
- NULL,
- RECEIVE_COMMAND(PACKET_UDP_CLIENT_GET_NEWGRFS),
- RECEIVE_COMMAND(PACKET_UDP_SERVER_NEWGRFS),
-};
-
-
-// If this fails, check the array above with network_data.h
-assert_compile(lengthof(_network_udp_packet) == PACKET_UDP_END);
-
-
-void NetworkHandleUDPPacket(Packet *p, struct sockaddr_in *client_addr)
-{
- byte type;
-
- /* Fake a client, so we can see when there is an illegal packet */
- _udp_cs.socket = INVALID_SOCKET;
- _udp_cs.has_quit = false;
-
- type = NetworkRecv_uint8(&_udp_cs, p);
-
- if (type < PACKET_UDP_END && _network_udp_packet[type] != NULL && !_udp_cs.has_quit) {
- _network_udp_packet[type](p, client_addr);
- } else {
- if (!_udp_cs.has_quit) {
- DEBUG(net, 0, "[udp] received invalid packet type %d", type);
- } else {
- DEBUG(net, 0, "[udp] received illegal packet");
- }
- }
-}
-
-
-// Close UDP connection
-void NetworkUDPClose(void)
-{
- DEBUG(net, 1, "[udp] closed listeners");
-
- if (_network_udp_server) {
- if (_udp_server_socket != INVALID_SOCKET) {
- closesocket(_udp_server_socket);
- _udp_server_socket = INVALID_SOCKET;
- }
-
- if (_udp_master_socket != INVALID_SOCKET) {
- closesocket(_udp_master_socket);
- _udp_master_socket = INVALID_SOCKET;
- }
-
- _network_udp_server = false;
- _network_udp_broadcast = 0;
- } else {
- if (_udp_client_socket != INVALID_SOCKET) {
- closesocket(_udp_client_socket);
- _udp_client_socket = INVALID_SOCKET;
- }
- _network_udp_broadcast = 0;
- }
-}
-
-// Broadcast to all ips
-static void NetworkUDPBroadCast(SOCKET udp)
-{
- Packet* p = NetworkSend_Init(PACKET_UDP_CLIENT_FIND_SERVER);
- uint i;
-
- for (i = 0; _broadcast_list[i] != 0; i++) {
- struct sockaddr_in out_addr;
-
- out_addr.sin_family = AF_INET;
- out_addr.sin_port = htons(_network_server_port);
- out_addr.sin_addr.s_addr = _broadcast_list[i];
-
- DEBUG(net, 4, "[udp] broadcasting to %s", inet_ntoa(out_addr.sin_addr));
-
- NetworkSendUDP_Packet(udp, p, &out_addr);
- }
-
- free(p);
-}
-
-
-// Request the the server-list from the master server
-void NetworkUDPQueryMasterServer(void)
-{
- struct sockaddr_in out_addr;
- Packet *p;
-
- if (_udp_client_socket == INVALID_SOCKET)
- if (!NetworkUDPListen(&_udp_client_socket, 0, 0, true))
- return;
-
- p = NetworkSend_Init(PACKET_UDP_CLIENT_GET_LIST);
-
- out_addr.sin_family = AF_INET;
- out_addr.sin_port = htons(NETWORK_MASTER_SERVER_PORT);
- out_addr.sin_addr.s_addr = NetworkResolveHost(NETWORK_MASTER_SERVER_HOST);
-
- // packet only contains protocol version
- NetworkSend_uint8(p, NETWORK_MASTER_SERVER_VERSION);
-
- NetworkSendUDP_Packet(_udp_client_socket, p, &out_addr);
-
- DEBUG(net, 2, "[udp] master server queried at %s:%d", inet_ntoa(out_addr.sin_addr),ntohs(out_addr.sin_port));
-
- free(p);
-}
-
-// Find all servers
-void NetworkUDPSearchGame(void)
-{
- // We are still searching..
- if (_network_udp_broadcast > 0) return;
-
- // No UDP-socket yet..
- if (_udp_client_socket == INVALID_SOCKET)
- if (!NetworkUDPListen(&_udp_client_socket, 0, 0, true))
- return;
-
- DEBUG(net, 0, "[udp] searching server");
-
- NetworkUDPBroadCast(_udp_client_socket);
- _network_udp_broadcast = 300; // Stay searching for 300 ticks
-}
-
-NetworkGameList *NetworkUDPQueryServer(const char* host, unsigned short port)
-{
- struct sockaddr_in out_addr;
- Packet *p;
- NetworkGameList *item;
-
- // No UDP-socket yet..
- if (_udp_client_socket == INVALID_SOCKET)
- if (!NetworkUDPListen(&_udp_client_socket, 0, 0, true))
- return NULL;
-
- out_addr.sin_family = AF_INET;
- out_addr.sin_port = htons(port);
- out_addr.sin_addr.s_addr = NetworkResolveHost(host);
-
- // Clear item in gamelist
- item = NetworkGameListAddItem(inet_addr(inet_ntoa(out_addr.sin_addr)), ntohs(out_addr.sin_port));
- memset(&item->info, 0, sizeof(item->info));
- ttd_strlcpy(item->info.server_name, host, lengthof(item->info.server_name));
- ttd_strlcpy(item->info.hostname, host, lengthof(item->info.hostname));
- item->online = false;
-
- // Init the packet
- p = NetworkSend_Init(PACKET_UDP_CLIENT_FIND_SERVER);
-
- NetworkSendUDP_Packet(_udp_client_socket, p, &out_addr);
-
- free(p);
-
- UpdateNetworkGameWindow(false);
- return item;
-}
-
-/* Remove our advertise from the master-server */
-void NetworkUDPRemoveAdvertise(void)
-{
- struct sockaddr_in out_addr;
- Packet *p;
-
- /* Check if we are advertising */
- if (!_networking || !_network_server || !_network_udp_server) return;
-
- /* check for socket */
- if (_udp_master_socket == INVALID_SOCKET)
- if (!NetworkUDPListen(&_udp_master_socket, _network_server_bind_ip, 0, false))
- return;
-
- DEBUG(net, 1, "[udp] removing advertise from master server");
-
- /* Find somewhere to send */
- out_addr.sin_family = AF_INET;
- out_addr.sin_port = htons(NETWORK_MASTER_SERVER_PORT);
- out_addr.sin_addr.s_addr = NetworkResolveHost(NETWORK_MASTER_SERVER_HOST);
-
- /* Send the packet */
- p = NetworkSend_Init(PACKET_UDP_SERVER_UNREGISTER);
- /* Packet is: Version, server_port */
- NetworkSend_uint8(p, NETWORK_MASTER_SERVER_VERSION);
- NetworkSend_uint16(p, _network_server_port);
- NetworkSendUDP_Packet(_udp_master_socket, p, &out_addr);
-
- free(p);
-}
-
-/* Register us to the master server
- This function checks if it needs to send an advertise */
-void NetworkUDPAdvertise(void)
-{
- struct sockaddr_in out_addr;
- Packet *p;
-
- /* Check if we should send an advertise */
- if (!_networking || !_network_server || !_network_udp_server || !_network_advertise)
- return;
-
- /* check for socket */
- if (_udp_master_socket == INVALID_SOCKET)
- if (!NetworkUDPListen(&_udp_master_socket, _network_server_bind_ip, 0, false))
- return;
-
- if (_network_need_advertise) {
- _network_need_advertise = false;
- _network_advertise_retries = ADVERTISE_RETRY_TIMES;
- } else {
- /* Only send once every ADVERTISE_NORMAL_INTERVAL ticks */
- if (_network_advertise_retries == 0) {
- if ((_network_last_advertise_frame + ADVERTISE_NORMAL_INTERVAL) > _frame_counter)
- return;
- _network_advertise_retries = ADVERTISE_RETRY_TIMES;
- }
-
- if ((_network_last_advertise_frame + ADVERTISE_RETRY_INTERVAL) > _frame_counter)
- return;
- }
-
- _network_advertise_retries--;
- _network_last_advertise_frame = _frame_counter;
-
- /* Find somewhere to send */
- out_addr.sin_family = AF_INET;
- out_addr.sin_port = htons(NETWORK_MASTER_SERVER_PORT);
- out_addr.sin_addr.s_addr = NetworkResolveHost(NETWORK_MASTER_SERVER_HOST);
-
- DEBUG(net, 1, "[udp] advertising to master server");
-
- /* Send the packet */
- p = NetworkSend_Init(PACKET_UDP_SERVER_REGISTER);
- /* Packet is: WELCOME_MESSAGE, Version, server_port */
- NetworkSend_string(p, NETWORK_MASTER_SERVER_WELCOME_MESSAGE);
- NetworkSend_uint8(p, NETWORK_MASTER_SERVER_VERSION);
- NetworkSend_uint16(p, _network_server_port);
- NetworkSendUDP_Packet(_udp_master_socket, p, &out_addr);
-
- free(p);
-}
-
-void NetworkUDPInitialize(void)
-{
- _udp_client_socket = INVALID_SOCKET;
- _udp_server_socket = INVALID_SOCKET;
- _udp_master_socket = INVALID_SOCKET;
-
- _network_udp_server = false;
- _network_udp_broadcast = 0;
-}
-
-#endif /* ENABLE_NETWORK */
diff --git a/network/network_udp.h b/network/network_udp.h
deleted file mode 100644
index 4488d19d4..000000000
--- a/network/network_udp.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* $Id$ */
-
-#ifndef NETWORK_UDP_H
-#define NETWORK_UDP_H
-
-#ifdef ENABLE_NETWORK
-
-void NetworkUDPInitialize(void);
-void NetworkUDPSearchGame(void);
-void NetworkUDPQueryMasterServer(void);
-NetworkGameList *NetworkUDPQueryServer(const char* host, unsigned short port);
-void NetworkUDPAdvertise(void);
-void NetworkUDPRemoveAdvertise(void);
-
-#endif /* ENABLE_NETWORK */
-
-#endif /* NETWORK_UDP_H */